Setup + Days 1, 2, 3
This commit is contained in:
60
src/bin/day01.rs
Normal file
60
src/bin/day01.rs
Normal 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
48
src/bin/day02.rs
Normal 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
62
src/bin/day03.rs
Normal 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(())
|
||||
}
|
||||
Reference in New Issue
Block a user