diff --git a/data/examples/01.txt b/data/examples/01.txt new file mode 100644 index 0000000..41aa89c --- /dev/null +++ b/data/examples/01.txt @@ -0,0 +1,7 @@ +two1nine +eightwothree +abcone2threexyz +xtwone3four +4nineeightseven2 +zoneight234 +7pqrstsixteen diff --git a/data/examples/02.txt b/data/examples/02.txt new file mode 100644 index 0000000..295c36d --- /dev/null +++ b/data/examples/02.txt @@ -0,0 +1,5 @@ +Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green +Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue +Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red +Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red +Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green diff --git a/data/examples/03.txt b/data/examples/03.txt new file mode 100644 index 0000000..b20187f --- /dev/null +++ b/data/examples/03.txt @@ -0,0 +1,10 @@ +467..114.. +...*...... +..35..633. +......#... +617*...... +.....+.58. +..592..... +......755. +...$.*.... +.664.598.. diff --git a/src/bin/01.rs b/src/bin/01.rs new file mode 100644 index 0000000..42b2ee0 --- /dev/null +++ b/src/bin/01.rs @@ -0,0 +1,83 @@ +advent_of_code::solution!(1); + +pub fn part_one(input: &str) -> Option { + let sum = input.lines().map(|line| { + let mut digits = line.chars().filter(|c| c.is_digit(10)); + let first = digits.next().expect("first should be there"); + let last = digits.next_back().unwrap_or_else(|| first); + let str = format!("{}{}", first, last); + str.parse::().unwrap_or_else(|x| panic!("{}", x)) + }).sum(); + Some(sum) +} + +pub fn part_two(input: &str) -> Option { + let sum = input.lines().map(|line| { + let fst = get_nr(line.chars().collect(), NAMES); + let lst = get_nr(line.chars().rev().collect(), NAMES_REV); + let str = format!("{}{}", fst, lst); + str.parse::().unwrap_or_else(|x| panic!("{}", x)) + }).sum(); + Some(sum) +} + +const NAMES: &[&str] = &[ + "one", + "two", + "three", + "four", + "five", + "six", + "seven", + "eight", + "nine", +]; + +const NAMES_REV: &[&str] = &[ + "eno", + "owt", + "eerht", + "ruof", + "evif", + "xis", + "neves", + "thgie", + "enin", +]; + +fn get_nr(chars: Vec, names: &[&str]) -> u32 { + for i in 0..chars.len() { + match names.iter().position(|&name| + chars[0..i].iter().collect::().contains(name) + ) { + Some(i) => { + return i as u32 + 1; + } + None => { + match chars[i].to_digit(10) { + Some(d) => { return d } + None => {} + } + } + } + } + return 0 +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_one() { + let result = part_one(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, None); + } + + #[test] + fn test_part_two() { + let result = part_two(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, None); + } +} diff --git a/src/bin/02.rs b/src/bin/02.rs new file mode 100644 index 0000000..d065178 --- /dev/null +++ b/src/bin/02.rs @@ -0,0 +1,83 @@ +advent_of_code::solution!(2); + +pub mod util; +use util::str_to_u32_or_panic; +use std::cmp::max; + +pub fn part_one(input: &str) -> Option { + let red_cubes = 12; + let green_cubes = 13; + let blue_cubes = 14; + + let sum = input.lines().filter_map(|line| { + let (game_str, draws) = line.split_once(": ").expect(": should be there"); + let is_valid_game = draws.split("; ").all(|draw| { + draw.split(", ").all(|cube| { + if cube.ends_with("red") { + let r = &cube[0..cube.len()-4]; + str_to_u32_or_panic(r) <= red_cubes + } else if cube.ends_with("green") { + let g = &cube[0..cube.len()-6]; + str_to_u32_or_panic(g) <= green_cubes + } else if cube.ends_with("blue") { + let b = &cube[0..cube.len()-5]; + str_to_u32_or_panic(b) <= blue_cubes + } else { + panic!("cubes_str was {}", cube); + } + }) + }); + if is_valid_game { + let game_id = str_to_u32_or_panic(&game_str[5..]); + Some(game_id) + } else { + None + } + }).sum(); + Some(sum) +} + +pub fn part_two(input: &str) -> Option { + let sum = input.lines().map(|line| { + let mut r = 0; + let mut g = 0; + let mut b = 0; + let (_, draws) = line.split_once(": ").expect(": should be there"); + + for draw in draws.split("; ") { + for cube in draw.split(", ") { + if cube.ends_with("red") { + let nr_r = &cube[0..cube.len()-4]; + r = max(r, str_to_u32_or_panic(nr_r)); + } else if cube.ends_with("green") { + let nr_g = &cube[0..cube.len()-6]; + g = max(g, str_to_u32_or_panic(nr_g)); + } else if cube.ends_with("blue") { + let nr_b = &cube[0..cube.len()-5]; + b = max(b, str_to_u32_or_panic(nr_b)); + } else { + panic!("cubes_str was {}", cube); + } + } + } + r * g * b + }).sum(); + Some(sum) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_one() { + let result = part_one(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some(8)); + } + + #[test] + fn test_part_two() { + let result = part_two(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some(2286)); + } +} diff --git a/src/bin/03.rs b/src/bin/03.rs new file mode 100644 index 0000000..0eab3c9 --- /dev/null +++ b/src/bin/03.rs @@ -0,0 +1,116 @@ +pub mod util; +use util::str_to_u32_or_panic; +use std::cmp::min; + +advent_of_code::solution!(3); + +pub fn part_one(input: &str) -> Option { + let mut numbers = Vec::::new(); + let vec: Vec> = input.lines().map(|line| line.chars().collect()).collect(); + + let part_number = |nr_str: &str, line: usize, start: usize, end: usize| -> u32 { + for i in line.saturating_sub(1)..min(line+2, vec.len() - 1) { + for j in start.saturating_sub(1)..min(end+1, vec[i].len() - 1) { + if i != line || (j == start.saturating_sub(1) || j == end) { + let char = vec[i][j]; + if char != '.' && !char.is_digit(10) { + return str_to_u32_or_panic(nr_str) + } + } + } + } + 0 + }; + + let mut sum = 0; + for (i, line) in vec.iter().enumerate() { + let mut parsing_nr = false; + for (j, char) in line.iter().enumerate() { + if char.is_digit(10) { + if parsing_nr { + numbers.last_mut().expect("last element should be there") + .push_str(&char.to_string()); + } else { + numbers.push(char.to_string()); + parsing_nr = true; + } + } else { + if parsing_nr { + let nr_str = numbers.last().expect("number should be there"); + sum += part_number(nr_str, i, j - nr_str.len(), j); + } + parsing_nr = false; + } + } + if parsing_nr { + let nr_str = numbers.last().expect("number should be there"); + sum += part_number(nr_str, i, line.len() - nr_str.len(), line.len()); + } + } + + Some(sum) +} + +pub fn part_two(input: &str) -> Option { + let mut numbers = Vec::::new(); + let vec: Vec>> = input.lines().map(|line| { + let mut parsing_nr = false; + line.chars().map(|char| { + if char.is_digit(10) { + if parsing_nr { + numbers.last_mut().expect("last element should be there") + .push_str(&char.to_string()); + numbers.last() + } else { + let s = char.to_string(); + numbers.push(s); + parsing_nr = true; + Some(&s) + } + } else { + parsing_nr = false; + None + } + }).collect() + }).collect(); + + + let gear_ratio = |line: usize, start: usize, end: usize| -> u32 { + let mut nr_of_adjacent_numbers = 0; + let mut product = 1; + for i in line.saturating_sub(1)..min(line+2, vec.len() - 1) { + for j in start.saturating_sub(1)..min(end+1, vec[i].len() - 1) { + if i != line || (j == start.saturating_sub(1) || j == end) { + if let Some(s) = vec[i][j] { + nr_of_adjacent_numbers += 1; + product *= str_to_u32_or_panic(s); + } + } + } + } + if nr_of_adjacent_numbers == 2 { + product + } else { + 0 + } + }; + + None +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_one() { + let result = part_one(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some(4361)); + } + + #[test] + fn test_part_two() { + let result = part_two(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, None); + } +} diff --git a/src/bin/util.rs b/src/bin/util.rs new file mode 100644 index 0000000..3fd57ec --- /dev/null +++ b/src/bin/util.rs @@ -0,0 +1,3 @@ +pub fn str_to_u32_or_panic (str: &str) -> u32 { + str.parse::().unwrap_or_else(|x| panic!("{}", x)) +}

AltStyle によって変換されたページ (->オリジナル) /