ソースを参照

Started solving day 21

Alexey Dorokhov 2 年 前
コミット
872eda598f
6 ファイル変更419 行追加0 行削除
  1. 32 0
      day_21a/Cargo.lock
  2. 9 0
      day_21a/Cargo.toml
  3. 111 0
      day_21a/src/main.rs
  4. 32 0
      day_21b/Cargo.lock
  5. 9 0
      day_21b/Cargo.toml
  6. 226 0
      day_21b/src/main.rs

+ 32 - 0
day_21a/Cargo.lock

@@ -0,0 +1,32 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "day_21a"
+version = "0.1.0"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]

+ 9 - 0
day_21a/Cargo.toml

@@ -0,0 +1,9 @@
+[package]
+name = "day_21a"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+nom = "7"

+ 111 - 0
day_21a/src/main.rs

@@ -0,0 +1,111 @@
+use std::fs;
+use std::env;
+
+use std::collections::HashSet;
+
+#[derive(Copy, Clone, Hash, PartialEq, Eq)]
+struct Coord {
+    row: i64,
+    col: i64,
+}
+
+fn get_adj_coords(c: Coord) -> Vec<Coord> {
+    vec![
+        Coord {
+            row: c.row + 1,
+            col: c.col,
+        },
+        Coord {
+            row: c.row - 1,
+            col: c.col,
+        },
+        Coord {
+            row: c.row,
+            col: c.col - 1,
+        },
+        Coord {
+            row: c.row,
+            col: c.col + 1,
+        },
+    ]
+}
+
+fn get_adj_plot_coords(c: Coord, grid: &Vec<Vec<char>>) -> Vec<Coord> {
+    let n_rows: i64 = grid.len().try_into().unwrap(); 
+    let n_cols: i64 = grid[0].len().try_into().unwrap(); 
+
+    let mut plots = Vec::new();
+    for n in get_adj_coords(c).into_iter() {
+        if n.row < 0 || n.row >= n_rows ||
+           n.col < 0 || n.col >=  n_cols {
+            continue;
+        }
+
+        if grid[n.row as usize][n.col as usize] == '#' {
+            continue;
+        }
+
+        plots.push(n);
+    }
+    plots
+}
+
+fn get_grid(text: String) -> Vec<Vec<char>> {
+    let mut grid = Vec::new();
+    let mut row = Vec::new();
+    for c in text.chars() {
+        if c == '\n' {
+            grid.push(row.clone());
+            row.clear();
+        } else {
+            row.push(c);
+        }
+    }
+    if !row.is_empty() {
+        grid.push(row)
+    }
+    grid
+}
+
+fn get_start_coord(grid: &Vec<Vec<char>>) -> Coord {
+    for r in 0..grid.len() {
+        for c in 0..grid[0].len() {
+            if grid[r][c] == 'S' {
+                return Coord {
+                    row: r.try_into().unwrap(), 
+                    col: c.try_into().unwrap(),
+                }
+            }
+        }
+    }
+    panic!("Can't get coord!");
+}
+
+fn make_step(positions: HashSet<Coord>, grid: &Vec<Vec<char>>) -> HashSet<Coord> {
+    let mut next_positions = HashSet::new();
+    for position in positions.into_iter() {
+        for next_position in get_adj_plot_coords(position, grid).into_iter() {
+            next_positions.insert(next_position);
+        }
+    }
+
+    next_positions
+}
+
+fn main() {
+    let steps = 64;
+
+    let args: Vec<String> = env::args().collect();
+    let file_path = &args[1];
+    let input_data = fs::read_to_string(file_path).unwrap_or_else(
+        |_|{panic!("Can't read file {}", file_path)});
+    let grid = get_grid(input_data);
+    let start_coord = get_start_coord(&grid);
+    let mut positions = HashSet::new();
+    positions.insert(start_coord);
+
+    for _i in 0..steps {
+        positions = make_step(positions, &grid);
+    }
+    println!("{}", positions.len());
+}

+ 32 - 0
day_21b/Cargo.lock

@@ -0,0 +1,32 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "day_21b"
+version = "0.1.0"
+dependencies = [
+ "nom",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
+
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
+[[package]]
+name = "nom"
+version = "7.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+]

+ 9 - 0
day_21b/Cargo.toml

@@ -0,0 +1,9 @@
+[package]
+name = "day_21b"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+nom = "7"

+ 226 - 0
day_21b/src/main.rs

@@ -0,0 +1,226 @@
+use std::fs;
+use std::env;
+
+use std::collections::HashSet;
+use std::collections::HashMap;
+
+#[derive(Copy, Clone, Hash, PartialEq, Eq)]
+struct Coord {
+    row: i64,
+    col: i64,
+    grid_row: i64,
+    grid_col: i64,
+}
+
+fn get_adj_coords(c: Coord, n_rows: i64, n_cols: i64) -> Vec<Coord> {
+    let mut n1 = c; 
+    n1.row = c.row + 1;
+    if n1.row >= n_rows {
+        n1.row -= n_rows;
+        n1.grid_row += 1;
+    }
+
+    let mut n2 = c; 
+    n2.row = c.row - 1;
+    if n2.row < 0 {
+        n2.row += n_rows;
+        n2.grid_row -= 1;
+    }
+
+    let mut n3 = c; 
+    n3.col = c.col + 1;
+    if n3.col >= n_cols {
+        n3.col -= n_cols;
+        n3.grid_col += 1;
+    }
+
+    let mut n4 = c; 
+    n4.col = c.col - 1;
+    if n4.col < 0 {
+        n4.col += n_cols;
+        n4.grid_col -= 1;
+    }
+
+    vec![n1, n2, n3, n4]
+}
+
+fn get_adj_plot_coords(c: Coord, grid: &Vec<Vec<char>>) -> Vec<Coord> {
+    let n_rows: i64 = grid.len().try_into().unwrap(); 
+    let n_cols: i64 = grid[0].len().try_into().unwrap(); 
+
+    let mut plots = Vec::new();
+    for n in get_adj_coords(c, n_rows, n_cols).into_iter() {
+        if grid[n.row as usize][n.col as usize] == '#' {
+            continue;
+        }
+
+        plots.push(n);
+    }
+    plots
+}
+
+fn get_grid(text: String) -> Vec<Vec<char>> {
+    let mut grid = Vec::new();
+    let mut row = Vec::new();
+    for c in text.chars() {
+        if c == '\n' {
+            grid.push(row.clone());
+            row.clear();
+        } else {
+            row.push(c);
+        }
+    }
+    if !row.is_empty() {
+        grid.push(row)
+    }
+    grid
+}
+
+fn get_start_coord(grid: &Vec<Vec<char>>) -> Coord {
+    for r in 0..grid.len() {
+        for c in 0..grid[0].len() {
+            if grid[r][c] == 'S' {
+                return Coord {
+                    row: r.try_into().unwrap(), 
+                    col: c.try_into().unwrap(),
+                    grid_row: 0,
+                    grid_col: 0,
+                }
+            }
+        }
+    }
+    panic!("Can't get coord!");
+}
+
+fn make_step(positions: HashSet<Coord>, grid: &Vec<Vec<char>>) -> HashSet<Coord> {
+    let mut next_positions = HashSet::new();
+    for position in positions.into_iter() {
+        for next_position in get_adj_plot_coords(position, grid).into_iter() {
+            next_positions.insert(next_position);
+        }
+    }
+
+    next_positions
+}
+
+
+fn populate_cache(cache: &mut HashMap<Coord, Vec<HashSet<Coord>>>, steps: usize, pos: Coord, grid: &Vec<Vec<char>>) {
+    let mut initial_pos = HashSet::new();
+    initial_pos.insert(pos);
+    cache.insert(pos, vec![initial_pos]);
+
+    let step_options = cache.get_mut(&pos).unwrap();
+    for _i in 0..steps {
+        let last_pos = step_options.last().unwrap().clone();
+        step_options.push(make_step(last_pos, grid));
+    }
+}
+
+fn get_cache_steps(cache: &HashMap<Coord, Vec<HashSet<Coord>>>,  grid: &Vec<Vec<char>>) -> usize {
+    for r in 0..grid.len() {
+        for c in 0..grid[0].len() {
+            if grid[r][c] != '#' {
+                let coord = Coord {
+                    row: r.try_into().unwrap(), 
+                    col: c.try_into().unwrap(),
+                    grid_row: 0,
+                    grid_col: 0,
+                };
+
+                return cache.get(&coord).unwrap().len() - 1;
+            }
+        }
+    }
+
+    panic!("can't find cache len");
+}
+
+fn make_steps_with_cache(cache: &HashMap<Coord, Vec<HashSet<Coord>>>, steps: &mut usize,
+                         positions: HashSet<Coord>, grid: &Vec<Vec<char>>)  -> HashSet<Coord> {
+    let cache_steps = get_cache_steps(cache, grid);
+    if cache_steps >= *steps {
+        let mut next_positions = HashSet::new();
+
+        for position in positions.into_iter() {
+            let normalized_position = Coord {
+                row: position.row,
+                col: position.col,
+                grid_row: 0,
+                grid_col: 0,
+            };
+
+            let step_options = cache.get(&normalized_position).unwrap();
+            for next_position in step_options[*steps].iter() {
+                next_positions.insert(Coord {
+                    row: next_position.row,
+                    col: next_position.col,
+                    grid_row: next_position.grid_row + position.grid_row,
+                    grid_col: next_position.grid_col + position.grid_col,
+                });
+            }
+        }
+        *steps = 0;
+        return next_positions;
+    } else {
+        let mut next_positions = HashSet::new();
+
+        for position in positions.into_iter() {
+            let normalized_position = Coord {
+                row: position.row,
+                col: position.col,
+                grid_row: 0,
+                grid_col: 0,
+            };
+
+            let step_options = cache.get(&normalized_position).unwrap();
+            for next_position in step_options[cache_steps].iter() {
+                next_positions.insert(Coord {
+                    row: next_position.row,
+                    col: next_position.col,
+                    grid_row: next_position.grid_row + position.grid_row,
+                    grid_col: next_position.grid_col + position.grid_col,
+                });
+            }
+        }
+        *steps -= cache_steps;
+        return next_positions;
+    }
+}
+
+fn main() {
+    let steps: usize = 500;
+
+    let args: Vec<String> = env::args().collect();
+    let file_path = &args[1];
+    let input_data = fs::read_to_string(file_path).unwrap_or_else(
+        |_|{panic!("Can't read file {}", file_path)});
+    let grid = get_grid(input_data);
+
+    let mut cache = HashMap::new();
+    for r in 0..grid.len() {
+        for c in 0..grid[0].len() {
+            if grid[r][c] != '#' {
+                let coord = Coord {
+                    row: r.try_into().unwrap(), 
+                    col: c.try_into().unwrap(),
+                    grid_row: 0,
+                    grid_col: 0,
+                };
+
+                populate_cache(&mut cache, 50, coord, &grid);
+            }
+        }
+    }
+
+    let start_coord = get_start_coord(&grid);
+    let mut positions = HashSet::new();
+    positions.insert(start_coord);
+
+    let mut steps_left = steps;
+    while steps_left > 0 {
+      positions = make_steps_with_cache(&mut cache, &mut steps_left, positions, &grid);
+
+    }
+
+    println!("{}", positions.len());
+}