From 1df50835beb82126c7de1e25b4992b00a395c45f Mon Sep 17 00:00:00 2001 From: Stefan Schwarz Date: Sun, 19 Apr 2020 01:56:59 +0200 Subject: [PATCH] init --- .gitignore | 2 + Cargo.lock | 5 +++ Cargo.toml | 21 ++++++++++ src/day1/main.rs | 24 +++++++++++ src/day2/main.rs | 102 +++++++++++++++++++++++++++++++++++++++++++++++ src/day3/main.rs | 94 +++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 3 ++ 7 files changed, 251 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/day1/main.rs create mode 100644 src/day2/main.rs create mode 100644 src/day3/main.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7945e87 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/input* +/target/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..81a581c --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aoc2019" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a57a67e --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "aoc2019" +version = "0.1.0" +authors = ["Stefan Schwarz "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] + +[[bin]] +name = "day1" +path = "src/day1/main.rs" + +[[bin]] +name = "day2" +path = "src/day2/main.rs" + +[[bin]] +name = "day3" +path = "src/day3/main.rs" \ No newline at end of file diff --git a/src/day1/main.rs b/src/day1/main.rs new file mode 100644 index 0000000..e95ccbe --- /dev/null +++ b/src/day1/main.rs @@ -0,0 +1,24 @@ +use std::io::{self, BufRead}; + +fn main() -> io::Result<()> { + let mut total: i64 = 0; + io::stdin() + .lock() + .lines() + .filter_map(|l| l.ok()) + .filter_map(|l| l.parse::().ok()) + .for_each(|line| { + let mut cost = fuel_cost(line); + while cost > 0 { + total += cost; + cost = fuel_cost(cost); + } + }); + + println!("total fuel needed: {}", total); + Ok(()) +} + +fn fuel_cost(mass: i64) -> i64 { + mass / 3 - 2 +} diff --git a/src/day2/main.rs b/src/day2/main.rs new file mode 100644 index 0000000..9a53e4b --- /dev/null +++ b/src/day2/main.rs @@ -0,0 +1,102 @@ +use std::io::{self, BufRead}; + +enum Opcode { + Add, + Multiply, + Halt, +} + +impl From for Opcode { + fn from(i: u64) -> Self { + match i { + 1 => Opcode::Add, + 2 => Opcode::Multiply, + 99 => Opcode::Halt, + _ => panic!("invalid opcode {}", i), + } + } +} + +fn main() -> io::Result<()> { + let stdin = io::stdin(); + let mut program: Vec = stdin + .lock() + .split(b',') + .map(|o| { + o.expect("") + .iter() + .filter(|i| **i >= b'0' && **i <= b'9') + .fold(0, |s, i| (i - b'0' + 10 * s)) + }) + .map(|i| i as u64) + .collect(); + program[1] = 12; + program[2] = 2; + let result = run(&mut program.clone()); + println!("result: {}", result); + + for a in 0..99 { + for b in 0..99 { + program[1] = a; + program[2] = b; + let result = run(&mut program.clone()); + if result == 19690720 { + println!("a: {}, b: {}", a, b); + return Ok(()); + } + } + } + Ok(()) +} + +fn run(program: &mut Vec) -> u64 { + let mut instruction_pointer: usize = 0; + loop { + let instruction = program[instruction_pointer]; + let advance = match instruction.into() { + Opcode::Add => add(program, instruction_pointer), + Opcode::Multiply => multiply(program, instruction_pointer), + Opcode::Halt => return program[0], + }; + instruction_pointer += advance; + } +} + +fn add(program: &mut Vec, pos: usize) -> usize { + let a_pos = program[pos + 1] as usize; + let b_pos = program[pos + 2] as usize; + let c_pos = program[pos + 3] as usize; + program[c_pos] = program[a_pos] + program[b_pos]; + 4 +} + +fn multiply(program: &mut Vec, pos: usize) -> usize { + let a_pos = program[pos + 1] as usize; + let b_pos = program[pos + 2] as usize; + let c_pos = program[pos + 3] as usize; + program[c_pos] = program[a_pos] * program[b_pos]; + 4 +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn example1() { + let mut program: Vec = vec![1, 9, 10, 3, 2, 3, 11, 0, 99, 30, 40, 50]; + assert_eq!(run(&mut program), 3500) + } + + #[test] + fn example2() { + let mut program: Vec = vec![1, 0, 0, 0, 99]; + assert_eq!(run(&mut program), 2) + } + + #[test] + fn example3() { + let mut program: Vec = vec![1, 1, 1, 4, 99, 5, 6, 0, 99]; + assert_eq!(run(&mut program), 30) + } +} diff --git a/src/day3/main.rs b/src/day3/main.rs new file mode 100644 index 0000000..1d02f82 --- /dev/null +++ b/src/day3/main.rs @@ -0,0 +1,94 @@ +use std::collections::HashSet; +use std::io::{self, BufRead}; + +#[derive(Debug)] +enum Step { + Up(usize), + Down(usize), + Left(usize), + Right(usize), +} + +impl Step { + fn draw(&self, map: &mut HashSet, start: &mut Point) { + let mover: (i64, i64, &usize) = match self { + Step::Up(s) => (0, 1, s), + Step::Down(s) => (0, -1, s), + Step::Left(s) => (-1, 0, s), + Step::Right(s) => (1, 0, s), + }; + let (x, y, steps) = mover; + map.reserve(*steps); + for _ in 0..*steps { + start.x += x; + start.y += y; + map.insert(start.clone()); + } + } +} + +impl From<&[u8]> for Step { + fn from(b: &[u8]) -> Self { + let steps: usize = b[0..] + .iter() + .filter(|i| **i >= b'0' && **i <= b'9') + .fold(0, |s, i| ((i - b'0') as usize + 10 * s)); + match b[0] { + b'U' => Step::Up(steps), + b'D' => Step::Down(steps), + b'L' => Step::Left(steps), + b'R' => Step::Right(steps), + _ => panic!("unknown directions"), + } + } +} + +#[derive(Eq, PartialEq, Hash, Clone, Copy, Debug)] +struct Point { + x: i64, + y: i64, +} + +impl Point { + fn dist_to_00(&self) -> u64 { + (self.x.abs() + self.y.abs()) as u64 + } +} + +impl From<(i64, i64)> for Point { + fn from(xy: (i64, i64)) -> Self { + Point { x: xy.0, y: xy.1 } + } +} + +fn main() -> io::Result<()> { + let commands = load(); + let mut wires: Vec> = vec![]; + commands.iter().enumerate().for_each(|(_, wire)| { + let mut map = HashSet::new(); + let mut p: Point = (0, 0).into(); + wire.iter().for_each(|step| { + step.draw(&mut map, &mut p); + }); + wires.push(map); + }); + let closest = wires[0].intersection(&wires[1]).fold(None, |min, point| { + let dist = point.dist_to_00(); + match min { + None => Some(dist), + Some(min) => Some(if dist < min { dist } else { min }), + } + }); + println!("closest: {}", closest.unwrap()); + Ok(()) +} + +fn load() -> Vec> { + let stdin = io::stdin(); + stdin + .lock() + .split(b'\n') + .filter_map(|i| i.ok()) + .map(|line| line.split(|b| *b == b',').map(|i| Step::from(i)).collect()) + .collect() +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..e7a11a9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +}