diff --git a/2023/16/.gitignore b/2023/16/.gitignore new file mode 100644 index 0000000..1de5659 --- /dev/null +++ b/2023/16/.gitignore @@ -0,0 +1 @@ +target \ No newline at end of file diff --git a/2023/16/Cargo.lock b/2023/16/Cargo.lock new file mode 100644 index 0000000..c97b08f --- /dev/null +++ b/2023/16/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "sixteenth" +version = "0.1.0" diff --git a/2023/16/Cargo.toml b/2023/16/Cargo.toml new file mode 100644 index 0000000..523f9da --- /dev/null +++ b/2023/16/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "sixteenth" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/2023/16/input1 b/2023/16/input1 new file mode 100644 index 0000000..c78b2e7 --- /dev/null +++ b/2023/16/input1 @@ -0,0 +1,10 @@ +.|...\.... +|.-.\..... +.....|-... +........|. +.......... +.........\ +..../.\\.. +.-.-/..|.. +.|....-|.\ +..//.|.... \ No newline at end of file diff --git a/2023/16/input2 b/2023/16/input2 new file mode 100644 index 0000000..4af9bc3 --- /dev/null +++ b/2023/16/input2 @@ -0,0 +1,110 @@ +\....-./...............\.............-../...|......../........../...............|......................./..... +\.......\..-.\/|..........|......|./..........|.../..................-...................................|.... +.|........................................./...|...........................-.........../..............\....../ +.-............................|....-./|.........-................/.-./................|...|/..............-... +/....................\..........\.//.....-..-.........................../\................|.....-/...\........ +...........................|..|..\...-......\............................../.-...|...-....../...-./.....\..... +..|......-\.....\.........\................../...|...|..\-........................................./.......... +............../..............|......../.....................\................/|.....\...........\...-......... +.....-................./-.\..\..........................-.\|.........../..................../.|............-.. +/..........|.........-....-.............|....................................../...\./................-.....-. +../|.....\|...|./.................../....../...../\/........\.......|./..-...................................| +.-./......|.........|.......\....\-..........................-..\/.../.....-.../...|....\...........-...../... +....................|................................../....-.......\......|..-............................... +......-............../....|..........-..../..........--.................../..|...|...\.............-....\...|. +.............|...................-......-...............-..|.-..-.........|..\......|......|......./.......... +......-....|.....\.................|\......................./..|.........-....|.....\.....|........-.........| +.....\............\..\...................|.../...\.....-.-.\.......|....../\.........|........................ +.........\./|\........................./........../............................../..\...-....................\ +....|.|...........||......\........\...................-......................|.....-.-.....\................. +.....|.........\............-..................../\...|...|../..........-/..-..-.........|.../................ +............|...|.............\.-....................|.....................\............\.............-../.... +................././......\................./..\./\..............\./.......|../......|............|..|......|. +...|...../........../..../.............|\...........|................./.........-......./..................... +../.|......-...........................|........-......|..\..........|.....\.../.............../.............. +.........................|.............................\...........-..../.................-............/.....\ +.....\.....|......./.\........../......................|....................................../......\..../..| +...\............|........\........\........../................./..........-....................|\............. +........................../............................./..../..../..../......|...../..\......\.........-.|... +............-.........|..................-...-......\.........\............|.|.\/....././|...|................ +......./....|.................................................|......../..-./..../..|......................... +./....-..........-........-......-.-.......-..........|-..\......|...../........................\.........../. +.....................|../|.-...........-....\..\.................|........-............|...|.|................ +..../..........||\....................-...........|...............-....../........\......\|..............\.... +.......\...|..........|.|.\....../.....|..|...........|..........-........../..\...-.............-............ +................\........../.../...-.....\.....|.-\......\.................................-.....|............ +......-.....|........\.............-........./....../.............|..........-.|..........|......\..-......... +.......................................\..\-..........-................../........-................./......... +../.............................-..........-........./..-.................../...../.....|......\.............. +.....\........\......-....\..........................\/..................\......\..............\|....../...... +................./...../....|......../........../..-.....-......../........................................./. +...................|..\...|....\..............|..........|.......|..............//\......\.......\...\..-..... +.........\........-.............\........\....................-.............|..............|\...|..-..\....... +..|--../.......\.........|.\.......-.........-.........../..|.....-\......-...|.........................-.\... +........|...............................-..........................-|.-.|\\|\.........-............../........ +.......................-...\...-.....-.............|..........-..-.\.....--.../........./......../...........\ +..-..|..|.............................|........................|......................\...................\|.. +....\...............\.\.|............................-|......-................\......|......|...............-. +..../\....\..................\.............\.......\...............|.-..../.................../.\....\........ +.......................|..........\.....-.|........./........../.....|...................../.|/............... +-...........||.........|........||.....................................................................-....\. +..\...../.........-......\....................................../........................|..|...-...|....|.../ +..-......\............................/.....-................./..-..........\..-.|...........|.-......|..\...\ +.........................\...\................\.................--......../.........|...|........|............ +\.....\../..........|.................-............-..............|..................\................\....-.. +....................-..........|....|..|-.................|.\.|/../....................|...................... +................/|../.../.\...../.\../...........|..\........./....\.-...................-|......./..........\ +.....\.........|..................\....../.........-.....\......\.....|....|../|.........|.................... +..............-..........././...................|..|.....|.\/....-............|..../....-..................... +....../.-..........................\..-..-........../............./.....|............/.......|.\.......-|....| +.....\.....................|.........../....-/............-|................/...../............./............. +...............................|.........\.......\.......|....|..................|................./.......... +.........../.........-........................................-/.......................\............-......... +..............................................-./......./.\........./......../...........\..|..............\\. +...........-..|........-.............\.-|............./...-..................|./.....|................../.\... +........|..\..\|...........-..|........-.......\..|.............-....\........./..|../....-\.........../...... +/.....|......|...............||.\|.............-..\.-....................../................../...........\... +../.-./................-................\.....\....................\-...................|-..\................. +....\.........................-.........|.|\......\../.................\-....../...|.....|\.|...........\..... +......\.........|.../.......\...-....../.....|.....-..-\...................\\.-.-||........................... +....-..../...|.......\............\.|...\.................\....../..../..|.\......|\|.|....................... +.../...........\...................../........................../......-...................................... +.-............./......\......../.........|/-........-....................................-.....-.............. +/................../...........-.........-................................\................................... +...../...../...................../....\..................................|../.....-................|.......... +.\.....\.-.....-...\.\-......./..........-.-....................-....................\.....\...-......-....... +..........................|......-........../....|..........\.......................................\......... +.................|\....\.............../\.............-.\.-.................-...........-..|......./.......... +..........|...|.-...|............./..|............-.................|............\...|.|.\.................... +.........../-....\./....-................\..-........\..............................-.........\.....|......... +.............|..........\.................-.................\\.........-/.................-|-.........-....... +......................./...........................\.................|...-.....\......\.........../.......|... +....-.....-.......|..--.......\....\..................................................../...........\......... +...........................-.\..\......................................\......|.......-........-.....|........ +..-.......\............................../...................|..-.....................-......./..\.......-.-.. +....|.....-./.................\......./...........|.............................-....|........-............-.. +.....-...............|...........-.......|/..\-.............|-|........\...........|./...../.................. +|...................-../../.....|./..................|........|....\..../.....|....................../......./ +...............-./\.......|.......|./....................-....\...................-.......................|... +.../..........\...........|.....-..../..-..-.......................|.......|.....-./......................|... +......-..\..\........................................|...-................................|.............|..... +...........|............-\.........../..\....../.....\....../...........|...........|.../............\........ +|....-..........-.|...........-..-..................-..\......\.......--............|.................|\\..... +.........../|.-..........|...\.|./......../...........\...........\/....-..........\...................../.... +.........................-...../.....-./.-............................\...........-...............\.\/....../. +..../........-...................../............../....\............................./............../.../..... +..................-/...-......................|....................\......\..../.........-......./............ +....../....................-....\...-.-.....//...|.....................\.........\............\.-....-../..... +......-.....\......|.|........................|.................-............../......./...................... +....../......../.........\..................|...|..................................|..-..........|....\....... +..........\.../......................\.......\/......................-....|.........................../.\..... +.........-..............-.|...../../............................\../...............-.............\......../... +...\............\......................\.\......\........\............\...-.....|./...-.............|....|.-.. +/........................../.-..\|.-........../.-............./../.........-.../.............................. +|....|.\.....-..|....|....../........|.|...........\-......................|......|..........................| +.......................\...........................................\..........|.............-.../............. +.\.........|.............|................................\..................|||........\...-|................ +..........\...............\.....................-.....|....................-..........\|..................|.|. +...|...........\.|......|/.-../....../.................../......\.........................|\.\..............\. +..........................................................\......................./.....--..........|...-..\.. +........-/...-................/........\..........................\..../........................\........-.... \ No newline at end of file diff --git a/2023/16/part1.py b/2023/16/part1.py new file mode 100644 index 0000000..d36af9b --- /dev/null +++ b/2023/16/part1.py @@ -0,0 +1,74 @@ + +map = [] + +for line in open('input1'): + map.append([x for x in line.strip()]) + +energised = [[False for _ in x] for x in map] + +def print_energised(): + for line in energised: + print(''.join(['#' if x else '.' for x in line])) + +# List of tuples of (x, y) coordinates and vec direction vectors +beams = [] + +VEC_RIGHT = (0, 1) +VEC_LEFT = (0, -1) +VEC_UP = (-1, 0) +VEC_DOWN = (1, 0) + +beams.append(((0, -1), VEC_RIGHT)) + +mirrorMap = { + ('/', VEC_RIGHT): VEC_UP, + ('/', VEC_LEFT): VEC_DOWN, + ('/', VEC_UP): VEC_RIGHT, + ('/', VEC_DOWN): VEC_LEFT, + ('\\', VEC_RIGHT): VEC_DOWN, + ('\\', VEC_LEFT): VEC_UP, + ('\\', VEC_UP): VEC_LEFT, + ('\\', VEC_DOWN): VEC_RIGHT +} + +def add(pos, vec): + return (pos[0] + vec[0], pos[1] + vec[1]) + +def append_if_not_in(list, item): + if item not in list: + list.append(item) + +offset = 0 +while len(beams) > offset: + beam = beams[offset] + offset += 1 + pos, vec = beam + x, y = beam[0] + dx, dy = beam[1] + # print("Beam at (%d, %d) with vector (%d, %d)" % (x, y, dx, dy)) + + if x + dx < 0 or x + dx >= len(map[0]) or y + dy < 0 or y + dy >= len(map): + continue + + new_pos = (x + dx, y + dy) + point = map[new_pos[0]][new_pos[1]] + # print('point: ' + point) + energised[new_pos[0]][new_pos[1]] = True + + if point == '.': + append_if_not_in(beams, (new_pos, vec)) + if point == '/' or point == '\\': + new_vec = mirrorMap[(point, vec)]; + append_if_not_in(beams, (new_pos, new_vec)) + if point == '-' or point == '|': + if (point == '-' and (vec == VEC_RIGHT or vec == VEC_LEFT)) or (point == '|' and (vec == VEC_UP or vec == VEC_DOWN)): + append_if_not_in(beams, (new_pos, vec)) + elif point == '-': + append_if_not_in(beams, (new_pos, VEC_LEFT)) + append_if_not_in(beams, (new_pos, VEC_RIGHT)) + elif point == '|': + append_if_not_in(beams, (new_pos, VEC_UP)) + append_if_not_in(beams, (new_pos, VEC_DOWN)) + +print_energised() +print(sum([sum([1 if x else 0 for x in y]) for y in energised])) \ No newline at end of file diff --git a/2023/16/src/main.rs b/2023/16/src/main.rs new file mode 100644 index 0000000..b5d19c0 --- /dev/null +++ b/2023/16/src/main.rs @@ -0,0 +1,268 @@ +use std::{fs::File, io::{BufReader, BufRead, Write}, ops::Add, fmt::Debug}; + +fn main() { + part1(); +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum Type { + /// Mirror bottom-to-top (/) + MirrorBT, + /// Mirror top-to-bottom (\) + MirrorTB, + /// Split horizontally (-) + SplitHorizontal, + /// Split vertically (|) + SplitVertical, +} + +fn vectors_from_split(split: Type) -> (Vector, Vector) { + match split { + Type::SplitHorizontal => (Vector { x: -1, y: 0}, Vector { x: 1, y: 0 }), + Type::SplitVertical => (Vector { x: 0, y: -1}, Vector { x: 0, y: 1 }), + _ => panic!("Not a split") + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct MapPoint { + point: Point, + mirror: Type +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct Point { + x: usize, + y: usize +} +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct Vector { + x: isize, + y: isize +} +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct Beam { + point: Point, + vector: Vector +} + +impl Vector { + fn map_by_mirror(&self, mirror: Type) -> Vector { + match mirror { + Type::MirrorBT => match self { + &VEC_RIGHT => VEC_UP, + &VEC_LEFT => VEC_DOWN, + &VEC_UP => VEC_RIGHT, + &VEC_DOWN => VEC_LEFT, + _ => panic!("Invalid vec") + }, + Type::MirrorTB => match self { + &VEC_RIGHT => VEC_DOWN, + &VEC_LEFT => VEC_UP, + &VEC_UP => VEC_LEFT, + &VEC_DOWN => VEC_RIGHT, + _ => panic!("Invalid vec") + }, + _ => panic!("Not a mirror") + } + } + + fn map_to_split(&self) -> Type { + match self { + &VEC_RIGHT => Type::SplitHorizontal, + &VEC_LEFT => Type::SplitHorizontal, + &VEC_UP => Type::SplitVertical, + &VEC_DOWN => Type::SplitVertical, + _ => panic!("Invalid vec") + } + } + + fn will_go_oob(&self, point: Point, max_point: Point) -> bool { + let nx = point.x as isize + self.x; + let ny = point.y as isize + self.y; + + nx < 0 || ny < 0 || nx >= max_point.x as isize || ny >= max_point.y as isize + } + + fn is_vertical(&self) -> bool { + self.x == 0 + } + + fn is_horizontal(&self) -> bool { + self.y == 0 + } + + fn is_positive(&self) -> bool { + self.x > 0 || self.y > 0 + } + + fn is_negative(&self) -> bool { + self.x < 0 || self.y < 0 + } +} +impl Add for Point { + type Output = Point; + + fn add(self, rhs: Vector) -> Self::Output { + Point { + x: (self.x as isize + rhs.x) as usize, + y: (self.y as isize + rhs.y) as usize + } + } +} + +const VEC_RIGHT : Vector = Vector { x: 1, y: 0 }; +const VEC_LEFT : Vector = Vector { x: -1, y: 0 }; +const VEC_UP : Vector = Vector { x: 0, y: -1 }; +const VEC_DOWN : Vector = Vector { x: 0, y: 1 }; + +fn print_energized(energized: &Vec>) -> Result<(), std::io::Error> { + let mut lock = std::io::stdout().lock(); + for y in 0..energized.len() { + for x in 0..energized[y].len() { + write!(lock, "{}", if energized[y][x] { '#' } else { '.' })?; + } + writeln!(lock)?; + } + Ok(()) +} + +fn append_if_not_in(vec: &mut Vec, item: T) { + if !vec.contains(&item) { + vec.push(item); + } +} +fn set_range(vec: &mut Vec, range: std::ops::Range, item: T) { + for i in range { + vec[i] = item; + } +} +fn set_range_in(vec: &mut Vec>, range: std::ops::Range, item: T, offset: usize) { + for i in range { + vec[i][offset] = item; + } +} + +fn mark(vec: Vector, point: Point, otherpos: usize, energized: &mut Vec>) { + if vec.is_vertical() { + if vec.is_positive() { + set_range_in(energized, point.y..otherpos, true, point.x); + } else { + set_range_in(energized, otherpos..(point.y + 1), true, point.x); + } + } else { + if vec.is_positive() { + set_range(&mut energized[point.y], point.x..otherpos, true); + } else { + set_range(&mut energized[point.y], otherpos..(point.x + 1), true); + } + } +} + +fn part1() { + let file = File::open("input2").expect("File not found"); + let reader = BufReader::new(file); + let map : Vec> = reader.lines().map(|l| l.unwrap().chars().collect()).collect(); + let mut energized : Vec> = map.iter().map(|l| l.iter().map(|_| false).collect()).collect(); + + let max_point = Point { x: map[0].len(), y: map.len() }; + + let rows: Vec> = map.iter().enumerate().map(|(y, row)| { + row + .iter() + .enumerate() + .filter(|(_, c)| **c != '.') + .map(|(x, c)| { + MapPoint { + point: Point { x, y }, + mirror: match c { + '/' => Type::MirrorBT, + '\\' => Type::MirrorTB, + '-' => Type::SplitHorizontal, + '|' => Type::SplitVertical, + _ => panic!("Invalid char") + } + } + }).collect() + }).collect(); + let columns: Vec> = (0..map[0].len()).map(|x| { + (0..map.len()) + .filter(|y| map[*y][x] != '.') + .map(|y| { + MapPoint { + point: Point { x, y }, + mirror: match map[y][x] { + '/' => Type::MirrorBT, + '\\' => Type::MirrorTB, + '-' => Type::SplitHorizontal, + '|' => Type::SplitVertical, + _ => panic!("Invalid char") + } + } + }).collect() + }).collect(); + + let mut beams : Vec = vec![Beam { + point: Point { x: 0, y: 0 }, + vector: VEC_RIGHT + }]; + + let mut offset = 0; + + while beams.len() > offset { + let beam = &beams[offset]; + offset += 1; + + let vec = beam.vector; + let mut relevant = { + (if vec.is_vertical() { + columns[beam.point.x].iter() + } else { + rows[beam.point.y].iter() + }) + .filter(|mp| { + let mpp = if vec.is_vertical() { mp.point.y } else { mp.point.x }; + let beamp = if vec.is_vertical() { beam.point.y } else { beam.point.x }; + // ignore splits that are the same direction as the beam + mp.mirror != vec.map_to_split() && + (mpp >= beamp && vec.is_positive() || mpp <= beamp && vec.is_negative()) + }) + }; + let closest = if vec.is_positive() { + relevant.next() + } else { + relevant.last() + }; + match closest { + None => { + mark(vec, beam.point, if vec.is_positive() { max_point.x } else { 0 }, &mut energized); + }, + Some(mappoint) => { + mark(vec, beam.point, (if vec.is_vertical() { mappoint.point.y } else { mappoint.point.x } ) + (if vec.is_positive() { 1 } else { 0 }), &mut energized); + let mut vecs = vec![]; + if mappoint.mirror == Type::SplitHorizontal || mappoint.mirror == Type::SplitVertical { + let (v1, v2) = vectors_from_split(mappoint.mirror); + vecs.push(v1); + vecs.push(v2); + } else { + vecs.push(vec.map_by_mirror(mappoint.mirror)); + } + let point = mappoint.point; + for v in vecs { + if !v.will_go_oob(point, max_point) { + let new_point = point + v; + let beam = Beam { + point: new_point, + vector: v + }; + append_if_not_in(&mut beams, beam); + } + } + } + } + } + print_energized(&energized).unwrap(); + + let count = energized.iter().map(|row| row.iter().filter(|&&b| b).count()).sum::(); + println!("Count: {}", count); +} \ No newline at end of file