View Kaizen LeaderBoard.
This project uses cargo-aoc
to simplify the interactions with the server.
cargo install cargo-aoc
cargo aoc
Split entries by empty lines, sum number groups using Iterator::fold()
Rust ownership is hard.
Complicated play with HashSet
intersections, &char
. Don't use union
but extend
instead to save your sanity.
Nice discovery of RangeInclusive
for i in 'a' ..= 'z' { }
Manually parse ranges and compute inclusion and overlap.
Move crates around, and return the topmost ones.
[D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2
Crate parse_display
facilitates parsing strings into structs:
// Input is "move 1 from 2 to 1"
#[derive(Display, FromStr, Debug, Copy, Clone)]
#[display("move {num} from {from} to {to}")]
pub struct Move {
num: usize,
from: usize,
to: usize,
}
This allows the following:
let mov: Move = "move 1 from 2 to 3".parse().unwrap();
Easily implemented with Vec::push()
and Vec::pop()
, to simulate a stack.
Implemented with Vec::split_off()
and Vec::extend()
Use a HashMap<char, usize>
to store char positions
while iterating (once) over the string. Maintain the count of current consecutive distinct chars and return index if count == required.
Trees and interesting data structures in Rust are Hard (tm)
Instead, we hard-code the tree traversal while parsing the input.
Simple loop to simulate movements knot by knot. Use integer euclidian distance and not manhattan distance!
Modular arithmetic used to keep worry levels managable. Part1 divides by 3, part2 divides by product of test values.
Classic Dijkstra. Use crates TooDee
and pathfinding
Part2 brute force requires searching through 4million * 4million positions, which is not really feasible.
Instead, since only one position is possible, iterate on the sensor perimeter (coverage+1) to cut down computations to ~200ms.