diff --git a/day10/Cargo.lock b/day10/Cargo.lock new file mode 100644 index 0000000..ecb68fc --- /dev/null +++ b/day10/Cargo.lock @@ -0,0 +1,93 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "autocfg" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "day10" +version = "0.1.0" +dependencies = [ + "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-bigint" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-complex" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-iter" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-rational" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-traits" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[metadata] +"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" +"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" +"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" +"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" +"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" +"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" diff --git a/day10/Cargo.toml b/day10/Cargo.toml new file mode 100644 index 0000000..c414765 --- /dev/null +++ b/day10/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day10" +version = "0.1.0" +authors = ["Tyler Hallada "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +num = "0.2" diff --git a/day10/input/input.txt b/day10/input/input.txt new file mode 100644 index 0000000..3d1b1f7 --- /dev/null +++ b/day10/input/input.txt @@ -0,0 +1,30 @@ +.#.####..#.#...#...##..#.#.##. +..#####.##..#..##....#..#...#. +......#.......##.##.#....##..# +..#..##..#.###.....#.#..###.#. +..#..#..##..#.#.##..###....... +...##....#.##.#.#..##.##.#...# +.##...#.#.##..#.#........#.#.. +.##...##.##..#.#.##.#.#.#.##.# +#..##....#...###.#..##.#...##. +.###.###..##......#..#...###.# +.#..#.####.#..#....#.##..#.#.# +..#...#..#.#######....###..... +####..#.#.#...##...##....#..## +##..#.##.#.#..##.###.#.##.##.. +..#.........#.#.#.#.......#..# +...##.#.....#.#.##........#..# +##..###.....#.............#.## +.#...#....#..####.#.#......##. +..#..##..###...#.....#...##..# +...####..#.#.##..#....#.#..... +####.#####.#.#....#.#....##.#. +#.#..#......#.........##..#.#. +#....##.....#........#..##.##. +.###.##...##..#.##.#.#...#.#.# +##.###....##....#.#.....#.###. +..#...#......#........####..#. +#....#.###.##.#...#.#.#.#..... +.........##....#...#.....#..## +###....#.........#..#..#.#.#.. +##...#...###.#..#.###....#.##. diff --git a/day10/input/test1.txt b/day10/input/test1.txt new file mode 100644 index 0000000..737ae7f --- /dev/null +++ b/day10/input/test1.txt @@ -0,0 +1,5 @@ +.#..# +..... +##### +....# +...## diff --git a/day10/input/test2.txt b/day10/input/test2.txt new file mode 100644 index 0000000..987698f --- /dev/null +++ b/day10/input/test2.txt @@ -0,0 +1,10 @@ +......#.#. +#..#.#.... +..#######. +.#.#.###.. +.#..#..... +..#....#.# +#..#....#. +.##.#..### +##...#..#. +.#....#### diff --git a/day10/input/test3.txt b/day10/input/test3.txt new file mode 100644 index 0000000..e28e424 --- /dev/null +++ b/day10/input/test3.txt @@ -0,0 +1,10 @@ +#.#...#.#. +.###....#. +.#....#... +##.#.#.#.# +....#.#.#. +.##..###.# +..#...##.. +..##....## +......#... +.####.###. diff --git a/day10/input/test4.txt b/day10/input/test4.txt new file mode 100644 index 0000000..af5b6e9 --- /dev/null +++ b/day10/input/test4.txt @@ -0,0 +1,10 @@ +.#..#..### +####.###.# +....###.#. +..###.##.# +##.##.#.#. +....###..# +..#.#..#.# +#..#.#.### +.##...##.# +.....#.#.. diff --git a/day10/input/test5.txt b/day10/input/test5.txt new file mode 100644 index 0000000..33437ba --- /dev/null +++ b/day10/input/test5.txt @@ -0,0 +1,20 @@ +.#..##.###...####### +##.############..##. +.#.######.########.# +.###.#######.####.#. +#####.##.#.##.###.## +..#####..#.######### +#################### +#.####....###.#.#.## +##.################# +#####.##.###..####.. +..######..##.####### +####.##.####...##..# +.#####..#.######.### +##...#.##########... +#.##########.####### +.####.#.###.###.#.## +....##.##.###..##### +.#.#.###########.### +#.#.#.#####.####.### +###.##.####.##.#..## diff --git a/day10/src/main.rs b/day10/src/main.rs new file mode 100644 index 0000000..d9fecf4 --- /dev/null +++ b/day10/src/main.rs @@ -0,0 +1,154 @@ +use std::collections::HashMap; +use std::error::Error; +use std::fs::File; +use std::io::{prelude::*, BufReader}; +use std::result; + +use num::integer::gcd; + +const INPUT: &str = "input/input.txt"; + +type Result = result::Result>; + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] +struct Point { + x: usize, + y: usize, +} + +#[derive(Debug, PartialEq)] +struct AsteroidField { + asteroids: Vec, +} + +impl AsteroidField { + fn find_monitoring_station(&self) -> (&Point, usize) { + let mut asteroid_detect_scores = HashMap::new(); + for asteroid in self.asteroids.iter() { + let mut lines_of_sight: HashMap<(i32, i32), Point> = HashMap::new(); + for other in self.asteroids.iter() { + if asteroid != other { + let x_dist: i32 = other.x as i32 - asteroid.x as i32; + let y_dist: i32 = other.y as i32 - asteroid.y as i32; + let mut x_ratio: i32 = 0; + let mut y_ratio: i32 = 0; + if x_dist == 0 { + if y_dist > 0 { + y_ratio = 1; + } else { + y_ratio = -1; + } + } else if y_dist == 0 { + if x_dist > 0 { + x_ratio = 1; + } else { + x_ratio = -1; + } + } else { + let gcd = gcd(x_dist, y_dist); + x_ratio = x_dist / gcd; + y_ratio = y_dist / gcd; + } + lines_of_sight + .entry((x_ratio, y_ratio)) + .and_modify(|current| { + if (current.x as i32 - asteroid.x as i32).abs() > x_dist.abs() + && (current.y as i32 - asteroid.y as i32).abs() > y_dist.abs() + { + current.x = other.x; + current.y = other.y; + } + }) + .or_insert(other.clone()); + } + } + + asteroid_detect_scores.insert(asteroid, lines_of_sight.len()); + } + + asteroid_detect_scores + .into_iter() + .max_by_key(|score| score.1) + .expect("No asteroid detect scores") + } +} + +fn read_asteroid_field(filename: &str) -> Result { + let file = File::open(filename)?; + let reader = BufReader::new(file); + let mut asteroids = vec![]; + + for (y, line) in reader.lines().enumerate() { + for (x, contents) in line?.chars().enumerate() { + if contents == '#' { + asteroids.push(Point { x, y }); + } + } + } + + Ok(AsteroidField { asteroids }) +} + +fn solve_part1() -> Result { + let asteroid_field = read_asteroid_field(INPUT)?; + Ok(asteroid_field.find_monitoring_station().1) +} + +fn solve_part2() -> Result { + Ok(1) +} + +fn main() -> Result<()> { + println!("Part 1: {}", solve_part1()?); + println!("Part 2: {}", solve_part2()?); + + Ok(()) +} + +#[cfg(test)] +mod tests { + use super::*; + + const TEST_INPUT1: &str = "input/test1.txt"; + const TEST_INPUT2: &str = "input/test2.txt"; + const TEST_INPUT3: &str = "input/test3.txt"; + const TEST_INPUT4: &str = "input/test4.txt"; + const TEST_INPUT5: &str = "input/test5.txt"; + + #[test] + fn reads_asteroid_field() { + assert_eq!( + read_asteroid_field(TEST_INPUT1).unwrap(), + AsteroidField { + asteroids: vec![ + Point { x: 1, y: 0 }, + Point { x: 4, y: 0 }, + Point { x: 0, y: 2 }, + Point { x: 1, y: 2 }, + Point { x: 2, y: 2 }, + Point { x: 3, y: 2 }, + Point { x: 4, y: 2 }, + Point { x: 4, y: 3 }, + Point { x: 3, y: 4 }, + Point { x: 4, y: 4 }, + ] + }, + ) + } + + #[test] + fn finds_monitoring_stations() { + for (input, monitoring_point) in [ + (TEST_INPUT1, Point { x: 3, y: 4 }), + (TEST_INPUT2, Point { x: 5, y: 8 }), + (TEST_INPUT3, Point { x: 1, y: 2 }), + (TEST_INPUT4, Point { x: 6, y: 3 }), + (TEST_INPUT5, Point { x: 11, y: 13 }), + ] + .iter() + { + let asteroid_field = read_asteroid_field(input).unwrap(); + assert_eq!(asteroid_field.find_monitoring_station().0, monitoring_point); + } + } +}