diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..74c3473 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +target +*-input.txt diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..45e6dbd --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,6 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "aoc" +version = "0.1.0" + diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..342c02b --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "aoc" +version = "0.1.0" +authors = ["Vladan Popovic "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/src/day_one.rs b/src/day_one.rs new file mode 100644 index 0000000..bc1b05e --- /dev/null +++ b/src/day_one.rs @@ -0,0 +1,29 @@ +fn fuel_for(mass: u64) -> u64 { + (mass / 3).saturating_sub(2) +} + +fn total_fuel(mass: u64) -> u64 { + std::iter::successors(Some(fuel_for(mass)), |&fuel| Some(fuel_for(fuel))) + .take_while(|&fuel| fuel > 0) + .sum() +} + +pub fn main(masses: Vec) { + let total: u64 = masses.into_iter().map(total_fuel).sum(); + println!("Fuel needed for bringing Santa home is: {}", total); +} + +#[test] +fn test_part1() { + assert_eq!(fuel_for(12), 2); + assert_eq!(fuel_for(14), 2); + assert_eq!(fuel_for(1969), 654); + assert_eq!(fuel_for(100756), 33583); +} + +#[test] +fn test_part2() { + assert_eq!(total_fuel(14), 2); + assert_eq!(total_fuel(1969), 966); + assert_eq!(total_fuel(100756), 50346); +} diff --git a/src/day_three.rs b/src/day_three.rs new file mode 100644 index 0000000..30459d0 --- /dev/null +++ b/src/day_three.rs @@ -0,0 +1,82 @@ +use std::collections::BTreeSet; +use std::fs::File; +use std::io::{self, BufRead, BufReader}; +use std::iter::{repeat, successors}; + +fn next(c: (i32, i32), direction: &str) -> (i32, i32) { + match direction { + "R" => (c.0 + 1, c.1), + "L" => (c.0 - 1, c.1), + "U" => (c.0, c.1 + 1), + "D" => (c.0, c.1 - 1), + _ => panic!("Wrong direction format!"), + } +} + +fn direction_length(entry: String) -> (String, usize) { + /// Creates a (direction, length) pair to later produce a string + /// on a direction with the given length. E.g. given "R10" the output of + ( + entry.chars().nth(0).unwrap().to_string(), + entry[1..].parse().unwrap(), + ) +} + +fn to_coordinates(entries: Vec) -> BTreeSet<(i32, i32)> { + let mut wire = BTreeSet::new(); + + let mut it = entries + .into_iter() + .map(direction_length) + .flat_map(|(direction, length)| repeat(direction).take(length)); + + successors( + it.next() + .map(|direction| (next((0, 0), direction.as_ref()))), + |c| it.next().map(|direction| (next(*c, direction.as_ref()))), + ) + .for_each(|c| { + wire.insert(c); + }); + + wire +} + +fn distance(position: (i32, i32)) -> i32 { + position.0.abs() + position.1.abs() +} + +pub fn main() -> io::Result<()> { + let f = BufReader::new(File::open("day3-input.txt")?); + let entries: Vec> = f + .lines() + .map(|line| line.unwrap().split(",").map(String::from).collect()) + .map(to_coordinates) + .collect(); + + let closest: Option = entries[0] + .intersection(&entries[1]) + .cloned() + .map(distance) + .min(); + println!("{:?}", closest); + + Ok(()) +} + +#[test] +fn test_coordinates_for_entry() { + let mut expected: BTreeSet<(i32, i32)> = BTreeSet::new(); + for i in 1..11 { + expected.insert((i, 0)); + } + assert_eq!(to_coordinates(vec!["R10".to_owned()]), expected); + + expected = BTreeSet::new(); + expected.insert((1, 0)); + expected.insert((2, 0)); + expected.insert((2, 1)); + expected.insert((2, 2)); + let input = "R2,U2".to_owned().split(",").map(String::from).collect(); + assert_eq!(to_coordinates(input), expected); +} diff --git a/src/day_two.rs b/src/day_two.rs new file mode 100644 index 0000000..8a102c6 --- /dev/null +++ b/src/day_two.rs @@ -0,0 +1,95 @@ +use std; + +fn compute_intcode(p: &mut Vec) -> Vec { + for idx in (0..(p.len())).step_by(4) { + match p[idx] { + 1 => { + let left = p[idx + 1]; + let right = p[idx + 2]; + let res = p[idx + 3]; + p[res] = p[left] + p[right]; + } + 2 => { + let left = p[idx + 1]; + let right = p[idx + 2]; + let res = p[idx + 3]; + p[res] = p[left] * p[right]; + } + 99 => break, + _ => panic!("Something went wrong!"), + } + } + p.to_vec() +} + +pub fn part_one() { + let mut input: Vec = std::include_str!("../day2-input.txt") + .trim() + .split(",") + .map(|x| x.parse().unwrap()) + .collect(); + + input[1] = 12; + input[2] = 2; + + println!("Intcode [0] is: {}", compute_intcode(&mut input)[0]); +} + +pub fn part_two() { + let mut input: Vec = std::include_str!("../day2-input.txt") + .trim() + .split(",") + .map(|x| x.parse().unwrap()) + .collect(); + + input[1] = 0; + input[2] = 0; + + let lookup_num = 19690720; + let mut found = false; + + for i in 0..99 { + input[1] = i; + for j in 0..99 { + input[2] = j; + let mut input_guess = input.clone(); + let computed = compute_intcode(&mut input_guess); + + found = computed[0] == lookup_num; + + if found { + let (noun, verb) = (computed[1], computed[2]); + println!( + "100 * noun({}) + verb({}) = {}", + noun, + verb, + 100 * noun + verb + ); + break; + } + } + if found { + break; + } + } +} + +#[test] +fn test_part_one() { + assert_eq!( + compute_intcode(&mut vec!(1, 0, 0, 0, 99)), + vec!(2, 0, 0, 0, 99) + ); + assert_eq!( + compute_intcode(&mut vec!(2, 3, 0, 3, 99)), + vec!(2, 3, 0, 6, 99) + ); + assert_eq!( + compute_intcode(&mut vec!(2, 4, 4, 5, 99, 0)), + vec!(2, 4, 4, 5, 99, 9801) + ); + assert_eq!( + compute_intcode(&mut vec!(1, 1, 1, 4, 99, 5, 6, 0, 99)), + vec!(30, 1, 1, 4, 2, 5, 6, 0, 99) + ); +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..68bcf50 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,22 @@ +mod day_one; +mod day_three; +mod day_two; + +use std::fs::File; +use std::io::{self, BufRead, BufReader}; + +fn main() -> io::Result<()> { + let f = BufReader::new(File::open("day1-input.txt")?); + let masses: Vec = f + .lines() + .map(|line| line.unwrap().parse().unwrap()) + .collect(); + day_one::main(masses); + + day_two::part_one(); + day_two::part_two(); + + day_three::main()?; + + Ok(()) +}