Setup + Days 1, 2, 3

This commit is contained in:
Christian
2023-12-03 21:20:45 +01:00
commit 6e60a3f2e6
12 changed files with 1618 additions and 0 deletions

60
src/bin/day01.rs Normal file
View File

@@ -0,0 +1,60 @@
use std::env;
use std::fs;
use anyhow::{Context, Result};
fn p1(line: &str) -> Option<u32> {
let digits = line.chars().filter_map(|a| a.to_digit(10));
let first = digits.clone().next()?;
let last = digits.rev().next()?;
Some(first * 10 + last)
}
const DIGIT_NAMES: [&'static str; 9] = [
"one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
];
const REV_DIGIT_NAMES: [&'static str; 9] = [
"eno", "owt", "eerht", "ruof", "evif", "xis", "neves", "thgie", "enin",
];
fn find_first_digit(line: &str, digit_names: &[&'static str; 9]) -> Option<usize> {
let digit_char_position = line.as_bytes().iter().position(u8::is_ascii_digit)?;
let digit_value = usize::from(line.as_bytes()[digit_char_position] - b'0');
(0..digit_char_position)
.find_map(|start| {
let sliced = &line[start..];
digit_names
.into_iter()
.position(|&digit_name| sliced.starts_with(digit_name))
.map(|v| v + 1)
})
.or(Some(digit_value))
}
fn p2(line: &str) -> Option<usize> {
let first = find_first_digit(line, &DIGIT_NAMES)?;
let rev_line = line.chars().rev().collect::<String>();
let last = find_first_digit(rev_line.as_str(), &REV_DIGIT_NAMES)?;
Some(first * 10 + last)
}
fn main() -> Result<()> {
let filename = env::args()
.nth(1)
.context("./day01 <path to puzzle input")?;
let input = fs::read_to_string(filename)?;
let ans1: u32 = input.lines().map(|line| p1(line).unwrap()).sum();
let ans2: usize = input.lines().map(|line| p2(line).unwrap()).sum();
println!("1) {}", ans1);
println!("2) {}", ans2);
Ok(())
}

48
src/bin/day02.rs Normal file
View File

@@ -0,0 +1,48 @@
use std::env;
use std::fs;
use anyhow::{Context, Result};
const MALFORMED: &str = "malformed input.";
fn main() -> Result<()> {
let filename = env::args()
.nth(1)
.context("./day02 <path to puzzle input>")?;
let input = fs::read_to_string(filename)?;
let mut part1 = 0;
let mut part2 = 0;
for line in input.lines() {
let (game_name, game) = line.split_once(": ").context(MALFORMED)?;
let game_id: usize = game_name.split_once(' ').context(MALFORMED)?.1.parse()?;
let mut draw_max = (0u32, 0u32, 0u32);
for draw in game.split("; ") {
for color in draw.split(", ") {
let (count_str, color) = color.split_once(' ').context(MALFORMED)?;
let count: u32 = count_str.parse()?;
match color {
"red" => draw_max.0 = draw_max.0.max(count),
"green" => draw_max.1 = draw_max.1.max(count),
"blue" => draw_max.2 = draw_max.2.max(count),
_ => unreachable!(),
};
}
}
if draw_max.0 <= 12 && draw_max.1 <= 13 && draw_max.2 <= 14 {
part1 += game_id
}
part2 += draw_max.0 * draw_max.1 * draw_max.2;
}
println!("1) {}", part1);
println!("2) {}", part2);
Ok(())
}

62
src/bin/day03.rs Normal file
View File

@@ -0,0 +1,62 @@
use std::collections::HashMap;
use std::env;
use std::fs;
use regex::bytes::Regex;
use anyhow::{Context, Result};
fn main() -> Result<()> {
let filename = env::args()
.nth(1)
.context("./day03 <path to puzzle input>")?;
let input = fs::read_to_string(filename)?;
let lines = input
.lines()
.map(|line| line.as_bytes())
.collect::<Vec<_>>();
let number_re = Regex::new(r"\d+")?;
let h = lines.len();
let w = lines[0].len();
let is_symbol = |c: u8| !c.is_ascii_digit() && c != b'.';
let mut part1: usize = 0;
let mut gears: HashMap<(usize, usize), Vec<_>> = HashMap::new();
for (row, line) in lines.iter().enumerate() {
for number_str in number_re.find_iter(line) {
let value = std::str::from_utf8(number_str.as_bytes())?.parse::<usize>()?;
let mut has_symbol_neighbour = false;
for x in [row.saturating_sub(1), row, row + 1] {
for y in number_str.start().saturating_sub(1)..=number_str.end() {
if x < h && y < w {
has_symbol_neighbour |= is_symbol(lines[x][y]);
if lines[x][y] == b'*' {
gears.entry((x, y)).or_default().push(value);
}
}
}
}
if has_symbol_neighbour {
part1 += value;
}
}
}
let part2: usize = gears
.values()
.filter(|v| v.len() == 2)
.map(|v| v[0] * v[1])
.sum();
println!("1) {}", part1);
println!("2) {}", part2);
Ok(())
}