This commit is contained in:
Tyler Hallada 2023-12-01 19:04:18 -05:00
parent 43b3ece2c3
commit e364357d00
7 changed files with 157 additions and 0 deletions

7
.gitignore vendored
View File

@ -12,3 +12,10 @@ Cargo.lock
# MSVC Windows builds of rustc generate these, which store debugging information # MSVC Windows builds of rustc generate these, which store debugging information
*.pdb *.pdb
# Added by cargo
/target
# Don't commit my personal input.txt files
input.txt

10
Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "advent-of-code-2023"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0"
phf = { version = "0.11", features = ["macros"] }

View File

@ -0,0 +1,4 @@
1abc2
pqr3stu8vwx
a1b2c3d4e5f
treb7uchet

View File

@ -0,0 +1,7 @@
two1nine
eightwothree
abcone2threexyz
xtwone3four
4nineeightseven2
zoneight234
7pqrstsixteen

107
src/day01/mod.rs Normal file
View File

@ -0,0 +1,107 @@
use std::cmp::min;
use anyhow::{anyhow, Result};
use phf::phf_map;
use crate::instrument::instrument;
const INPUT: &str = include_str!("input/input.txt");
static DIGITS: phf::Map<&[u8], u8> = phf_map! {
b"zero" => 0,
b"one" => 1,
b"two" => 2,
b"three" => 3,
b"four" => 4,
b"five" => 5,
b"six" => 6,
b"seven" => 7,
b"eight" => 8,
b"nine" => 9,
b"0" => 0,
b"1" => 1,
b"2" => 2,
b"3" => 3,
b"4" => 4,
b"5" => 5,
b"6" => 6,
b"7" => 7,
b"8" => 8,
b"9" => 9,
};
fn find_num(line: &[u8], reverse: bool) -> Option<u8> {
let window_size = min(line.len(), 5);
for i in 0..line.len() {
for j in 1..min(window_size + 1, line.len() - i + 1) {
if j == 2 {
continue; // no two-byte digits
}
if !reverse {
if let Some(digit) = DIGITS.get(&line[i..i + j]) {
return Some(*digit);
}
} else if let Some(digit) = DIGITS.get(&line[line.len() - i - j..line.len() - i]) {
return Some(*digit);
}
}
}
None
}
fn part1(input: &str) -> Result<u32> {
let mut sum: u32 = 0;
for line in input.trim().split('\n') {
let first = line
.as_bytes()
.iter()
.find(|c| c.is_ascii_digit())
.map(|c| c - b'0')
.ok_or_else(|| anyhow!("Invalid input: no digits found in line {}", line))?;
let last = line
.as_bytes()
.iter()
.rev()
.find(|c| c.is_ascii_digit())
.map(|c| c - b'0')
.ok_or_else(|| anyhow!("Invalid input: no digits found in line {}", line))?;
sum += (first as u32 * 10) + last as u32;
}
Ok(sum)
}
fn part2(input: &str) -> Result<u32> {
let mut sum = 0;
for line in input.trim().split('\n') {
let first = find_num(line.as_bytes(), false)
.ok_or_else(|| anyhow!("Invalid input: no digits found in line {}", line))?;
let last = find_num(line.as_bytes(), true)
.ok_or_else(|| anyhow!("Invalid input: no digits found in line {}", line))?;
sum += (first as u32 * 10) + last as u32;
}
Ok(sum)
}
pub fn solve() -> Result<()> {
println!("Day 01");
instrument!(part1(INPUT)?, part2(INPUT)?);
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
const TEST_INPUT1: &str = include_str!("input/test1.txt");
const TEST_INPUT2: &str = include_str!("input/test2.txt");
#[test]
fn test_part1() {
assert_eq!(part1(TEST_INPUT1).unwrap(), 142);
}
#[test]
fn test_part2() {
assert_eq!(part2(TEST_INPUT1).unwrap(), 142);
assert_eq!(part2(TEST_INPUT2).unwrap(), 281);
}
}

12
src/instrument.rs Normal file
View File

@ -0,0 +1,12 @@
macro_rules! instrument {
($part1:expr, $part2:expr) => {
let mut now = std::time::Instant::now();
println!("Part 1: {}", $part1);
println!("(elapsed: {:?})", now.elapsed());
now = std::time::Instant::now();
println!("");
println!("Part 2: {}", $part2);
println!("(elapsed: {:?})", now.elapsed());
};
}
pub(crate) use instrument;

10
src/main.rs Normal file
View File

@ -0,0 +1,10 @@
pub mod day01;
pub mod instrument;
use anyhow::Result;
fn main() -> Result<()> {
println!("Advent of Code 2023");
day01::solve()?;
Ok(())
}