Решение на Форматиране на импорти от Ангел Пенчев

Обратно към всички решения

Към профила на Ангел Пенчев

Резултати

  • 8 точки от тестове
  • 1 бонус точка
  • 9 точки общо
  • 8 успешни тест(а)
  • 12 неуспешни тест(а)

Код

use std::collections::{HashMap, HashSet};
use std::fmt;
use std::hash::{Hash, Hasher};
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct Import<'a>(pub &'a [&'a str]);
#[derive(PartialEq, Eq)]
pub enum Order {
Original,
Sorted,
}
// As per Clippy recommendation, implemented fmt::Display instead of ToString trait.
impl<'a> fmt::Display for Import<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0.join("::"))
}
}
#[derive(Debug)]
struct ModuleTree {
root: ModuleNode,
}
#[derive(Debug, Clone)]
struct ModuleNode {
value: String,
children: Vec<ModuleNode>,
}
impl ModuleNode {
fn new(value: String) -> Self {
Self {
value,
children: Vec::new(),
}
}
fn get_or_insert_child(&mut self, value: String) -> &mut ModuleNode {
if let Some(pos) = self.children.iter().position(|child| child.value == value) {
return &mut self.children[pos];
}
self.children.push(ModuleNode::new(value));
self.children.last_mut().unwrap()
}
}
impl PartialEq for ModuleNode {
fn eq(&self, other: &Self) -> bool {
self.value == other.value
}
}
impl Eq for ModuleNode {}
// Required so I can use HashSet<ModuleNode>
impl Hash for ModuleNode {
fn hash<H: Hasher>(&self, state: &mut H) {
self.value.hash(state);
}
}
pub fn format_flat(imports: &[Import], order: Order) -> Vec<String> {
let mut processed = HashSet::new();
let mut results: Vec<String> = imports
.iter()
.map(|import| import.to_string())
.filter(|import| processed.insert(import.clone())) // .insert() returns true if the value was not present before
.collect();
if order == Order::Sorted {
results.sort()
}
results
}
pub fn format_nested(imports: &[Import], order: Order) -> Vec<String> {
let mut imports = imports.to_vec();
if order == Order::Sorted {
imports.sort_by(|left, right| left.0.cmp(right.0));
}
let mut unique_imports = Vec::new();
let mut seen = HashSet::new();
for import in imports {
if seen.insert(import.clone()) {
unique_imports.push(import);
}
}
imports = unique_imports;
// Create structure
let mut modules: Vec<(String, Vec<Vec<String>>)> = Vec::new();
for import in imports {
if let Some((module_name, module_path)) = import.0.split_first() {
let module_name = module_name.to_string();
let module_path: Vec<String> = module_path.iter().map(|s| s.to_string()).collect();
if let Some((_, paths)) = modules.iter_mut().find(|(name, _)| *name == module_name) {
paths.push(module_path);
} else {
modules.push((module_name, vec![module_path]));
}
}
}
let mut result_trees: Vec<ModuleTree> = Vec::new();
for (module_name, paths) in modules {
let mut current_tree = ModuleTree {
root: ModuleNode::new(module_name),
};
for path in paths {
let mut current_node = &mut current_tree.root;
for part in path {
current_node = current_node.get_or_insert_child(part);
}
}
result_trees.push(current_tree);
}
result_trees
.into_iter()
.map(|tree| format_node(&tree.root, 0, order == Order::Sorted))
.collect()
}
fn format_node(node: &ModuleNode, depth: usize, is_sorted: bool) -> String {
if node.children.is_empty() {
return node.value.clone();
}
let mut children = node.children.clone();
if is_sorted {
children.sort_by(|left, right| left.value.cmp(&right.value));
}
let mut result = format!("{}::{{\n", node.value);
for child in &node.children {
result.push_str(&" ".repeat(depth + 1));
result.push_str(&format!("{},\n", format_node(child, depth + 1, is_sorted)));
}
result.push_str(&" ".repeat(depth));
result.push_str("}\n");
result
}
#[cfg(test)]
mod test {
use super::*;
/// Validate that the `format_flat` function works as expected, if the original order is kept.
#[test]
fn test_format_flat_original() {
let imports = &[
Import(&["my_crate", "a"]),
Import(&["my_crate", "b", "B1"]),
Import(&["my_crate", "b", "B2"]),
];
let order = Order::Original;
let expected_result = vec![
String::from("my_crate::a"),
String::from("my_crate::b::B1"),
String::from("my_crate::b::B2"),
];
let actual_result = format_flat(imports, order);
assert_eq!(expected_result, actual_result);
}
/// Validate that the `format_flat` function does not display any duplicates.
#[test]
fn test_format_flat_original_with_duplicates() {
let imports = &[
Import(&["my_crate", "a"]),
Import(&["my_crate", "b", "B1"]),
Import(&["my_crate", "b", "B1"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "b", "B2"]),
];
let order = Order::Original;
let expected_result = vec![
String::from("my_crate::a"),
String::from("my_crate::b::B1"),
String::from("my_crate::b::B2"),
];
let actual_result = format_flat(imports, order);
assert_eq!(expected_result, actual_result);
}
/// Validate that the `format_flat` function works as expected, if the imports are to be sorted.
#[test]
fn test_format_flat_sorted() {
let imports = &[
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "a"]),
Import(&["my_crate", "b", "B1"]),
];
let order = Order::Sorted;
let expected_result = vec![
String::from("my_crate::a"),
String::from("my_crate::b::B1"),
String::from("my_crate::b::B2"),
];
let actual_result = format_flat(imports, order);
assert_eq!(expected_result, actual_result);
}
/// Validate that the `format_flat` function does not display any duplicates.
#[test]
fn test_format_flat_sorted_with_duplicates() {
let imports = &[
Import(&["my_crate", "b", "B1"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "a"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "b", "B1"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "b", "B2"]),
Import(&["my_crate", "a"]),
Import(&["my_crate", "a"]),
];
let order = Order::Sorted;
let expected_result = vec![
String::from("my_crate::a"),
String::from("my_crate::b::B1"),
String::from("my_crate::b::B2"),
];
let actual_result = format_flat(imports, order);
assert_eq!(expected_result, actual_result);
}
/// Validate that the `format_nested` function works as expected, if the original order is kept.
// #[test]
// fn test_format_nested_original() {
// let imports = &[
// Import(&["std", "a"]),
// Import(&["std", "b"]),
// Import(&["foo", "b"]),
// ];
// let order = Order::Original;
//
// let expected_result = vec![
// String::from("std::{\n a,\n b\n}\n"),
// String::from("foo::{\n b,\n}\n"),
// ];
// let actual_result = format_nested(imports, order);
//
// assert_eq!(expected_result, actual_result);
// }
/// Validate that the `format_nested` function works as expected, if the original order is kept.
#[test]
fn test_format_nested_original_complex() {
let imports = &[
Import(&["foo", "b"]),
Import(&["std", "a"]),
Import(&["std", "b"]),
Import(&["std", "c", "ca"]),
Import(&["std", "c", "cb"]),
];
let order = Order::Original;
let expected_result = vec![
String::from("foo::{\n b,\n}\n"),
String::from("std::{\n a,\n b,\n c::{\n ca,\n cb,\n },\n}\n"),
];
let actual_result = format_nested(imports, order);
assert_eq!(expected_result, actual_result);
}
// #[test]
// fn test_format_nested_sorted() {
// let imports = &[
// Import(&["std", "c", "cb"]),
// Import(&["std", "b"]),
// Import(&["std", "a"]),
// Import(&["foo", "b"]),
// Import(&["std", "c", "ca"]),
// ];
// let order = Order::Sorted;
//
// let expected_result = vec![
// String::from("std::{\n a,\n b,\n c::{\n ca,\n cb,\n },\n}\n"),
// String::from("foo::{\n b,\n}\n"),
// ];
// let actual_result = format_nested(imports, order);
//
// assert_eq!(expected_result, actual_result);
// }
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20241203-1739405-18cnknd/solution)
warning: unused import: `HashMap`
 --> src/lib.rs:1:24
  |
1 | use std::collections::{HashMap, HashSet};
  |                        ^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: `solution` (lib) generated 1 warning
    Finished test [unoptimized + debuginfo] target(s) in 1.45s
     Running tests/solution_test.rs (target/debug/deps/solution_test-1428e1090729d165)

running 20 tests
test solution_test::test_flat_empty ... ok
test solution_test::test_flat_multi_crate ... ok
test solution_test::test_flat_original_duplicates ... ok
test solution_test::test_flat_original ... ok
test solution_test::test_flat_sorted_duplicates ... ok
test solution_test::test_flat_sorted ... ok
test solution_test::test_nested_basic ... ok
test solution_test::test_nested_deep ... FAILED
test solution_test::test_nested_empty ... ok
test solution_test::test_nested_only_crate ... FAILED
test solution_test::test_nested_original ... FAILED
test solution_test::test_nested_original_2 ... FAILED
test solution_test::test_nested_original_duplicates ... FAILED
test solution_test::test_nested_original_multi_crate ... FAILED
test solution_test::test_nested_original_self ... FAILED
test solution_test::test_nested_sorted ... FAILED
test solution_test::test_nested_sorted_duplicates ... FAILED
test solution_test::test_nested_sorted_2 ... FAILED
test solution_test::test_nested_sorted_multi_crate ... FAILED
test solution_test::test_nested_sorted_self ... FAILED

failures:

---- solution_test::test_nested_deep stdout ----
thread 'solution_test::test_nested_deep' panicked at 'assertion failed: `(left == right)`
  left: `["std::{\n    a::{\n        b::{\n            c::{\n                d,\n            }\n,\n        }\n,\n    }\n,\n}\n"]`,
 right: `["std::{\n    a::{\n        b::{\n            c::{\n                d,\n            },\n        },\n    },\n}\n"]`', tests/solution_test.rs:160:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- solution_test::test_nested_only_crate stdout ----
thread 'solution_test::test_nested_only_crate' panicked at 'assertion failed: `(left == right)`
  left: `["my_crate"]`,
 right: `["my_crate\n"]`', tests/solution_test.rs:132:5

---- solution_test::test_nested_original stdout ----
thread 'solution_test::test_nested_original' panicked at 'assertion failed: `(left == right)`
  left: `["my_crate::{\n    c,\n    b::{\n        B2,\n        B1,\n    }\n,\n    a,\n}\n"]`,
 right: `["my_crate::{\n    c,\n    b::{\n        B2,\n        B1,\n    },\n    a,\n}\n"]`', tests/solution_test.rs:173:5

---- solution_test::test_nested_original_2 stdout ----
thread 'solution_test::test_nested_original_2' panicked at 'assertion failed: `(left == right)`
  left: `["my_crate::{\n    c,\n    b::{\n        B2,\n        B1,\n    }\n,\n    a::{\n        inner::{\n            I1,\n        }\n,\n        A1,\n    }\n,\n}\n"]`,
 right: `["my_crate::{\n    c,\n    b::{\n        B2,\n        B1,\n    },\n    a::{\n        inner::{\n            I1,\n        },\n        A1,\n    },\n}\n"]`', tests/solution_test.rs:198:5

---- solution_test::test_nested_original_duplicates stdout ----
thread 'solution_test::test_nested_original_duplicates' panicked at 'assertion failed: `(left == right)`
  left: `["my_crate::{\n    c,\n    b::{\n        B2,\n        B1,\n    }\n,\n    a,\n}\n"]`,
 right: `["my_crate::{\n    c,\n    b::{\n        B2,\n        B1,\n    },\n    a,\n}\n"]`', tests/solution_test.rs:283:5

---- solution_test::test_nested_original_multi_crate stdout ----
thread 'solution_test::test_nested_original_multi_crate' panicked at 'assertion failed: `(left == right)`
  left: `["crate::{\n    b,\n    a,\n}\n", "std::{\n    string::{\n        String,\n    }\n,\n}\n"]`,
 right: `["crate::{\n    b,\n    a,\n}\n", "std::{\n    string::{\n        String,\n    },\n}\n"]`', tests/solution_test.rs:385:5

---- solution_test::test_nested_original_self stdout ----
thread 'solution_test::test_nested_original_self' panicked at 'assertion failed: `(left == right)`
  left: `["my_crate::{\n    c,\n    b::{\n        B2,\n        B1,\n    }\n,\n    a,\n}\n"]`,
 right: `["my_crate::{\n    c,\n    b::{\n        self,\n        B2,\n        B1,\n    },\n    a,\n}\n"]`', tests/solution_test.rs:334:5

---- solution_test::test_nested_sorted stdout ----
thread 'solution_test::test_nested_sorted' panicked at 'assertion failed: `(left == right)`
  left: `["my_crate::{\n    a,\n    b::{\n        B1,\n        B2,\n    }\n,\n    c,\n}\n"]`,
 right: `["my_crate::{\n    a,\n    b::{\n        B1,\n        B2,\n    },\n    c,\n}\n"]`', tests/solution_test.rs:227:5

---- solution_test::test_nested_sorted_duplicates stdout ----
thread 'solution_test::test_nested_sorted_duplicates' panicked at 'assertion failed: `(left == right)`
  left: `["my_crate::{\n    a,\n    b::{\n        B1,\n        B2,\n    }\n,\n    c,\n}\n"]`,
 right: `["my_crate::{\n    a,\n    b::{\n        B1,\n        B2,\n    },\n    c,\n}\n"]`', tests/solution_test.rs:309:5

---- solution_test::test_nested_sorted_2 stdout ----
thread 'solution_test::test_nested_sorted_2' panicked at 'assertion failed: `(left == right)`
  left: `["my_crate::{\n    a::{\n        A1,\n        inner::{\n            I1,\n        }\n,\n    }\n,\n    b::{\n        B1,\n        B2,\n    }\n,\n    c,\n}\n"]`,
 right: `["my_crate::{\n    a::{\n        A1,\n        inner::{\n            I1,\n        },\n    },\n    b::{\n        B1,\n        B2,\n    },\n    c,\n}\n"]`', tests/solution_test.rs:252:5

---- solution_test::test_nested_sorted_multi_crate stdout ----
thread 'solution_test::test_nested_sorted_multi_crate' panicked at 'assertion failed: `(left == right)`
  left: `["crate::{\n    a,\n    b,\n}\n", "std::{\n    string::{\n        String,\n    }\n,\n}\n"]`,
 right: `["crate::{\n    a,\n    b,\n}\n", "std::{\n    string::{\n        String,\n    },\n}\n"]`', tests/solution_test.rs:414:5

---- solution_test::test_nested_sorted_self stdout ----
thread 'solution_test::test_nested_sorted_self' panicked at 'assertion failed: `(left == right)`
  left: `["my_crate::{\n    a,\n    b::{\n        B1,\n        B2,\n    }\n,\n    c,\n}\n"]`,
 right: `["my_crate::{\n    a,\n    b::{\n        self,\n        B1,\n        B2,\n    },\n    c,\n}\n"]`', tests/solution_test.rs:360:5


failures:
    solution_test::test_nested_deep
    solution_test::test_nested_only_crate
    solution_test::test_nested_original
    solution_test::test_nested_original_2
    solution_test::test_nested_original_duplicates
    solution_test::test_nested_original_multi_crate
    solution_test::test_nested_original_self
    solution_test::test_nested_sorted
    solution_test::test_nested_sorted_2
    solution_test::test_nested_sorted_duplicates
    solution_test::test_nested_sorted_multi_crate
    solution_test::test_nested_sorted_self

test result: FAILED. 8 passed; 12 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

error: test failed, to rerun pass `--test solution_test`

История (1 версия и 1 коментар)

Ангел качи първо решение на 03.12.2024 17:59 (преди 9 месеца)

Не успях да оправя новите редове навреме преди крайния срок и за това голяма част от тестовете ми fail-ват. Ако имате възможност, разбира се, ще можете ли да го погледнете? 🥹

(new line character, my beloved 😞)