├── .gitignore
├── inputs
├── day11.txt
├── day21.txt
├── day17.txt
├── day08.txt
├── day10.txt
├── day24.txt
├── day14.txt
├── day06.txt
├── day09.txt
├── day03.txt
└── day04.txt
├── .idea
├── .gitignore
├── vcs.xml
├── modules.xml
└── aoc-2024.iml
├── Cargo.toml
├── src
├── main.rs
├── day01.rs
├── day03.rs
├── day19.rs
├── day02.rs
├── day10.rs
├── day18.rs
├── day17.rs
├── day07.rs
├── day25.rs
├── day23.rs
├── day09.rs
├── day22.rs
├── day04.rs
├── day08.rs
├── day06.rs
├── day11.rs
├── day05.rs
├── day14.rs
├── day24.rs
├── day12.rs
├── day16.rs
├── day20.rs
├── day13.rs
├── day21.rs
└── day15.rs
├── README.md
└── Cargo.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 |
--------------------------------------------------------------------------------
/inputs/day11.txt:
--------------------------------------------------------------------------------
1 | 554735 45401 8434 0 188 7487525 77 7
2 |
--------------------------------------------------------------------------------
/inputs/day21.txt:
--------------------------------------------------------------------------------
1 | 671A
2 | 279A
3 | 083A
4 | 974A
5 | 386A
6 |
--------------------------------------------------------------------------------
/inputs/day17.txt:
--------------------------------------------------------------------------------
1 | Register A: 64012472
2 | Register B: 0
3 | Register C: 0
4 |
5 | Program: 2,4,1,7,7,5,0,3,1,7,4,1,5,5,3,0
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Editor-based HTTP Client requests
5 | /httpRequests/
6 | # Datasource local storage ignored files
7 | /dataSources/
8 | /dataSources.local.xml
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "aoc-2024"
3 | version = "0.1.0"
4 | edition = "2021"
5 |
6 | [dependencies]
7 | ahash = "0.8.11"
8 | glam = "0.29.2"
9 | itertools = "0.13.0"
10 | ndarray = "0.16.1"
11 | nom = "7.1.3"
12 | nom_locate = "4.2.0"
13 | pathfinding = "4.12.0"
14 | petgraph = "0.6.5"
15 | rayon = "1.10.0"
16 | regex = "1.11.1"
17 |
--------------------------------------------------------------------------------
/.idea/aoc-2024.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/main.rs:
--------------------------------------------------------------------------------
1 | #![allow(dead_code)]
2 |
3 | mod day01;
4 | mod day02;
5 | mod day03;
6 | mod day04;
7 | mod day05;
8 | mod day06;
9 | mod day07;
10 | mod day08;
11 | mod day09;
12 | mod day10;
13 | mod day11;
14 | mod day12;
15 | mod day13;
16 | mod day14;
17 | mod day15;
18 | mod day16;
19 | mod day17;
20 | mod day18;
21 | mod day19;
22 | mod day20;
23 | mod day21;
24 | mod day22;
25 | mod day23;
26 | mod day24;
27 | mod day25;
28 |
29 | fn main() {
30 | // day01::solution();
31 | // day02::solution();
32 | // day03::solution();
33 | // day04::solution();
34 | // day05::solution();
35 | // day06::solution();
36 | // day07::solution();
37 | // day08::solution();
38 | // day09::solution();
39 | // day10::solution();
40 | // day11::solution();
41 | // day12::solution();
42 | // day13::solution();
43 | // day14::solution();
44 | // day15::solution();
45 | // day16::solution();
46 | // day17::solution();
47 | // day18::solution();
48 | // day19::solution();
49 | // day20::solution();
50 | // day21::solution();
51 | // day22::solution();
52 | // day23::solution();
53 | // day24::solution();
54 | day25::solution();
55 | }
56 |
--------------------------------------------------------------------------------
/src/day01.rs:
--------------------------------------------------------------------------------
1 | use std::fs;
2 | use std::str::FromStr;
3 |
4 | pub fn solution() {
5 | // A.
6 | let aoc_2024_01 =
7 | fs::read_to_string("./inputs/day01.txt").expect("Something went wrong reading the file");
8 | let mut a = Vec::new();
9 | let mut b = Vec::new();
10 |
11 | for line in aoc_2024_01.lines() {
12 | // split by tab
13 | let mut parts = line.split_whitespace();
14 | a.push(::from_str(parts.next().unwrap()).unwrap());
15 | b.push(::from_str(parts.next().unwrap()).unwrap());
16 | }
17 |
18 | // unstable sorting is faster, and we can use this because the inputs are integers
19 | a.sort_unstable();
20 | b.sort_unstable();
21 |
22 | // calculate the difference between the two arrays
23 | let diff = a
24 | .iter()
25 | .zip(&b)
26 | .map(|(a, b)| (a - b).abs())
27 | .collect::>()
28 | .iter()
29 | .sum::();
30 | println!("The difference is: {}", diff);
31 |
32 | // B.
33 | let sum = a
34 | .iter()
35 | .map(|x| x * b.iter().filter(|&y| x == y).count() as i32)
36 | .sum::();
37 |
38 | println!("The sum of duplicates is: {}", sum);
39 | }
40 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 🎄 Advent of Code 2024 Solutions in Rust
2 |
3 | Welcome to our **Advent of Code 2024 (in Rust)** repository! 🎅✨ This project provides **daily solutions** for the [Advent of Code](https://adventofcode.com/) challenges, implemented in the Rust programming language.
4 |
5 | We update the repository **every day** with solutions for the latest puzzles. Whether you're learning Rust, solving puzzles, or looking for inspiration, we hope this repository proves useful to you.
6 |
7 | ## 📁 Directory Structure
8 |
9 | ```plaintext
10 | 📂 src/
11 | ├── day01.rs # Solution for Day 1
12 | ├── day02.rs # Solution for Day 2
13 | ├── ...
14 | 📂 inputs/
15 | ├── day01.txt # Input data for Day 1
16 | ├── day02.txt # Input data for Day 2
17 | ├── ...
18 | ```
19 |
20 | - src/: Contains the Rust solution files for each day.
21 | - inputs/: Stores the input data used for the puzzles.
22 |
23 |
24 | ## 🚀 Usage
25 |
26 | 1. Clone the repository:
27 |
28 | ```bash
29 | git clone https://github.com/rust-dd/aoc-2024.git
30 | cd aoc-2024
31 | ```
32 |
33 | 2. Update the repository daily to get the latest solutions:
34 |
35 | ```bash
36 | git pull
37 | ```
38 |
39 |
40 | ## 🌟 Acknowledgements
41 |
42 | - Advent of Code by Eric Wastl for the incredible challenges.
43 | - The Rust community for their tools and support.
44 |
45 | ---
46 |
47 | 🎉 Happy Coding and enjoy solving puzzles with Rust! 🎄
48 |
--------------------------------------------------------------------------------
/src/day03.rs:
--------------------------------------------------------------------------------
1 | use std::fs;
2 |
3 | use regex::Regex;
4 |
5 | pub fn solution() {
6 | let aoc_2024_03 =
7 | fs::read_to_string("./inputs/day03.txt").expect("Something went wrong reading the file");
8 |
9 | // A.
10 | let matching_regex = Regex::new(r"mul\((\d+),(\d+)\)").unwrap();
11 | let caps = matching_regex.captures_iter(&aoc_2024_03);
12 |
13 | let mut sum = 0;
14 | for cap in caps {
15 | let first_value = cap.get(1).unwrap().as_str().parse::().unwrap();
16 | let second_value = cap.get(2).unwrap().as_str().parse::().unwrap();
17 | sum = sum + (first_value * second_value);
18 | }
19 | println!("Result: {}", sum);
20 |
21 | // B.
22 | let text_without_new_lines = aoc_2024_03.replace("\n", "to");
23 | let regex_do_not_do = Regex::new(r"don't.*?(do\(\)|$)").unwrap();
24 | let text_without_do_not_do = regex_do_not_do.replace_all(&text_without_new_lines, "");
25 | let matching_regex = Regex::new(r"mul\((\d+),(\d+)\)").unwrap();
26 | let caps = matching_regex.captures_iter(&text_without_do_not_do);
27 | let mut sum = 0;
28 | for cap in caps {
29 | let first_value = cap.get(1).unwrap().as_str().parse::().unwrap();
30 | let second_value = cap.get(2).unwrap().as_str().parse::().unwrap();
31 | sum = sum + (first_value * second_value);
32 | }
33 |
34 | println!("Result: {}", sum);
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/src/day19.rs:
--------------------------------------------------------------------------------
1 | use std::fs;
2 | use std::io::{self, BufRead};
3 | use std::collections::HashMap;
4 |
5 | fn count_ways(onsen_part: &str, patterns: &[String], memo: &mut HashMap) -> u64 {
6 | if onsen_part.is_empty() {
7 | return 1;
8 | }
9 |
10 | if let Some(&count) = memo.get(onsen_part) {
11 | return count;
12 | }
13 |
14 | let mut total = 0;
15 | for pattern in patterns {
16 | if onsen_part.starts_with(pattern) {
17 | let remainder = &onsen_part[pattern.len()..];
18 | total += count_ways(remainder, patterns, memo);
19 | }
20 | }
21 | memo.insert(onsen_part.to_string(), total);
22 | total
23 | }
24 |
25 | pub fn solution() {
26 | let file = fs::File::open("./inputs/day19.txt").expect("Failed to open file");
27 | let reader = io::BufReader::new(file);
28 | let mut lines_iter = reader.lines().map(|line| line.expect("Failed to read line"));
29 | let towel_pattern_line = lines_iter.next().expect("No towel patterns found");
30 | let towel_patterns: Vec = towel_pattern_line
31 | .split(',')
32 | .map(|s| s.trim().to_string())
33 | .collect();
34 |
35 | // blank line
36 | lines_iter.next();
37 |
38 | let onsens: Vec = lines_iter.collect();
39 |
40 | let mut total_match_count = 0u64;
41 | let mut onsen_count_that_can_match = 0u64;
42 |
43 | for onsen in &onsens {
44 | let mut memo: HashMap = HashMap::new();
45 | let ways = count_ways(onsen, &towel_patterns, &mut memo);
46 | if ways > 0 {
47 | onsen_count_that_can_match += 1;
48 | total_match_count += ways;
49 | }
50 | }
51 |
52 | println!("Result A: {}", onsen_count_that_can_match);
53 | println!("Result B: {}", total_match_count);
54 | }
--------------------------------------------------------------------------------
/src/day02.rs:
--------------------------------------------------------------------------------
1 | use std::fs;
2 |
3 | pub fn solution() {
4 | let aoc_2024_02 =
5 | fs::read_to_string("./inputs/day02.txt").expect("Something went wrong reading the file");
6 |
7 | // A.
8 | let mut safe_reports_a = 0;
9 | let mut safe_reports = Vec::::new();
10 | for (idx, line) in aoc_2024_02.lines().enumerate() {
11 | let numbers = line
12 | .split_whitespace()
13 | .map(|u| u.parse::().unwrap())
14 | .collect::>();
15 | let ascending = |a: &i8, b: &i8| *a < *b && *b <= (*a + 3);
16 | let descending = |a: &i8, b: &i8| *a > *b && *b >= (*a - 3);
17 |
18 | if numbers.is_sorted_by(ascending) || numbers.is_sorted_by(descending) {
19 | safe_reports_a = safe_reports_a + 1;
20 |
21 | // collect the indexes of the unsafe reports
22 | safe_reports.push(idx);
23 | }
24 | }
25 | println!("Number of safe reports is: {}", safe_reports_a);
26 |
27 | // B.
28 | let asc = |levels: &[i8]| {
29 | levels
30 | .windows(2)
31 | .all(|w| w[1] > w[0] && (1..=3).contains(&(w[1] - w[0])))
32 | };
33 | let desc = |levels: &[i8]| {
34 | levels
35 | .windows(2)
36 | .all(|w| w[1] < w[0] && (1..=3).contains(&(w[0] - w[1])))
37 | };
38 |
39 | let is_safe = |levels: &[i8]| -> bool {
40 | (asc(levels) || desc(levels))
41 | || (0..levels.len()).any(|i| {
42 | let mut levels = levels.to_vec();
43 | levels.remove(i);
44 | asc(&levels) || desc(&levels)
45 | })
46 | };
47 |
48 | let levels = aoc_2024_02
49 | .lines()
50 | .map(|line| {
51 | line.split_whitespace()
52 | .map(|u| u.parse::().unwrap())
53 | .collect::>()
54 | })
55 | .collect::>>();
56 |
57 | let count = levels.into_iter().filter(|l| is_safe(l)).count();
58 | println!("Number of safe reports is: {}", count);
59 | }
60 |
--------------------------------------------------------------------------------
/src/day10.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashSet;
2 | use std::fs::File;
3 | use std::io::{self, BufRead};
4 |
5 | pub fn solution() {
6 | let aoc_2024_10 =
7 | File::open("./inputs/day10.txt").expect("Something went wrong reading the file");
8 | let grid = io::BufReader::new(aoc_2024_10)
9 | .lines()
10 | .filter_map(|line| line.ok())
11 | .map(|line| {
12 | line.chars()
13 | .map(|c| c.to_digit(10).map(|d| d as usize).unwrap_or(99))
14 | .collect::>()
15 | })
16 | .collect::>>();
17 |
18 | let rows = grid.len() as i32;
19 | let cols = grid[0].len() as i32;
20 |
21 | let zero_positions: Vec<(i32, i32)> = (0..rows)
22 | .flat_map(|i| (0..cols).map(move |j| (i, j)))
23 | .filter(|&(i, j)| grid[i as usize][j as usize] == 0)
24 | .collect();
25 |
26 | let mut sum_of_scores = 0;
27 | let mut sum_of_ratings = 0;
28 | for (i, j) in zero_positions {
29 | let mut queue = Vec::new();
30 | queue.push((0, (i, j)));
31 | let mut scores: HashSet<(i32, i32)> = HashSet::new();
32 | let directions = [(-1, 0), (1, 0), (0, 1), (0, -1)];
33 | while let Some((actual_value, (x, y))) = queue.pop() {
34 | let next_value = actual_value + 1;
35 |
36 | for &(dx, dy) in &directions {
37 | let next_x = x + dx;
38 | let next_y = y + dy;
39 |
40 | if let Some(actual_value) = get_value(&grid, rows, cols, next_x, next_y) {
41 | if actual_value == next_value {
42 | if actual_value == 9 {
43 | scores.insert((next_x, next_y));
44 | sum_of_ratings += 1;
45 | } else {
46 | queue.push((next_value, (next_x, next_y)));
47 | }
48 | }
49 | }
50 | }
51 | }
52 | sum_of_scores += scores.len();
53 | }
54 |
55 | println!("matches a {}", sum_of_scores);
56 | println!("matches b {}", sum_of_ratings);
57 | }
58 |
59 | fn get_value(grid: &Vec>, rows: i32, cols: i32, r: i32, c: i32) -> Option {
60 | if r >= 0 && r < rows && c >= 0 && c < cols {
61 | Some(grid[r as usize][c as usize])
62 | } else {
63 | None
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/inputs/day08.txt:
--------------------------------------------------------------------------------
1 | ..................................................
2 | .................................C................
3 | .e..........7O....................................
4 | .....................................z............
5 | ......................t.........C.......k.........
6 | ............h................................9....
7 | .............5.7....O.............9C..............
8 | .......5.O................T.......................
9 | .............................o...c....z...........
10 | .hH...........e..7.............................w..
11 | ......H...................c....3.T..5.............
12 | .....H........5..........B...........3..z..c......
13 | ....6........H.........t..........................
14 | ........O..................e........3.............
15 | ............e.........o..............9............
16 | .........s.........o..............................
17 | .......................k........4.....3..z.w......
18 | ......s.................t..T.k............8.......
19 | .......s............................T.....w.......
20 | ..................................C.7.............
21 | ..................................................
22 | .........................t......b.w...............
23 | ............................X...................8.
24 | .............6..........k.........................
25 | ............................1................8....
26 | ...............................8..................
27 | ....h........................b....................
28 | ............................................c.....
29 | ..J...............................................
30 | .....................................K............
31 | ..............................x...................
32 | ..................................................
33 | ....2......0...................x...........1......
34 | ...4.....0......................1b................
35 | .............h......................K.jW..........
36 | 6...........0...............W.....................
37 | .........6........B...............................
38 | .......2................B..........x........K.....
39 | ..................................................
40 | .................................G.......j........
41 | ....................E.............................
42 | .......................................S...ZX.....
43 | .....4.......2...B........Wj.....S................
44 | ..o...............2..................W....j.......
45 | .....................E..........S..........J......
46 | ................E......................1..........
47 | ......................G........K.........g........
48 | ..............................G....J....S.........
49 | ...................G....................Z..Xg.....
50 | 4..................E..............J.g....X........
--------------------------------------------------------------------------------
/inputs/day10.txt:
--------------------------------------------------------------------------------
1 | 56760198543405456770107687012987873265430701234123
2 | 47891087612514320889298596543236982176321878985054
3 | 30932912503423411978321436760145453089490965076567
4 | 21043803498598502565450345897896334569584324105498
5 | 43256754387687643445601231056787276578675013212389
6 | 50105620896014553238782322348996189432106522301210
7 | 60234211205423469109695210567345023456987101232569
8 | 71454301312345678100556501051269010787832198543478
9 | 82365985407856743291447892340178732696949037643323
10 | 99878876556989856782332309650065341054658743252110
11 | 12389565445845698943221218761234456565789650167087
12 | 03458890330532787892100321052442787074656782108996
13 | 12766721221621056521098478934321692183245891210105
14 | 00875437876521245430167569035630013290194300121234
15 | 21980356985430130101456122128754324389980215432101
16 | 32341245234561221212340033439961015671271326990123
17 | 41239832101676678703121542345872343760362347887654
18 | 50146701098787569254035671096112654854454558943210
19 | 69655410889693452164549389987003569943003967656787
20 | 78789324989582543076678432176124578752112876545490
21 | 49670123476451001289986581065437669801198743454321
22 | 34565404560302654345677893034458954321034652345210
23 | 21670313401212701238766732123361056700125601216787
24 | 10781223304343870349676678901272341811098700305891
25 | 87690433210154901234587565078980110925643212456730
26 | 98521049873269100448996652169765223434756965569821
27 | 83430656794378234567385543258894304589807874321034
28 | 12345690185123247855434789043210113676212981012125
29 | 04396783276030110982329872178901923494345891234596
30 | 65287654896543225671012763561032876587436780989687
31 | 70132108987652334430101654432945214306525891078765
32 | 89945345456701498521012346547876305211014342569854
33 | 67876276789876567677890107236521456523210213410743
34 | 56940189678930438988743298101430567894765104323212
35 | 45434328509821321089654340122334567765894101298701
36 | 50125613410030012127763019831021998568903210345692
37 | 23498701322147897898892123742340867478912653210789
38 | 10567654213456786721089054654356789302801743105678
39 | 01678123402110995437658766789210676211010892234109
40 | 67569016567021874378941043212101245432346781103201
41 | 58454323898134565632332456701234306011015490321232
42 | 49323454234012906701454327890965412102367305410147
43 | 31012365125643812898765410378876543233458216568758
44 | 21009876034756763019034101269989100146569325679669
45 | 21898745129829654323129654352123299656478012784578
46 | 30743231065018760563238765543034788798329983693056
47 | 45656189654323011056769894672145632347012674212147
48 | 01218088745896522349850123283034701456981065100238
49 | 14309893236787631438943210190129892123672578921109
50 | 25456782101896540127654301012010181034543465433212
51 |
--------------------------------------------------------------------------------
/src/day18.rs:
--------------------------------------------------------------------------------
1 | use std::collections::VecDeque;
2 | use std::fs;
3 | use std::io::{self, BufRead};
4 |
5 | const GRID_SIZE: usize = 71;
6 | const NUM_ROWS: usize = 1024;
7 |
8 | type Point = (usize, usize);
9 |
10 | fn bfs(grid: &[[char; GRID_SIZE]; GRID_SIZE]) -> (bool, usize) {
11 | let directions: [(isize, isize); 4] = [(0, 1), (1, 0), (0, -1), (-1, 0)];
12 | let mut queue = VecDeque::new();
13 | let mut visited = [[false; GRID_SIZE]; GRID_SIZE];
14 | let mut path_length = 0;
15 |
16 | queue.push_back((0, 0, vec![(0,0)]));
17 | visited[0][0] = true;
18 |
19 | while let Some((x, y, path)) = queue.pop_front() {
20 | if (x, y) == (GRID_SIZE - 1, GRID_SIZE - 1) {
21 | path_length = path.len() -1;
22 | return (true, path_length);
23 | }
24 |
25 | for &(dx, dy) in &directions {
26 | let nx = x as isize + dx;
27 | let ny = y as isize + dy;
28 |
29 | if nx >= 0 && nx < GRID_SIZE as isize && ny >= 0 && ny < GRID_SIZE as isize {
30 | let (nx, ny) = (nx as usize, ny as usize);
31 | if !visited[nx][ny] && grid[nx][ny] == '.' {
32 | let mut new_path = path.clone();
33 | new_path.push((nx,ny));
34 | queue.push_back((nx, ny, new_path));
35 | visited[nx][ny] = true;
36 | }
37 | }
38 | }
39 | }
40 | (false, path_length)
41 | }
42 |
43 | pub fn solution() {
44 | let file = fs::File::open("./inputs/day18.txt").expect("Failed to open file");
45 | let reader = io::BufReader::new(file);
46 | let mut lines_iter = reader.lines().map(Result::unwrap);
47 | let mut grid = [['.'; GRID_SIZE]; GRID_SIZE];
48 |
49 | // Initial grid setup
50 | for line_content in lines_iter.by_ref().take(NUM_ROWS) {
51 | let (y_str, x_str) = line_content.trim().split_once(',').unwrap();
52 | let (x, y): (usize, usize) = (x_str.parse().unwrap(), y_str.parse().unwrap());
53 | if x < GRID_SIZE && y < GRID_SIZE {
54 | grid[x][y] = '#';
55 | }
56 | }
57 |
58 | // Part A
59 | let (path_found, path_length) = bfs(&grid);
60 | if path_found {
61 | println!("Result A: {}", path_length);
62 | }
63 |
64 |
65 | // Part B
66 | for line_content in lines_iter {
67 | let (y_str, x_str) = line_content.trim().split_once(',').unwrap();
68 | let (x, y): (usize, usize) = (x_str.parse().unwrap(), y_str.parse().unwrap());
69 |
70 | if x < GRID_SIZE && y < GRID_SIZE {
71 | grid[x][y] = '#';
72 | }
73 |
74 | let (path_found, _) = bfs(&grid);
75 | if !path_found {
76 | println!("Result B: {},{}", y, x);
77 | break;
78 | }
79 | }
80 | }
--------------------------------------------------------------------------------
/src/day17.rs:
--------------------------------------------------------------------------------
1 | use std::fs;
2 | use regex::Regex;
3 |
4 | pub fn solution() {
5 | let input = fs::read_to_string("./inputs/day17.txt").expect("Failed to read file");
6 | let re = Regex::new(r"Register A:\s*(\d+)\s*Register B:\s*(\d+)\s*Register C:\s*(\d+)\s*Program:\s*([\d,]+)").unwrap();
7 | let caps = re.captures(&input).expect("Failed to parse input");
8 |
9 | let a_init: u64 = caps[1].parse().unwrap();
10 | let b_init: u64 = caps[2].parse().unwrap();
11 | let c_init: u64 = caps[3].parse().unwrap();
12 | let programs: Vec = caps[4]
13 | .split(',')
14 | .map(|x| x.trim().parse().unwrap())
15 | .collect();
16 |
17 | // Part A
18 | let result_a = run_program(a_init, b_init, c_init, &programs);
19 | let result_a_joined = result_a.iter()
20 | .map(u64::to_string)
21 | .collect::>()
22 | .join(",");
23 | println!("Part A Result: {}", result_a_joined);
24 |
25 | // Part B
26 | let result_b = find_part_b_initial_a(b_init, c_init, &programs).unwrap();
27 | println!("Part B Result: {}", result_b);
28 | }
29 |
30 | fn run_program(mut a: u64, mut b: u64, mut c: u64, programs: &[u64]) -> Vec {
31 | let mut result = Vec::new();
32 | let mut pointer = 0;
33 |
34 | while pointer < programs.len() {
35 | let opcode = programs[pointer];
36 | let operand = programs[pointer + 1];
37 | let combo = get_combo(operand, a, b, c);
38 |
39 | match opcode {
40 | 0 => a /= 1 << combo,
41 | 1 => b ^= operand,
42 | 2 => b = combo % 8,
43 | 3 => if a != 0 {
44 | pointer = operand as usize;
45 | continue;
46 | },
47 | 4 => b ^= c,
48 | 5 => result.push(combo % 8),
49 | 6 => b = a / (1 << combo),
50 | 7 => c = a / (1 << combo),
51 | _ => println!("Unknown opcode: {}", opcode),
52 | }
53 | pointer += 2;
54 | }
55 | result
56 | }
57 |
58 | fn get_combo(operand: u64, a: u64, b: u64, c: u64) -> u64 {
59 | match operand {
60 | 4 => a,
61 | 5 => b,
62 | 6 => c,
63 | _ => operand,
64 | }
65 | }
66 |
67 |
68 | fn find_part_b_initial_a(b_init: u64, c_init: u64, programs: &[u64]) -> Option {
69 | let mut candidates = vec![0];
70 | while !candidates.is_empty() {
71 | let mut next: Vec = vec![];
72 | for base in candidates {
73 | for i in 0..=7 {
74 | let a: u64 = 8 * base + i;
75 | let output = run_program(a, b_init, c_init, programs);
76 | if output == programs {
77 | return Some(a);
78 | }
79 | if programs.ends_with(&output) {
80 | next.push(a);
81 | }
82 | }
83 | }
84 | candidates = next;
85 | }
86 | None
87 | }
--------------------------------------------------------------------------------
/src/day07.rs:
--------------------------------------------------------------------------------
1 | use std::fs;
2 |
3 | use nom::{
4 | bytes::complete::tag,
5 | character::complete::{self, line_ending, space1},
6 | multi::separated_list1,
7 | sequence::separated_pair,
8 | IResult,
9 | };
10 |
11 | pub fn solution() {
12 | let input = fs::read_to_string("./inputs/day07.txt").expect("Failed to read input file");
13 | let data: IResult<&str, Vec<(u64, Vec)>, nom::error::Error<&str>> = separated_list1(
14 | line_ending,
15 | separated_pair(
16 | complete::u64,
17 | tag(": "),
18 | separated_list1(space1, complete::u64),
19 | ),
20 | )(input.as_str());
21 | let (_, data) = data.unwrap();
22 |
23 | // A.
24 | let mut result = 0;
25 |
26 | for (left, right) in &data {
27 | let len = right.len();
28 |
29 | if len < 1 {
30 | continue;
31 | }
32 |
33 | // Test every combination of add/mul between the right side
34 | // All combinations are 2^(len - 1)
35 | // generate all possible combinations of add/mul in binary form
36 | for i in 0..(1 << (len - 1)) {
37 | let mut sum = right[0];
38 |
39 | for j in 0..(len - 1) {
40 | // bit masking to check if the j-th bit in i is a 1 or 0
41 | // if 1, add, else multiply
42 | if i & (1 << j) != 0 {
43 | sum += right[j + 1];
44 | } else {
45 | sum *= right[j + 1];
46 | }
47 | }
48 |
49 | if &sum == left {
50 | result += left;
51 | break;
52 | }
53 | }
54 | }
55 |
56 | println!("Result part A: {}", result);
57 |
58 | // B.
59 | let mut result = 0;
60 |
61 | for (left, right) in &data {
62 | let len = right.len();
63 |
64 | if len < 1 {
65 | continue;
66 | }
67 |
68 | // Test every combination of add/mul between the right side
69 | // All combinations are 2^(len - 1)
70 | // || use for concatenation and get the result of the left side
71 | // e.g 156: 15 6
72 | // 156 = 15 || 6
73 | for mut i in 0..3i64.pow((len - 1) as u32) {
74 | let mut sum = right[0];
75 |
76 | for j in 0..(len - 1) {
77 | let op = i % 3;
78 | i /= 3;
79 |
80 | match op {
81 | 0 => sum += right[j + 1],
82 | 1 => sum *= right[j + 1],
83 | _ => {
84 | sum = format!("{}{}", sum, right[j + 1].to_string())
85 | .parse()
86 | .unwrap()
87 | }
88 | }
89 | }
90 |
91 | if &sum == left {
92 | result += left;
93 | break;
94 | }
95 | }
96 | }
97 |
98 | println!("Result part B: {}", result);
99 | }
100 |
--------------------------------------------------------------------------------
/src/day25.rs:
--------------------------------------------------------------------------------
1 | use std::{
2 | fs::File,
3 | io::{BufRead, BufReader},
4 | };
5 |
6 | #[derive(Debug)]
7 | struct Block {
8 | origin: String,
9 | heights: Vec,
10 | }
11 |
12 | pub fn solution() {
13 | let file = File::open("./inputs/day25.txt").expect("Could not open input file");
14 | let reader = BufReader::new(file);
15 | let lines: Vec = reader.lines().map(|line| line.expect("Could not read line")).collect();
16 |
17 | let blocks = parse_blocks(&lines);
18 | let processed_blocks: Vec = blocks
19 | .iter()
20 | .map(|block| {
21 | let origin = determine_block_origin(block);
22 | let heights = calculate_heights(block, &origin);
23 | Block { origin, heights }
24 | })
25 | .collect();
26 |
27 | let match_count = count_matches(&processed_blocks);
28 | println!("Result A: {}", match_count);
29 | }
30 |
31 | fn parse_blocks(lines: &[String]) -> Vec> {
32 | let mut blocks = vec![];
33 | let mut current = vec![];
34 |
35 | for line in lines {
36 | if line.trim().is_empty() {
37 | if !current.is_empty() {
38 | blocks.push(current.clone());
39 | current.clear();
40 | }
41 | } else {
42 | current.push(line.clone());
43 | if current.len() == 7 {
44 | blocks.push(current.clone());
45 | current.clear();
46 | }
47 | }
48 | }
49 |
50 | if !current.is_empty() {
51 | blocks.push(current);
52 | }
53 |
54 | blocks
55 | }
56 |
57 | fn determine_block_origin(block: &[String]) -> String {
58 | let first_line_hashes = block[0].chars().filter(|&c| c == '#').count();
59 | let last_line_hashes = block[6].chars().filter(|&c| c == '#').count();
60 |
61 | if first_line_hashes > last_line_hashes {
62 | "Top".to_string()
63 | } else {
64 | "Bottom".to_string()
65 | }
66 | }
67 |
68 | fn calculate_heights(block: &[String], origin: &str) -> Vec {
69 | (0..block.iter().map(|line| line.len()).max().unwrap())
70 | .map(|col| {
71 | let mut height = 0;
72 | let rows = if origin == "Top" {
73 | (1..7).collect::>()
74 | } else {
75 | (0..6).rev().collect::>()
76 | };
77 |
78 | for row in rows {
79 | if block[row].chars().nth(col).unwrap_or('.') == '#' {
80 | height += 1;
81 | } else {
82 | break;
83 | }
84 | }
85 |
86 | height
87 | })
88 | .collect()
89 | }
90 |
91 | fn count_matches(blocks: &[Block]) -> i32 {
92 | let mut match_count = 0;
93 |
94 | for (i, block_a) in blocks.iter().enumerate() {
95 | for block_b in blocks.iter().skip(i + 1) {
96 | if block_a.origin != block_b.origin
97 | && block_a.heights.iter().zip(&block_b.heights).all(|(a, b)| a + b < 6)
98 | {
99 | match_count += 1;
100 | }
101 | }
102 | }
103 |
104 | match_count
105 | }
106 |
--------------------------------------------------------------------------------
/src/day23.rs:
--------------------------------------------------------------------------------
1 | use std::{
2 | collections::{HashMap, HashSet},
3 | fs::File,
4 | io::{BufRead, BufReader},
5 | };
6 |
7 | use petgraph::{
8 | graph::{Graph, NodeIndex},
9 | Undirected,
10 | };
11 |
12 | pub fn solution() {
13 | let file = File::open("./inputs/day23.txt").unwrap();
14 | let reader = BufReader::new(file);
15 |
16 | let mut graph = Graph::::new_undirected();
17 | let mut nodes: HashMap = HashMap::new();
18 |
19 | for line_result in reader.lines() {
20 | let line = line_result.unwrap();
21 | let parts: Vec = line.split('-').map(|s| s.to_string()).collect();
22 | let computer1 = &parts[0];
23 | let computer2 = &parts[1];
24 |
25 | let node1 = *nodes
26 | .entry(computer1.to_string())
27 | .or_insert_with(|| graph.add_node(computer1.to_string()));
28 | let node2 = *nodes
29 | .entry(computer2.to_string())
30 | .or_insert_with(|| graph.add_node(computer2.to_string()));
31 |
32 | graph.add_edge(node1, node2, ());
33 | }
34 |
35 | // A
36 | let mut three_node_sets: HashSet> = HashSet::new();
37 | for u in graph.node_indices() {
38 | let neighbors: Vec<_> = graph.neighbors(u).collect();
39 | for i in 0..neighbors.len() {
40 | for j in (i + 1)..neighbors.len() {
41 | let n1 = neighbors[i];
42 | let n2 = neighbors[j];
43 |
44 | if graph.contains_edge(n1, n2) {
45 | let mut tri = vec![graph[u].clone(), graph[n1].clone(), graph[n2].clone()];
46 | tri.sort();
47 | three_node_sets.insert(tri);
48 | }
49 | }
50 | }
51 | }
52 |
53 | let set_has_node_start_with_t = three_node_sets
54 | .iter()
55 | .filter(|triangle| triangle.iter().any(|label| label.starts_with('t')))
56 | .count();
57 | println!("Result A: {}", set_has_node_start_with_t);
58 |
59 | // B
60 | let mut largest_set: HashSet = HashSet::new();
61 | for current_node in graph.node_indices() {
62 | let mut current_set = HashSet::new();
63 | current_set.insert(current_node);
64 | let mut neighbours: Vec = graph.neighbors(current_node).collect();
65 |
66 | while let Some(neighbour) = neighbours.pop() {
67 | let is_fully_connected = current_set
68 | .iter()
69 | .all(|¤t| graph.contains_edge(neighbour, current) || current == neighbour);
70 |
71 | if is_fully_connected {
72 | current_set.insert(neighbour);
73 | for neighbour_of_neighbour in graph.neighbors(neighbour) {
74 | if !current_set.contains(&neighbour_of_neighbour)
75 | && !neighbours.contains(&neighbour_of_neighbour)
76 | {
77 | neighbours.push(neighbour_of_neighbour);
78 | }
79 | }
80 | }
81 | }
82 | if current_set.len() > largest_set.len() {
83 | largest_set = current_set;
84 | }
85 | }
86 |
87 | let mut labels: Vec = largest_set.into_iter().map(|i| graph[i].clone()).collect();
88 | labels.sort();
89 |
90 | println!("Result B: {}", labels.join(","));
91 | }
92 |
--------------------------------------------------------------------------------
/src/day09.rs:
--------------------------------------------------------------------------------
1 | use itertools::Itertools;
2 | use std::fs;
3 |
4 | pub fn solution() {
5 | let input = fs::read_to_string("./inputs/day09.txt").expect("Failed to read input file");
6 | let input = input.trim();
7 | let mut disk = Vec::new();
8 |
9 | let bytes = input.bytes().enumerate();
10 | let mut bytes_rev = bytes.clone().rev();
11 |
12 | let mut bytes_rev_i;
13 | let mut bytes_rev_i_id;
14 | let mut bytes_rev_b;
15 | let mut bytes_rev_b_remaining;
16 |
17 | (bytes_rev_i, bytes_rev_b) = bytes_rev.next().unwrap();
18 |
19 | if bytes_rev_i % 2 == 1 {
20 | (bytes_rev_i, bytes_rev_b) = bytes_rev.next().unwrap();
21 | }
22 |
23 | bytes_rev_i_id = bytes_rev_i / 2;
24 | bytes_rev_b_remaining = bytes_rev_b - b'0';
25 |
26 | for (i, b) in bytes {
27 | if i >= bytes_rev_i {
28 | for _ in 0..bytes_rev_b_remaining {
29 | disk.push(bytes_rev_i_id);
30 | }
31 | break;
32 | }
33 | if i % 2 == 0 {
34 | let i_id = i / 2;
35 | for _ in 0..(b - b'0') {
36 | disk.push(i_id);
37 | }
38 | } else {
39 | for _ in 0..(b - b'0') {
40 | if bytes_rev_b_remaining == 0 {
41 | _ = bytes_rev.next().unwrap();
42 | (bytes_rev_i, bytes_rev_b) = bytes_rev.next().unwrap();
43 | if i >= bytes_rev_i {
44 | break;
45 | }
46 | bytes_rev_i_id = bytes_rev_i / 2;
47 | bytes_rev_b_remaining = bytes_rev_b - b'0';
48 | }
49 | bytes_rev_b_remaining -= 1;
50 | disk.push(bytes_rev_i_id);
51 | }
52 | }
53 | }
54 |
55 | let sum: usize = disk.into_iter().enumerate().map(|(i, id)| i * id).sum();
56 | println!("Result part A: {}", sum);
57 |
58 | // B.
59 | // (id, start, length)
60 | let mut files = Vec::new();
61 |
62 | let _ = input.bytes().enumerate().fold(0, |mut c, (i, b)| {
63 | let length = b - b'0';
64 |
65 | if i % 2 == 0 {
66 | files.push((i / 2, c, length));
67 | }
68 |
69 | c += length as usize;
70 | c
71 | });
72 |
73 | for id in (0..=files.last().unwrap().0).rev() {
74 | let file_index = files.iter().position(|file| file.0 == id).unwrap();
75 |
76 | if let Some(new_position) = files
77 | .iter()
78 | .tuple_windows()
79 | .find_map(|(a, b)| {
80 | let a_end = a.1 + a.2 as usize;
81 | let f = &files[file_index];
82 |
83 | if a_end > f.1 {
84 | return Some(None);
85 | }
86 |
87 | let gap = b.1 - a_end;
88 | if gap >= f.2 as usize {
89 | return Some(Some(a_end));
90 | }
91 |
92 | None
93 | })
94 | .flatten()
95 | {
96 | files[file_index].1 = new_position;
97 | }
98 |
99 | files.sort_by_key(|f| f.1);
100 | }
101 |
102 | let sum = files
103 | .into_iter()
104 | .map(|f| {
105 | (f.1..f.1 + f.2 as usize)
106 | .map(|idx| idx * f.0)
107 | .sum::()
108 | })
109 | .sum::();
110 |
111 | println!("Result part B: {}", sum);
112 | }
113 |
--------------------------------------------------------------------------------
/src/day22.rs:
--------------------------------------------------------------------------------
1 | use itertools::iproduct;
2 | use rayon::prelude::*;
3 | use std::fs::File;
4 | use std::io::{BufRead, BufReader};
5 |
6 | const MODULO: u64 = 16_777_216;
7 |
8 | fn next_secret(s: u32) -> u32 {
9 | let mut s64 = s as u64;
10 | let m1 = s64.checked_mul(64).unwrap();
11 | s64 ^= m1;
12 | s64 %= MODULO;
13 | let m2 = s64 / 32;
14 | s64 ^= m2;
15 | s64 %= MODULO;
16 | let m3 = s64.checked_mul(2048).unwrap();
17 | s64 ^= m3;
18 | s64 %= MODULO;
19 | s64 as u32
20 | }
21 |
22 | fn generate_2000th_secret(initial: u32) -> u32 {
23 | let mut s = initial;
24 | for _ in 0..2000 {
25 | s = next_secret(s);
26 | }
27 | s
28 | }
29 |
30 | fn generate_secret_sequence(initial: u32) -> Vec {
31 | let mut seq = Vec::with_capacity(2001);
32 | seq.push(initial);
33 | let mut current = initial;
34 | for _ in 0..2000 {
35 | current = next_secret(current);
36 | seq.push(current);
37 | }
38 | seq
39 | }
40 |
41 | fn to_prices(secrets: &[u32]) -> Vec {
42 | secrets.iter().map(|&s| (s % 10) as u8).collect()
43 | }
44 |
45 | fn to_price_changes(prices: &[u8]) -> Vec {
46 | let mut changes = Vec::with_capacity(prices.len().saturating_sub(1));
47 | for w in prices.windows(2) {
48 | changes.push(w[1] as i8 - w[0] as i8);
49 | }
50 | changes
51 | }
52 |
53 | fn first_occurrence_bananas(changes: &[i8], prices: &[u8], pattern: &[i8]) -> u32 {
54 | if changes.len() < pattern.len() {
55 | return 0;
56 | }
57 | for i in 0..=(changes.len() - pattern.len()) {
58 | if &changes[i..i + pattern.len()] == pattern {
59 | return prices[i + pattern.len()] as u32;
60 | }
61 | }
62 | 0
63 | }
64 |
65 | pub fn solution() {
66 | // A.
67 | let file = File::open("./inputs/day22.txt").unwrap();
68 | let reader = BufReader::new(file);
69 | let mut inputs_part1 = Vec::new();
70 | for line in reader.lines() {
71 | let value: u32 = line.unwrap().trim().parse().unwrap();
72 | inputs_part1.push(value);
73 | }
74 |
75 | let mut total_sum_part1 = 0u64;
76 | for &initial_secret in &inputs_part1 {
77 | let val = generate_2000th_secret(initial_secret);
78 | total_sum_part1 += val as u64;
79 | }
80 |
81 | println!("Part 1 total sum: {}", total_sum_part1);
82 |
83 | // B.
84 | let mut all_prices = Vec::new();
85 | let mut all_changes = Vec::new();
86 | for &initial_secret in &inputs_part1 {
87 | let secrets = generate_secret_sequence(initial_secret);
88 | let prices = to_prices(&secrets);
89 | let changes = to_price_changes(&prices);
90 | all_prices.push(prices);
91 | all_changes.push(changes);
92 | }
93 |
94 | // Brute force all possible patterns.
95 | // The pattern is a 4-tuple of i8 values.
96 | // This is a brute force solution, but it's fast enough.
97 | let best_sum = iproduct!(-9..=9, -9..=9, -9..=9, -9..=9)
98 | .par_bridge()
99 | .into_par_iter()
100 | .map(|(a, b, c, d)| {
101 | let pattern = [a, b, c, d];
102 | all_changes
103 | .par_iter()
104 | .zip(all_prices.par_iter())
105 | .map(|(ch, pr)| first_occurrence_bananas(ch, pr, &pattern) as u64)
106 | .sum::()
107 | })
108 | .max()
109 | .unwrap_or(0);
110 |
111 | println!("Part 2 max bananas: {}", best_sum);
112 | }
113 |
--------------------------------------------------------------------------------
/src/day04.rs:
--------------------------------------------------------------------------------
1 | use ndarray::Array2;
2 | use std::fs::File;
3 | use std::io::BufRead;
4 |
5 | pub fn solution() {
6 | let aoc_2024_a =
7 | File::open("./inputs/day04.txt").expect("Something went wrong reading the file");
8 | let lines = std::io::BufReader::new(aoc_2024_a)
9 | .lines()
10 | .filter_map(|line| line.ok())
11 | .map(|line| line.chars().collect())
12 | .collect::>>();
13 |
14 | // A.
15 | let rows = lines.len();
16 | let cols = lines[0].len();
17 | let data = lines.into_iter().flatten().collect::>();
18 | let grid = Array2::from_shape_vec((rows, cols), data).unwrap();
19 |
20 | let target = "XMAS".chars().collect::>();
21 | let rows = grid.nrows() as i32;
22 | let cols = grid.ncols() as i32;
23 |
24 | let dxdy: [(i32, i32); 8] = [
25 | (0, 1),
26 | (0, -1),
27 | (1, 0),
28 | (-1, 0),
29 | (1, 1),
30 | (-1, -1),
31 | (1, -1),
32 | (-1, 1),
33 | ];
34 |
35 | let mut count = 0;
36 | for i in 0..rows {
37 | for j in 0..cols {
38 | for &(dx, dy) in &dxdy {
39 | let mut found = true;
40 | for k in 0..target.len() {
41 | let x = i + dx * k as i32;
42 | let y = j + dy * k as i32;
43 | if x < 0
44 | || y < 0
45 | || x >= rows
46 | || y >= cols
47 | || grid[[x as usize, y as usize]] != target[k]
48 | {
49 | found = false;
50 | break;
51 | }
52 | }
53 | if found {
54 | count += 1;
55 | }
56 | }
57 | }
58 | }
59 |
60 | println!("The number of XMAS is: {}", count);
61 |
62 | // B.
63 | let mas = ['M', 'A', 'S'];
64 | let sam = ['S', 'A', 'M'];
65 | let targets = [(&mas, &mas), (&mas, &sam), (&sam, &mas), (&sam, &sam)];
66 | let mut count = 0;
67 |
68 | for i in 0..rows {
69 | for j in 0..cols {
70 | if grid[[i as usize, j as usize]] == 'A' {
71 | let diag1 = [(i - 1, j - 1), (i, j), (i + 1, j + 1)];
72 | let diag2 = [(i - 1, j + 1), (i, j), (i + 1, j - 1)];
73 |
74 | let in_diag1 = diag1
75 | .iter()
76 | .all(|&(x, y)| x >= 0 && y >= 0 && x < rows && y < cols);
77 | let in_diag2 = diag2
78 | .iter()
79 | .all(|&(x, y)| x >= 0 && y >= 0 && x < rows && y < cols);
80 |
81 | if in_diag1 && in_diag2 {
82 | let x_in_diag1 = diag1
83 | .iter()
84 | .map(|&(x, y)| grid[[x as usize, y as usize]])
85 | .collect::>();
86 | let x_in_diag2 = diag2
87 | .iter()
88 | .map(|&(x, y)| grid[[x as usize, y as usize]])
89 | .collect::>();
90 |
91 | for &(diag1_word, diag2_word) in &targets {
92 | if x_in_diag1 == diag1_word && x_in_diag2 == diag2_word {
93 | count += 1;
94 | }
95 | }
96 | }
97 | }
98 | }
99 | }
100 |
101 | println!("The number of MAS is: {}", count);
102 | }
103 |
--------------------------------------------------------------------------------
/src/day08.rs:
--------------------------------------------------------------------------------
1 | use ndarray::Array2;
2 | use std::collections::HashMap;
3 | use std::fs::File;
4 | use std::io::BufRead;
5 |
6 | pub fn solution() {
7 | let aoc_2024_08 =
8 | File::open("./inputs/day08.txt").expect("Something went wrong reading the file");
9 | let lines = std::io::BufReader::new(aoc_2024_08)
10 | .lines()
11 | .filter_map(|line| line.ok())
12 | .map(|line| line.chars().collect())
13 | .collect::>>();
14 |
15 | let rows = lines.len();
16 | let cols = lines[0].len();
17 | let data = lines.into_iter().flatten().collect::>();
18 |
19 | let grid = Array2::from_shape_vec((rows, cols), data).unwrap();
20 | let mut positions_by_key: HashMap> = HashMap::new();
21 | let rows = grid.nrows() as i32;
22 | let cols = grid.ncols() as i32;
23 |
24 | let mut sum = 0;
25 | for i in 0..rows {
26 | for j in 0..cols {
27 | let key = grid[[i as usize, j as usize]];
28 | if grid[[i as usize, j as usize]] != '.' {
29 | positions_by_key
30 | .entry(key)
31 | .and_modify(|vec| vec.push((i, j)))
32 | .or_insert_with(|| vec![(i, j)]);
33 | }
34 | }
35 | }
36 |
37 | // A.
38 | let mut grid_a = grid.clone();
39 | for entry in &positions_by_key {
40 | let values = entry.1;
41 |
42 | for i in 0..values.len() {
43 | let first = values.get(i).unwrap();
44 | for j in 0..values.len() {
45 | if i == j {
46 | continue;
47 | }
48 | let second = values.get(j).unwrap();
49 |
50 | let x_diff = second.0 - first.0;
51 | let y_diff = second.1 - first.1;
52 | let new_x = second.0 + x_diff;
53 | let new_y = second.1 + y_diff;
54 |
55 | if new_x < rows && new_y < cols && new_x >= 0 && new_y >= 0 {
56 | let cell = grid_a[(new_x as usize, new_y as usize)];
57 | if cell != '#' {
58 | sum += 1;
59 | grid_a[(new_x as usize, new_y as usize)] = '#';
60 | }
61 | }
62 | }
63 | }
64 | }
65 | println!("Result: {}", sum);
66 |
67 | // B
68 | let mut grid_b = grid.clone();
69 | for entry in &positions_by_key {
70 | let values = entry.1;
71 |
72 | for i in 0..values.len() {
73 | let first = values.get(i).unwrap();
74 | for j in 0..values.len() {
75 | if i == j {
76 | continue;
77 | }
78 | let second = values.get(j).unwrap();
79 |
80 | let x_diff = second.0 - first.0;
81 | let y_diff = second.1 - first.1;
82 | let mut new_x = second.0 + x_diff;
83 | let mut new_y = second.1 + y_diff;
84 |
85 | while (0..rows).contains(&new_x) && (0..cols).contains(&new_y) {
86 | let cell = grid_b[(new_x as usize, new_y as usize)];
87 | if cell != '#' {
88 | grid_b[(new_x as usize, new_y as usize)] = '#';
89 | }
90 | new_x = new_x + x_diff;
91 | new_y = new_y + y_diff;
92 | }
93 | }
94 | }
95 | }
96 |
97 | let mut sum = 0;
98 | for i in 0..rows {
99 | for j in 0..cols {
100 | if grid_b[[i as usize, j as usize]] != '.' {
101 | sum += 1;
102 | }
103 | }
104 | }
105 | println!("Result: {}", sum)
106 | }
107 |
--------------------------------------------------------------------------------
/src/day06.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashSet;
2 | use std::fs;
3 |
4 | pub fn solution() {
5 | let input = fs::read_to_string("./inputs/day06.txt").expect("Failed to read input file");
6 | let mut map = input
7 | .lines()
8 | .map(|line| line.chars().collect())
9 | .collect::>>();
10 |
11 | // A.
12 | let mut p = (0, 0);
13 | let mut d = (0, -1);
14 | let dirs = [(0, -1), (1, 0), (0, 1), (-1, 0)];
15 |
16 | for (y, row) in map.iter_mut().enumerate() {
17 | for (x, &cell) in row.iter().enumerate() {
18 | if cell == '^' {
19 | p = (x, y);
20 | row[x] = '.';
21 | break;
22 | }
23 | }
24 | }
25 |
26 | let mut visited = HashSet::<(usize, usize)>::new();
27 | visited.insert(p);
28 |
29 | loop {
30 | let (x, y) = p;
31 | let (dx, dy) = d;
32 | let next_position = ((x as isize + dx) as usize, (y as isize + dy) as usize);
33 |
34 | if next_position.1 >= map.len() || next_position.0 >= map[0].len() {
35 | break;
36 | }
37 |
38 | match map[next_position.1][next_position.0] {
39 | '#' => {
40 | d = dirs[(dirs.iter().position(|&_d| _d == d).unwrap() + 1) % dirs.len()];
41 | }
42 | '.' => {
43 | p = next_position;
44 | visited.insert(p);
45 | }
46 | _ => {
47 | break;
48 | }
49 | }
50 | }
51 |
52 | println!("Result part A: {}", visited.len());
53 |
54 | // B.
55 | let input = fs::read_to_string("./inputs/day06.txt").expect("Failed to read input file");
56 | let mut map = input
57 | .lines()
58 | .map(|line| line.chars().collect())
59 | .collect::>>();
60 |
61 | let mut looping_positions = HashSet::<(usize, usize)>::new();
62 | let mut p = (0, 0);
63 | let d = (0, -1);
64 |
65 | for (y, row) in map.iter_mut().enumerate() {
66 | for (x, &cell) in row.iter().enumerate() {
67 | if cell == '^' {
68 | p = (x, y);
69 | row[x] = '.';
70 | break;
71 | }
72 | }
73 | }
74 |
75 | for y in 0..map.len() {
76 | for x in 0..map[0].len() {
77 | if map[y][x] == '.' && (x, y) != p {
78 | map[y][x] = '#';
79 |
80 | if simulate_guard(&mut map, p, d, &dirs).is_some() {
81 | looping_positions.insert((x, y));
82 | }
83 |
84 | map[y][x] = '.';
85 | }
86 | }
87 | }
88 |
89 | println!("Part B Result: {}", looping_positions.len());
90 | }
91 |
92 | fn simulate_guard(
93 | map: &Vec>,
94 | start_pos: (usize, usize),
95 | start_dir: (isize, isize),
96 | dirs: &[(isize, isize)],
97 | ) -> Option> {
98 | let mut visited = HashSet::<(usize, usize)>::new();
99 | let mut states = HashSet::<((usize, usize), (isize, isize))>::new();
100 | let mut p = start_pos;
101 | let mut d = start_dir;
102 |
103 | loop {
104 | let (x, y) = p;
105 | let (dx, dy) = d;
106 | let next = ((x as isize + dx) as usize, (y as isize + dy) as usize);
107 |
108 | if next.1 >= map.len() || next.0 >= map[0].len() {
109 | return None;
110 | }
111 |
112 | match map[next.1][next.0] {
113 | '#' => {
114 | d = dirs[(dirs.iter().position(|&_d| _d == d).unwrap() + 1) % dirs.len()];
115 | }
116 | '.' => {
117 | p = next;
118 | if !states.insert((p, d)) {
119 | return Some(visited);
120 | }
121 | visited.insert(p);
122 | }
123 | _ => {
124 | return None;
125 | }
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/src/day11.rs:
--------------------------------------------------------------------------------
1 | use ahash::AHashMap;
2 | use rayon::prelude::*;
3 |
4 | pub fn solution() {
5 | let input = std::fs::read_to_string("./inputs/day11.txt").expect("Failed to read input file");
6 |
7 | let parse = |input: &str| {
8 | input
9 | .split_whitespace()
10 | .filter_map(|x| x.parse::().ok())
11 | .fold(AHashMap::new(), |mut acc, x| {
12 | *acc.entry(x).or_insert(0) += 1;
13 | acc
14 | })
15 | };
16 |
17 | let run = |stones: &mut AHashMap, iter: &mut i32| {
18 | while *iter > 0 {
19 | let mut next_stones = AHashMap::new();
20 |
21 | for (stone, count) in stones.iter() {
22 | if *stone == 0 {
23 | *next_stones.entry(1).or_insert(0) += count;
24 | } else if stone.to_string().len() % 2 == 0 {
25 | let stone_str = stone.to_string();
26 | let mid = stone_str.len() / 2;
27 | let left = stone_str[..mid].parse::().unwrap();
28 | let right = stone_str[mid..].parse::().unwrap();
29 | *next_stones.entry(left).or_insert(0) += count;
30 | *next_stones.entry(right).or_insert(0) += count;
31 | } else {
32 | let new_stone = stone * 2024;
33 | *next_stones.entry(new_stone).or_insert(0) += count;
34 | }
35 | }
36 |
37 | *stones = next_stones;
38 | *iter -= 1;
39 | }
40 |
41 | println!("Result : {}", stones.values().sum::());
42 | };
43 |
44 | // A.
45 | let mut stones = parse(&input);
46 | let mut iterations = 25;
47 | run(&mut stones, &mut iterations);
48 |
49 | // B.
50 | iterations = 75;
51 | let mut stones = parse(&input);
52 | run(&mut stones, &mut iterations);
53 | }
54 |
55 | pub fn solution_par() {
56 | let input = std::fs::read_to_string("./inputs/day11.txt").expect("Failed to read input file");
57 | let parse = |input: &str| {
58 | input
59 | .split_whitespace()
60 | .filter_map(|x| x.parse::().ok())
61 | .fold(AHashMap::new(), |mut acc, x| {
62 | *acc.entry(x).or_insert(0) += 1;
63 | acc
64 | })
65 | };
66 |
67 | let run = |stones: &mut AHashMap, iter: &mut i32| {
68 | while *iter > 0 {
69 | let next_stones = stones
70 | .par_iter()
71 | .flat_map(|(&stone, &count)| {
72 | if stone == 0 {
73 | vec![(1, count)]
74 | } else if stone.to_string().len() % 2 == 0 {
75 | let stone_str = stone.to_string();
76 | let mid = stone_str.len() / 2;
77 | let left = stone_str[..mid].parse::().unwrap();
78 | let right = stone_str[mid..].parse::().unwrap();
79 | vec![(left, count), (right, count)]
80 | } else {
81 | let new_stone = stone * 2024;
82 | vec![(new_stone, count)]
83 | }
84 | })
85 | .fold(AHashMap::new, |mut acc, (stone, count)| {
86 | *acc.entry(stone).or_insert(0) += count;
87 | acc
88 | })
89 | .reduce_with(|mut acc, map| {
90 | for (stone, count) in map {
91 | *acc.entry(stone).or_insert(0) += count;
92 | }
93 | acc
94 | })
95 | .unwrap_or_default();
96 |
97 | *stones = next_stones;
98 | *iter -= 1;
99 | }
100 |
101 | println!("Result: {}", stones.values().sum::());
102 | };
103 |
104 | // A.
105 | let mut stones = parse(&input);
106 | let mut iterations = 25;
107 | run(&mut stones, &mut iterations);
108 |
109 | // B.
110 | iterations = 75;
111 | let mut stones = parse(&input);
112 | run(&mut stones, &mut iterations);
113 | }
114 |
--------------------------------------------------------------------------------
/src/day05.rs:
--------------------------------------------------------------------------------
1 | use std::fs;
2 |
3 | use petgraph::{
4 | graph::{DiGraph, NodeIndex},
5 | visit::IntoNodeReferences,
6 | Direction,
7 | };
8 |
9 | pub fn solution() {
10 | let aoc_2024_04 =
11 | fs::read_to_string("./inputs/day05.txt").expect("Something went wrong reading the file");
12 |
13 | let mut parts = aoc_2024_04.split("\n\n");
14 | let page_ordering_rules_text = parts.next().unwrap();
15 | let page_ordering_rules: Vec<(i8, i8)> = page_ordering_rules_text
16 | .lines()
17 | .map(|line| {
18 | let mut numbers = line.split('|').map(|n| n.parse::().unwrap());
19 | (numbers.next().unwrap(), numbers.next().unwrap())
20 | })
21 | .collect();
22 |
23 | let pages_to_reproduce_text = parts.next().unwrap();
24 | let pages_to_reproduce: Vec> = pages_to_reproduce_text
25 | .lines()
26 | .map(|line| line.split(',').map(|n| n.parse::().unwrap()).collect())
27 | .collect();
28 |
29 | // A.
30 | let sum: i32 = pages_to_reproduce
31 | .iter()
32 | .filter(|page| {
33 | page_ordering_rules.iter().all(|&(left_rule, right_rule)| {
34 | let left_index = page.iter().position(|&r| r == left_rule);
35 | let right_index = page.iter().position(|&r| r == right_rule);
36 |
37 | match (left_index, right_index) {
38 | (Some(left), Some(right)) => left <= right,
39 | _ => true,
40 | }
41 | })
42 | })
43 | .map(|page| *(page.get(page.len() / 2).unwrap()) as i32)
44 | .sum();
45 | println!("Result: {}", sum);
46 |
47 | // B.
48 | let mut sum: i32 = 0;
49 | let mut failed_rows = Vec::new();
50 | for page in &pages_to_reproduce {
51 | for rule in &page_ordering_rules {
52 | let left_index = page.iter().position(|&r| r == rule.0);
53 | let right_index = page.iter().position(|&r| r == rule.1);
54 |
55 | if left_index.is_some() && right_index.is_some() {
56 | if left_index.unwrap() > right_index.unwrap() {
57 | failed_rows.push(page);
58 | break;
59 | }
60 | }
61 | }
62 | }
63 | for failed_row in failed_rows {
64 | let mut graph = DiGraph::<&i8, ()>::new();
65 | for number in failed_row {
66 | graph.add_node(number);
67 | }
68 | for first in failed_row {
69 | for second in failed_row {
70 | let rule = page_ordering_rules
71 | .iter()
72 | .position(|&r| r.0 == *first && r.1 == *second);
73 | if rule.is_some() {
74 | let first_node = find_node_by_value(&graph, first);
75 | let second_node = find_node_by_value(&graph, second);
76 | graph.add_edge(first_node.unwrap(), second_node.unwrap(), ());
77 | }
78 | }
79 | }
80 | let mut no_inbound = Vec::new();
81 | for node in graph.node_indices() {
82 | if graph
83 | .neighbors_directed(node, Direction::Incoming)
84 | .next()
85 | .is_none()
86 | {
87 | no_inbound.push(node);
88 | }
89 | }
90 |
91 | let mut nodes: Vec<(NodeIndex, usize, usize)> = graph
92 | .node_indices()
93 | .map(|node| {
94 | let incoming_count = graph
95 | .neighbors_directed(node, Direction::Incoming)
96 | .count();
97 | let outgoing_count = graph
98 | .neighbors_directed(node, Direction::Outgoing)
99 | .count();
100 | (node, incoming_count, outgoing_count)
101 | })
102 | .collect();
103 |
104 | nodes.sort_by_key(|&(_, incoming_count, outgoing_count)| (incoming_count, outgoing_count));
105 |
106 |
107 | let middle_index = nodes.len() / 2;
108 | let middle_node = nodes[middle_index].0;
109 | let middle_value = graph[middle_node];
110 | sum = sum + *middle_value as i32;
111 | }
112 | println!("Result: {}", sum);
113 | }
114 |
115 | fn find_node_by_value(graph: &DiGraph<&i8, ()>, value: &i8) -> Option {
116 | for (node_index, node_value) in graph.node_references() {
117 | if *node_value == value {
118 | return Some(node_index);
119 | }
120 | }
121 | None
122 | }
123 |
--------------------------------------------------------------------------------
/src/day14.rs:
--------------------------------------------------------------------------------
1 | use regex::Regex;
2 | use std::array;
3 | use std::fs::File;
4 | use std::io::{BufRead, BufReader};
5 |
6 | #[derive(Debug, Clone, Copy)]
7 | struct Robot {
8 | x: i32,
9 | y: i32,
10 | velocity_x: i32,
11 | velocity_y: i32,
12 | }
13 |
14 | fn read_input(path: &str) -> std::io::Result> {
15 | let file = File::open(path)?;
16 | let reader = BufReader::new(file);
17 |
18 | let re = Regex::new(r"^p=(-?\d+),(-?\d+)\s+v=(-?\d+),(-?\d+)$").unwrap();
19 |
20 | let mut robots = Vec::new();
21 | let mut lines = reader.lines().filter_map(|l| l.ok());
22 |
23 | while let Some(line) = lines.next() {
24 | if let Some(caps) = re.captures(&line) {
25 | let p1 = caps.get(1).unwrap().as_str();
26 | let p2 = caps.get(2).unwrap().as_str();
27 | let v1 = caps.get(3).unwrap().as_str();
28 | let v2 = caps.get(4).unwrap().as_str();
29 |
30 | robots.push(Robot {
31 | x: p1.parse::().unwrap(),
32 | y: p2.parse::().unwrap(),
33 | velocity_x: v1.parse::().unwrap(),
34 | velocity_y: v2.parse::().unwrap(),
35 | });
36 | } else {
37 | println!("No match found.");
38 | }
39 | }
40 |
41 | Ok(robots)
42 | }
43 |
44 | pub fn solution() {
45 | let robots = read_input("./inputs/day14.txt").unwrap();
46 |
47 | const WIDE: usize = 101;
48 | const TALL: usize = 103;
49 |
50 | // A
51 | const SECONDS: i32 = 100;
52 | let middle_x = (WIDE as i32) / 2;
53 | let middle_y = (TALL as i32) / 2;
54 | let mut robots_a = robots.clone();
55 | let mut quadrant_counts = [0; 4];
56 | for robot in &mut robots_a {
57 | robot.x = (robot.x + SECONDS * robot.velocity_x) % (WIDE as i32);
58 | robot.y = (robot.y + SECONDS * robot.velocity_y) % (TALL as i32);
59 |
60 | if robot.x < 0 {
61 | robot.x += WIDE as i32;
62 | }
63 | if robot.y < 0 {
64 | robot.y += TALL as i32;
65 | }
66 | if robot.x != middle_x && robot.y != middle_y {
67 | if robot.x > middle_x && robot.y < middle_y {
68 | quadrant_counts[0] += 1;
69 | } else if robot.x < middle_x && robot.y < middle_y {
70 | quadrant_counts[1] += 1;
71 | } else if robot.x < middle_x && robot.y > middle_y {
72 | quadrant_counts[2] += 1;
73 | } else if robot.x > middle_x && robot.y > middle_y {
74 | quadrant_counts[3] += 1;
75 | }
76 | }
77 |
78 | }
79 |
80 | let result = quadrant_counts[0] * quadrant_counts[1] * quadrant_counts[2] * quadrant_counts[3];
81 | println!("Result A: {}", result);
82 |
83 | // B
84 | for second in 0.. {
85 | let mut robots_b = robots.clone();
86 | let mut tiles: [[String; WIDE]; TALL] =
87 | array::from_fn(|_| array::from_fn(|_| String::from(".")));
88 | tiles
89 | .iter_mut()
90 | .for_each(|row| row.iter_mut().for_each(|tile| *tile = String::from(".")));
91 |
92 | for robot in &mut robots_b {
93 | robot.x = (robot.x + second * robot.velocity_x) % (WIDE as i32);
94 | robot.y = (robot.y + second * robot.velocity_y) % (TALL as i32);
95 |
96 | if robot.x < 0 {
97 | robot.x += WIDE as i32;
98 | }
99 | if robot.y < 0 {
100 | robot.y += TALL as i32;
101 | }
102 |
103 | tiles[robot.y as usize][robot.x as usize] = "#".to_string();
104 | }
105 |
106 | let mut expected_longest = 1;
107 | let mut increase_count = 0;
108 |
109 | for (_, row) in tiles.iter().enumerate() {
110 | let mut current_longest = 0;
111 | let mut count = 0;
112 |
113 | for tile in row {
114 | if tile == "#" {
115 | count += 1;
116 | if count > current_longest {
117 | current_longest = count;
118 | }
119 | } else {
120 | count = 0;
121 | }
122 | }
123 |
124 | if current_longest == expected_longest {
125 | increase_count += 1;
126 | expected_longest += 2; // should be symmetric
127 | }
128 |
129 | }
130 | if increase_count > 5 {
131 | println!("Result B: {}", second);
132 | break;
133 | }
134 |
135 | }
136 |
137 | }
138 |
--------------------------------------------------------------------------------
/src/day24.rs:
--------------------------------------------------------------------------------
1 | use std::collections::{HashMap, HashSet};
2 | use std::fs;
3 |
4 | pub fn solution() {
5 | let input = fs::read_to_string("./inputs/day24.txt").unwrap();
6 | let lines: Vec<&str> = input
7 | .lines()
8 | .map(str::trim)
9 | .filter(|l| !l.is_empty())
10 | .collect();
11 | let mut init = HashMap::new();
12 | let mut gs = Vec::new();
13 |
14 | // A.
15 | let mut parsing_init = true;
16 | for l in &lines {
17 | if parsing_init {
18 | if let Some((w, v)) = l.split_once(':') {
19 | let v = v.trim();
20 | if v == "0" || v == "1" {
21 | init.insert(w.trim().to_string(), v == "1");
22 | } else {
23 | parsing_init = false;
24 | }
25 | } else {
26 | parsing_init = false;
27 | }
28 | }
29 | if !parsing_init {
30 | let parts: Vec<_> = l.split("->").collect();
31 | if parts.len() != 2 {
32 | continue;
33 | }
34 | let s: Vec<_> = parts[0].split_whitespace().collect();
35 | if s.len() != 3 {
36 | continue;
37 | }
38 | let g = match s[1].to_uppercase().as_str() {
39 | "AND" => 'A',
40 | "OR" => 'O',
41 | "XOR" => 'X',
42 | _ => continue,
43 | };
44 | gs.push((
45 | s[0].to_string(),
46 | s[2].to_string(),
47 | parts[1].trim().to_string(),
48 | g,
49 | ));
50 | }
51 | }
52 | let mut wires = HashMap::new();
53 | for (k, &v) in &init {
54 | wires.insert(k.clone(), Some(v));
55 | }
56 | for (a, b, o, _) in &gs {
57 | wires.entry(a.clone()).or_insert(None);
58 | wires.entry(b.clone()).or_insert(None);
59 | wires.entry(o.clone()).or_insert(None);
60 | }
61 | let mut change = true;
62 | while change {
63 | change = false;
64 | for (a, b, o, g) in &gs {
65 | if let (Some(a_val), Some(b_val)) = (wires[a], wires[b]) {
66 | let r = match g {
67 | 'A' => a_val && b_val,
68 | 'O' => a_val || b_val,
69 | 'X' => a_val ^ b_val,
70 | _ => false,
71 | };
72 | if wires[o] != Some(r) {
73 | wires.insert(o.clone(), Some(r));
74 | change = true;
75 | }
76 | }
77 | }
78 | }
79 | let mut zs: Vec<_> = wires.keys().filter(|x| x.starts_with('z')).collect();
80 | zs.sort_by_key(|x| x[1..].parse::().unwrap_or(0));
81 | let dec = zs.iter().enumerate().fold(0u64, |acc, (i, k)| {
82 | acc | ((wires[*k] == Some(true)) as u64) << i
83 | });
84 | println!("Part A: {}", dec);
85 |
86 | // B.
87 | let connections = input.split_once("\n\n").map(|(_, c)| c).unwrap();
88 | let parsed: Vec<(String, char, String, String)> = connections
89 | .lines()
90 | .filter_map(|line| {
91 | let tokens: Vec<_> = line.split_whitespace().collect();
92 | if tokens.len() >= 5 && tokens[3] == "->" {
93 | let op = match tokens[1].to_uppercase().as_str() {
94 | "AND" => 'A',
95 | "OR" => 'O',
96 | "XOR" => 'X',
97 | _ => return None,
98 | };
99 | Some((
100 | tokens[0].to_string(),
101 | op,
102 | tokens[2].to_string(),
103 | tokens[4].to_string(),
104 | ))
105 | } else {
106 | None
107 | }
108 | })
109 | .collect();
110 | let connection_cache: HashSet<_> = parsed
111 | .iter()
112 | .flat_map(|(l, op, r, _)| [(l.clone(), *op), (r.clone(), *op)])
113 | .collect();
114 | let mut results: Vec = parsed
115 | .iter()
116 | .filter_map(|(l, op, r, ret)| match *op {
117 | 'A' if l != "x00" && r != "x00" && !connection_cache.contains(&(ret.clone(), 'O')) => {
118 | Some(ret.clone())
119 | }
120 | 'X' if ((l.starts_with('x') || r.starts_with('x'))
121 | && l != "x00"
122 | && r != "x00"
123 | && !connection_cache.contains(&(ret.clone(), 'X')))
124 | || (!ret.starts_with('z') && !l.starts_with('x') && !r.starts_with('x')) =>
125 | {
126 | Some(ret.clone())
127 | }
128 | 'O' if ret.starts_with('z') && ret != "z45" => Some(ret.clone()),
129 | _ => None,
130 | })
131 | .collect();
132 | results.sort();
133 | println!("Part B: {}", results.join(","));
134 | }
135 |
--------------------------------------------------------------------------------
/src/day12.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashSet;
2 | use std::fs::File;
3 | use std::io::{self, BufRead};
4 |
5 | use petgraph::adj::NodeIndex;
6 | use petgraph::algo;
7 | use petgraph::prelude::UnGraphMap;
8 | use petgraph::visit::IntoNodeReferences;
9 |
10 | pub fn solution() {
11 | let aoc_2024_12 = File::open("./inputs/day12.txt").expect("Failed to open file");
12 | let grid: Vec> = io::BufReader::new(aoc_2024_12)
13 | .lines()
14 | .filter_map(|line| line.ok())
15 | .map(|line| line.chars().collect())
16 | .collect();
17 |
18 | let rows = grid.len() as i32;
19 | let cols = grid[0].len() as i32;
20 |
21 | let mut visited = HashSet::new();
22 | let directions = [(0, 1), (1, 0), (0, -1), (-1, 0)];
23 |
24 | let mut total_sum = 0;
25 |
26 | for r in 0..rows {
27 | for c in 0..cols {
28 | if visited.contains(&(r, c)) {
29 | continue;
30 | }
31 |
32 | let mut queue = vec![(r, c)];
33 | visited.insert((r, c));
34 |
35 | let mut group_size = 0;
36 | let mut perimeter = 0;
37 |
38 | while let Some((x, y)) = queue.pop() {
39 | let value = grid[x as usize][y as usize];
40 | let mut local_perimeter = 4;
41 | group_size += 1;
42 |
43 | for &(dx, dy) in &directions {
44 | let nx = x + dx;
45 | let ny = y + dy;
46 |
47 | if nx >= 0 && nx < rows && ny >= 0 && ny < cols {
48 | if grid[nx as usize][ny as usize] == value {
49 | if visited.insert((nx, ny)) {
50 | queue.push((nx, ny));
51 | }
52 | local_perimeter -= 1;
53 | }
54 | }
55 | }
56 | perimeter += local_perimeter;
57 | }
58 | total_sum += group_size * perimeter;
59 | }
60 | }
61 | println!("Result: {}", total_sum);
62 |
63 | // B.
64 | let mut graph = UnGraphMap::<(i32, i32), ()>::new();
65 |
66 | for y in 0..rows {
67 | for x in 0..cols {
68 | // Add node to the graph
69 | let node = graph.add_node((x, y));
70 | let c = grid[y as usize][x as usize];
71 |
72 | // Add edges to the graph
73 | for &(dx, dy) in &directions {
74 | let nx = x + dx;
75 | let ny = y + dy;
76 |
77 | // Check if the node is within the grid
78 | if nx >= 0 && nx < cols && ny >= 0 && ny < rows {
79 | if grid[ny as usize][nx as usize] == c {
80 | graph.add_edge(node, (nx, ny), ());
81 | }
82 | }
83 | }
84 | }
85 | }
86 |
87 | let graph = algo::condensation(graph.into_graph::(), false);
88 | let sum = graph.node_references().map(|(_, nodes)| {
89 | let id = grid[nodes[0].1 as usize][nodes[0].0 as usize];
90 | let node_size = nodes.len();
91 | let perimeter = nodes
92 | .iter()
93 | .map(|n| {
94 | let mut count = 0;
95 |
96 | for i in 0..4 {
97 | let (dx, dy) = directions[i];
98 | let (dx1, dy1) = directions[(i + 1) % 4];
99 |
100 | let first_neighbor_same_region = {
101 | let nx = n.0 + dx;
102 | let ny = n.1 + dy;
103 | nx >= 0
104 | && ny >= 0
105 | && (ny as usize) < grid.len()
106 | && (nx as usize) < grid[ny as usize].len()
107 | && grid[ny as usize][nx as usize] == id
108 | };
109 |
110 | let second_neighbor_same_region = {
111 | let nx = n.0 + dx1;
112 | let ny = n.1 + dy1;
113 | nx >= 0
114 | && ny >= 0
115 | && (ny as usize) < grid.len()
116 | && (nx as usize) < grid[ny as usize].len()
117 | && grid[ny as usize][nx as usize] == id
118 | };
119 |
120 | let diagonal_test = {
121 | let nx = n.0 + dx + dx1;
122 | let ny = n.1 + dy + dy1;
123 | nx >= 0
124 | && ny >= 0
125 | && (ny as usize) < grid.len()
126 | && (nx as usize) < grid[ny as usize].len()
127 | && grid[ny as usize][nx as usize] != id
128 | };
129 |
130 | if first_neighbor_same_region && second_neighbor_same_region && diagonal_test {
131 | count += 1;
132 | } else if !first_neighbor_same_region && !second_neighbor_same_region {
133 | count += 1;
134 | }
135 | }
136 |
137 | count
138 | })
139 | .sum::();
140 |
141 | node_size * perimeter
142 | });
143 |
144 | println!("Result: {}", sum.sum::());
145 | }
146 |
--------------------------------------------------------------------------------
/src/day16.rs:
--------------------------------------------------------------------------------
1 | use pathfinding::prelude::dijkstra_all;
2 | use std::{collections::HashMap, fs, path::Path};
3 |
4 | #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
5 | struct State {
6 | row: usize,
7 | col: usize,
8 | dir: usize,
9 | }
10 |
11 | pub fn solution() {
12 | let input = fs::read_to_string(Path::new("./inputs/day16.txt")).unwrap();
13 | let maze = input.lines().collect::>();
14 | let rows = maze.len();
15 | let cols = if rows > 0 { maze[0].len() } else { 0 };
16 | let maze_grid = maze
17 | .iter()
18 | .map(|line| line.chars().collect())
19 | .collect::>>();
20 |
21 | // A.
22 | let (mut start_row, mut start_col) = (0, 0);
23 | let (mut end_row, mut end_col) = (0, 0);
24 | for r in 0..rows {
25 | for c in 0..cols {
26 | match maze_grid[r][c] {
27 | 'S' => {
28 | start_row = r;
29 | start_col = c;
30 | }
31 | 'E' => {
32 | end_row = r;
33 | end_col = c;
34 | }
35 | _ => {}
36 | }
37 | }
38 | }
39 |
40 | let forward_successors = |&State { row, col, dir }: &State| -> Vec<(State, u64)> {
41 | let mut next = Vec::with_capacity(3);
42 |
43 | next.push((
44 | State {
45 | row,
46 | col,
47 | dir: (dir + 3) % 4,
48 | },
49 | 1000,
50 | ));
51 |
52 | next.push((
53 | State {
54 | row,
55 | col,
56 | dir: (dir + 1) % 4,
57 | },
58 | 1000,
59 | ));
60 |
61 | let (dr, dc) = match dir {
62 | 0 => (0, 1),
63 | 1 => (1, 0),
64 | 2 => (0, -1),
65 | 3 => (-1, 0),
66 | _ => unreachable!(),
67 | };
68 |
69 | let nr = row as isize + dr;
70 | let nc = col as isize + dc;
71 | if nr >= 0 && nr < rows as isize && nc >= 0 && nc < cols as isize {
72 | if maze_grid[nr as usize][nc as usize] != '#' {
73 | next.push((
74 | State {
75 | row: nr as usize,
76 | col: nc as usize,
77 | dir,
78 | },
79 | 1,
80 | ));
81 | }
82 | }
83 | next
84 | };
85 |
86 | let start_state = State {
87 | row: start_row,
88 | col: start_col,
89 | dir: 0,
90 | };
91 |
92 | let dist_s_map = dijkstra_all(&start_state, forward_successors);
93 | let mut best_score = u64::MAX;
94 |
95 | for d in 0..4 {
96 | let e_state = State {
97 | row: end_row,
98 | col: end_col,
99 | dir: d,
100 | };
101 | if let Some((_, cost)) = dist_s_map.get(&e_state) {
102 | best_score = best_score.min(*cost);
103 | }
104 | }
105 |
106 | println!("Result: {}", best_score);
107 |
108 | // B.
109 | let reverse_successors = |&State { row, col, dir }: &State| -> Vec<(State, u64)> {
110 | let mut neighbors = Vec::with_capacity(3);
111 |
112 | neighbors.push((
113 | State {
114 | row,
115 | col,
116 | dir: (dir + 1) % 4,
117 | },
118 | 1000,
119 | ));
120 |
121 | neighbors.push((
122 | State {
123 | row,
124 | col,
125 | dir: (dir + 3) % 4,
126 | },
127 | 1000,
128 | ));
129 |
130 | let (dr, dc) = match dir {
131 | 0 => (0, -1),
132 | 1 => (-1, 0),
133 | 2 => (0, 1),
134 | 3 => (1, 0),
135 | _ => unreachable!(),
136 | };
137 |
138 | let rr = row as isize + dr;
139 | let cc = col as isize + dc;
140 |
141 | if rr >= 0 && rr < rows as isize && cc >= 0 && cc < cols as isize {
142 | if maze_grid[rr as usize][cc as usize] != '#' {
143 | neighbors.push((
144 | State {
145 | row: rr as usize,
146 | col: cc as usize,
147 | dir,
148 | },
149 | 1,
150 | ));
151 | }
152 | }
153 | neighbors
154 | };
155 |
156 | let mut dist_e_map = HashMap::::new();
157 | for d in 0..4 {
158 | let e_state = State {
159 | row: end_row,
160 | col: end_col,
161 | dir: d,
162 | };
163 | let partial_map = dijkstra_all(&e_state, reverse_successors);
164 |
165 | for (st, (_, cost)) in partial_map {
166 | dist_e_map
167 | .entry(st)
168 | .and_modify(|existing| {
169 | if cost < existing.1 {
170 | existing.1 = cost;
171 | }
172 | })
173 | .or_insert((e_state, cost));
174 | }
175 | }
176 |
177 | let mut on_best_path = vec![vec![false; cols]; rows];
178 | for (&st, &(_, cost_s)) in &dist_s_map {
179 | if let Some((_, cost_e)) = dist_e_map.get(&st) {
180 | if cost_s + cost_e == best_score {
181 | on_best_path[st.row][st.col] = true;
182 | }
183 | }
184 | }
185 |
186 | on_best_path[start_row][start_col] = true;
187 | on_best_path[end_row][end_col] = true;
188 |
189 | let count = on_best_path
190 | .iter()
191 | .flat_map(|row| row.iter())
192 | .filter(|&&b| b)
193 | .count();
194 |
195 | println!("Result: {}", count);
196 | }
197 |
--------------------------------------------------------------------------------
/src/day20.rs:
--------------------------------------------------------------------------------
1 | use std::{
2 | collections::{HashMap, VecDeque},
3 | fs,
4 | io::{self, BufRead},
5 | };
6 |
7 | #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
8 | struct Pos {
9 | r: usize,
10 | c: usize,
11 | }
12 |
13 | pub fn solution() {
14 | let file = fs::File::open("./inputs/day20.txt").expect("Failed to open file");
15 | let reader = io::BufReader::new(file);
16 |
17 | let map: Vec = reader
18 | .lines()
19 | .map(|line| line.expect("Could not parse line"))
20 | .collect();
21 |
22 | let mut start = Pos { r: 0, c: 0 };
23 | let mut end = Pos { r: 0, c: 0 };
24 | let rows = map.len();
25 | let cols = map[0].len();
26 |
27 | for r in 0..rows {
28 | for c in 0..cols {
29 | let ch = map[r].chars().nth(c).unwrap();
30 | if ch == 'S' {
31 | start = Pos { r, c };
32 | } else if ch == 'E' {
33 | end = Pos { r, c };
34 | }
35 | }
36 | }
37 |
38 | let dist_from_start = bfs_no_cheat_from(&map, start);
39 | let dist_from_end = bfs_no_cheat_from(&map, end);
40 | let dist_no_cheat = *dist_from_start.get(&end).unwrap();
41 |
42 | let count_2 = count_cheats_saving_100(
43 | &map,
44 | &dist_from_start,
45 | &dist_from_end,
46 | dist_no_cheat,
47 | 2
48 | );
49 | println!("Result A: {}", count_2);
50 |
51 | let count_20 = count_cheats_saving_100(
52 | &map,
53 | &dist_from_start,
54 | &dist_from_end,
55 | dist_no_cheat,
56 | 20
57 | );
58 | println!("Result B: {}", count_20);
59 | }
60 |
61 | fn bfs_no_cheat_from(map: &[String], start: Pos) -> HashMap {
62 | let rows = map.len();
63 | let cols = map[0].len();
64 |
65 | let mut dist_map = HashMap::::new();
66 | let mut visited = vec![vec![false; cols]; rows];
67 |
68 | visited[start.r][start.c] = true;
69 | dist_map.insert(start, 0);
70 |
71 | let mut queue = VecDeque::new();
72 | queue.push_back(start);
73 |
74 | let directions = [(1,0), (-1,0), (0,1), (0,-1)];
75 |
76 | while let Some(cur) = queue.pop_front() {
77 | let current_dist = dist_map[&cur];
78 | for (dr, dc) in directions {
79 | let nr = cur.r as isize + dr;
80 | let nc = cur.c as isize + dc;
81 | if nr < 0 || nc < 0 {
82 | continue;
83 | }
84 | let nr = nr as usize;
85 | let nc = nc as usize;
86 | if nr < rows && nc < cols && !visited[nr][nc] {
87 | let ch = map[nr].chars().nth(nc).unwrap();
88 | if ch != '#' {
89 | visited[nr][nc] = true;
90 | let nxt = Pos { r: nr, c: nc };
91 | dist_map.insert(nxt, current_dist + 1);
92 | queue.push_back(nxt);
93 | }
94 | }
95 | }
96 | }
97 |
98 | dist_map
99 | }
100 |
101 | fn count_cheats_saving_100(
102 | map: &[String],
103 | dist_s: &HashMap,
104 | dist_e: &HashMap,
105 | dist_no_cheat: usize,
106 | max_steps: usize,
107 | ) -> usize {
108 | let mut cheat_best_dist = HashMap::<(Pos, Pos), usize>::new();
109 |
110 | let is_track = |r: usize, c: usize| {
111 | let ch = map[r].chars().nth(c).unwrap();
112 | ch != '#'
113 | };
114 |
115 | for (&x, &dist_sx) in dist_s.iter() {
116 | if !is_track(x.r, x.c) {
117 | continue;
118 | }
119 |
120 | let mut visited_steps = vec![vec![None; map[0].len()]; map.len()];
121 | visited_steps[x.r][x.c] = Some(0);
122 | let mut queue = VecDeque::new();
123 | queue.push_back(x);
124 |
125 | while let Some(cur) = queue.pop_front() {
126 | let steps_so_far = visited_steps[cur.r][cur.c].unwrap();
127 | if steps_so_far >= max_steps {
128 | continue;
129 | }
130 |
131 | for (dr, dc) in [(1, 0), (-1, 0), (0, 1), (0, -1)] {
132 | let nr = cur.r as isize + dr;
133 | let nc = cur.c as isize + dc;
134 | if nr < 0 || nc < 0 {
135 | continue;
136 | }
137 | let nr = nr as usize;
138 | let nc = nc as usize;
139 | if nr >= map.len() || nc >= map[0].len() {
140 | continue;
141 | }
142 | // ignoring walls => always can go
143 | if visited_steps[nr][nc].is_none() {
144 | visited_steps[nr][nc] = Some(steps_so_far + 1);
145 | queue.push_back(Pos { r: nr, c: nc });
146 | }
147 | }
148 | }
149 |
150 | // Evaluate each reachable y for 1 <= steps <= max_steps
151 | for r in 0..map.len() {
152 | for c in 0..map[0].len() {
153 | if let Some(steps) = visited_steps[r][c] {
154 | if steps >= 1 && steps <= max_steps && is_track(r, c) {
155 | let y = Pos { r, c };
156 | if let Some(&dist_ey) = dist_e.get(&y) {
157 | let candidate_dist = dist_sx + steps + dist_ey;
158 | let entry = cheat_best_dist.entry((x, y)).or_insert(candidate_dist);
159 | if candidate_dist < *entry {
160 | *entry = candidate_dist;
161 | }
162 | }
163 | }
164 | }
165 | }
166 | }
167 | }
168 |
169 | let mut count_ge_100 = 0;
170 | for &cheat_dist in cheat_best_dist.values() {
171 | let saving = dist_no_cheat.saturating_sub(cheat_dist);
172 | if saving >= 100 {
173 | count_ge_100 += 1;
174 | }
175 | }
176 | count_ge_100
177 | }
178 |
--------------------------------------------------------------------------------
/inputs/day24.txt:
--------------------------------------------------------------------------------
1 | x00: 1
2 | x01: 0
3 | x02: 1
4 | x03: 1
5 | x04: 0
6 | x05: 0
7 | x06: 1
8 | x07: 1
9 | x08: 0
10 | x09: 1
11 | x10: 1
12 | x11: 1
13 | x12: 1
14 | x13: 1
15 | x14: 1
16 | x15: 0
17 | x16: 0
18 | x17: 1
19 | x18: 0
20 | x19: 0
21 | x20: 0
22 | x21: 0
23 | x22: 0
24 | x23: 1
25 | x24: 0
26 | x25: 0
27 | x26: 1
28 | x27: 1
29 | x28: 0
30 | x29: 1
31 | x30: 1
32 | x31: 0
33 | x32: 0
34 | x33: 0
35 | x34: 0
36 | x35: 1
37 | x36: 0
38 | x37: 1
39 | x38: 1
40 | x39: 0
41 | x40: 1
42 | x41: 0
43 | x42: 1
44 | x43: 0
45 | x44: 1
46 | y00: 1
47 | y01: 0
48 | y02: 0
49 | y03: 1
50 | y04: 1
51 | y05: 0
52 | y06: 0
53 | y07: 0
54 | y08: 0
55 | y09: 0
56 | y10: 0
57 | y11: 1
58 | y12: 0
59 | y13: 0
60 | y14: 1
61 | y15: 1
62 | y16: 1
63 | y17: 0
64 | y18: 1
65 | y19: 0
66 | y20: 1
67 | y21: 0
68 | y22: 1
69 | y23: 0
70 | y24: 0
71 | y25: 0
72 | y26: 0
73 | y27: 1
74 | y28: 1
75 | y29: 0
76 | y30: 1
77 | y31: 1
78 | y32: 1
79 | y33: 1
80 | y34: 1
81 | y35: 0
82 | y36: 1
83 | y37: 1
84 | y38: 0
85 | y39: 0
86 | y40: 1
87 | y41: 1
88 | y42: 0
89 | y43: 1
90 | y44: 1
91 |
92 | y16 AND x16 -> bss
93 | wrt OR pss -> fjs
94 | qpd AND hnk -> tdb
95 | ncp AND drd -> ktn
96 | vnw AND ftq -> kgt
97 | y12 XOR x12 -> dbg
98 | y05 AND x05 -> jfq
99 | x16 XOR y16 -> grr
100 | y39 AND x39 -> tbr
101 | crp AND gkk -> qkk
102 | x02 AND y02 -> jrf
103 | x09 AND y09 -> nwn
104 | vmf AND bkp -> rjw
105 | qpd XOR hnk -> z34
106 | x06 XOR y06 -> kcc
107 | x30 AND y30 -> bgj
108 | rhk AND btv -> rmv
109 | fjs XOR bmv -> z44
110 | btv XOR rhk -> z25
111 | wgk OR ppp -> vnc
112 | kcm XOR grr -> fkb
113 | fkb AND rcc -> fbb
114 | dbd XOR shb -> z15
115 | y38 XOR x38 -> vsq
116 | sfs OR hmh -> qpd
117 | bmv AND fjs -> kwh
118 | ftq XOR vnw -> z11
119 | cjt OR svk -> kcm
120 | y33 XOR x33 -> ttn
121 | x18 XOR y18 -> dwd
122 | qpk OR btq -> nkn
123 | nnq OR pfb -> mfc
124 | crp XOR gkk -> z39
125 | x28 AND y28 -> dwg
126 | y07 XOR x07 -> ncp
127 | ssf AND hqr -> swq
128 | mfc AND hdk -> pqk
129 | y44 XOR x44 -> bmv
130 | x35 XOR y35 -> jdq
131 | y30 XOR x30 -> jnr
132 | x32 XOR y32 -> dfn
133 | ccw OR fbb -> hnq
134 | pqk OR dwg -> rsj
135 | jrk OR cpr -> kgn
136 | x01 AND y01 -> kmf
137 | kcm AND grr -> tnn
138 | y28 XOR x28 -> hdk
139 | mtb AND jdk -> fmr
140 | y29 XOR x29 -> ccs
141 | vhv OR cbh -> btv
142 | hdk XOR mfc -> z28
143 | dbg AND bcq -> wgk
144 | x11 XOR y11 -> ftq
145 | y04 XOR x04 -> mtb
146 | vnm AND mgr -> phc
147 | jfq OR tsw -> ksh
148 | gcg XOR nbm -> rrn
149 | wdv OR qph -> mcv
150 | x19 AND y19 -> pdb
151 | rqf XOR hvv -> z21
152 | y27 AND x27 -> nnq
153 | rdg OR scw -> jmt
154 | qkk OR tbr -> ggg
155 | jtm AND rqw -> tsw
156 | ccs AND rsj -> thq
157 | kgt OR qmm -> bcq
158 | kwh OR qqr -> z45
159 | twj XOR qft -> z08
160 | ttn AND jmt -> hmh
161 | y44 AND x44 -> qqr
162 | x03 XOR y03 -> mgr
163 | x40 AND y40 -> ntw
164 | jmt XOR ttn -> z33
165 | x43 XOR y43 -> dnf
166 | rmv OR smj -> hnv
167 | y17 AND x17 -> ccw
168 | y22 XOR x22 -> jck
169 | tph AND hbk -> jhd
170 | x34 AND y34 -> hrd
171 | ssf XOR hqr -> z19
172 | y37 AND x37 -> z37
173 | y04 AND x04 -> dgw
174 | qft AND twj -> qpn
175 | tnn OR bss -> z16
176 | x12 AND y12 -> ppp
177 | kmf OR cdb -> qnf
178 | vsq XOR jrg -> z38
179 | ccs XOR rsj -> z29
180 | y01 XOR x01 -> jnj
181 | mtb XOR jdk -> z04
182 | y21 AND x21 -> rqf
183 | hnq XOR dwd -> z18
184 | x19 XOR y19 -> ssf
185 | y34 XOR x34 -> hnk
186 | shp AND kcp -> pkv
187 | x08 XOR y08 -> twj
188 | fvc OR pkv -> thm
189 | x41 AND y41 -> gtv
190 | x06 AND y06 -> qmr
191 | qsj AND tjk -> z31
192 | vhj OR rrn -> jrg
193 | jrg AND vsq -> tkt
194 | y15 AND x15 -> svk
195 | prt XOR jnj -> z01
196 | shb AND dbd -> cjt
197 | hbc AND qst -> vhv
198 | x10 AND y10 -> vsm
199 | bkp XOR vmf -> z10
200 | y33 AND x33 -> sfs
201 | kgn XOR pgq -> z14
202 | y36 AND x36 -> fjn
203 | x00 XOR y00 -> z00
204 | y40 XOR x40 -> wqg
205 | vsm OR rjw -> vnw
206 | y42 XOR x42 -> kcp
207 | y29 AND x29 -> knv
208 | nbm AND gcg -> vhj
209 | y13 AND x13 -> cpr
210 | y32 AND x32 -> scw
211 | dgr AND vnc -> jrk
212 | thm XOR dnf -> z43
213 | bgj OR chb -> qsj
214 | qsj XOR tjk -> rdn
215 | thq OR knv -> rbk
216 | sqr AND njb -> smh
217 | x15 XOR y15 -> shb
218 | qfv OR qcm -> rcm
219 | x25 XOR y25 -> rhk
220 | y31 XOR x31 -> tjk
221 | rdn OR pct -> vtb
222 | sqr XOR njb -> z20
223 | fjc XOR rcm -> z27
224 | x42 AND y42 -> fvc
225 | y14 AND x14 -> qtq
226 | x36 XOR y36 -> ckw
227 | y39 XOR x39 -> gkk
228 | gtv OR jhd -> shp
229 | x38 AND y38 -> knb
230 | kgn AND pgq -> rhw
231 | sfw AND jck -> qpk
232 | pwb XOR jdq -> z35
233 | y05 XOR x05 -> rqw
234 | x23 XOR y23 -> crt
235 | x09 XOR y09 -> jtc
236 | ksh XOR kcc -> z06
237 | hnv AND mcj -> qcm
238 | y17 XOR x17 -> rcc
239 | y23 AND x23 -> nbr
240 | bqm OR qpn -> vrr
241 | fpv OR smh -> hvv
242 | swq OR pdb -> njb
243 | x13 XOR y13 -> dgr
244 | jnj AND prt -> cdb
245 | x10 XOR y10 -> vmf
246 | y37 XOR x37 -> gcg
247 | x21 XOR y21 -> nnr
248 | qst XOR hbc -> z24
249 | rcm AND fjc -> pfb
250 | y18 AND x18 -> pnv
251 | wqg AND ggg -> fvv
252 | mcj XOR hnv -> z26
253 | dwd AND hnq -> cdt
254 | wsm XOR qnf -> z02
255 | vnm XOR mgr -> z03
256 | sfw XOR jck -> z22
257 | x08 AND y08 -> bqm
258 | qmr OR fjt -> drd
259 | cdt OR pnv -> hqr
260 | ksh AND kcc -> fjt
261 | wqt OR ktn -> qft
262 | y24 AND x24 -> cbh
263 | x00 AND y00 -> prt
264 | dgr XOR vnc -> z13
265 | vrr XOR jtc -> z09
266 | fmr OR dgw -> jtm
267 | jnr AND rbk -> chb
268 | rqf AND hvv -> jsd
269 | x11 AND y11 -> qmm
270 | y31 AND x31 -> pct
271 | jrf OR shr -> vnm
272 | ckw AND mcv -> crk
273 | x43 AND y43 -> pss
274 | jnr XOR rbk -> z30
275 | x20 AND y20 -> fpv
276 | ntw OR fvv -> tph
277 | x14 XOR y14 -> pgq
278 | tph XOR hbk -> z41
279 | nbr OR spp -> qst
280 | ckw XOR mcv -> z36
281 | pps OR phc -> jdk
282 | vrr AND jtc -> hwp
283 | jdq AND pwb -> wdv
284 | y20 XOR x20 -> sqr
285 | crk OR fjn -> nbm
286 | hwp OR nwn -> bkp
287 | wsm AND qnf -> shr
288 | x26 AND y26 -> qfv
289 | y26 XOR x26 -> mcj
290 | crt XOR nkn -> z23
291 | ncp XOR drd -> z07
292 | vtb AND dfn -> rdg
293 | wqg XOR ggg -> z40
294 | x27 XOR y27 -> fjc
295 | fkb XOR rcc -> z17
296 | vtb XOR dfn -> z32
297 | rqw XOR jtm -> z05
298 | kcp XOR shp -> z42
299 | hrd OR tdb -> pwb
300 | x35 AND y35 -> qph
301 | y22 AND x22 -> btq
302 | tkt OR knb -> crp
303 | y03 AND x03 -> pps
304 | x41 XOR y41 -> hbk
305 | x25 AND y25 -> smj
306 | dnf AND thm -> wrt
307 | y02 XOR x02 -> wsm
308 | y07 AND x07 -> wqt
309 | dbg XOR bcq -> z12
310 | y24 XOR x24 -> hbc
311 | nkn AND crt -> spp
312 | qtq OR rhw -> dbd
313 | jsd OR nnr -> sfw
314 |
--------------------------------------------------------------------------------
/src/day13.rs:
--------------------------------------------------------------------------------
1 | use regex::Regex;
2 | use std::fs::File;
3 | use std::io::{BufRead, BufReader};
4 |
5 | #[derive(Debug)]
6 | struct Machine {
7 | x_a: usize,
8 | y_a: usize,
9 | x_b: usize,
10 | y_b: usize,
11 | x_prize: usize,
12 | y_prize: usize,
13 | }
14 |
15 | fn read_input(path: &str) -> std::io::Result> {
16 | let file = File::open(path)?;
17 | let reader = BufReader::new(file);
18 |
19 | let re_button_a = Regex::new(r"Button A:\s*X\+(\d+),\s*Y\+(\d+)").unwrap();
20 | let re_button_b = Regex::new(r"Button B:\s*X\+(\d+),\s*Y\+(\d+)").unwrap();
21 | let re_prize = Regex::new(r"Prize:\s*X=(\d+),\s*Y=(\d+)").unwrap();
22 |
23 | let mut machines = Vec::new();
24 | let mut lines = reader.lines().filter_map(|l| l.ok());
25 |
26 | while let Some(line_a) = lines.next() {
27 | if line_a.trim().is_empty() {
28 | continue;
29 | }
30 | let line_b = match lines.next() {
31 | Some(line) => line,
32 | None => break,
33 | };
34 | let line_p = match lines.next() {
35 | Some(line) => line,
36 | None => break,
37 | };
38 |
39 | let caps_a = re_button_a.captures(&line_a).unwrap();
40 | let caps_b = re_button_b.captures(&line_b).unwrap();
41 | let caps_p = re_prize.captures(&line_p).unwrap();
42 |
43 | let x_a = caps_a[1].parse::().unwrap();
44 | let y_a = caps_a[2].parse::().unwrap();
45 | let x_b = caps_b[1].parse::().unwrap();
46 | let y_b = caps_b[2].parse::().unwrap();
47 | let x_prize = caps_p[1].parse::().unwrap();
48 | let y_prize = caps_p[2].parse::().unwrap();
49 |
50 | machines.push(Machine {
51 | x_a,
52 | y_a,
53 | x_b,
54 | y_b,
55 | x_prize,
56 | y_prize,
57 | });
58 |
59 | let _ = lines.next();
60 | }
61 |
62 | Ok(machines)
63 | }
64 |
65 | pub fn solution() {
66 | let machines = read_input("./inputs/day13.txt").unwrap();
67 |
68 | // A.
69 | // a * (XA, YA) + b * (XB, YB) = (X_prize, Y_prize)
70 | let mut total = 0;
71 | for m in &machines {
72 | let mut min_cost = None;
73 | for a in 0..=100 {
74 | for b in 0..=100 {
75 | let x = a * m.x_a + b * m.x_b;
76 | let y = a * m.y_a + b * m.y_b;
77 | if x == m.x_prize && y == m.y_prize {
78 | let cost = 3 * a + b;
79 | match min_cost {
80 | None => min_cost = Some(cost),
81 | Some(prev) if cost < prev => min_cost = Some(cost),
82 | _ => {}
83 | }
84 | }
85 | }
86 | }
87 |
88 | if let Some(c) = min_cost {
89 | total += c;
90 | }
91 | }
92 |
93 | println!("Total cost: {}", total);
94 |
95 | // B.
96 | // We add the offset (10,000,000,000,000) to each prize coordinate.
97 | // Instead of brute-forcing values of `a` and `b`, we use a direct formula approach to calculate them:
98 | //
99 | // a = (x_b * y_prize - y_b * x_prize) / (x_a * y_b - y_a * x_b)
100 | // b = (x_prize - x_a * a) / x_b
101 | //
102 | // Here:
103 | // - `x_a`, `y_a` are the x and y increments when Button A is pressed.
104 | // - `x_b`, `y_b` are the x and y increments when Button B is pressed.
105 | // - `(x_prize, y_prize)` is the target coordinate (after adding the offset in Part B).
106 | //
107 | // Let D = (x_a * y_b - y_a * x_b), which is the determinant of the 2D linear system:
108 | // a * (x_a, y_a) + b * (x_b, y_b) = (x_prize, y_prize)
109 | //
110 | // If D ≠ 0, the vectors (x_a, y_a) and (x_b, y_b) are not collinear, so the system has a unique solution in real numbers.
111 | // - We calculate `a` and `b` using the formulas above.
112 | // - Check if `a` and `b` are integers (i.e., no remainder when dividing).
113 | // - Check if `a` and `b` are both nonnegative.
114 | // - If all conditions are satisfied, the solution is valid, and the cost is `3 * a + b`.
115 | //
116 | // If D = 0, the vectors (x_a, y_a) and (x_b, y_b) are collinear.
117 | // - In this case, the system cannot determine a unique solution using the direct formula approach.
118 | // - Special handling is needed to check if the target coordinate (x_prize, y_prize) is reachable along the single direction defined by the collinear vectors.
119 | // - If reachable, we calculate the minimum cost separately (e.g., using parameterized solutions along the line).
120 | //
121 | // If the solution is invalid (e.g., non-integer `a` or `b`, or negative values), we skip the machine for Part B.
122 | //
123 | let offset = 10_000_000_000_000usize;
124 | let mut total = 0;
125 | let mut solved = 0;
126 |
127 | for m in &machines {
128 | let x_prize_b = (m.x_prize as i64) + offset as i64;
129 | let y_prize_b = (m.y_prize as i64) + offset as i64;
130 |
131 | let x_a = m.x_a as i64;
132 | let y_a = m.y_a as i64;
133 | let x_b = m.x_b as i64;
134 | let y_b = m.y_b as i64;
135 |
136 | let d = x_a * y_b - y_a * x_b;
137 | if d == 0 {
138 | // Collinear or no solution
139 | continue;
140 | } else {
141 | // Non-collinear => unique solution (if integral)
142 | let a_num = y_b * x_prize_b - x_b * y_prize_b;
143 | let denom = d;
144 | if a_num % denom != 0 {
145 | // not an integer solution
146 | continue;
147 | }
148 |
149 | let a = a_num / denom;
150 | let b_num = x_prize_b - x_a * a;
151 | if x_b == 0 {
152 | // If xb=0 but we ended up here, it's likely no solution or handled differently.
153 | continue;
154 | }
155 |
156 | if b_num % x_b != 0 {
157 | // not integer
158 | continue;
159 | }
160 |
161 | let b = b_num / x_b;
162 |
163 | // Check nonnegative and that it indeed hits the goal
164 | if a < 0 || b < 0 {
165 | continue;
166 | }
167 |
168 | let final_x = x_a * a + x_b * b;
169 | let final_y = y_a * a + y_b * b;
170 | if final_x == x_prize_b && final_y == y_prize_b {
171 | let cost = 3 * a + b;
172 | total += cost;
173 | solved += 1;
174 | }
175 | }
176 | }
177 |
178 | println!("Part B, solved {} with total cost {}", solved, total);
179 | }
180 |
--------------------------------------------------------------------------------
/src/day21.rs:
--------------------------------------------------------------------------------
1 | use std::{collections::HashMap, fs};
2 |
3 | struct Solution {
4 | moves1: HashMap<(char, char), Vec>,
5 | moves2: HashMap<(char, char), Vec>,
6 | }
7 |
8 | impl Solution {
9 | fn new(keypad1: &[&str], keypad2: &[&str]) -> Self {
10 | let moves1 = Self::parse_moves(keypad1);
11 | let moves2 = Self::parse_moves(keypad2);
12 | Self { moves1, moves2 }
13 | }
14 |
15 | fn parse_moves(keypad: &[&str]) -> HashMap<(char, char), Vec> {
16 | fn get_key_pos(keypad: &[&str]) -> HashMap {
17 | let mut pos = HashMap::new();
18 | for (r, row) in keypad.iter().enumerate() {
19 | for (c, key) in row.chars().enumerate() {
20 | pos.insert(key, (r, c));
21 | }
22 | }
23 | pos
24 | }
25 |
26 | let pos = get_key_pos(keypad);
27 | let mut moves: HashMap<(char, char), Vec> = HashMap::new();
28 | let mut keys: Vec = pos.keys().cloned().collect();
29 | keys.sort();
30 |
31 | let hash_pos = pos.get(&'#').expect("Keypad must contain '#'");
32 |
33 | for &key1 in &keys {
34 | if key1 == '#' {
35 | continue;
36 | }
37 | for &key2 in &keys {
38 | if key2 == '#' || key1 == key2 {
39 | continue;
40 | }
41 | let p1 = pos[&key1];
42 | let p2 = pos[&key2];
43 | let mut sequences = Vec::new();
44 |
45 | if p1.0 == p2.0 {
46 | let dir = if p2.1 > p1.1 { '>' } else { '<' };
47 | let distance = (p2.1 as isize - p1.1 as isize).abs();
48 | let move_seq = format!("{}A", dir.to_string().repeat(distance as usize));
49 | sequences.push(move_seq);
50 | } else if p1.1 == p2.1 {
51 | let dir = if p2.0 > p1.0 { 'v' } else { '^' };
52 | let distance = (p2.0 as isize - p1.0 as isize).abs();
53 | let move_seq = format!("{}A", dir.to_string().repeat(distance as usize));
54 | sequences.push(move_seq);
55 | } else {
56 | if p1.0 != hash_pos.0 || p2.1 != hash_pos.1 {
57 | let dir1 = if p2.1 > p1.1 { '>' } else { '<' };
58 | let distance1 = (p2.1 as isize - p1.1 as isize).abs();
59 | let dir2 = if p2.0 > p1.0 { 'v' } else { '^' };
60 | let distance2 = (p2.0 as isize - p1.0 as isize).abs();
61 | let move_seq = format!(
62 | "{}{}A",
63 | dir1.to_string().repeat(distance1 as usize),
64 | dir2.to_string().repeat(distance2 as usize)
65 | );
66 | sequences.push(move_seq);
67 | }
68 |
69 | // First vertical then horizontal
70 | if p1.1 != hash_pos.1 || p2.0 != hash_pos.0 {
71 | let dir1 = if p2.0 > p1.0 { 'v' } else { '^' };
72 | let distance1 = (p2.0 as isize - p1.0 as isize).abs();
73 | let dir2 = if p2.1 > p1.1 { '>' } else { '<' };
74 | let distance2 = (p2.1 as isize - p1.1 as isize).abs();
75 | let move_seq = format!(
76 | "{}{}A",
77 | dir1.to_string().repeat(distance1 as usize),
78 | dir2.to_string().repeat(distance2 as usize)
79 | );
80 | sequences.push(move_seq);
81 | }
82 | }
83 |
84 | if !sequences.is_empty() {
85 | moves.insert((key1, key2), sequences);
86 | }
87 | }
88 | }
89 |
90 | moves
91 | }
92 |
93 | fn build_combinations(&self, arrays: &[Vec]) -> Vec> {
94 | let mut results: Vec> = vec![Vec::new()];
95 | for array in arrays {
96 | let mut temp = Vec::new();
97 | for combination in &results {
98 | for item in array {
99 | let mut new_combination = combination.clone();
100 | new_combination.push(item.clone());
101 | temp.push(new_combination);
102 | }
103 | }
104 | results = temp;
105 | }
106 | results
107 | }
108 |
109 | fn translate(
110 | &self,
111 | code: &str,
112 | depth: usize,
113 | cache: &mut HashMap<(String, usize), usize>,
114 | ) -> usize {
115 | if let Some(&cached) = cache.get(&(code.to_string(), depth)) {
116 | return cached;
117 | }
118 |
119 | let moves = if code.chars().next().unwrap().is_numeric() {
120 | self.translate_numpad(code)
121 | } else {
122 | self.translate_keypad(code)
123 | };
124 |
125 | let result = if depth == 0 {
126 | moves
127 | .iter()
128 | .map(|move_seq| move_seq.iter().map(|s| s.len()).sum::())
129 | .min()
130 | .unwrap_or(0)
131 | } else {
132 | moves
133 | .iter()
134 | .map(|move_seq| {
135 | move_seq
136 | .iter()
137 | .map(|s| self.translate(s, depth - 1, cache))
138 | .sum::()
139 | })
140 | .min()
141 | .unwrap_or(0)
142 | };
143 |
144 | cache.insert((code.to_string(), depth), result);
145 | result
146 | }
147 |
148 | fn translate_numpad(&self, code: &str) -> Vec> {
149 | let mut code_chars: Vec = code.chars().collect();
150 | code_chars.insert(0, 'A');
151 | let mut moves_list = Vec::new();
152 |
153 | for pair in code_chars.windows(2) {
154 | if let [a, b] = pair {
155 | if let Some(moves) = self.moves1.get(&(*a, *b)) {
156 | moves_list.push(moves.clone());
157 | } else {
158 | moves_list.push(vec!["A".to_string()]);
159 | }
160 | }
161 | }
162 |
163 | self.build_combinations(&moves_list)
164 | }
165 |
166 | fn translate_keypad(&self, code: &str) -> Vec> {
167 | let mut code_chars: Vec = code.chars().collect();
168 | code_chars.insert(0, 'A');
169 | let mut moves_list = Vec::new();
170 |
171 | for pair in code_chars.windows(2) {
172 | if let [a, b] = pair {
173 | if *a != *b {
174 | if let Some(moves) = self.moves2.get(&(*a, *b)) {
175 | moves_list.push(moves.clone());
176 | } else {
177 | // If no move exists, use a default move
178 | moves_list.push(vec!["A".to_string()]);
179 | }
180 | } else {
181 | moves_list.push(vec!["A".to_string()]);
182 | }
183 | }
184 | }
185 |
186 | self.build_combinations(&moves_list)
187 | }
188 |
189 | fn solve(&self, data: &[&str], depth: usize) -> usize {
190 | let mut complexities = 0;
191 | let mut cache = HashMap::new();
192 |
193 | for code in data {
194 | let min_len = self.translate(code, depth, &mut cache);
195 | if let Some(num_str) = code.strip_suffix(&code.chars().last().unwrap().to_string()) {
196 | if let Ok(num) = num_str.parse::() {
197 | complexities += min_len * num;
198 | }
199 | }
200 | }
201 |
202 | complexities
203 | }
204 | }
205 |
206 | pub fn solution() {
207 | let keypad1 = ["789", "456", "123", "#0A"];
208 | let keypad2 = ["#^A", ""];
209 | let solution = Solution::new(&keypad1, &keypad2);
210 | let input = fs::read_to_string("./inputs/day21.txt").unwrap();
211 | let data: Vec<&str> = input
212 | .lines()
213 | .map(str::trim)
214 | .filter(|l| !l.is_empty())
215 | .collect();
216 |
217 | let part1 = solution.solve(&data, 2);
218 | println!("Part 1: {}", part1);
219 |
220 | // Part 2 is insipired by:
221 | // https://github.com/nitekat1124/advent-of-code-2024/blob/main/solutions/day21.py
222 | let part2 = solution.solve(&data, 25);
223 | println!("Part 2: {}", part2);
224 | }
225 |
--------------------------------------------------------------------------------
/src/day15.rs:
--------------------------------------------------------------------------------
1 | use std::collections::HashSet;
2 |
3 | const DIRS: [(isize, isize); 4] = [(-1, 0), (1, 0), (0, -1), (0, 1)];
4 |
5 | struct Warehouse;
6 |
7 | impl Warehouse {
8 | fn get_direction(&self, mv: char) -> Option<(isize, isize)> {
9 | match mv {
10 | '^' => Some(DIRS[0]),
11 | 'v' => Some(DIRS[1]),
12 | '<' => Some(DIRS[2]),
13 | '>' => Some(DIRS[3]),
14 | _ => None,
15 | }
16 | }
17 |
18 | fn get_robot_pos(&self, grid: &Vec>) -> Option<(usize, usize)> {
19 | for (i, row) in grid.iter().enumerate() {
20 | for (j, &cell) in row.iter().enumerate() {
21 | if cell == '@' {
22 | return Some((i, j));
23 | }
24 | }
25 | }
26 | None
27 | }
28 |
29 | fn moving(
30 | &self,
31 | mut grid: Vec>,
32 | mut pos: (usize, usize),
33 | moves: Vec,
34 | part: usize,
35 | ) -> Vec> {
36 | for mv in moves {
37 | let (dy, dx) = match self.get_direction(mv) {
38 | Some(dir) => dir,
39 | None => {
40 | continue;
41 | }
42 | };
43 |
44 | let ny = pos.0 as isize + dy;
45 | let nx = pos.1 as isize + dx;
46 |
47 | if ny < 0 || nx < 0 || ny >= grid.len() as isize || nx >= grid[0].len() as isize {
48 | continue;
49 | }
50 |
51 | let ny_usize = ny as usize;
52 | let nx_usize = nx as usize;
53 |
54 | match grid[ny_usize][nx_usize] {
55 | '.' => pos = (ny_usize, nx_usize),
56 | '#' => continue,
57 | _ => {
58 | let (edges, adjs) = self.get_adjs_and_edges(&grid, pos, mv, part);
59 | let mut blocked = 0;
60 | for (ey, ex) in edges {
61 | let (ey_new, ex_new) = (ey as isize + dy, ex as isize + dx);
62 | if ey_new < 0
63 | || ex_new < 0
64 | || ey_new >= grid.len() as isize
65 | || ex_new >= grid[0].len() as isize
66 | || grid[ey_new as usize][ex_new as usize] == '#'
67 | {
68 | blocked += 1;
69 | }
70 | }
71 |
72 | if blocked == 0 {
73 | grid = self.update_grid(grid, adjs, mv);
74 | pos = (ny_usize, nx_usize);
75 | }
76 | }
77 | }
78 | }
79 | grid
80 | }
81 |
82 | fn get_adjs_and_edges(
83 | &self,
84 | grid: &Vec>,
85 | pos: (usize, usize),
86 | move_dir: char,
87 | part: usize,
88 | ) -> (Vec<(usize, usize)>, HashSet<(usize, usize)>) {
89 | let (mut y, mut x) = pos;
90 | let (dy, dx) = self.get_direction(move_dir).unwrap();
91 | let mut adjs = HashSet::new();
92 |
93 | if part == 1 || "<>".contains(move_dir) {
94 | loop {
95 | let ny = y as isize + dy;
96 | let nx = x as isize + dx;
97 |
98 | if ny < 0 || nx < 0 || ny >= grid.len() as isize || nx >= grid[0].len() as isize {
99 | return (vec![(y, x)], adjs);
100 | }
101 |
102 | let ny_usize = ny as usize;
103 | let nx_usize = nx as usize;
104 |
105 | if grid[ny_usize][nx_usize] == '.' || grid[ny_usize][nx_usize] == '#' {
106 | return (vec![(y, x)], adjs);
107 | }
108 |
109 | y = ny_usize;
110 | x = nx_usize;
111 | adjs.insert((y, x));
112 | }
113 | } else {
114 | let mut edges = Vec::new();
115 | let mut queue = vec![(y, x)];
116 | while let Some((cy, cx)) = queue.pop() {
117 | if adjs.contains(&(cy, cx)) {
118 | continue;
119 | }
120 | adjs.insert((cy, cx));
121 |
122 | let ny = cy as isize + dy;
123 | let nx = cx as isize + dx;
124 |
125 | if ny < 0 || nx < 0 || ny >= grid.len() as isize || nx >= grid[0].len() as isize {
126 | continue;
127 | }
128 |
129 | let ny_usize = ny as usize;
130 | let nx_usize = nx as usize;
131 |
132 | match grid[ny_usize][nx_usize] {
133 | '.' | '#' => edges.push((cy, cx)),
134 | '[' => {
135 | if nx + 1 < grid[0].len() as isize {
136 | queue.push((ny_usize, nx_usize));
137 | queue.push((ny_usize, nx_usize + 1));
138 | }
139 | }
140 | ']' => {
141 | if nx >= 1 {
142 | queue.push((ny_usize, nx_usize));
143 | queue.push((ny_usize, nx_usize - 1));
144 | }
145 | }
146 | _ => (),
147 | }
148 | }
149 | (edges, adjs)
150 | }
151 | }
152 |
153 | fn update_grid(
154 | &self,
155 | mut grid: Vec>,
156 | adjs: HashSet<(usize, usize)>,
157 | move_dir: char,
158 | ) -> Vec> {
159 | let mut sorted_coords = adjs.into_iter().collect::>();
160 | match move_dir {
161 | '^' => sorted_coords.sort_by_key(|&(y, _)| y),
162 | 'v' => sorted_coords.sort_by_key(|&(y, _)| std::cmp::Reverse(y)),
163 | '<' => sorted_coords.sort_by_key(|&(_, x)| x),
164 | '>' => sorted_coords.sort_by_key(|&(_, x)| std::cmp::Reverse(x)),
165 | _ => (),
166 | }
167 |
168 | let (dy, dx) = self.get_direction(move_dir).unwrap();
169 | for (y, x) in sorted_coords {
170 | let ny = y as isize + dy;
171 | let nx = x as isize + dx;
172 |
173 | if ny < 0 || nx < 0 || ny >= grid.len() as isize || nx >= grid[0].len() as isize {
174 | continue;
175 | }
176 |
177 | let ny_usize = ny as usize;
178 | let nx_usize = nx as usize;
179 |
180 | grid[ny_usize][nx_usize] = grid[y][x];
181 | grid[y][x] = '.';
182 | }
183 |
184 | grid
185 | }
186 |
187 | fn get_coords_sum(&self, grid: &Vec>, part: usize) -> usize {
188 | let box_char = if part == 2 { '[' } else { 'O' };
189 | grid.iter()
190 | .enumerate()
191 | .map(|(y, row)| {
192 | row.iter()
193 | .enumerate()
194 | .filter_map(|(x, &cell)| {
195 | if cell == box_char {
196 | Some(100 * y + x)
197 | } else {
198 | None
199 | }
200 | })
201 | .sum::()
202 | })
203 | .sum()
204 | }
205 |
206 | fn resize_grid(&self, grid: &Vec>) -> Vec> {
207 | let mappings = vec![('#', "##"), ('O', "[]"), ('.', ".."), ('@', "@.")]
208 | .into_iter()
209 | .collect::>();
210 |
211 | grid.iter()
212 | .map(|row| {
213 | row.iter()
214 | .flat_map(|&c| mappings.get(&c).unwrap_or(&"").chars())
215 | .collect()
216 | })
217 | .collect()
218 | }
219 |
220 | pub fn solve(&self, data: &str, part: usize) -> usize {
221 | let parts = data.split("\n\n").collect::>();
222 | if parts.len() != 2 {
223 | return 0;
224 | }
225 |
226 | let mut grid = parts[0].lines().map(|l| l.chars().collect()).collect();
227 | let valid_moves = vec!['^', 'v', '<', '>'];
228 | let moves = parts[1]
229 | .chars()
230 | .filter(|c| valid_moves.contains(c))
231 | .collect();
232 |
233 | if part == 2 {
234 | grid = self.resize_grid(&grid);
235 | }
236 |
237 | let pos = match self.get_robot_pos(&grid) {
238 | Some(p) => p,
239 | None => return 0,
240 | };
241 | grid[pos.0][pos.1] = '.';
242 |
243 | let grid = self.moving(grid, pos, moves, part);
244 | self.get_coords_sum(&grid, part)
245 | }
246 | }
247 |
248 | pub fn solution() {
249 | let data = std::fs::read_to_string("inputs/day15.txt").unwrap();
250 |
251 | let a = Warehouse.solve(&data, 1);
252 | println!("Part A: {}", a);
253 |
254 | // Part 2 is inspired by:
255 | // https://github.com/nitekat1124/advent-of-code-2024/blob/main/solutions/day15.py
256 | let b = Warehouse.solve(&data, 2);
257 | println!("Part B: {}", b);
258 | }
259 |
--------------------------------------------------------------------------------
/inputs/day14.txt:
--------------------------------------------------------------------------------
1 | p=10,22 v=50,-21
2 | p=35,60 v=-8,52
3 | p=79,50 v=82,9
4 | p=52,1 v=-28,-55
5 | p=85,67 v=-51,-18
6 | p=72,34 v=82,13
7 | p=57,0 v=67,75
8 | p=7,52 v=85,67
9 | p=81,19 v=-73,-21
10 | p=46,32 v=-82,29
11 | p=68,101 v=-73,30
12 | p=23,42 v=-36,-63
13 | p=25,93 v=40,-16
14 | p=30,93 v=-76,-55
15 | p=22,58 v=72,-9
16 | p=25,84 v=18,-87
17 | p=38,80 v=39,-42
18 | p=35,71 v=-55,-53
19 | p=88,60 v=-32,-29
20 | p=86,86 v=-16,98
21 | p=30,102 v=66,35
22 | p=64,88 v=54,75
23 | p=24,4 v=18,93
24 | p=4,6 v=4,-93
25 | p=57,70 v=-7,-42
26 | p=23,38 v=-37,56
27 | p=75,84 v=-89,-21
28 | p=10,83 v=30,-33
29 | p=77,66 v=-73,-2
30 | p=4,15 v=84,2
31 | p=44,34 v=-48,31
32 | p=15,78 v=-4,50
33 | p=31,60 v=-26,-66
34 | p=62,50 v=34,-94
35 | p=98,25 v=37,49
36 | p=74,81 v=1,59
37 | p=94,81 v=-38,-60
38 | p=70,20 v=-54,-60
39 | p=89,51 v=-85,-32
40 | p=49,51 v=-48,76
41 | p=53,66 v=33,83
42 | p=61,29 v=-47,-63
43 | p=49,43 v=94,-7
44 | p=17,23 v=-49,-30
45 | p=15,55 v=24,-63
46 | p=82,3 v=-13,77
47 | p=77,44 v=54,20
48 | p=8,43 v=30,-76
49 | p=70,72 v=-34,97
50 | p=58,10 v=96,45
51 | p=67,95 v=-20,39
52 | p=92,81 v=-83,-26
53 | p=44,98 v=64,-41
54 | p=1,99 v=71,73
55 | p=81,25 v=-59,44
56 | p=16,31 v=91,-32
57 | p=48,44 v=-41,-63
58 | p=88,11 v=-72,37
59 | p=31,89 v=-77,-75
60 | p=42,41 v=-40,33
61 | p=61,41 v=-73,-16
62 | p=96,7 v=-71,-37
63 | p=16,35 v=-43,-43
64 | p=80,79 v=-59,70
65 | p=20,35 v=-70,-5
66 | p=41,47 v=-50,-70
67 | p=86,37 v=11,-72
68 | p=61,97 v=54,-73
69 | p=82,4 v=90,-3
70 | p=24,35 v=38,80
71 | p=52,93 v=-81,2
72 | p=90,37 v=90,-43
73 | p=18,28 v=31,11
74 | p=33,58 v=-2,56
75 | p=100,102 v=-32,19
76 | p=97,51 v=-45,-15
77 | p=68,17 v=76,-93
78 | p=100,13 v=83,-46
79 | p=88,8 v=-12,75
80 | p=71,14 v=-6,-30
81 | p=83,10 v=15,-37
82 | p=81,84 v=35,12
83 | p=98,90 v=-52,43
84 | p=91,60 v=65,82
85 | p=3,72 v=-24,-40
86 | p=84,49 v=-58,22
87 | p=82,75 v=-99,27
88 | p=4,73 v=46,79
89 | p=15,32 v=51,24
90 | p=6,32 v=-44,-81
91 | p=21,101 v=-36,28
92 | p=21,100 v=51,-73
93 | p=50,32 v=-92,-98
94 | p=1,58 v=-24,-2
95 | p=52,96 v=-95,-64
96 | p=83,28 v=-60,11
97 | p=85,101 v=-59,-26
98 | p=19,2 v=-31,-97
99 | p=50,32 v=-68,31
100 | p=13,66 v=43,36
101 | p=100,15 v=-30,-14
102 | p=84,78 v=-58,88
103 | p=65,50 v=-53,-21
104 | p=50,75 v=26,61
105 | p=89,60 v=-93,47
106 | p=15,39 v=38,4
107 | p=15,50 v=-90,-27
108 | p=63,66 v=29,60
109 | p=17,79 v=-50,-89
110 | p=21,39 v=-83,60
111 | p=62,35 v=6,-51
112 | p=99,44 v=9,8
113 | p=32,4 v=-43,-35
114 | p=57,2 v=-81,39
115 | p=4,7 v=-44,-10
116 | p=93,12 v=56,-19
117 | p=33,79 v=45,-24
118 | p=66,72 v=86,-41
119 | p=84,83 v=-28,39
120 | p=11,30 v=56,-88
121 | p=51,19 v=-54,-89
122 | p=0,36 v=-32,-28
123 | p=69,39 v=41,20
124 | p=75,88 v=8,79
125 | p=5,12 v=-64,93
126 | p=38,9 v=-62,91
127 | p=25,100 v=64,-15
128 | p=97,60 v=-12,-69
129 | p=57,76 v=-7,-13
130 | p=42,48 v=-69,32
131 | p=31,35 v=-81,65
132 | p=28,28 v=46,85
133 | p=77,84 v=-73,68
134 | p=57,18 v=-54,44
135 | p=48,98 v=59,17
136 | p=28,86 v=92,-17
137 | p=1,93 v=90,-53
138 | p=0,31 v=84,-32
139 | p=87,34 v=9,-65
140 | p=20,20 v=44,-25
141 | p=65,93 v=-96,-54
142 | p=45,75 v=-82,-87
143 | p=48,58 v=26,65
144 | p=87,76 v=-86,16
145 | p=31,79 v=52,34
146 | p=100,101 v=58,-36
147 | p=76,20 v=59,-76
148 | p=100,91 v=-85,-4
149 | p=14,13 v=92,-46
150 | p=72,66 v=-60,-65
151 | p=74,41 v=-60,96
152 | p=73,17 v=48,80
153 | p=48,50 v=-48,94
154 | p=76,50 v=-81,12
155 | p=51,102 v=80,1
156 | p=44,12 v=93,-86
157 | p=49,16 v=40,-43
158 | p=75,97 v=2,-24
159 | p=54,35 v=13,-34
160 | p=50,4 v=-75,75
161 | p=28,87 v=77,81
162 | p=50,38 v=13,60
163 | p=51,43 v=-27,22
164 | p=71,52 v=-13,29
165 | p=37,74 v=-29,-40
166 | p=67,82 v=-13,61
167 | p=4,21 v=-97,-50
168 | p=36,2 v=25,-66
169 | p=17,67 v=-30,-87
170 | p=90,29 v=96,15
171 | p=90,96 v=-52,39
172 | p=20,9 v=78,17
173 | p=70,74 v=-32,-93
174 | p=77,60 v=-83,51
175 | p=74,97 v=92,1
176 | p=75,82 v=28,61
177 | p=40,4 v=-58,-94
178 | p=64,26 v=6,-86
179 | p=71,14 v=-81,-93
180 | p=11,96 v=24,70
181 | p=97,26 v=97,-61
182 | p=77,53 v=-44,55
183 | p=1,93 v=83,46
184 | p=11,59 v=90,54
185 | p=3,2 v=-85,-8
186 | p=18,90 v=79,-60
187 | p=82,31 v=96,-34
188 | p=41,22 v=-9,-72
189 | p=52,17 v=86,-95
190 | p=48,39 v=-41,-63
191 | p=3,61 v=-16,-35
192 | p=6,26 v=50,42
193 | p=73,91 v=-53,99
194 | p=55,89 v=-54,-35
195 | p=24,22 v=17,-66
196 | p=80,84 v=-97,53
197 | p=20,73 v=69,-40
198 | p=26,100 v=-83,19
199 | p=68,87 v=-40,88
200 | p=80,45 v=-15,-4
201 | p=2,80 v=-98,23
202 | p=30,71 v=-62,9
203 | p=2,89 v=-50,88
204 | p=19,99 v=21,-1
205 | p=11,81 v=-3,-13
206 | p=70,59 v=-32,34
207 | p=84,68 v=89,-22
208 | p=48,35 v=-48,-79
209 | p=78,80 v=-60,34
210 | p=10,50 v=77,-31
211 | p=94,79 v=23,90
212 | p=46,47 v=-68,2
213 | p=20,52 v=30,-56
214 | p=79,36 v=2,-97
215 | p=75,21 v=-74,-22
216 | p=54,53 v=4,-75
217 | p=100,76 v=69,43
218 | p=95,33 v=-64,22
219 | p=26,61 v=38,63
220 | p=13,20 v=43,-59
221 | p=20,36 v=72,47
222 | p=78,98 v=49,-24
223 | p=83,76 v=-12,-22
224 | p=79,98 v=-73,77
225 | p=31,22 v=-96,33
226 | p=61,22 v=27,-90
227 | p=83,41 v=22,40
228 | p=98,15 v=76,-37
229 | p=23,46 v=-49,43
230 | p=2,87 v=-52,-8
231 | p=74,2 v=74,-57
232 | p=19,36 v=51,36
233 | p=30,93 v=-3,-93
234 | p=75,21 v=90,-28
235 | p=2,32 v=30,-12
236 | p=69,88 v=-40,-90
237 | p=1,77 v=-81,27
238 | p=1,70 v=-3,56
239 | p=60,70 v=3,-13
240 | p=54,14 v=67,8
241 | p=1,61 v=64,-47
242 | p=50,99 v=-40,72
243 | p=62,43 v=74,76
244 | p=63,30 v=14,98
245 | p=10,3 v=24,-46
246 | p=25,64 v=-83,-87
247 | p=8,31 v=-70,54
248 | p=17,18 v=-80,-95
249 | p=100,53 v=42,-6
250 | p=61,101 v=28,-44
251 | p=91,34 v=-6,23
252 | p=43,28 v=-31,62
253 | p=52,88 v=75,6
254 | p=45,66 v=-28,-96
255 | p=29,40 v=5,78
256 | p=21,91 v=-50,97
257 | p=72,6 v=48,35
258 | p=4,11 v=97,48
259 | p=66,89 v=-72,4
260 | p=63,70 v=-47,56
261 | p=28,75 v=10,-78
262 | p=94,47 v=-65,-27
263 | p=14,74 v=51,25
264 | p=34,65 v=5,-29
265 | p=61,65 v=-73,47
266 | p=88,17 v=-12,-28
267 | p=46,43 v=-76,40
268 | p=78,76 v=21,34
269 | p=54,32 v=-41,-7
270 | p=48,92 v=-41,-35
271 | p=89,59 v=29,9
272 | p=89,66 v=36,-58
273 | p=38,83 v=-19,16
274 | p=84,4 v=38,66
275 | p=39,101 v=88,54
276 | p=6,32 v=82,50
277 | p=30,79 v=-63,-80
278 | p=54,35 v=41,-16
279 | p=33,102 v=-49,35
280 | p=23,37 v=-91,-61
281 | p=77,30 v=-35,-69
282 | p=79,4 v=35,-57
283 | p=45,29 v=-95,-23
284 | p=49,57 v=87,71
285 | p=53,31 v=87,-7
286 | p=10,78 v=-34,35
287 | p=10,16 v=-37,26
288 | p=46,15 v=-41,-95
289 | p=2,26 v=49,-30
290 | p=15,68 v=-50,52
291 | p=69,40 v=-47,-90
292 | p=53,39 v=14,9
293 | p=23,61 v=11,83
294 | p=44,33 v=-27,-79
295 | p=81,2 v=-40,-55
296 | p=89,42 v=-72,31
297 | p=18,32 v=-39,19
298 | p=97,91 v=-76,52
299 | p=51,80 v=60,-64
300 | p=48,36 v=53,98
301 | p=86,91 v=97,1
302 | p=48,88 v=-22,-42
303 | p=100,17 v=-24,-90
304 | p=40,52 v=-36,-85
305 | p=65,52 v=-19,-25
306 | p=0,45 v=82,-84
307 | p=12,102 v=78,-73
308 | p=67,19 v=87,-43
309 | p=24,78 v=84,93
310 | p=68,52 v=-14,71
311 | p=57,10 v=-7,6
312 | p=4,10 v=87,62
313 | p=64,38 v=41,51
314 | p=23,56 v=12,-38
315 | p=53,25 v=46,-54
316 | p=16,90 v=-84,59
317 | p=23,97 v=-36,-35
318 | p=35,78 v=85,92
319 | p=53,31 v=-53,19
320 | p=61,84 v=54,41
321 | p=86,93 v=76,10
322 | p=78,80 v=-46,-24
323 | p=2,6 v=43,46
324 | p=58,82 v=20,97
325 | p=46,20 v=-75,15
326 | p=60,85 v=30,-54
327 | p=57,29 v=-7,-96
328 | p=75,98 v=62,79
329 | p=64,44 v=54,24
330 | p=42,51 v=-76,19
331 | p=37,66 v=-70,-9
332 | p=85,16 v=-58,60
333 | p=8,70 v=-57,-69
334 | p=36,55 v=-73,-96
335 | p=67,93 v=88,30
336 | p=18,48 v=54,-94
337 | p=53,14 v=20,-93
338 | p=28,37 v=24,-10
339 | p=64,10 v=-94,-94
340 | p=10,19 v=-41,-19
341 | p=6,80 v=-64,-98
342 | p=30,66 v=52,54
343 | p=35,24 v=5,-3
344 | p=14,1 v=18,-60
345 | p=54,0 v=-61,-17
346 | p=27,2 v=38,60
347 | p=49,88 v=48,-17
348 | p=63,1 v=-7,-94
349 | p=98,75 v=-78,43
350 | p=88,97 v=-25,10
351 | p=30,75 v=-68,26
352 | p=65,57 v=68,18
353 | p=19,30 v=3,49
354 | p=52,47 v=-50,94
355 | p=16,8 v=27,-52
356 | p=27,64 v=-84,-29
357 | p=85,30 v=49,31
358 | p=94,20 v=10,80
359 | p=57,84 v=-84,32
360 | p=45,93 v=-2,-46
361 | p=94,68 v=-79,83
362 | p=61,27 v=-73,2
363 | p=15,64 v=99,-4
364 | p=28,82 v=46,-51
365 | p=88,14 v=81,74
366 | p=2,90 v=67,48
367 | p=8,66 v=64,-31
368 | p=4,5 v=-97,48
369 | p=39,60 v=5,74
370 | p=62,11 v=81,-75
371 | p=82,54 v=35,-84
372 | p=89,72 v=-88,-24
373 | p=42,45 v=73,67
374 | p=77,78 v=89,90
375 | p=44,5 v=80,28
376 | p=58,28 v=-31,-31
377 | p=91,68 v=-73,-22
378 | p=68,48 v=-76,80
379 | p=22,26 v=24,6
380 | p=34,6 v=-69,-83
381 | p=64,81 v=-13,-8
382 | p=15,16 v=-16,64
383 | p=42,49 v=93,-56
384 | p=87,38 v=-59,58
385 | p=95,34 v=-92,-79
386 | p=66,101 v=7,-19
387 | p=63,38 v=82,1
388 | p=95,53 v=63,-27
389 | p=95,2 v=-65,-48
390 | p=16,73 v=-64,-78
391 | p=13,60 v=-58,27
392 | p=69,55 v=34,-11
393 | p=32,20 v=10,-71
394 | p=52,100 v=-95,-84
395 | p=50,16 v=-21,35
396 | p=42,44 v=73,85
397 | p=87,33 v=-93,74
398 | p=60,75 v=40,34
399 | p=7,1 v=27,-13
400 | p=12,63 v=29,-63
401 | p=18,56 v=-90,-18
402 | p=30,49 v=-56,-92
403 | p=49,8 v=-63,49
404 | p=80,15 v=64,-79
405 | p=36,66 v=25,-24
406 | p=76,37 v=-80,22
407 | p=76,68 v=29,-31
408 | p=90,2 v=-92,51
409 | p=14,42 v=72,49
410 | p=57,89 v=-94,-53
411 | p=48,63 v=29,-14
412 | p=80,2 v=-86,19
413 | p=62,45 v=-53,36
414 | p=40,36 v=67,67
415 | p=45,96 v=62,-66
416 | p=42,61 v=-81,18
417 | p=54,69 v=-27,-79
418 | p=72,17 v=55,-97
419 | p=92,93 v=-3,3
420 | p=11,97 v=10,59
421 | p=33,61 v=5,-65
422 | p=26,31 v=-48,34
423 | p=1,32 v=81,-18
424 | p=68,70 v=27,-54
425 | p=89,10 v=-99,-12
426 | p=32,102 v=65,-64
427 | p=52,89 v=-41,-62
428 | p=100,10 v=-11,-59
429 | p=93,63 v=83,34
430 | p=16,67 v=-23,43
431 | p=58,35 v=13,-10
432 | p=24,31 v=85,-81
433 | p=17,94 v=58,10
434 | p=40,55 v=-22,-65
435 | p=47,12 v=-10,54
436 | p=52,29 v=-68,-25
437 | p=11,83 v=-71,-80
438 | p=62,29 v=-46,-25
439 | p=73,95 v=67,47
440 | p=74,25 v=81,14
441 | p=99,45 v=11,-13
442 | p=31,13 v=76,26
443 | p=27,90 v=17,-42
444 | p=68,80 v=89,-95
445 | p=14,54 v=57,94
446 | p=97,56 v=29,-9
447 | p=65,8 v=-68,57
448 | p=86,76 v=82,83
449 | p=81,43 v=96,-54
450 | p=86,17 v=56,26
451 | p=41,92 v=-82,-10
452 | p=49,41 v=60,58
453 | p=49,72 v=93,3
454 | p=50,13 v=-7,17
455 | p=46,85 v=-5,81
456 | p=7,40 v=-51,78
457 | p=88,91 v=62,59
458 | p=97,14 v=93,86
459 | p=62,80 v=98,62
460 | p=22,50 v=51,-65
461 | p=14,34 v=77,38
462 | p=34,86 v=-54,-6
463 | p=2,86 v=-85,25
464 | p=67,28 v=-15,51
465 | p=90,87 v=19,-48
466 | p=13,25 v=45,-5
467 | p=59,62 v=13,-67
468 | p=53,40 v=13,11
469 | p=48,52 v=37,74
470 | p=82,62 v=-66,-47
471 | p=74,64 v=-25,-25
472 | p=72,28 v=-68,-37
473 | p=51,8 v=-48,73
474 | p=46,32 v=-89,75
475 | p=100,15 v=-34,58
476 | p=34,39 v=-8,71
477 | p=78,70 v=47,-22
478 | p=31,50 v=-49,2
479 | p=15,84 v=64,-98
480 | p=76,92 v=75,-6
481 | p=40,18 v=54,-96
482 | p=81,3 v=1,-96
483 | p=9,95 v=-85,-89
484 | p=64,18 v=34,87
485 | p=72,100 v=48,12
486 | p=39,77 v=40,-53
487 | p=74,11 v=95,-77
488 | p=29,20 v=72,51
489 | p=96,91 v=-19,-75
490 | p=11,68 v=51,-58
491 | p=64,9 v=67,28
492 | p=73,94 v=-46,30
493 | p=77,39 v=15,49
494 | p=100,20 v=-85,-77
495 | p=92,80 v=-5,-64
496 | p=80,11 v=-62,-41
497 | p=78,47 v=-54,74
498 | p=32,76 v=24,-12
499 | p=13,22 v=-10,-52
500 | p=30,78 v=-49,-53
501 |
--------------------------------------------------------------------------------
/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 4
4 |
5 | [[package]]
6 | name = "ahash"
7 | version = "0.8.11"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
10 | dependencies = [
11 | "cfg-if",
12 | "getrandom",
13 | "once_cell",
14 | "version_check",
15 | "zerocopy",
16 | ]
17 |
18 | [[package]]
19 | name = "aho-corasick"
20 | version = "1.1.3"
21 | source = "registry+https://github.com/rust-lang/crates.io-index"
22 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
23 | dependencies = [
24 | "memchr",
25 | ]
26 |
27 | [[package]]
28 | name = "aoc-2024"
29 | version = "0.1.0"
30 | dependencies = [
31 | "ahash",
32 | "glam",
33 | "itertools",
34 | "ndarray",
35 | "nom",
36 | "nom_locate",
37 | "pathfinding",
38 | "petgraph",
39 | "rayon",
40 | "regex",
41 | ]
42 |
43 | [[package]]
44 | name = "autocfg"
45 | version = "1.4.0"
46 | source = "registry+https://github.com/rust-lang/crates.io-index"
47 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
48 |
49 | [[package]]
50 | name = "bytecount"
51 | version = "0.6.8"
52 | source = "registry+https://github.com/rust-lang/crates.io-index"
53 | checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce"
54 |
55 | [[package]]
56 | name = "cfg-if"
57 | version = "1.0.0"
58 | source = "registry+https://github.com/rust-lang/crates.io-index"
59 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
60 |
61 | [[package]]
62 | name = "crossbeam-deque"
63 | version = "0.8.5"
64 | source = "registry+https://github.com/rust-lang/crates.io-index"
65 | checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
66 | dependencies = [
67 | "crossbeam-epoch",
68 | "crossbeam-utils",
69 | ]
70 |
71 | [[package]]
72 | name = "crossbeam-epoch"
73 | version = "0.9.18"
74 | source = "registry+https://github.com/rust-lang/crates.io-index"
75 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
76 | dependencies = [
77 | "crossbeam-utils",
78 | ]
79 |
80 | [[package]]
81 | name = "crossbeam-utils"
82 | version = "0.8.20"
83 | source = "registry+https://github.com/rust-lang/crates.io-index"
84 | checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
85 |
86 | [[package]]
87 | name = "deprecate-until"
88 | version = "0.1.1"
89 | source = "registry+https://github.com/rust-lang/crates.io-index"
90 | checksum = "7a3767f826efbbe5a5ae093920b58b43b01734202be697e1354914e862e8e704"
91 | dependencies = [
92 | "proc-macro2",
93 | "quote",
94 | "semver",
95 | "syn",
96 | ]
97 |
98 | [[package]]
99 | name = "either"
100 | version = "1.13.0"
101 | source = "registry+https://github.com/rust-lang/crates.io-index"
102 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
103 |
104 | [[package]]
105 | name = "equivalent"
106 | version = "1.0.1"
107 | source = "registry+https://github.com/rust-lang/crates.io-index"
108 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
109 |
110 | [[package]]
111 | name = "fixedbitset"
112 | version = "0.4.2"
113 | source = "registry+https://github.com/rust-lang/crates.io-index"
114 | checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
115 |
116 | [[package]]
117 | name = "getrandom"
118 | version = "0.2.15"
119 | source = "registry+https://github.com/rust-lang/crates.io-index"
120 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
121 | dependencies = [
122 | "cfg-if",
123 | "libc",
124 | "wasi",
125 | ]
126 |
127 | [[package]]
128 | name = "glam"
129 | version = "0.29.2"
130 | source = "registry+https://github.com/rust-lang/crates.io-index"
131 | checksum = "dc46dd3ec48fdd8e693a98d2b8bafae273a2d54c1de02a2a7e3d57d501f39677"
132 |
133 | [[package]]
134 | name = "hashbrown"
135 | version = "0.15.2"
136 | source = "registry+https://github.com/rust-lang/crates.io-index"
137 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
138 |
139 | [[package]]
140 | name = "indexmap"
141 | version = "2.7.0"
142 | source = "registry+https://github.com/rust-lang/crates.io-index"
143 | checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f"
144 | dependencies = [
145 | "equivalent",
146 | "hashbrown",
147 | ]
148 |
149 | [[package]]
150 | name = "integer-sqrt"
151 | version = "0.1.5"
152 | source = "registry+https://github.com/rust-lang/crates.io-index"
153 | checksum = "276ec31bcb4a9ee45f58bec6f9ec700ae4cf4f4f8f2fa7e06cb406bd5ffdd770"
154 | dependencies = [
155 | "num-traits",
156 | ]
157 |
158 | [[package]]
159 | name = "itertools"
160 | version = "0.13.0"
161 | source = "registry+https://github.com/rust-lang/crates.io-index"
162 | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
163 | dependencies = [
164 | "either",
165 | ]
166 |
167 | [[package]]
168 | name = "libc"
169 | version = "0.2.168"
170 | source = "registry+https://github.com/rust-lang/crates.io-index"
171 | checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d"
172 |
173 | [[package]]
174 | name = "matrixmultiply"
175 | version = "0.3.9"
176 | source = "registry+https://github.com/rust-lang/crates.io-index"
177 | checksum = "9380b911e3e96d10c1f415da0876389aaf1b56759054eeb0de7df940c456ba1a"
178 | dependencies = [
179 | "autocfg",
180 | "rawpointer",
181 | ]
182 |
183 | [[package]]
184 | name = "memchr"
185 | version = "2.7.4"
186 | source = "registry+https://github.com/rust-lang/crates.io-index"
187 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
188 |
189 | [[package]]
190 | name = "minimal-lexical"
191 | version = "0.2.1"
192 | source = "registry+https://github.com/rust-lang/crates.io-index"
193 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
194 |
195 | [[package]]
196 | name = "ndarray"
197 | version = "0.16.1"
198 | source = "registry+https://github.com/rust-lang/crates.io-index"
199 | checksum = "882ed72dce9365842bf196bdeedf5055305f11fc8c03dee7bb0194a6cad34841"
200 | dependencies = [
201 | "matrixmultiply",
202 | "num-complex",
203 | "num-integer",
204 | "num-traits",
205 | "portable-atomic",
206 | "portable-atomic-util",
207 | "rawpointer",
208 | ]
209 |
210 | [[package]]
211 | name = "nom"
212 | version = "7.1.3"
213 | source = "registry+https://github.com/rust-lang/crates.io-index"
214 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
215 | dependencies = [
216 | "memchr",
217 | "minimal-lexical",
218 | ]
219 |
220 | [[package]]
221 | name = "nom_locate"
222 | version = "4.2.0"
223 | source = "registry+https://github.com/rust-lang/crates.io-index"
224 | checksum = "1e3c83c053b0713da60c5b8de47fe8e494fe3ece5267b2f23090a07a053ba8f3"
225 | dependencies = [
226 | "bytecount",
227 | "memchr",
228 | "nom",
229 | ]
230 |
231 | [[package]]
232 | name = "num-complex"
233 | version = "0.4.6"
234 | source = "registry+https://github.com/rust-lang/crates.io-index"
235 | checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
236 | dependencies = [
237 | "num-traits",
238 | ]
239 |
240 | [[package]]
241 | name = "num-integer"
242 | version = "0.1.46"
243 | source = "registry+https://github.com/rust-lang/crates.io-index"
244 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
245 | dependencies = [
246 | "num-traits",
247 | ]
248 |
249 | [[package]]
250 | name = "num-traits"
251 | version = "0.2.19"
252 | source = "registry+https://github.com/rust-lang/crates.io-index"
253 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
254 | dependencies = [
255 | "autocfg",
256 | ]
257 |
258 | [[package]]
259 | name = "once_cell"
260 | version = "1.20.2"
261 | source = "registry+https://github.com/rust-lang/crates.io-index"
262 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
263 |
264 | [[package]]
265 | name = "pathfinding"
266 | version = "4.12.0"
267 | source = "registry+https://github.com/rust-lang/crates.io-index"
268 | checksum = "0699ae2f1524f028d52ff9de21e06c000118731572ef9c2da81c4b6d573f9b79"
269 | dependencies = [
270 | "deprecate-until",
271 | "indexmap",
272 | "integer-sqrt",
273 | "num-traits",
274 | "rustc-hash",
275 | "thiserror",
276 | ]
277 |
278 | [[package]]
279 | name = "petgraph"
280 | version = "0.6.5"
281 | source = "registry+https://github.com/rust-lang/crates.io-index"
282 | checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
283 | dependencies = [
284 | "fixedbitset",
285 | "indexmap",
286 | ]
287 |
288 | [[package]]
289 | name = "portable-atomic"
290 | version = "1.10.0"
291 | source = "registry+https://github.com/rust-lang/crates.io-index"
292 | checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6"
293 |
294 | [[package]]
295 | name = "portable-atomic-util"
296 | version = "0.2.4"
297 | source = "registry+https://github.com/rust-lang/crates.io-index"
298 | checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
299 | dependencies = [
300 | "portable-atomic",
301 | ]
302 |
303 | [[package]]
304 | name = "proc-macro2"
305 | version = "1.0.92"
306 | source = "registry+https://github.com/rust-lang/crates.io-index"
307 | checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
308 | dependencies = [
309 | "unicode-ident",
310 | ]
311 |
312 | [[package]]
313 | name = "quote"
314 | version = "1.0.37"
315 | source = "registry+https://github.com/rust-lang/crates.io-index"
316 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
317 | dependencies = [
318 | "proc-macro2",
319 | ]
320 |
321 | [[package]]
322 | name = "rawpointer"
323 | version = "0.2.1"
324 | source = "registry+https://github.com/rust-lang/crates.io-index"
325 | checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3"
326 |
327 | [[package]]
328 | name = "rayon"
329 | version = "1.10.0"
330 | source = "registry+https://github.com/rust-lang/crates.io-index"
331 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
332 | dependencies = [
333 | "either",
334 | "rayon-core",
335 | ]
336 |
337 | [[package]]
338 | name = "rayon-core"
339 | version = "1.12.1"
340 | source = "registry+https://github.com/rust-lang/crates.io-index"
341 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
342 | dependencies = [
343 | "crossbeam-deque",
344 | "crossbeam-utils",
345 | ]
346 |
347 | [[package]]
348 | name = "regex"
349 | version = "1.11.1"
350 | source = "registry+https://github.com/rust-lang/crates.io-index"
351 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
352 | dependencies = [
353 | "aho-corasick",
354 | "memchr",
355 | "regex-automata",
356 | "regex-syntax",
357 | ]
358 |
359 | [[package]]
360 | name = "regex-automata"
361 | version = "0.4.9"
362 | source = "registry+https://github.com/rust-lang/crates.io-index"
363 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
364 | dependencies = [
365 | "aho-corasick",
366 | "memchr",
367 | "regex-syntax",
368 | ]
369 |
370 | [[package]]
371 | name = "regex-syntax"
372 | version = "0.8.5"
373 | source = "registry+https://github.com/rust-lang/crates.io-index"
374 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
375 |
376 | [[package]]
377 | name = "rustc-hash"
378 | version = "2.1.0"
379 | source = "registry+https://github.com/rust-lang/crates.io-index"
380 | checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497"
381 |
382 | [[package]]
383 | name = "semver"
384 | version = "1.0.24"
385 | source = "registry+https://github.com/rust-lang/crates.io-index"
386 | checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba"
387 |
388 | [[package]]
389 | name = "syn"
390 | version = "2.0.90"
391 | source = "registry+https://github.com/rust-lang/crates.io-index"
392 | checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31"
393 | dependencies = [
394 | "proc-macro2",
395 | "quote",
396 | "unicode-ident",
397 | ]
398 |
399 | [[package]]
400 | name = "thiserror"
401 | version = "2.0.7"
402 | source = "registry+https://github.com/rust-lang/crates.io-index"
403 | checksum = "93605438cbd668185516ab499d589afb7ee1859ea3d5fc8f6b0755e1c7443767"
404 | dependencies = [
405 | "thiserror-impl",
406 | ]
407 |
408 | [[package]]
409 | name = "thiserror-impl"
410 | version = "2.0.7"
411 | source = "registry+https://github.com/rust-lang/crates.io-index"
412 | checksum = "e1d8749b4531af2117677a5fcd12b1348a3fe2b81e36e61ffeac5c4aa3273e36"
413 | dependencies = [
414 | "proc-macro2",
415 | "quote",
416 | "syn",
417 | ]
418 |
419 | [[package]]
420 | name = "unicode-ident"
421 | version = "1.0.14"
422 | source = "registry+https://github.com/rust-lang/crates.io-index"
423 | checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
424 |
425 | [[package]]
426 | name = "version_check"
427 | version = "0.9.5"
428 | source = "registry+https://github.com/rust-lang/crates.io-index"
429 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
430 |
431 | [[package]]
432 | name = "wasi"
433 | version = "0.11.0+wasi-snapshot-preview1"
434 | source = "registry+https://github.com/rust-lang/crates.io-index"
435 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
436 |
437 | [[package]]
438 | name = "zerocopy"
439 | version = "0.7.35"
440 | source = "registry+https://github.com/rust-lang/crates.io-index"
441 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
442 | dependencies = [
443 | "zerocopy-derive",
444 | ]
445 |
446 | [[package]]
447 | name = "zerocopy-derive"
448 | version = "0.7.35"
449 | source = "registry+https://github.com/rust-lang/crates.io-index"
450 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
451 | dependencies = [
452 | "proc-macro2",
453 | "quote",
454 | "syn",
455 | ]
456 |
--------------------------------------------------------------------------------
/inputs/day06.txt:
--------------------------------------------------------------------------------
1 | ..............................#.................................#...............#........#.#..#......#..#........#....#...........
2 | ..................##.........#..............................#...........#......................#........#.........................
3 | ...............#...............#...............................#...#..............................#.....#...............#....#..#.
4 | .........................#.........................................................#........................#.....................
5 | #...#.#.........#..#..........................#............................#.....................#................................
6 | ......................................................#......................#..............................#..........#.........#
7 | ......................................#.#.....#....................#..................................##..........................
8 | ...............#.....................#..........#.......................#.................#............##......................#..
9 | .............................................................................................................#....................
10 | .........#.#..........#....#......#.................#......................#......................................................
11 | ..........................................................................#................................#..#......#............
12 | .............#............#............#..................................#............#...........#......#................#......
13 | ....................#........##....................................................#.........................................#....
14 | ..........................................................................#.....#.............#................................#..
15 | ...#.#.....#...........##..#.......................#.............................................................#................
16 | ..............#.........#.........#...........................#...................................#...........#.................##
17 | ....................#.............................#.......##..#...............#.......................#...#....#..............#...
18 | ....................#..................................................................................#...........#.........#....
19 | .......#....#.#..............................#.......................................#...........#.#..............................
20 | .........#................................#..................#.#...........#........#..#........#...#................#............
21 | ............................................................#......................#........#....................#.#..............
22 | .....#......#.......#.................#.#......#..............................#..................#.................#..........#...
23 | ........................................#..........#...............##...#............................#.#.........#...#....##......
24 | #.....#..............................................................................#............#............#..................
25 | .................................#...........#.......................##.#..#......................................................
26 | .....#......#........................#...................................................................#........................
27 | ..................#.........#.............................#....#..................................................................
28 | ...#................#......................#....#............#.....................#...#..#...................................#...
29 | .#.#...................#........................................#...#..............#.#...................#.#.................#.#.#
30 | ........#................................##.#......#..............................................................................
31 | .......................................#..#.........................................#...........................................#.
32 | ..........#.............#..............................................#...............................#..#........#..............
33 | ..........#................##..#..............#............................................................#......................
34 | .............................................................................#....#...........................#...................
35 | ...#..#.....#......#...............#...........##.....#...#......#...#..........#.........#....................#....#.............
36 | ............................#............#...#..........#................................................................#........
37 | .............#...........................................................................................#..........#........#.#..
38 | ...................##..#............................................#.................#...#..............................#........
39 | ...............................................#.......#.....#.........................#...................#......................
40 | .................................................................................#.#..............................................
41 | ...#...................#.................#......#..............................................................................#..
42 | ....##.........................#....................................#.....#..................................#......#....##.......
43 | ......#...........................................................#......................................#.........#..............
44 | ..........##.#.........#.........................#......#......................................................#..................
45 | ..................................##.............#.#................#......#..................#..................................#
46 | ....#.............................................................................................#......................#....##..
47 | .................#.....#..........................................................................................................
48 | .............................................................................................#.............#.#....................
49 | ........#...........................................................................#..............#...#...............#..........
50 | .....................#...........#.............#...............#....#.....#.......................#......#........................
51 | ........#................................................................................#.............#.........#................
52 | .............#.................................................................#.............#...................................#
53 | .............#.................#..#.....#........#..#.................#............###.........#.................#.............#..
54 | .....................#.........#......................................................................................#.....#.....
55 | #...#...........##...........................#......................#.........................................................#...
56 | ........................................#.................#....#..........#....#...#.................#.....##.#..#................
57 | ...............................#..........#..................................#...............................................#....
58 | ................##..............#...............................#.#....................#...................................#.#....
59 | ...............................................................................................................#....#.............
60 | ......#......#....................................................................................................................
61 | ......................#................#............#............................#........................................#.......
62 | ...............................................................#..............^..................................................#
63 | .......##..........#................................................................................................#.............
64 | ..##......#................................#.................................#......#.................#...........#.#.............
65 | #..........................................................................................#...........#......................#...
66 | .............#......#....#.............#.................................................................................#...#....
67 | ..................#.....#.............................................................#................#..........................
68 | .....#..............................................................................................................#..#..........
69 | .....#........#................#....#.............#..........#...............#.....................#..........##..................
70 | ......#...................................#...................##..................................................#..........#....
71 | ...#..................................................................#...............#...............#...........................
72 | ..............#..........#.....................#.................................#...........................#............#...#...
73 | ......#...........................#...................#........................#...................................#......#.......
74 | .................#...........#...............................................................#.......#.......#................#...
75 | ................................#.........#..........................#......................#..#...........#.................#....
76 | .........................#..........................#.........#.....#..................#..........#.....#.........................
77 | .............##.......#.......................................................#..............................#............#.......
78 | ..............................................#.......................#...........................................................
79 | #...............................#.................#.......................................#.......#...............................
80 | .....#......#....#........#.......................................................................................#.............#.
81 | ...#........#...................#...............................................................##...............................#
82 | ...................#................#....................#.................................#.......................#...........#..
83 | ..................#.......#............................................................#...........#...............#..............
84 | .............................#.#....#..............................................................#..............................
85 | ..................#...........................#.............................#.......#.......#.#.#....#............................
86 | .........................................................................................................#......#.................
87 | #....................................#.........................#....................#........#....................................
88 | ..............#..........#............................................................#.........#..............................#..
89 | ....................#.....#..............................................#.#...#......#........................#..................
90 | .#.........................#..#.........#.........................................................................................
91 | .........................................................#..................#.............#.............................#.........
92 | .............#..........#...............#..#......................................................................................
93 | ....................#.#.............................#.#.................................#.........................................
94 | ....................................#................................................#.....................................#......
95 | .............##...........................................................#.#....................#................................
96 | ....................................#.#.........................................................#...............#.................
97 | ........#..........................................................#.......................#..................................#...
98 | #..........................#.............................#....#...........................##..............#.......................
99 | ..........#...#...............................................#..#..................#...........#......#...................#......
100 | ..............#........#..........#.................#......#...........#.........##................#..#...............#...........
101 | ..............#...............#.....................#...............#...........#.......................................#.......#.
102 | .........#..#...................................#.................#...............................................................
103 | ...............#.........#......#......#..#..#..#................#..........................#..................#.....#............
104 | .......#.......#.........................#......#.................................................................................
105 | .#...................................................................#.................................#.........#.........#......
106 | #............#..................#....................#...............#.........................................#..................
107 | .....................#............................................#...#......................................................##...
108 | ...#........................................................................#......................................#.....#........
109 | ...................................#............#.......#.#......................#...........#.........#..........#...............
110 | .....#................................#.#..#...............#..................#......#.............................#..............
111 | .....#......................#.....................#........#................#..................................................#..
112 | ....................#..............#..........#........................#............#.......................#........#............
113 | .......................................#............#.......##....#..#.............................#....................#.........
114 | ..#.......#..................#....................#.#..........#........................#......#................#.................
115 | ................#.......#...............#.........#...............................................................................
116 | ..............................................#..#........#..........#...#...........................#....................###.....
117 | ...............#..........................................#.........#........#....................................................
118 | ..#..................................................#...............#....#.......#.........................#.....#...............
119 | .........#....................................#.............#.......................#...............#..................#..........
120 | .....................................#..........................................#..........................................#..#...
121 | .#...#............#...................................................#...................................................#.......
122 | ..#..............................#..#....#.....#...#.....#........##............#........#.##.....................#............#..
123 | #............#.................................................#..................................................................
124 | .......#.#....................................#.............#......#......#..................#..........#.........................
125 | ..........#......#...#...............................................................................##................#.........#
126 | ........#................................................#.....#.........#.#......................#.....#..........#..............
127 | ..............#..........................#..#..#.............##...............#..............#.............#...........##.#.......
128 | .......................#............#................................#.........................#..........#.....................#.
129 | .#..............................................................#................#..............................................#.
130 | .....#..#........................#...............#....#......#........................................#...........#...............
131 |
--------------------------------------------------------------------------------
/inputs/day09.txt:
--------------------------------------------------------------------------------
1 | 9883356733752069656661181949779760668336947879672334631498492012279248564815678743918257448799319394268097164282313431712170232427711341278448916123555398963258649192254954428653124048627490363654445098463746705264577434331872739013223257852686325396697166785638826129755245235190709399598738659344508060635161185663324868573885182433469142265019784585737647295954667470632356552310324986978582442373946683324324964975714411442032304368571210978040452375554437723241626980594046753116656563509033582217499974991050134612298676291437298830232670458958219114171954451027352367739620478811495628756386541454713737366356111396226531647796778156447213557264103125841191713843757879301825505533453412476928891777791351737361271824619255577975586534476383753744919060501896538114501577965998706141772971209530162029611212394330506366554760555985142486615059863665687038214179699497301518671235225039492252152831716676249276459715873878384073464072107130115017397861339839974612262240665898961586771878531734607833716543388957148829186678512928177033946090629333529733506188186491613897795746195676809483647332656452184268453163657020142050372765496336683247811884935692201117801592269834244542309222751840604155598822227798309394498363764883786862121857736540788261474227727573412175921075911613378269583723493564169193703048107587824874507062172662316199464348924079568980207043197747731699644026757735542726813181286644228218672046427990847221832377789165397153394375317488763889333787123219407819215168529579908731886226239268502975706487441416997356682064305998636328307113664355564840868361978472573841164836852638262380254558998276331311259321936449351314839691926943221768453235649270701181576626894059389974499339646710732716693944726670597014216317455536154850912570211723421084726837163066678451494298835856395177169799446984621942806126353719503476824664397994141971252455842399737184857680309555968583267395151918467779142081885016329640358734318651614815274714217361819541411245482744942727223724341036719762295093691593943642695981904245811763931437506664169019253386477962205615978146656122809239164153984041695920788386152526156651567161529613461075949987112434688430577931309566169938658238131388748673502393192966732727669176892230919335512042768019752490429924614995548790485236919892572581165918181889945981625991679388139740392886185070704069391458729396629064967719294157985428512749485068703151629444515826641465363794311668907458547074287419227448154297192011603664309292416178131683644752872050258037223667895571881735267731619682303693113966616892347897586716546532647515254969203958682032224086613534856095312173392176821627487358438155926690388994175855839248259592583158115924176581194228135144321212144612404814173818165971197080324010425577891463533490228555831854329959177368166973665428489143193498369966397039974022459115212827302769786335383711753289878858888347477763603116959748371911358872941047169133943230873983851190696084753533987563447044225998578548836074893487135550728570221787647980451277456271891871624638884052965468227916727087869861795555886885968159474793392795528716972474306285699940177438694265557321776690614226501349518145887036414862424271735173151666215396509958697963466163651799397415229168111121912551489570394885715344189110112361282433604124163632175357526337118452132159963182341630539680977021753880579239457089551634994026538289663528325339236328152566952086836038905324227172132834124329594591191923629950743453145992306064672222762235807963593817695660515172482489453688919570595591433751273030183683714995478755667593325936204584941326969197226471128682728999845978288190492744518431783416339478743290182163593658604157792595274347414386866048553430198923828336873693295851831465287047112486725349632081905333758331119996211127566234502295418282558161312537781738584112391614856516295872955898538881702494502275922438131954803275957973305149586967106220974672724018361192186118906128163176626674873244874518431436966840218178724296142054642332557418129132414956123214407158419679596279181341745495813039235143194037441769115217676181107224378686288044659623815988405093577141274491494270284546184583747873214053423324458846314462282862392472318084336060531738151829485076295782113040501365477364524166505660316865952326609661798143592651341054228799358817759077687559318451287829184584385093763848924720114437615427904852166522586453549189178513691669963062202377767713866084969138581221644642388399515572532717438159263432583293559754549669296578758984347086627546465729605425905342101995416573335592158918466882541643249199901697467353472250175852479938791414295165433144796691478486471251301526439296744457536479351413254751913262292810401851177040286959929252685979462173928453424181742375153072621370196987618980939081678477621248512397161496561374797886371885134691398185204413863348846133589520134176681445787399786095818933664384183427582728461416372811364896875186814192397537182244209297699374782329548370982283244568347180377438697436769588211147489572225869289915678735405977955611786722962839425875896145836157532148177590323673661595675760398879674958588684941757527660131284495090587120429395916753595621718487925288324276511897387259894614543017155269757980165877386816289598581129741553826921279815849997601295477318217671633886459583199792664652792237553557298879911191726664957522628280488559609331673161471215491261656077833025156243223613651267812936647915922771602291878249426456657170877766652440119725798137236697446243623747952092198298491293717551344060899159934356754713287233988775597913407833832821517710207972896154637773949752549652316350784061433763175887354294973443432075491063295635718679865271717197692751216898466464977727373035735337619642315897228286778046935972676291157094792637486367344697926164362672118840126234222022167810474828404259701635339838619688621165477773519813975974119050657962471951967662135826361927674365912932544210327883394764742693492498358639797913793165675220263267764515187896594166988398323144988844332310409276448397888411314185882019538359434410898991975023609032111767196983746852191727117694312525529312979422563983596667231244735696227768231823394254706367861427999915841574871739502958495024921482375264347725117418369250437463793329785224905992684494976994345413663252629190526169492437863027811827395072638493319834411679973598833926917635318230847549926486984555575936265161249083679957775878456430244885781189527810586767371570268733339614916325492498722861462145144585172083785627558451569647242372647113602570963095195526251747743377484637208429169391841791576577821548784743847045603848253573396726986010488485724511296317779148953279124572734961525144663788541031829439328485764236389524725750574924955224512159226810741863167669289751303648851248799554104765601536179821872419916433506936555193536661706634688039295915461836968769163994341118639640919795404147933484583999255262835130509610115293919094802334531636491840487441956648269753906091548766333284886769567419576499547484957039103052141481667125596671194617264176102970392179201337564770912210943015203357549427894822516880757125855017481690143193859769698923759315353860205477764052446110158873208167146159773031609545598613924922403957894319914486214276285373267931326517925796713440119530959681465422502431124787407210719016601289473011936960634435865472728412594038314377371629989325451260597040987079419244216625219042928049436462823767396545627662384468208636911356935412866488682223105098704351917686462317462737495078259533819724563196142740383870838970398824897218624563153918243444288932986299583879434777872728797391951096517361157031975220487824964765206833417591584320413070957565462750869468118068739887353356173251883879564991782334983239994675671187964648348746364977932941578098106497518274593629998739452867233724301617247747461181675033569757405914624084617431304688551663802455601699952448718537227028642394647845875030162873474155787570389232502111833053786758397197444912285715931641452866459016135571438420905596182318851743513973274885643988767539699913422282465984693031233445641547432292324497816881584881921455407546983543982744914223211481551713388590165443467143836213704116936644913234302732419476714536653492541650193538583766675980411225258388904469808333548776389373554798162057953994187749792157721191417115879418923652566924322175113370123291248866131934728030871129273756323138454526744397714477164662678170266767207738141737322444457262818889918657723047277336639311422661292245415664665679939720685089986275972755469876619265807572869691812540143116946188305772525451984316529142943847739769364089668278532341472668899964548671801677547655284524691522845863907661332425473048796291529060104646943543242644785993667484604322619926714135363664242234797818669825284349641067348834638825937976531164702993654755267026468028282322151318323383544912891799584927419399711257932820524019511648983147707319416212138761983179614075947884513751587480556343267138511220492730932194903095129997865667752025896178168778312769676973313741946364158284663676712581126191594749456696356943982985719792718120283071634894639782876384942619186629285514244646446276811559585938784996513539217080497590264040595468899471826313528045222311973659136224168474477073263710714312401516298752783723733132576294375148917549801687247725786096953910635612158423264026364767401629672977142824675884437978818877532650467813881335887184169897801949479139561121557374714268112312199674693378383123551841124152525635831483769084201285222988529225526427724820512611976717757032616330475269684298802332721518172382643261568798115759763674218539933065288769882029276526988932997439668829252573177698311294149983775050129494971332155834229542614384614363789299582468619481794753538878237078822093177480229616893650739618186560477853494015808190999386187221112835682661778530254353528145929646747070418588992874869834336747784160803639119869908434708286816737919416936766484365789961689581202667178412841418237921974335931834162381924495532571303286135047781690531425403085662520734974325720961919706653973438432277444132257635723236242481571736157614721619937912946235708370677284684287286862917742881055988327311457301546778244851128724568533537594138537178639297353880705637612885877136336013214118283975679792134536326662228548882487671665508189766433747463795533452639259465391358181697587065279138184314602959371854621675838435832258336496237617779993735667418234176146936436259168947396682999894955659055817127357567593394797375162816495112742211472421417542734461604328877268347132677528833365101399549177105986645449119996561338576983732761367813185275335861292594267441516546978885868731537195649458896524546124693268162248306493697839383363454521958915751930925213217627713472521830363388882813981333293378479633651931984595923183929922702834966844285456469445105126896854368696946254668381641788305986462240835393229783999080156430716930181457195935656397784952542830289785909252153982533332458022803474184516234763684521705622811145679082151287356723537999356814512532528949528969579149153420261525717336728254855457827980242427304257316437821868161726375297745426711048769060879245681159838438595564231082891597185147474329185291245193104954341266827012466119427710716361762496497271526730643241627790778667959896345064608438662893761130512829847121145443214639412281277646244264293479869736776852446198669374601371636554711726845892357654378590208272665129166086236636718157524337811652279283845620103951484662204444137037838593716574932031815427231056635580608546296233386598571968384441443263648547513657497758603765738354528157578318266460565644125676694848913622905317825980542226791695123783728881592098922243741934607241892380764459272741695817747362868038577165359829287047994916661958583447543716265743491084349882309696279131416771192463894871798276256038329986927658216244841243929145518992274721935892717037751987411022129998674498981942906222829795881667831050857254179929636697862155557081207248336012849368586846364246682468596584227918659329347194812776589361831491585814421023357676102175876363832595274114137536209574544825362219561319284938214024903748803539392679528466299824896550804443446613188281353444468885625310638293952010346964995524861034529197984964478376694431778475374325642770609251467057219274367932833869822783514718836563506163534338548484114576359459802354886311741960628279479841178795893845551568269399577846172279124161435489342668586349317329872674326228863962813645315423417015676112675571905611663349145153531034403010121230413525237243926568443338495356568037999870368212631424971015639252197676896218582221271633639584863883476422801093982915855989315079981481115653656515396597144516992884707788254456898021105752159350207689797625203774248828666824178049238211545072717756141020453086939596358067154454469827485749165218223445948739163333769241679325826049572488739978581560321865462558686412232868766211387579443898987472933063362273276621648570879416542180727314369154377940658965651537136769401910424984434474599717628123277330632597717052328514961280987692184774529111165996376713335716915097503778196741959743976712578096663843919527843748966263645268486572487333199866647414302517185990944275189279599476108948814844479797451994857498825139308999362277975838752373876849765353406321518493719024601398967117126675684438324214707255963551912627812726823467271440104569959638701254673847686892322659269438191292454640589915171054541779864960196872759993272999994361558930322226339250552928878051612070104913719592769739527543664363208299845051598218159315165292706331396133576692331148869665783187473163779475127711144998841473954184711296959670998035235763747529647456188252616397511064495832622610512622429821445016327820975755998693842362134465609270863033129961562396549435338586198563992216846142989932249969101535435684889022218510866318824367526572944795701266531259966291826331565950189825647174682838183774427947415560816811612050352737263973105281812389921422711087164182568670317165646714182440661055381478247181808580511746476874721445762976444141977588173328242131227147488043102351806698672280663128174352336514938599305131889693142336129066813611434424702467247362593013386559353821971589679097811575497399196911143992496274655978715883136585606930437668166225566586741178663830337748666120654313345564131888351942751929813352616568583531656460161360262287989055923449115723314312638598644347357852101229638211295235826199419529564072255776988278266041606510364484421272474269671333233171755916647444617057792777362758456493823114691019916823794563693224567965699772404738498892892557987349753045507189862756513479963084918433846043297773713552184735178444528529507922847850182748671835105892964058384824129948415690909067469252802112289940747020107042618913975694113861841296315448998338729770706075176447644672372642955963407027866531611342959968281356672696924293668235378697525664912724784027164858201094527579287624679181197234361482684077871276728788159435699350564246701177267853685421366479418977384867802955803067623018421043596741295395117381454523186422615430398196242825218139756498107776299919923990277614317514254319647176164774539059469459273156184687134886732289347259323082461959973155364576553041157952443629422394796120594888385496545177775875756325861926214291185063481294874928731422799598285482459849358195636148579116417121745476449279823242866066102823274343994631233029913997472636963847165053653696105325181531381750769133645956354365722982219734651340188174673327944331893427496810491589427270289639402646226711287010197277345173318251507755146643547630528289954530503112342780875519312760138141619322496324657264428630303552269369534148557144298743224786459285322472673681943125554985948163842575129682236661127655346054589393817658386596419268328656257467429815453879409578518592706815886573863879378611702782468230408029978028193858137498781550798897337390615839457199397428111413722777763676128364606334909374439676673672853531726417616987867187914722739850898627299196541262145670152016219190857499211168453797692977572959281597929397822962477717615984396274164939506022776754941341182160748969968767598617169581662397771428616899186915696495338679451035999757834370354924879113741549942795772923668558947377915787314396371394784574968656158657565034693327456669177542915051905575476059783220545938234511664396882360139286175046298217436760766478444144239015741869846029592198486630951993557029614379476451855626704420128482327451306211791445514343485438834838254817528567461895424434927737596953315987301041864246188076624099882225138985974070315096895247371594315518941299735368195663976255876311536117877671696713896571239689407411105863756557126785316795308321935041688243204793646782432842896615328240411178152380836310798421441414998550662721133367707695624710896079356996993398863426731931367136278855144259958374123588219098301313434052176087104260814545475984715232614135281064485520635647985723917549698547635161714156946491604895132583175915936986321747784782159327832216262363512314463047832025813650866580461426239786919410892638354986248312186078607613292361444941481225631938207179352183101491743583202525718936755176273745476514797419679385413652583789695544452574488910931419803094382972331662155934237519663035824462139056969293596223386740271396244648812626208685795151783198808765533716762215903286314824679789706966919730981389129868223264509149918326231354949775592894773060947721231771567520795093435943298935531127156036153229527893158193692547394157985344892778576396165853941433272563854629232415414558109468168580524017852887924867859193824113874799836175795642352189506093747771622286795913321781835214247039494167143024926110785963995243168120124151175117527585514788423023343548337053489558454252283119447817657214985891662945789263812772977599415677761196381630436217542659189774895473905068312810114795404115752971807892372944385039542765599320172062393919675693863178204285738196311664432131437198895895167079642438744971794673623472384321327130295244905287363349231569734748752634443433862991718624123293493795753482352958876888186729827834136910497521113229382378264724465037498817795944301971554926639884344917864352912850815182373519382370193416377770789013827445711290637077463235494549834253518858208063208837324028968650398093293415238250209584476670813270577333236447449476915841657725403640513440989848444096261146604093177865856867612867554348642727386495831786896854473143839375792289368695951677651330795881722354919165985744364645495588387635765512585336994940947050403564912573644162129261158863226697959180185853225285948933473694429341622845108910986057958186228283388596609389382957848980671524959892333379899910785149696732686117329513644252644981691769313951562037421222993327511475946320337518332434356511712259919160684168129731625519709719108515583846226357991832662963654427133359517239771987149692949560235952873845479365716649255485336458641678652557832418958364273773454558921840679291282097401461794629792769898821224694171789318371185634581664575790211914303680806346953355577035136965373530349083216614907713955965674163396666802591993767767387548959681183517692702051751690279948371546689786275717953692839630869253939643739644632081737839636392969140819870364611893354811171277341897772942685307541378978725525275544286263658370642730212142991677979888586318155787998298197290786627724729871127129226649077369522214915591915613284422234968237932718685496539140297692797728656173577027541573318631905889913920278168965292503997496138847265404592246221721197612058875021818240531368656885324733776159855470235250439667495331505251964381962790644713216414954067451724232177991311285437255575853951924022769756568557759888934784289431766810165798775124752348769764812653485034652388885945266761959047895756407468418363815018837670378564595271856184176694895293417846989544812915358344271478803880344167564821918594453538344091329
2 |
--------------------------------------------------------------------------------
/inputs/day03.txt:
--------------------------------------------------------------------------------
1 | why()$mul(735,469)^?!what()don't()~~('mul(982,758)what()^-^who()mul(294,364)/ )&%)[~mul(285,81)what()[{where()+ mul(129,761)^]why()>$^<>who()mul(53,344)select()%mul(567,352),mul(915,20)/#(>+^how()'mul(141,658){&~!how()from()?~?who()mul(830,116)#%;mul(139,634)?,#+who()@mul(169,719)[)?'-who();mul(18,751)},when(){;/mul(691,391)mul(856,314)^mul(558,88)]('/>how()@where()(,mul(274,100)%who()#~*mul(220,748)@how(){$how()/*%$when()mul(718,754)[!when(617,291)!{(what()+*do()[;<+ /from()[mul(840,803)}?mul(429,848)?select()how()^why()],select()mul(519,894){ !>:^@+mul(522,225)@!^^/'[>select(118,66)>mul(847,195)when(585,749)]mul(641,667):>mul(317,349) +:/^*what()mul(352,440)select()mul(349,981))@mul(450,917)why()how()mul(471,401)?where():}select():mul(632,956))mul(727,370)!}$~*%+$don't()why()select()^]who():mul(276,773)*^^mul(757,668):}mul(232,346)%[*@$ where()mul(898,992)who()why()~+['mul(43,434),where()who()>what()mul(908,953)select();do()}!select()when()!mul(676,368)how()from(966,785)@:$+)how()mul(414,120)mul(108,395) +~{#!@select(),mul(483,964)&do()?>mul(963,893)$,,/%'mul(318,508)?,{mul(390,813)select()>(select()mul(792,357)!{where();mul(717,18)why()$#]why()$^?mul(948,239)how()&>$from()]:>?select()mul(453,180)&&]&,[how()mul(674,281);*how()mul(548,919)how()]{{who()~+where()where()&mul(962,14)/why(),%>when()mul(31,451)/)&:,>}mul(225,266)-*)where()who()]#mul(224,69)#&-+~mul(309,393)@#;%!(][select()mul(389,558)+*how()*^+when()]when()mul(995,181);(mul(5,74)&(#^from()$~&don't()}? ,($ when()mul(216,767)>()!,/how():@mul(425,905):]>>from()mul(93,831)}select()(mul(70,72)mul(137,510)[]{where()mul(477,400)&?/who()who(335,756){/mul(364,311),$select()what()mul(710,251){mul(351,763)+-}mul(517,661)mul!}?how()where()mul(948,407)-{<]*^from()who()from()mul(979,180)/,:#mul(602,496)%'what(),#}what()~how()mul(343,710))'when()from()#mul(314,877)(+,[?mul(480,685),;do()%*<^)from()what()#@what()mul(502,65)where()why()(!*where()from(){/mul(847,541)mul(116,490)]';how(612,404))when()who()&; don't()mul(446,220)(%'?;{^?mul(784,876);)]mul(959,402)%]];mul(362,432)mul(330,805)where()mul(142,473)~don't()-who()mul(965,688)when()[]):-}from()%mul(949,478)why()>~+,!&~,select()mul(633,237!-who()>where()]mul(809,464){@'/when()when()mul(720,462)&select()select() )@}'~how()mul(518,133)mul(512,118)/}what()*][++mul(56,978when(),where()&don't()who()}where()mul(329,879))&$,:when()#when()@what()mul)~who()(;mul(141,130)'?^}#+#from()'-mul(237,78)&what();];%where(614,809){:mul(391,45)mul(787,970)from()-?&~when()mul(59,790) what()where()~?what()mul(399,503)^from()where()when()mul(190,97);why()who() ,select(){mul(428,654)mul(350,302)?{mul(592,241)when()how()mul(705,191)who() !who()mul(50,6)~'from()% &]mul(902,106),select();/ why()from()>mul(800,867)select(659,586)~ )when()}~&'mul(709,298)-:'do()[who()what() mul(31,997)$%(where(309,559)%: mul(177,184)@mul(58,102)
2 | '^why()>-why()mul(489,67)who(682,115)where()how()>why()~;'^mul(179,994)who()#[+when()}mul(343,121)]^mul(622how()select()<{how()mul(315,335)-:%mul(611,869)who()when()$where()who()mul(242who()from()%&!['do()@:^-})}';*mul(266,851);^[{!&why()how()from()mul(980,269)^{where()how()/where():;+mul(971,795)#>][+^where()mul(279,554)/why()mul(736,24)mul(63,622when()who()how() -;mul(500,888) ]where()where()when();mul(255,25)<]!-,#!+how()@do()mul(670,579)?(//]from(41,426)$do()mul(427,50)/%mul(359,247)'what()~{~-?[#mul(862,40)]{from()when()mul(426,212)>who()mul(653,462)why()mul(15,779))]mul(258,38)how()**$?(}% ;mul(624,853)[;&select()where()*-)<)mul(111,225)mul(440,503)/what()###mul(840,369)who()mul(529,595)>(-/who()mul(168,832)mul(658,544)%:~~)what()why()%+]mul(358,878)who()'$+@-)*mul(30,603)&-do()mul(627?mul(834,46)+when(751,926)-mul(132,173)who()do()-%where()mul(487,54)!$what(),{mul(546,92):$where())&/mul(978,930)-/mul)#mul(693,136)!$select()mul(490,906)%!}({;where()mul(853,453)*]!<%what(85,66)+ mul(720,355)]+mul(65,942)? $mul(736,168)#who()from()< %mul(279,223),,how()select()'mul(949,79)@)-who()when()+;/why(),don't()~(@,^~mul(55,965)what()select()'where()$)?mul(615,265)mul(801,65/why())mul(55,877)[why()+>:~&%~mul(418,463)from()+'who()(how()who()when()mul(176,831)!#'mul(350,399)>'@{ '!mul(847,397):{who()'#$where() @mul(148,609))&,+,<->$@mul(475,800)who()what()do())}from()&why(821,875))mul(675when()select()), %mul(786,308)-[,/,+mul(305,3)how()what(107,974);!}+how()mul(535,976)from()[)mul(820,558):(why(){^mul(715,523);mul(288,378)'why()$why(),@mul(184,850)when()'';^where()mul(957,549)do():~{:{)select()mul(347,642)from():(mul(834,376)>mul(803,111)(,,'select()select()who()[ !mul(143,742)+:# {mul(891,385)where()}<%^>mul(995,109)'?from()$):who()mul(414,498)&/%mul(809,958),why()[!>,mul(591,908!(how()}mul(600,673)'%* *mul(48:$);(/from(371,7)(>mul(261,884)?&don't())mul(246,229) >;*'&!don't(),+mul(131,199),$don't()-(what()mul(13,595)'don't(),who()how() %mul(839,198))do()select()*from()mul(903,555)what()mul(74,674)%;@mul(190,543#)])[^*! ,>mul(428,756)/:>+%?mul(585,685)?@~/*why()){[mul(87,499)],@~!}mul(585,674) [,],]}?[:mul(511,978)!?)don't()&~*mul(735,638)select()[{from()!{>mul(897,633)select() #*mul(680,8)mul(671*how()^mul(580,632)(} how(9,101)from()where()'<&mul(936,112)select()what()how()#mul(720,608)'&^/ &when()@mul(697,116),#from(),what()!where();(:mul(833,800#mul(842,722)why()$from()[(^from()/mul(591,920)how()(don't()}mul(65,254)#why()@mul(696,883)^?what()mul(917,413)from();>{~mul(524,943)mul(465,955)how()select() &how()how()mul(528,18)how()]]do(){who();~>who()&mul(837,821)
3 | +when()mul(957,88){mul(446,234),(%[mul(225,735)mul(616,489)<[]~+@why(274,559)-why(45,518)mul(841,337)@mul(826,883)-(where()don't();@'+~/from()mul(829,811)(what()how()how()#mul(435,969)mul(743,179)from()/'[/,];mul(797,84)[from()>:~&$} mul(934,535)@?'select(),,<)mul(281,662)when()why()$>})%mul(630,155)]mul(81,271)why();@;%]who()mul(616,154)^do()^)-*;/mul(562,475)select()(select())$mul(119,594)what()?mul(103,712)why()(what()mul(358,496),why()~+select()what()~select()from()mul(316,752):+^mul(851,254)select()from(){when(216,975):*mul(776,658)from()from()?!mul(724,606)from()mul(878what()^%'why()>]mul(920,733)mul(500,262)when()why()do()]!who(333,560)]why()^ ,}mul(594,767)~':}!mul(69,623)})where()where()@-^mul(510,559)from()where()mul(990,412)%)[ how()mul(627,280)@mul(314,481)- from()how()who()}'<^*mul(515,459)$how()do()]mul(307,482)@~( $(@-%:mul(460,946)%mul(942,646) {>mul(160,832)where()when()what()~{where()&@mul(24,840)^#[mul(344,387)#how();mul(525,285)mul(221,638)-!/?#-$^don't()mul(91,395)select(43,376)what()]~mul(677,682)from()$ mul(358,545)$+%mul(697,89):how()who()^mul(599,952)?where()#mul(752,46)where()* ?},#'mul(803,569)select()+()-when()*mul(5,223)'<])#~*^[mul(360,79)<$+mul(784,713)-%when();from()why()<]mul(288,526)';^~do()[;where()}%?<^+<mul(25,575)#^;mul(169,580)when() ^where();]mul(575,888)'who() &::,mul(172,538)@when()*!mul(718,235)%+/mul(281,117)who(),don't();what()how()select(126,34);why(460,565)mul(153,278)~when()*]mul(284,592)what()#@mul(416,344)+how()from(472,343)+]+*? mul(218,315)who()#:$@{}mul(415,704)mul(367,153)*where()!'do()what()[mul(298,416)<'*$:} !mul(8,562 ~#/[{~-$what()&mul(312,424) '??mul-$ -mul(49,590)>[+{how(472,207)]^mul(482,423)&why()(#^' mul(178,565)~^&>from()!#?don't()why()who(596,596))who()from()>how():{@mul(385,718) ~?@//**mul(783,105)~why(22,278):#how()do(),from()!:mul(40,924){[when(),/*mul(694~+mul(311,607)who()[/'mul(744,908)%>: ]~,:mul(310,993)from()%:-(+where()when()[mul(455,786)from()~]?from()^where()mul(460,406)how()when(831,855)'where()>[,:mul(250,253)~:select()){#)[[[mul(825!<{from()mul(205,719))why()@?%mul(729,531):where(); $~ mul(547,617)when()/mul(791,433)from()%select()what()%how()%}}mul(616,548)?%:',when()where()who(),mul(417,691)mul(548,124)<-%mul(459,792)mul(93,742)&from()who()select()mul(38,516)why()$ ; -how();mul(682,71);*why(603,344)mul(588,565)*#:do()'from()!who()-mul(564,344)mul(58,41)mul(881,91) when();/#!/usr/bin/perl!+'mul(791,572)
4 | %mul(264,168)mul(409,229)[#what()mul(393,212)$-from()'*do()mul(274,560)-{+::&>,mul(778,511)when()[;why()'how(701,98)%}mul(630,304){%{>*why(52,488)?}[(mul(149,108&'why(222,790)[mul(8,101)}>;why())what()mul$-%^why()mul(823,831)'*+mul(2,756)>, *don't();/}~&mul(602,479)~%)from()*}-when()%^mul(849,417)$>!-+from() +mul(280,463)'select(),@how(637,7)+&?mulhow(771,951)$mul(373,910)what()when()from()-]:why()mul(835,707):<]&when(915,675)~mul(628,69)&^@)mul(419,539):%:mul(534,992)'mul(987,602}why() when()]mul(438,915)~}$why()@!'#>don't()^)}?-select(355,550)},,(mul(649,262)^ *[&}/%mul(867,47)mul(104,808):@why()'@'($$mul(74,805)what(597,630)}(;]>~mul(217,927)>what()mul(669,965)>from()mul(647,126)->mul(52,497) select()mul(22,612from()why()'mul(277,463)!mul(473,104)[!:;mul(655,992)how()>%(what()-mul'why()!&where(11,929)+mul(314,422)$how()what(610,732):&{~}#select()mul(517,349)why()!mul(815,441)#why(349,312)))how()['$where()[mul(593,303)]#$^;mul(901,6)<-}:,who()mul(254,964)select()@['mul(297,705) who()#^mul(794,226)when()who()who(562,667)>}[mul(265,242$'from()@}mul(724,493)mul(313,610)*->%,mul(83,839)^)%mul(149,753)&when()select()from() 'mul(3,784)select()select(715,428)mul(502,975)how()who() !when();{[mul(106,800)<;mul(513,728)select()select()}@;':from():mul(259,697}'$]&':+mul(998,295)how()@who();!mul(947,199)?/what()where()where()]mul(415,221)select(487,105)^mul(688,128)#&mul(394,445)mul(384,810) @!why()do();&!where(424,549)why()mul(934,449)%()-^from()?who()<(do()when()'what()#mul(424select(76,581):<+}from()#>+mul(616,317)#$what()@-select(425,315)mul(146,882)mul(509,291/#from()mul(152,967)why()how()mul(348,501)<[&^who()why():+mul(36/mul(856,681)!mul(46,203)
5 | mul(315,935)mul(451,658)when()when(353,392)<