diff options
| author | Reiner Herrmann <reiner@reiner-h.de> | 2020-12-24 16:09:48 +0100 |
|---|---|---|
| committer | Reiner Herrmann <reiner@reiner-h.de> | 2020-12-24 16:09:48 +0100 |
| commit | e2fedcbca8df3ac1849c544eef672c5dc793789c (patch) | |
| tree | 5a8a5352218986987f551e0ebca22ae34a939136 /src/main.rs | |
| parent | db055828ef14e84557248bf2d02e20c1a6b97b17 (diff) | |
day24
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 187 |
1 files changed, 186 insertions, 1 deletions
diff --git a/src/main.rs b/src/main.rs index 460dff8..d6375b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2310,8 +2310,155 @@ fn day23() { println!("23b: {}", play_cups_game2(&input, 10000000)); } +#[derive(PartialEq,Eq,Copy,Clone,Hash)] +struct Pointi { + x: isize, + y: isize, +} + +enum HexDirection { + SE, + NE, + SW, + NW, + W, + E, +} + +fn parse_directions(input: &[String]) -> Vec<Vec<HexDirection>> { + let mut directions_list = Vec::new(); + let dir_re = Regex::new("([ns]?[ew])").unwrap(); + + for line in input { + let mut directions = Vec::new(); + for cap in dir_re.captures_iter(line) { + let dir = match cap.get(1).unwrap().as_str() { + "e" => HexDirection::E, + "w" => HexDirection::W, + "ne" => HexDirection::NE, + "nw" => HexDirection::NW, + "se" => HexDirection::SE, + "sw" => HexDirection::SW, + _ => panic!("invalid direction"), + }; + directions.push(dir); + } + directions_list.push(directions); + } + directions_list +} + +fn flip_tiles(directions_list: &[Vec<HexDirection>]) -> HashMap<Pointi,usize> { + let mut flipped = HashMap::new(); + + for directions in directions_list { + let mut pos = Pointi { x:0, y:0 }; + for dir in directions { + match dir { + HexDirection::E => pos.x += 1, + HexDirection::W => pos.x -= 1, + HexDirection::NE => { + pos.y += 1; + pos.x += 1; + }, + HexDirection::NW => { + pos.y += 1; + }, + HexDirection::SE => { + pos.y -= 1; + }, + HexDirection::SW => { + pos.y -= 1; + pos.x -= 1; + }, + } + } + let count = flipped.entry(pos).or_insert(0); + *count += 1; + } + flipped +} + +fn count_tile_neighbors(tiles: &[Pointi], tile: &Pointi) -> usize { + let mut count = 0; + if tiles.iter().any(|pos| (pos.x == tile.x + 1) && (pos.y == tile.y)) { + /* east */ + count += 1; + } + if tiles.iter().any(|pos| (pos.x == tile.x - 1) && (pos.y == tile.y)) { + /* west */ + count += 1; + } + if tiles.iter().any(|pos| (pos.x == tile.x - 1) && (pos.y == tile.y - 1)) { + /* south-west */ + count += 1; + } + if tiles.iter().any(|pos| (pos.x == tile.x) && (pos.y == tile.y - 1)) { + /* south-east */ + count += 1; + } + if tiles.iter().any(|pos| (pos.x == tile.x) && (pos.y == tile.y + 1)) { + /* north-west */ + count += 1; + } + if tiles.iter().any(|pos| (pos.x == tile.x + 1) && (pos.y == tile.y + 1)) { + /* north-east */ + count += 1; + } + count +} + +fn flip_tiles_per_day(black_tiles: &[Pointi]) -> Vec<Pointi> { + let mut new_tiles = Vec::new(); + + let mut x_min = 0; + let mut x_max = 0; + let mut y_min = 0; + let mut y_max = 0; + + for tile in black_tiles { + x_min = cmp::min(x_min, tile.x); + y_min = cmp::min(y_min, tile.y); + x_max = cmp::max(x_max, tile.x); + y_max = cmp::max(y_max, tile.y); + } + + for x in x_min-1 ..= x_max+1 { + for y in y_min-1 ..= y_max+1 { + let current = Pointi { x, y }; + let neighbors = count_tile_neighbors(black_tiles, ¤t); + if black_tiles.iter().any(|x| *x == current) { + if neighbors > 0 && neighbors <= 2 { + /* it stays black */ + new_tiles.push(current); + } + } else if neighbors == 2 { + new_tiles.push(current); + } + } + } + new_tiles +} + +fn day24() { + let input = read_lines("input24"); + + let directions_list = parse_directions(&input); + let flipped : Vec<Pointi> = flip_tiles(&directions_list).iter() + .filter(|(_,val)| *val % 2 == 1) + .map(|(pos,_)| *pos) + .collect(); + println!("24a: {}", flipped.len()); + + let mut flipped = flipped; + for _ in 0..100 { + flipped = flip_tiles_per_day(&flipped); + } + println!("24b: {}", flipped.len()); +} + fn main() { - day23(); + day24(); } #[cfg(test)] @@ -2938,4 +3085,42 @@ mod tests { } assert_eq!(play_cups_game2(&input, 10000000), 149245887792); } + + #[test] + fn test_day24() { + let input = "sesenwnenenewseeswwswswwnenewsewsw\n\ + neeenesenwnwwswnenewnwwsewnenwseswesw\n\ + seswneswswsenwwnwse\n\ + nwnwneseeswswnenewneswwnewseswneseene\n\ + swweswneswnenwsewnwneneseenw\n\ + eesenwseswswnenwswnwnwsewwnwsene\n\ + sewnenenenesenwsewnenwwwse\n\ + wenwwweseeeweswwwnwwe\n\ + wsweesenenewnwwnwsenewsenwwsesesenwne\n\ + neeswseenwwswnwswswnw\n\ + nenwswwsewswnenenewsenwsenwnesesenew\n\ + enewnwewneswsewnwswenweswnenwsenwsw\n\ + sweneswneswneneenwnewenewwneswswnese\n\ + swwesenesewenwneswnwwneseswwne\n\ + enesenwswwswneneswsenwnewswseenwsese\n\ + wnwnesenesenenwwnenwsewesewsesesew\n\ + nenewswnwewswnenesenwnesewesw\n\ + eneswnwswnwsenenwnwnwwseeswneewsenese\n\ + neswnwewnwnwseenwseesewsenwsweewe\n\ + wseweeenwnesenwwwswnew\n"; + let input = read_lines_str(&input); + + let directions_list = parse_directions(&input); + let flipped : Vec<Pointi> = flip_tiles(&directions_list).iter() + .filter(|(_,val)| *val % 2 == 1) + .map(|(pos,_)| *pos) + .collect(); + assert_eq!(flipped.len(), 10); + + let mut flipped = flipped; + for _ in 0..100 { + flipped = flip_tiles_per_day(&flipped); + } + assert_eq!(flipped.len(), 2208); + } } |
