day 10 (only part 1) + 11
This commit is contained in:
parent
5abf4a2916
commit
ff54ef107a
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -34,6 +34,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
name = "day1"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "day10"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "day11"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"shared 0.1.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "day2"
|
||||
version = "0.1.0"
|
||||
|
@ -9,5 +9,7 @@ members = [
|
||||
"day7",
|
||||
"day8",
|
||||
"day9",
|
||||
"day10",
|
||||
"day11",
|
||||
"shared",
|
||||
]
|
||||
|
10
day10/Cargo.toml
Normal file
10
day10/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "day10"
|
||||
version = "0.1.0"
|
||||
authors = ["Stefan Bühler <stbuehler@web.de>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.8.2"
|
26
day10/src/input.txt
Normal file
26
day10/src/input.txt
Normal file
@ -0,0 +1,26 @@
|
||||
#.#.###.#.#....#..##.#....
|
||||
.....#..#..#..#.#..#.....#
|
||||
.##.##.##.##.##..#...#...#
|
||||
#.#...#.#####...###.#.#.#.
|
||||
.#####.###.#.#.####.#####.
|
||||
#.#.#.##.#.##...####.#.##.
|
||||
##....###..#.#..#..#..###.
|
||||
..##....#.#...##.#.#...###
|
||||
#.....#.#######..##.##.#..
|
||||
#.###.#..###.#.#..##.....#
|
||||
##.#.#.##.#......#####..##
|
||||
#..##.#.##..###.##.###..##
|
||||
#..#.###...#.#...#..#.##.#
|
||||
.#..#.#....###.#.#..##.#.#
|
||||
#.##.#####..###...#.###.##
|
||||
#...##..#..##.##.#.##..###
|
||||
#.#.###.###.....####.##..#
|
||||
######....#.##....###.#..#
|
||||
..##.#.####.....###..##.#.
|
||||
#..#..#...#.####..######..
|
||||
#####.##...#.#....#....#.#
|
||||
.#####.##.#.#####..##.#...
|
||||
#..##..##.#.##.##.####..##
|
||||
.##..####..#..####.#######
|
||||
#.#..#.##.#.######....##..
|
||||
.#.##.##.####......#.##.##
|
107
day10/src/main.rs
Normal file
107
day10/src/main.rs
Normal file
@ -0,0 +1,107 @@
|
||||
use itertools::Itertools;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct Position {
|
||||
pub x: usize,
|
||||
pub y: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct Field {
|
||||
rows: usize,
|
||||
columns: usize,
|
||||
astroids: Vec<bool>,
|
||||
}
|
||||
|
||||
fn gcd(mut x: isize, mut y: isize) -> isize {
|
||||
loop {
|
||||
if y == 0 { return x; }
|
||||
x = x % y;
|
||||
if x == 0 { return y; }
|
||||
y = y % x;
|
||||
}
|
||||
}
|
||||
|
||||
impl Field {
|
||||
pub fn parse(input: &str) -> Self {
|
||||
let lines = input.lines().collect::<Vec<_>>();
|
||||
let rows = lines.len();
|
||||
let columns = lines[0].len();
|
||||
let mut astroids = Vec::new();
|
||||
for line in lines {
|
||||
assert_eq!(columns, line.len());
|
||||
for cell in line.chars() {
|
||||
astroids.push(match cell {
|
||||
'#' => true,
|
||||
'.' => false,
|
||||
_ => panic!("Unexpected cell: {:?}", cell),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Self {
|
||||
rows,
|
||||
columns,
|
||||
astroids,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sees(&self, a: Position, b: Position) -> bool {
|
||||
if a == b { return true; }
|
||||
let diff_x = b.x as isize - a.x as isize;
|
||||
let diff_y = b.y as isize - a.y as isize;
|
||||
let d = gcd(diff_x, diff_y).abs();
|
||||
let diff_x = diff_x / d;
|
||||
let diff_y = diff_y / d;
|
||||
let mut pos = a;
|
||||
loop {
|
||||
pos.x = (pos.x as isize + diff_x) as usize;
|
||||
pos.y = (pos.y as isize + diff_y) as usize;
|
||||
if pos == b { return true; }
|
||||
if self[pos] { return false; }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn all_astroids(&self) -> impl Iterator<Item = Position> + '_ {
|
||||
(0..self.columns).cartesian_product(0..self.rows).map(|(x, y)| Position { x, y }).filter(move |pos| self[*pos])
|
||||
}
|
||||
|
||||
pub fn best_monitoring_station(&self) -> (Position, usize) {
|
||||
self.all_astroids().map(|monitor| {
|
||||
// can see itself, but only count "others"
|
||||
(monitor, self.all_astroids().filter(|astroid| self.sees(monitor, *astroid)).count() - 1)
|
||||
}).max_by_key(|(_, n)| *n).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Index<Position> for Field {
|
||||
type Output = bool;
|
||||
|
||||
fn index(&self, index: Position) -> &Self::Output {
|
||||
assert!(index.x < self.columns);
|
||||
assert!(index.y < self.rows);
|
||||
&self.astroids[index.y * self.columns + index.x]
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let input = include_str!("input.txt");
|
||||
println!("Best monitoring station sees astroids: {}", Field::parse(input).best_monitoring_station().1);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod day10test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn examples1() {
|
||||
assert_eq!(
|
||||
Field::parse(".#..#
|
||||
.....
|
||||
#####
|
||||
....#
|
||||
...##").best_monitoring_station(),
|
||||
(Position { x: 3, y: 4 }, 8),
|
||||
);
|
||||
}
|
||||
}
|
10
day11/Cargo.toml
Normal file
10
day11/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "day11"
|
||||
version = "0.1.0"
|
||||
authors = ["Stefan Bühler <stbuehler@web.de>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
shared = { path = "../shared" }
|
1
day11/src/input.txt
Normal file
1
day11/src/input.txt
Normal file
@ -0,0 +1 @@
|
||||
3,8,1005,8,309,1106,0,11,0,0,0,104,1,104,0,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,1001,8,0,29,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,102,1,8,51,3,8,102,-1,8,10,1001,10,1,10,4,10,108,0,8,10,4,10,1002,8,1,72,1,1104,8,10,2,1105,15,10,2,1106,0,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,101,0,8,107,3,8,102,-1,8,10,1001,10,1,10,4,10,108,1,8,10,4,10,101,0,8,128,2,6,8,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,102,1,8,155,1006,0,96,2,108,10,10,1,101,4,10,3,8,1002,8,-1,10,101,1,10,10,4,10,1008,8,0,10,4,10,1002,8,1,188,2,1,5,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,0,10,4,10,102,1,8,214,2,6,18,10,1006,0,78,1,105,1,10,3,8,1002,8,-1,10,1001,10,1,10,4,10,1008,8,1,10,4,10,102,1,8,247,2,103,8,10,2,1002,10,10,2,106,17,10,1,1006,15,10,3,8,102,-1,8,10,101,1,10,10,4,10,1008,8,1,10,4,10,101,0,8,285,1,1101,18,10,101,1,9,9,1007,9,992,10,1005,10,15,99,109,631,104,0,104,1,21102,387507921664,1,1,21102,1,326,0,1106,0,430,21102,932826591260,1,1,21102,337,1,0,1106,0,430,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,3,10,104,0,104,1,3,10,104,0,104,0,3,10,104,0,104,1,21101,206400850983,0,1,21101,0,384,0,1105,1,430,21102,3224464603,1,1,21102,395,1,0,1106,0,430,3,10,104,0,104,0,3,10,104,0,104,0,21102,838433657700,1,1,21102,418,1,0,1106,0,430,21101,825012007272,0,1,21101,429,0,0,1106,0,430,99,109,2,21202,-1,1,1,21101,40,0,2,21101,461,0,3,21102,1,451,0,1105,1,494,109,-2,2105,1,0,0,1,0,0,1,109,2,3,10,204,-1,1001,456,457,472,4,0,1001,456,1,456,108,4,456,10,1006,10,488,1102,1,0,456,109,-2,2106,0,0,0,109,4,1202,-1,1,493,1207,-3,0,10,1006,10,511,21101,0,0,-3,21202,-3,1,1,21201,-2,0,2,21102,1,1,3,21102,1,530,0,1106,0,535,109,-4,2106,0,0,109,5,1207,-3,1,10,1006,10,558,2207,-4,-2,10,1006,10,558,22101,0,-4,-4,1106,0,626,22102,1,-4,1,21201,-3,-1,2,21202,-2,2,3,21101,0,577,0,1106,0,535,22102,1,1,-4,21101,1,0,-1,2207,-4,-2,10,1006,10,596,21102,0,1,-1,22202,-2,-1,-2,2107,0,-3,10,1006,10,618,21201,-1,0,1,21102,618,1,0,105,1,493,21202,-2,-1,-2,22201,-4,-2,-4,109,-5,2105,1,0
|
107
day11/src/main.rs
Normal file
107
day11/src/main.rs
Normal file
@ -0,0 +1,107 @@
|
||||
use shared::intcode::{IntCode, SimulateStep};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub enum Direction {
|
||||
Up,
|
||||
Right,
|
||||
Down,
|
||||
Left,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
pub fn turn_right(self) -> Self {
|
||||
match self {
|
||||
Self::Up => Self::Right,
|
||||
Self::Right => Self::Down,
|
||||
Self::Down => Self::Left,
|
||||
Self::Left => Self::Up,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn turn_left(self) -> Self {
|
||||
match self {
|
||||
Self::Up => Self::Left,
|
||||
Self::Right => Self::Up,
|
||||
Self::Down => Self::Right,
|
||||
Self::Left => Self::Down,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct Position {
|
||||
pub x: isize,
|
||||
pub y: isize,
|
||||
}
|
||||
|
||||
impl std::ops::Add<Direction> for Position {
|
||||
type Output = Position;
|
||||
|
||||
fn add(mut self, rhs: Direction) -> Self::Output {
|
||||
match rhs {
|
||||
Direction::Up => self.y -= 1,
|
||||
Direction::Right => self.x += 1,
|
||||
Direction::Down => self.y += 1,
|
||||
Direction::Left => self.x -= 1,
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
fn paint(mut ic: IntCode, start_white: bool) -> HashMap<Position, bool> {
|
||||
let mut painted = HashMap::new();
|
||||
let mut pos = Position { x: 0, y: 0 };
|
||||
let mut direction = Direction::Up;
|
||||
if start_white {
|
||||
painted.insert(pos, true);
|
||||
}
|
||||
loop {
|
||||
let is_white = painted.get(&pos).cloned().unwrap_or(false);
|
||||
ic.next_input = Some(if is_white { 1 } else { 0 });
|
||||
match ic.simulate_step() {
|
||||
SimulateStep::WaitForInput => panic!("no further input until paint and movement done"),
|
||||
SimulateStep::Finished => break,
|
||||
SimulateStep::Output(n) => {
|
||||
match n {
|
||||
0 => { painted.insert(pos, false); },
|
||||
1 => { painted.insert(pos, true); },
|
||||
_ => panic!("invalid paint: {}", n),
|
||||
}
|
||||
}
|
||||
}
|
||||
match ic.simulate_step().expect_output() {
|
||||
0 => direction = direction.turn_left(),
|
||||
1 => direction = direction.turn_right(),
|
||||
n => panic!("invalid rotation: {}", n),
|
||||
}
|
||||
pos = pos + direction;
|
||||
}
|
||||
painted
|
||||
}
|
||||
|
||||
fn visualize(painted: HashMap<Position, bool>) {
|
||||
let painted_white: HashSet<Position> = painted.into_iter().filter_map(|(k, v)| if v { Some(k) } else { None }).collect();
|
||||
let left = painted_white.iter().map(|p| p.x).min().unwrap();
|
||||
let right = painted_white.iter().map(|p| p.x).max().unwrap();
|
||||
let top = painted_white.iter().map(|p| p.y).min().unwrap();
|
||||
let bottom = painted_white.iter().map(|p| p.y).max().unwrap();
|
||||
for y in top..=bottom {
|
||||
for x in left..=right {
|
||||
if painted_white.contains(&Position { x, y }) {
|
||||
print!("#");
|
||||
} else {
|
||||
print!(" ");
|
||||
}
|
||||
}
|
||||
println!("");
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let ic = include_str!("input.txt").parse::<IntCode>().unwrap();
|
||||
let painted = paint(ic.clone(), false);
|
||||
println!("First try: Painted {} tiles.", painted.len());
|
||||
let painted = paint(ic, true);
|
||||
visualize(painted);
|
||||
}
|
Loading…
Reference in New Issue
Block a user