diff --git a/day23/Cargo.lock b/day23/Cargo.lock new file mode 100644 index 0000000..f019bb8 --- /dev/null +++ b/day23/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day23" +version = "0.1.0" diff --git a/day23/Cargo.toml b/day23/Cargo.toml new file mode 100644 index 0000000..3e1aa7d --- /dev/null +++ b/day23/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "day23" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/day23/input.txt b/day23/input.txt new file mode 100644 index 0000000..6ee8eb0 --- /dev/null +++ b/day23/input.txt @@ -0,0 +1,141 @@ +#.########################################################################################################################################### +#.#.................#...#...#...###.....#####...#.....###...#...###...#.......#.....#...#...###...###...#...###...###...#...#.....#...#.....# +#.#.###############.#.#.#.#.#.#.###.###.#####.#.#.###.###.#.#.#.###.#.#.#####.#.###.#.#.#.#.###.#.###.#.#.#.###.#.###.#.#.#.#.###.#.#.#.###.# +#.#...#.............#.#...#.#.#...#.#...#.....#.#...#...#.#...#.#...#.#.....#...#...#.#.#.#.#...#.###.#.#.#.#...#.....#.#.#.#...#...#.#...#.# +#.###.#.#############.#####.#.###.#.#.###.#####.###.###.#.#####.#.###.#####.#####.###.#.#.#.#.###.###.#.#.#.#.#########.#.#.###.#####.###.#.# +#.#...#.....#...#...#...#...#.#...#.#...#.....#.#...#...#...#...#...#.#...#...#...###.#.#.#.#...#.#...#.#.#.#.#.........#.#.#...#.....#...#.# +#.#.#######.#.#.#.#.###.#.###.#.###.###.#####.#.#.###.#####.#.#####.#.#.#.###.#.#####.#.#.#.###.#.#.###.#.#.#.#.#########.#.#.###.#####.###.# +#.#.#.......#.#.#.#.#...#...#.#...#.#...#.....#.#...#.#...#.#...>.>.#...#.#...#.>.>.#.#.#.#.###.#.#.#...#.#.#.#.###.....#.#.#.#...#...#.#...# +#.#.#.#######.#.#.#.#.#####.#.###.#.#.###.#####.###.#.#.#.#.#####v#######.#.#####v#.#.#.#.#.###.#.#.#.###.#.#.#.###.###.#.#.#.#.###.#.#.#.### +#.#.#...#...#.#.#.#.#...#...#.#...#.#.###.....#...#.#.#.#.#.....#.......#.#...###.#.#.#.#.#...#.#...#...#.#.#.#.>.>.#...#.#.#.#.#...#.#.#...# +#.#.###v#.#.#.#.#.#.###.#.###.#.###.#.#######.###.#.#.#.#.#####.#######.#.###.###.#.#.#.#.###.#.#######.#.#.#.###v###.###.#.#.#.#.###.#.###.# +#...###.>.#.#.#.#.#.#...#...#.#.#...#...###...#...#.#.#.#.......#...#...#.....#...#...#.#...#.#.#.......#.#...#...#...#...#.#.#...#...#.#...# +#######v###.#.#.#.#.#.#####.#.#.#.#####.###.###.###.#.#.#########.#.#.#########.#######.###.#.#.#.#######.#####.###.###.###.#.#####.###.#.### +#.....#...#.#.#.#.#.#.....#.#.#.#...#...#...###...#.#...#...#.....#...###...#...###.....#...#...#.....#...#.....###...#...#.#.#.....#...#...# +#.###.###.#.#.#.#.#.#####.#.#.#.###.#.###.#######.#.#####.#.#.###########.#.#.#####.#####.###########.#.###.#########.###.#.#.#.#####.#####.# +#...#.....#...#.#.#...#...#.#.#.#...#.>.>.#...#...#.#...#.#.#.........###.#.#.....#.....#.........###.#.###.......#...#...#.#.#.....#.#.....# +###.###########.#.###.#.###.#.#.#.#####v###.#.#.###.#.#.#.#.#########.###.#.#####.#####.#########.###.#.#########.#.###.###.#.#####.#.#.##### +###.....#...###...###.#.#...#.#...#...#.....#.#.....#.#...#.....#...#.....#.#.....###...#...#.....#...#...###...#.#...#.#...#.#.....#.#.....# +#######.#.#.#########.#.#.###.#####.#.#######.#######.#########.#.#.#######.#.#######.###.#.#.#####.#####.###.#.#.###.#.#.###.#.#####.#####.# +#.......#.#.........#.#.#...#...#...#...#.....###.....#.......#...#...#.....#.......#.#...#.#.....#.#.....#...#.#...#.#.#...#.#.#...#.#.....# +#.#######.#########.#.#.###.###.#.#####.#.#######.#####.#####.#######.#.###########.#.#.###.#####.#.#.#####.###.###.#.#.###.#.#.#.#.#.#.##### +#.#.....#.#.........#.#.###.#...#.....#...###.....#.....#####.......#.#.#...........#...###.#.....#...###...###...#.#.#...#...#...#...#.....# +#.#.###.#.#.#########.#.###.#.#######.#######.#####.###############.#.#.#.#################.#.###########.#######.#.#.###.#################.# +#.#.#...#.#.........#.#.#...#.#.....#.......#.......#...............#...#.................#.#.#.....#.....#...###...#.....###...............# +#.#.#.###.#########.#.#.#.###.#.###.#######.#########.###################################.#.#.#.###.#.#####.#.###############.############### +#...#...#.#.......#.#...#.....#...#.........#.....#...#.................#.......#...#.....#...#...#.#...###.#...#...#...###...#.........#...# +#######.#.#.#####.#.#############.###########.###.#.###.###############.#.#####.#.#.#.###########.#.###.###.###.#.#.#.#.###.###.#######.#.#.# +#...###...#.....#...###...###...#.........#...#...#.....#####...#...#...#.#...#...#.#...#.........#...#.....#...#.#...#...#.....###...#...#.# +#.#.###########v#######.#.###.#.#########.#.###.#############.#.#.#.#.###.#.#.#####.###.#.###########.#######.###.#######.#########.#.#####.# +#.#...........#.>.###...#.#...#...........#...#...#...#...#...#...#...###...#.....#.....#.......#...#.......#.###.#.......#...#.....#.....#.# +#.###########.#v#.###.###.#.#################.###.#.#.#.#.#.#####################.#############.#.#.#######.#.###.#.#######.#.#.#########.#.# +#...........#...#.#...#...#...........###...#.#...#.#.#.#.#...#...#...###...#...#.#...#.....###...#.#...###...#...#...#...#.#.#.........#...# +###########.#####.#.###.#############.###.#.#.#.###.#.#.#.###.#.#.#.#.###.#.#.#.#.#.#.#.###.#######.#.#.#######.#####.#.#.#.#.#########.##### +#.........#.....#.#...#.#...###.......#...#...#.#...#.#.#.#...#.#.#.#...#.#...#...#.#.#...#.....###...#...#...#...#...#.#.#.#.#...#.....#...# +#.#######.#####.#.###.#.#.#.###.#######.#######.#.###.#.#.#.###.#.#.###.#.#########.#.###.#####.#########.#.#.###.#.###.#.#.#.#.#.#v#####.#.# +#.......#.#.....#.#...#.#.#...#...#...#.......#.#.#...#.#.#...#.#.#...#.#.....###...#...#.....#.#...#.....#.#...#.#...#.#.#.#...#.>.#...#.#.# +#######.#.#.#####.#.###.#.###.###v#.#.#######.#.#.#.###.#.###v#.#.###.#.#####v###.#####.#####.#.#.#.#.#####.###.#.###.#.#.#.#######v#.#.#.#.# +#.......#.#.....#.#.###...#...#.>.>.#...#...#.#.#.#.#...#...>.>.#...#.#...#.>.>.#...#...#...#.#.#.#.#...###...#...###.#.#.#.......#.#.#...#.# +#.#######.#####.#.#.#######.###.#v#####.#.#.#.#.#.#.#.#######v#####.#.###.#.#v#.###.#.###.#.#.#.#.#.###v#####.#######.#.#.#######.#.#.#####.# +#.......#.#.....#.#.......#.....#...#...#.#.#.#.#.#...#####...#####.#.###...#.#.#...#...#.#.#.#...#...>.>...#.......#...#.#...#...#.#.#.....# +#######.#.#.#####.#######.#########.#.###.#.#.#.#.#########.#######.#.#######.#.#.#####.#.#.#.#########v###.#######.#####.#.#.#.###.#.#.##### +#.......#...#...#.....#...###...#...#.#...#.#.#.#.....#.....#.....#.#.#.......#.#.....#...#.#.###...#...#...#.......#.....#.#.#.#...#.#.....# +#.###########.#.#####.#.#####.#.#.###.#.###.#.#.#####.#.#####.###.#.#.#.#######.#####.#####.#.###.#.#.###.###.#######.#####.#.#.#.###.#####.# +#.............#.....#...###...#...###...###...#.#.....#.......#...#...#.......#.#.....#.....#.#...#...###...#.......#.....#.#...#.....#.....# +###################.#######.###################.#.#############.#############.#.#.#####.#####.#.###########.#######.#####.#.###########.##### +#.........#.....#...###...#.....#.....#...#...#.#.#.......#...#.....#...#...#.#...#...#...#...#.....###...#.#.....#.....#...###...#...#.....# +#.#######.#.###.#.#####.#.#####.#.###.#.#.#.#.#.#.#.#####.#.#.#####.#.#.#.#.#.#####.#.###.#.#######.###.#.#.#.###.#####.#######.#.#.#.#####.# +#...#...#...###...#...#.#.#.....#.#...#.#...#.#...#.....#...#.......#.#.#.#.#.#...#.#.###.#.#...###.....#.#...###...#...#.......#...#.......# +###.#.#.###########.#.#.#.#.#####.#.###.#####.#########.#############.#.#.#.#.#.#.#.#.###.#.#.#.#########.#########.#.###.################### +#...#.#.#...#...###.#.#.#.#.......#...#.#.....#.....###.......#.....#.#...#.#...#...#...#.#.#.#.........#.........#.#.###...#...#...........# +#.###.#.#.#.#.#.###.#.#.#.###########.#.#.#####.###.#########.#.###.#.#####.###########.#.#.#.#########.#########.#.#.#####.#.#.#.#########.# +#.....#...#...#...#.#...#.#...#.......#.#...#...#...#...#.....#...#.#.....#.............#...#.#.....###...........#.#.#...#...#...#.........# +#################.#.#####.#.#.#.#######.###.#.###.###.#.#.#######.#.#####.###################.#.###.###############.#.#.#.#########.######### +#.......#.........#.#.....#.#.#.#...#...#...#...#...#.#.#...#...#.#.#...#.......#.....###...#...###.........#.....#...#.#.###.....#.#.....### +#.#####.#.#########.#.#####.#.#v#.#.#.###.#####.###.#.#.###.#.#.#.#.#.#.#######.#.###.###.#.###############.#.###.#####.#.###.###.#.#.###.### +#.....#.#.......#...#.#...#.#.>.>.#...#...#...#.#...#.#.###.#.#.#.#...#.#.......#.#...#...#.###.............#...#...#...#.#...#...#...###...# +#####.#.#######.#.###.#.#.#.###v#######.###.#.#.#.###.#.###v#.#.#.#####.#.#######.#.###.###.###.###############.###.#.###.#.###.###########.# +#...#.#.........#...#.#.#.#.###.......#...#.#.#.#...#.#.#.>.>.#.#.....#.#.......#.#...#...#...#.............#...#...#...#.#...#.#...#.......# +#.#.#.#############.#.#.#.#.#########.###.#.#.#.###.#.#.#.#v###.#####.#.#######.#.###.###.###.#############.#.###.#####.#.###.#.#.#.#.####### +#.#...#.....#...#...#...#...#.........###.#.#.#.###...#.#.#.###.#...#.#.#.......#.#...###.#...#...#.........#...#.#...#.#.###.#.#.#.#.....### +#.#####.###.#.#.#.###########.###########.#.#.#.#######.#.#.###.#.#.#.#.#.#######.#.#####.#.###.#.#v###########.#.#.#.#.#.###.#.#.#.#####.### +#.......###.#.#.#...........#...#.......#.#.#.#.......#.#.#...#.#.#.#.#.#.....###.#...#...#.#...#.>.>.#...#...#.#.#.#.#.#...#.#.#.#.#...#...# +###########v#.#.###########.###.#.#####.#.#.#.#######.#.#.###.#.#.#.#.#.#####v###.###.#.###.#.#####v#.#.#.#.#.#.#.#.#.#.###.#.#.#.#.#.#.###.# +#.........#.>.#.#...#.....#.#...#.#.....#...#...#...#.#.#.#...#...#...#...#.>.>...#...#...#...#.....#.#.#.#.#.#.#.#.#.#...#.#.#.#.#.#.#.#...# +#.#######.#v###.#.#.#.###.#.#.###.#.###########.#.#.#.#.#.#.#############.#.#v#####.#####.#####.#####.#.#.#.#.#.#.#.#.###.#.#.#.#.#.#.#.#v### +#.....#...#.#...#.#...###.#.#...#.#.......#####.#.#.#.#...#.....###...###.#.#...#...#...#.....#.#...#...#.#.#...#.#.#...#.#.#.#.#.#.#.#.>.### +#####.#.###.#.###.#######.#.###.#.#######.#####.#.#.#.#########.###.#.###.#.###.#.###.#.#####.#.#.#.#####.#.#####.#.###.#.#.#.#.#.#.#.###v### +#.....#.....#...#.......#...###...#.....#.....#...#.#.#.........#...#...#.#.#...#.....#.#.....#...#.#.....#.....#.#...#...#.#.#...#.#.#...### +#.#############.#######.###########.###.#####.#####.#.#.#########.#####.#.#.#.#########.#.#########.#.#########.#.###.#####.#.#####.#.#.##### +#.............#.#.....#.....###...#...#.......#...#...#...........#.....#...#...#.....#...#.........#...#...#...#.#...#.....#.....#...#.....# +#############.#.#.###.#####.###.#.###.#########.#.#################.###########.#.###.#####.###########.#.#.#.###.#.###.#########.#########.# +#.............#...###.....#.#...#.###.#.........#.....#.......#...#.....###.....#.#...#...#...........#...#.#.###.#...#.#...#.....###...#...# +#.#######################.#.#.###.###.#.#############.#.#####.#.#.#####.###.#####.#.###.#.###########.#####.#.###.###.#.#.#.#.#######.#.#.### +#.#...#...###.........###...#...#.....#.#.............#.....#...#.......#...#...#.#...#.#.....#.......#...#.#...#.#...#...#...###...#.#...### +#.#.#.#.#.###.#######.#########.#######.#.#################.#############.###.#.#.###.#.#####.#.#######.#.#.###.#.#.#############.#.#.####### +#...#...#.....#.....#...#.....#...#.....#.#.....#...#.....#.#...#...#...#...#.#.#.#...#.#.....#.#...###.#.#.#...#...#...#...#...#.#.#...##### +###############.###.###.#.###.###.#.#####.#.###.#.#.#.###.#.#.#.#.#.#.#.###.#.#.#.#.###.#.#####.#.#.###.#.#.#.#######.#.#.#.#.#.#.#.###.##### +###.........#...###.....#...#.....#.#.....#.#...#.#...#...#...#...#...#.#...#.#...#...#.#.....#...#...#.#.#...#...#...#.#.#.#.#.#.#.###.....# +###.#######.#.#############.#######.#.#####.#.###.#####.###############.#.###.#######.#.#####.#######.#.#.#####.#.#.###.#.#.#.#.#.#.#######.# +#...#.....#...###...###...#.........#.....#.#...#...#...#...#...###.....#.....#...###...#.....#...#...#.#.#...#.#.#...#.#.#.#.#.#.#.#...#...# +#.###.###.#######.#.###.#.###############.#.###.###.#.###.#.#.#.###v###########.#.#######.#####.#.#v###.#.#.#.#.#.###.#.#.#.#.#.#.#.#v#.#.### +#.....###.......#.#...#.#.#...#.....#.....#...#...#.#...#.#...#...>.>.#####...#.#.###...#.#...#.#.>.>...#...#.#.#.#...#.#.#.#.#.#.#.>.#...### +###############.#.###.#.#.#.#.#.###.#.#######.###.#.###.#.#########v#.#####.#.#.#.###.#.#v#.#.#.###v#########.#.#.#.###.#.#.#.#.#.###v####### +#.......#.......#.#...#.#...#...#...#.....###...#.#.#...#...#.......#...#...#.#.#.#...#.>.>.#.#.###...#.....#.#.#.#...#.#.#.#.#.#.###.......# +#.#####.#v#######.#.###.#########.#######.#####.#.#.#.#####.#.#########.#.###.#.#.#.#####v###.#.#####.#.###.#.#.#.###.#.#.#.#.#.#.#########.# +#.....#.#.>.#...#.#...#.........#...#...#.#.....#...#.......#.......###...###.#.#...#.....###...#...#.#.#...#...#.#...#...#.#.#...###...#...# +#####.#.#v#.#.#.#.###.#########.###.#.#.#.#.#######################.#########.#.#####.###########.#.#.#.#.#######.#.#######.#.#######.#.#.### +###...#...#.#.#.#...#.#...#...#.#...#.#.#.#.........###...#.......#.#...#...#...###...#...###.....#.#...#...#...#.#.......#...#...#...#...### +###.#######.#.#.###.#.#.#.#.#.#.#.###.#.#v#########.###.#.#.#####.#.#.#.#.#.#######.###.#.###.#####.#######.#.#.#.#######.#####.#.#.######### +#...#.....#...#...#.#.#.#.#.#.#.#...#.#.>.>.#...#...#...#.#.....#.#...#...#...#...#.....#.....#.....#...###...#.#.#.......#.....#...###.....# +#.###.###.#######.#.#.#.#.#.#.#.###.#.###v#.#.#.#.###.###.#####.#.###########.#.#.#############.#####.#.#######.#.#.#######.###########.###.# +#...#...#...#...#...#.#.#.#.#.#.#...#.#...#...#...###...#.#...#.#.#...#...#...#.#...#...#.......###...#.........#...#...###...#...#...#.#...# +###.###.###.#.#.#####.#.#.#.#.#.#.###.#.###############.#.#.#.#.#.#.#.#.#.#.###.###.#.#.#.#########.#################.#.#####.#.#.#.#.#.#.### +#...#...###...#.....#.#.#.#.#...#.#...#.......#.........#...#.#.#...#...#.#...#...#...#...#...#.....#.................#...#...#.#.#.#.#.#.### +#.###.#############.#.#.#.#.#####.#.#########.#.#############.#.#########.###.###.#########.#.#.#####.###################.#.###.#.#.#.#.#.### +#.#...#...........#.#...#...###...#...#.......#...#.....#.....#.....#.....#...#...#...#.....#.#.......#...###.............#...#.#...#...#...# +#.#.###.#########.#.###########.#####.#.#########.#.###.#.#########.#.#####.###.###.#.#.#####.#########.#.###.###############.#.###########.# +#.#.###.........#.#.#.....#...#.......#.......###...#...#.....#...#.#.#...#...#.....#...#.....#.........#.#...#.....#...#...#...#...#...#...# +#.#.###########.#.#.#.###.#.#.###############.#######.#######.#.#.#.#.#.#.###.###########.#####.#########.#.###.###.#.#.#.#.#####.#.#.#.#.### +#...#...........#...#.#...#.#.#...#...........#.....#.......#.#.#...#...#.#...###...#.....#...#.........#.#.....#...#.#.#.#.#.....#.#.#.#.### +#####.###############.#.###.#.#.#.#.###########.###.#######.#.#.#########.#.#####.#.#.#####.#.#########.#.#######.###.#.#.#.#.#####.#.#.#.### +#.....#.........#...#.#...#.#.#.#.#...........#...#.###.....#.#...#...###...#...#.#.#.......#.....#.....#...#.....###.#.#.#.#.....#...#...### +#.#####.#######.#.#.#.###.#.#.#.#.###########.###.#.###.#####.###.#.#.#######.#.#.#.#############.#.#######.#.#######.#.#.#.#####v########### +#.#.....#.......#.#.#.#...#.#.#.#.###.........#...#.....#...#.....#.#.#.....#.#.#.#...#.....#.....#.......#.#...###...#.#.#...#.>.###...#...# +#.#.#####.#######.#.#.#.###.#.#.#.###v#########.#########.#.#######.#.#.###.#.#.#.###.#.###.#.###########.#.###.###.###.#.###.#.#v###.#.#.#.# +#...#...#.#...###.#.#.#.#...#.#.#...>.>.......#.........#.#.###...#.#.#.#...#.#.#.#...#...#...#...###...#.#.#...#...###...#...#.#.#...#...#.# +#####.#.#.#.#v###.#.#.#.#.###.#.#####v#######.#########.#.#.###.#.#.#.#.#.###.#.#.#.#####v#####.#.###.#.#.#.#v###.#########.###.#.#.#######.# +###...#...#.#.>.#.#.#.#.#.###.#.#.....#.......#...#...#.#.#.....#...#.#.#.#...#.#.#.#...>.>.#...#.#...#.#.#.>.>.#...#.......#...#...#.......# +###.#######.#v#.#.#.#.#.#.###.#.#.#####.#######.#.#.#.#v#.###########.#.#.#.###.#.#.#.###v#.#.###.#.###.#.###v#.###.#.#######.#######.####### +#...#...#...#.#.#.#.#.#.#...#...#.....#...#...#.#.#.#.>.>.#...###.....#.#.#...#.#.#.#.#...#...###.#.#...#.#...#.#...#.....#...#.....#.......# +#.###.#.#.###.#.#.#.#.#.###.#########.###.#.#.#.#.#.###v###.#.###.#####.#.###.#.#.#.#.#.#########.#.#.###.#.###.#.#######.#.###.###.#######.# +#.....#...#...#...#.#.#...#...#.......###.#.#.#.#.#.###.#...#...#.....#.#.#...#...#...#.........#.#.#...#.#...#.#.....###...###...#.........# +###########.#######.#.###.###.#.#########.#.#.#.#.#.###.#.#####.#####.#.#.#.###################.#.#.###.#.###.#.#####.###########.########### +#...#.......#####...#.###.#...#.........#...#.#.#.#...#.#.#.....#...#...#...#...#.......#.......#...###...#...#...#...#...........#...#.....# +#.#.#.###########.###.###.#.###########.#####.#.#.###.#.#.#.#####.#.#########.#.#.#####.#.#################.#####.#.###.###########.#.#.###.# +#.#.#...........#.#...###...#...........#...#.#.#.#...#.#.#.......#.......#...#...#...#...#...#...###.......#...#...#...#.........#.#.#.#...# +#.#.###########.#.#.#########.###########.#.#.#.#.#.###.#.###############.#.#######.#.#####.#.#.#.###.#######.#.#####.###.#######.#.#.#.#.### +#.#.............#...###.......#.........#.#.#...#.#.###...###...#...#...#.#.........#.......#...#...#...#...#.#.....#.....#.......#.#...#...# +#.#####################.#######.#######.#.#.#####.#.#########.#.#.#.#.#.#.#########################.###.#.#.#.#####.#######.#######.#######.# +#...#.............#...#...#.....#.......#.#.###...#...#.......#...#...#.#...###...###...#.......#...###...#...#...#.......#.......#.#.......# +###.#.###########.#.#.###.#.#####.#######.#.###.#####.#.###############.###.###.#.###.#.#.#####.#.#############.#.#######.#######.#.#.####### +###...#...........#.#...#...#...#.........#...#.......#...............#.....#...#...#.#...#...#...#####...#...#.#.........###.....#.#.#...### +#######.###########.###.#####.#.#############.#######################.#######.#####.#.#####.#.#########.#.#.#.#.#############.#####.#.#.#.### +#.......#...#...###...#.#.....#.......#.......#...#...................###...#...#...#.......#...#...#...#.#.#.#.........#.....#.....#...#...# +#.#######.#.#.#.#####.#.#.###########.#.#######.#.#.#####################.#.###.#.#############.#.#.#.###.#.#.#########.#.#####.###########.# +#...#.....#...#...#...#.#...........#...#.....#.#.#.................#.....#.....#.#.............#.#.#.#...#.#...#.....#.#.......#...........# +###.#.###########.#.###.###########.#####.###.#.#.#################.#.###########.#.#############.#.#.#.###v###.#.###.#.#########.########### +#...#.#...........#...#.###.....###...###...#.#.#...#...#...#.......#...........#.#.......#...#...#...#.#.>.>.#...#...#.#.....###...........# +#.###.#.#############.#.###.###.#####.#####.#.#.###.#.#.#.#.#.#################.#.#######.#.#.#.#######.#.###.#####.###.#.###.#############.# +#...#.#...........#...#...#...#.#.....#...#.#.#.#...#.#.#.#.#.###...#.....#.....#...#...#.#.#.#.......#.#.#...#...#.....#...#...#####.......# +###.#.###########.#.#####.###.#.#.#####.#.#.#.#.#.###.#.#.#.#v###.#.#.###.#.#######.#.#.#.#.#.#######.#.#.#.###.#.#########.###.#####.####### +#...#.#...........#...#...###.#.#...#...#.#.#...#.#...#.#.#.>.>.#.#.#.#...#.....#...#.#.#.#.#.#...#...#...#...#.#...###...#...#...#...#...### +#.###.#.#############.#.#####.#.###.#.###.#.#####.#.###.#.#####.#.#.#.#.#######.#.###.#.#v#.#.#.#.#.#########.#.###.###.#.###.###.#.###.#.### +#.#...#.......###...#.#.#...#.#.###.#...#.#.....#.#.#...#.....#.#.#.#.#.....#...#.#...#.>.>.#.#.#.#.......###...###...#.#.#...#...#...#.#...# +#.#.#########.###.#.#.#.#.#.#.#.###v###.#.#####.#.#.#.#######.#.#.#.#.#####.#.###.#.#########.#.#.#######.###########.#.#.#.###.#####.#.###.# +#...#...#.....#...#.#.#.#.#.#.#.#.>.>.#.#.#...#.#.#.#.....#...#...#.#.#.....#.#...#...###.....#.#...#...#.#...........#.#.#.#...#...#...#...# +#####.#.#.#####.###.#.#.#.#.#.#.#.###.#.#.#.#.#.#.#.#####.#.#######.#.#.#####.#.#####.###.#####.###.#.#.#.#.###########.#.#.#.###.#.#####v### +#.....#...#...#.#...#.#.#.#.#.#.#.#...#.#.#.#.#.#.#.#.....#.......#.#.#...#...#.#...#...#.....#...#.#.#.#.#.#...#.....#.#.#.#...#.#...#.>.### +#.#########.#.#.#.###.#.#.#.#.#.#.#.###.#.#.#.#.#.#.#.###########.#.#.###.#.###.#.#.###.#####.###.#.#.#.#.#.#.#.#.###.#.#.#.###.#.###.#.#v### +#...........#...#.....#...#...#...#.....#...#...#...#.............#...###...###...#.....#####.....#...#...#...#...###...#...###...###...#...# +###########################################################################################################################################.# diff --git a/day23/src/main.rs b/day23/src/main.rs new file mode 100644 index 0000000..db6878d --- /dev/null +++ b/day23/src/main.rs @@ -0,0 +1,281 @@ +use std::cmp; +use std::fs::read_to_string; +use std::time::Instant; +use std::collections::{HashMap, HashSet}; + +#[derive(Copy, Clone, PartialEq)] +#[repr(u8)] +enum Direction { + Left = 0, + Right = 1, + Up = 2, + Down = 3, +} + +const ALL_DIRECTIONS: [Direction; 4] = [Direction::Left, Direction::Right, Direction::Up, Direction::Down]; +const OPPOSITE_DIRECTION: [Direction; 4] = [Direction::Right, Direction::Left, Direction::Down, Direction::Up]; +const DIRECTION_OFFSET: [(i32, i32); 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)]; + +// Tries to find the longest path while parsing input on the fly, slow +fn find_longest_walk_naive(layout: &[&[u8]], slopes: bool) -> i32 { + let start_x = layout[0].iter().position(|&c| c == b'.').unwrap() as i32; + find_longest_walk_naive_inner(layout, slopes, (start_x, 0), Direction::Down, HashSet::new()) +} + +// Inner recursive function for find_longest_walk_naive, takes a set of already visited junctions +fn find_longest_walk_naive_inner(layout: &[&[u8]], slopes: bool, mut pos: (i32, i32), mut dir: Direction, + mut visited_junctions: HashSet<(i32, i32)>) -> i32 { + let last_row = layout.len() - 1; + let mut steps = 0; + let mut longest_alternative = 0; + let mut options: Vec<((i32, i32), Direction)> = vec![]; + loop { + if pos.1 == 0 { + pos.1 += 1; + dir = Direction::Down; + steps += 1; + } else if pos.1 == last_row as i32 { + return cmp::max(steps, longest_alternative); + } else { + if visited_junctions.contains(&pos) { + return longest_alternative; + } + let mut add_direction_option = |new_dir: Direction| { + let offset = DIRECTION_OFFSET[new_dir as usize]; + let new_pos = (pos.0 + offset.0, pos.1 + offset.1); + if layout[new_pos.1 as usize][new_pos.0 as usize] == b'#' { + return; + } + options.push((new_pos, new_dir)); + }; + let mut add_all_options = || { + for new_dir in ALL_DIRECTIONS { + if new_dir == OPPOSITE_DIRECTION[dir as usize] { + continue; + } + add_direction_option(new_dir); + } + }; + if slopes { + match layout[pos.1 as usize][pos.0 as usize] { + b'<' => add_direction_option(Direction::Left), + b'>' => add_direction_option(Direction::Right), + b'^' => add_direction_option(Direction::Up), + b'v' => add_direction_option(Direction::Down), + _ => add_all_options() + } + } else { + add_all_options(); + } + + if options.is_empty() { + // Dead end, doesn't happen but i put it for the sake of completeness + return longest_alternative; + } + if options.len() > 1 { + visited_junctions.insert(pos); + } + for (i, &(new_pos, new_dir)) in options.iter().enumerate() { + if i > 0 { + let alternative = find_longest_walk_naive_inner( + layout, slopes, new_pos, new_dir, visited_junctions.clone()); + longest_alternative = cmp::max(longest_alternative, steps + alternative); + } else { + pos = new_pos; + dir = new_dir; + steps += 1; + } + } + options.clear(); + } + } +} + +// Each element is one node, which is an array of (neighbour index, distance) +type HikingGraph = Vec>; + +// Transforms the input map into a graph of junctions, with edges being distances +// First element is the start and last element is the end +fn get_hiking_graph(layout: &[&[u8]], slopes: bool) -> HikingGraph { + let start_x = layout[0].iter().position(|&c| c == b'.').unwrap() as i32; + let last_row = layout.len() - 1; + let mut options: Vec<((i32, i32), Direction)> = vec![]; + let mut junction_node_mapping: HashMap<(i32, i32), u32> = HashMap::new(); + let mut graph: HikingGraph = vec![]; + graph.push(vec![]); + let mut edge_finding_stack: Vec<(u32, (i32, i32), Direction)> = vec![]; + edge_finding_stack.push((0, (start_x, 1), Direction::Down)); + let mut end_node: u32 = 0; + const DIR_SLOPES: [u8; 4] = [b'<', b'>', b'^', b'v']; + loop { + if let Some((id, mut pos, mut dir)) = edge_finding_stack.pop() { + let mut steps = 1; + let mut possible_forward = true; + let mut possible_backward = true; + loop { + if pos.1 == 0 { + pos.1 += 1; + dir = Direction::Down; + steps += 1; + } else if pos.1 == last_row as i32 { + let new_id = graph.len() as u32; + junction_node_mapping.insert(pos, new_id); + if possible_forward { + graph[id as usize].push((new_id, steps)); + } + if possible_backward { + graph.push(vec![(id, steps)]); + } else { + graph.push(vec![]); + } + end_node = new_id; + break; + } else { + match junction_node_mapping.get(&pos) { + None => {} + Some(&other_id) => { + if !graph[id as usize].iter().any(|(that_id, _)| *that_id == other_id) { + if possible_forward { + graph[id as usize].push((other_id, steps)); + } + if possible_backward { + graph[other_id as usize].push((id, steps)); + } + } + break; + } + } + let mut add_direction_option = |new_dir: Direction| { + let offset = DIRECTION_OFFSET[new_dir as usize]; + let new_pos = (pos.0 + offset.0, pos.1 + offset.1); + if layout[new_pos.1 as usize][new_pos.0 as usize] == b'#' { + return; + } + options.push((new_pos, new_dir)); + }; + let mut add_all_options = || { + for new_dir in ALL_DIRECTIONS { + if new_dir == OPPOSITE_DIRECTION[dir as usize] { + continue; + } + add_direction_option(new_dir); + } + }; + add_all_options(); + if options.is_empty() { + // Dead end, doesn't happen but i put it for the sake of completeness + break; + } + if options.len() == 1 { + let &(new_pos, new_dir) = &options[0]; + if slopes { + if layout[pos.1 as usize][pos.0 as usize] + == DIR_SLOPES[dir as usize] { + possible_backward = false; + } else if layout[pos.1 as usize][pos.0 as usize] + == DIR_SLOPES[OPPOSITE_DIRECTION[dir as usize] as usize] { + possible_forward = false; + } + } + pos = new_pos; + dir = new_dir; + steps += 1; + options.clear(); + } else { + let new_id = graph.len() as u32; + junction_node_mapping.insert(pos, new_id); + if possible_forward { + graph[id as usize].push((new_id, steps)); + } + if possible_backward { + graph.push(vec![(id, steps)]); + } else { + graph.push(vec![]); + } + for &(new_pos, new_dir) in options.iter() { + edge_finding_stack.push((new_id, new_pos, new_dir)); + } + options.clear(); + break; + } + } + } + } else { + break; + } + } + // Swaps the end node with the last in array node + let last_node = graph.len() as u32 - 1; + graph.swap(end_node as usize, last_node as usize); + for node in graph.iter_mut() { + node.iter_mut().for_each(|to_node| + if to_node.0 == end_node { + to_node.0 = last_node; + } else if to_node.0 == last_node { + to_node.0 = end_node; + }); + }; + graph +} + +// Finds the longest path in a graph in a general case +fn find_longest_walk_graph(graph: &HikingGraph, node_from: u32, node_to: u32) -> i32 { + let visited = vec![false; graph.len()]; + find_longest_walk_graph_inner(graph, node_from, node_to, visited) +} + +// Recursive helper for find_longest_walk_graph, has a set (vec) of visited nodes +fn find_longest_walk_graph_inner(graph: &HikingGraph, mut node_from: u32, node_to: u32, + mut visited: Vec) -> i32 { + let mut length = 0; + let mut longest_alternative = -1; + loop { + if node_from == node_to { + return cmp::max(length, longest_alternative); + } else { + if visited[node_from as usize] { + return longest_alternative; + } + let connections = &graph[node_from as usize]; + if connections.is_empty() { + // Dead end, doesn't happen but i put it for the sake of completeness + return longest_alternative; + } + visited[node_from as usize] = true; + let mut connections_iter = connections.iter(); + let &(first_node, first_edge) = connections_iter.next().unwrap(); + for &(new_node, edge) in connections_iter { + let new_length = length + edge as i32; + let alternative = find_longest_walk_graph_inner( + graph, new_node, node_to, visited.clone()); + if alternative != -1 { + longest_alternative = cmp::max(longest_alternative, new_length + alternative); + } + } + node_from = first_node; + length += first_edge as i32; + } + } +} + +// Finds the longest path with given input by building the graph of junctions and finding +// the longest path +fn find_longest_walk(layout: &[&[u8]], slopes: bool) -> i32 { + let graph = get_hiking_graph(layout, slopes); + find_longest_walk_graph(&graph, 0, graph.len() as u32 - 1) +} + +fn main() { + let time_start = Instant::now(); + let input_str = read_to_string("input.txt").unwrap(); + let time_start_no_io = Instant::now(); + let layout: Vec<&[u8]> = input_str.lines().map(|s| s.as_bytes()).collect(); + let result1 = find_longest_walk(&layout, true); + let result2 = find_longest_walk(&layout, false); + let elapsed = time_start.elapsed().as_micros(); + let elapsed_no_io = time_start_no_io.elapsed().as_micros(); + println!("Time: {}us", elapsed); + println!("Time without file i/o: {}us", elapsed_no_io); + println!("Result1: {}", result1); + println!("Result2: {}", result2); +}