diff options
Diffstat (limited to 'd13/src')
| -rw-r--r-- | d13/src/main.rs | 79 | 
1 files changed, 79 insertions, 0 deletions
diff --git a/d13/src/main.rs b/d13/src/main.rs new file mode 100644 index 0000000..52ef4ce --- /dev/null +++ b/d13/src/main.rs @@ -0,0 +1,79 @@ +use std::collections::VecDeque; + +fn is_space(seed: usize, (x, y): (usize, usize)) -> bool { +    let sum = x*x + 3*x + 2*x*y + y + y*y + seed; +    let bin = format!("{:#b}", sum); +    bin.matches('1').count() % 2 == 0 +} + +fn solve_puzzle(seed: usize, part1_goal: (usize, usize), part2_limit: usize) -> (usize, usize) { +    let mut part1_found = false; +    let mut part1_depth = 0; +    let mut part2_count = 1; + +    // Breadth-first search of the maze +    let start = (1, 1); +    let mut visited = vec![start]; +    let mut queue = VecDeque::from([(start, 0)]); +    loop { +        let (pos, depth) = queue.pop_front().unwrap(); + +        // Is this the shortest path to `part1_goal'? +        if pos == part1_goal && !part1_found { +            part1_found = true; +            part1_depth = depth; +        } +        // Have we found all the information we want? +        if depth > part2_limit && part1_found { +            return (part1_depth, part2_count); +        } + +        // The grid extends infinitely far in the positive directions +        let mut adjacents = vec![ +            (pos.0 + 1, pos.1), +            (pos.0, pos.1 + 1), +        ]; +        if pos.0 > 0 { +            adjacents.push((pos.0 - 1, pos.1)); +        } +        if pos.1 > 0 { +            adjacents.push((pos.0, pos.1 - 1)); +        } + +        for adj in adjacents { +            // Is this a valid move to a space we haven't visited before? +            if is_space(seed, adj) && !visited.contains(&adj) { +                visited.push(adj); +                queue.push_back((adj, depth + 1)); + +                // Count locations reachable in at most `part2_limit' steps +                if depth < part2_limit { +                    part2_count += 1; +                } +            } +        } +    } +} + +fn main() { +    // My personal puzzle input +    let seed = 1358; + +    let (part1, part2) = solve_puzzle(seed, (31, 39), 50); + +    // Part 1 gives 96 for me +    println!("Part 1 solution: {}", part1); + +    // Part 2 gives 141 for me +    println!("Part 2 solution: {}", part2); +} + +#[cfg(test)] +mod tests { +    use super::*; + +    #[test] +    fn part1_example1() { +        assert_eq!(solve_puzzle(10, (7, 4), 42).0, 11); +    } +}  | 
