day 10 (only part 1) + 11

This commit is contained in:
Stefan Bühler 2019-12-11 07:09:31 +01:00
parent 5abf4a2916
commit ff54ef107a
8 changed files with 277 additions and 0 deletions

14
Cargo.lock generated
View File

@ -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"

View File

@ -9,5 +9,7 @@ members = [
"day7",
"day8",
"day9",
"day10",
"day11",
"shared",
]

10
day10/Cargo.toml Normal file
View 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
View File

@ -0,0 +1,26 @@
#.#.###.#.#....#..##.#....
.....#..#..#..#.#..#.....#
.##.##.##.##.##..#...#...#
#.#...#.#####...###.#.#.#.
.#####.###.#.#.####.#####.
#.#.#.##.#.##...####.#.##.
##....###..#.#..#..#..###.
..##....#.#...##.#.#...###
#.....#.#######..##.##.#..
#.###.#..###.#.#..##.....#
##.#.#.##.#......#####..##
#..##.#.##..###.##.###..##
#..#.###...#.#...#..#.##.#
.#..#.#....###.#.#..##.#.#
#.##.#####..###...#.###.##
#...##..#..##.##.#.##..###
#.#.###.###.....####.##..#
######....#.##....###.#..#
..##.#.####.....###..##.#.
#..#..#...#.####..######..
#####.##...#.#....#....#.#
.#####.##.#.#####..##.#...
#..##..##.#.##.##.####..##
.##..####..#..####.#######
#.#..#.##.#.######....##..
.#.##.##.####......#.##.##

107
day10/src/main.rs Normal file
View 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
View 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
View 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
View 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);
}