add: more days

This commit is contained in:
Charles
2024-12-03 21:38:03 -08:00
parent 79d1618ede
commit 9f780311ed
19 changed files with 389 additions and 201 deletions
+29
View File
@@ -0,0 +1,29 @@
use advent_of_code_2024::{make_main, SResult};
use regex::Regex;
make_main!();
fn solve(lines: Vec<String>) -> SResult<usize> {
let mut result = 0;
let re = Regex::new(r"mul\((?<mul1>\d{1,3}),(?<mul2>\d{1,3})\)")?;
for line in lines {
for caps in re.captures_iter(&line) {
result += caps["mul1"].parse::<usize>().unwrap() * caps["mul2"].parse::<usize>().unwrap();
}
}
Ok(result)
}
#[cfg(test)]
mod tests {
use advent_of_code_2024::input;
use super::*;
#[test]
fn sample_input() {
let strings: Vec<String> = input!("d3p1.txt");
let got = solve(strings).unwrap();
assert_eq!(got, 161);
}
}
+1
View File
@@ -0,0 +1 @@
xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
+94
View File
@@ -0,0 +1,94 @@
use advent_of_code_2024::{make_main, SResult};
make_main!();
type PResult<'a, T> = Result<(&'a str, T), ()>;
fn literal<'a, 'b>(p: &'a str, lit: &'b str) -> PResult<'a, ()> {
if p.len() < lit.len() {
Err(())
} else {
let (found, rest) = p.split_at(lit.len());
if found == lit {
Ok((rest, ()))
} else {
Err(())
}
}
}
fn next(p: &str) -> PResult<char> {
let mut chars = p.chars();
let next = chars.next().ok_or(())?;
Ok((chars.as_str(), next))
}
fn int(mut p: &str) -> PResult<usize> {
let (_p, total) = next(p)?;
let mut total = total.to_digit(10).ok_or(())?;
p = _p;
let mut i = 1;
while let Ok((_p, digit)) = next(p) {
if !digit.is_digit(10) {
break;
}
total = (total * 10) + digit.to_digit(10).ok_or(())?;
p = _p;
// We only accept integers between 1 and 3 digits
i += 1;
if i > 3 {
return Err(());
}
}
Ok((p, total as usize))
}
fn mul(p: &str) -> PResult<usize> {
let (p, _) = literal(p, "mul(")?;
let (p, mul1) = int(p)?;
let (p, _) = literal(p, ",")?;
let (p, mul2) = int(p)?;
let (p, _) = literal(p, ")")?;
Ok((p, mul1*mul2))
}
fn solve(lines: Vec<String>) -> SResult<usize> {
let mut result = 0;
let mut enabled = true;
for line in lines {
let mut line = line.as_str();
while line.len() > 0 {
if let Ok(val) = mul(&line) {
if enabled {
result += val.1;
}
line = val.0;
} else if let Ok(val) = literal(&line, "do()") {
enabled = true;
line = val.0;
} else if let Ok(val) = literal(&line, "don't()") {
enabled = false;
line = val.0;
} else {
let n = next(line).unwrap();
line = n.0;
}
}
}
Ok(result)
}
#[cfg(test)]
mod tests {
use advent_of_code_2024::input;
use super::*;
#[test]
fn sample_input() {
let strings: Vec<String> = input!("d3p2.txt");
let got = solve(strings).unwrap();
assert_eq!(got, 48);
}
}
+36
View File
@@ -0,0 +1,36 @@
use advent_of_code_2024::{make_main, SResult};
use regex::Regex;
make_main!();
fn solve(lines: Vec<String>) -> SResult<usize> {
let mut result = 0;
let re = Regex::new(r"(?<do>do\(\))|(?<dont>don't\(\))|mul\(((?<mul1>\d{1,3})),((?<mul2>\d{1,3}))\)")?;
let mut enabled = true;
for line in lines {
for caps in re.captures_iter(&line) {
if caps.name("do").is_some() {
enabled = true;
} else if caps.name("dont").is_some() {
enabled = false;
} else if caps.name("mul1").is_some() && enabled {
result += caps["mul1"].parse::<usize>().unwrap() * caps["mul2"].parse::<usize>().unwrap();
}
}
}
Ok(result)
}
#[cfg(test)]
mod tests {
use advent_of_code_2024::input;
use super::*;
#[test]
fn sample_input() {
let strings: Vec<String> = input!("d3p2.txt");
let got = solve(strings).unwrap();
assert_eq!(got, 48);
}
}
+1
View File
@@ -0,0 +1 @@
xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))
+61
View File
@@ -0,0 +1,61 @@
use advent_of_code_2024::{make_main, SResult};
make_main!();
fn solve(lines: Vec<String>) -> SResult<usize> {
// Convert to a grid of chars for easy searching
let mut grid = vec!();
for line in lines {
let line: Vec<char> = line.chars().collect();
grid.push(line);
}
let mut total = 0;
let word: Vec<char> = "XMAS".chars().collect();
for x in 0..grid.len() {
for y in 0..grid[x].len() {
for vel in [(1, 0), (-1, 0), (0, 1), (0, -1), (1, 1), (-1, -1), (-1, 1), (1, -1)] {
let mut matches = 0;
let mut pos = (x, y);
for c in &word {
if grid[pos.0][pos.1] != *c {
break;
}
matches += 1;
if let Some(_pos) = next(pos, vel, grid.len()) {
pos = _pos;
} else {
break;
}
}
if matches == word.len() {
total += 1;
}
}
}
}
Ok(total)
}
fn next((x, y): (usize, usize), (xvel, yvel): (i64, i64), width: usize) -> Option<(usize, usize)> {
let x = x as i64 + xvel;
let y = y as i64 + yvel;
if x < 0 || y < 0 || x == width as i64 || y == width as i64 {
None
} else {
Some((x as usize, y as usize))
}
}
#[cfg(test)]
mod tests {
use advent_of_code_2024::input;
use super::*;
#[test]
fn sample_input() {
let strings: Vec<String> = input!("d4p1.txt");
let got = solve(strings).unwrap();
assert_eq!(got, 18);
}
}
+10
View File
@@ -0,0 +1,10 @@
MMMSXXMASM
MSAMXMSMSA
AMXSXMAAMM
MSAMASMSMX
XMASAMXAMM
XXAMMXXAMA
SMSMSASXSS
SAXAMASAAA
MAMMMXMMMM
MXMXAXMASX
+73
View File
@@ -0,0 +1,73 @@
use advent_of_code_2024::{make_main, SResult};
make_main!();
fn solve(lines: Vec<String>) -> SResult<usize> {
// Convert to a grid of chars for easy searching
let mut grid = vec!();
for line in lines {
let line: Vec<char> = line.chars().collect();
grid.push(line);
}
let mut total = 0;
let word: Vec<char> = "XMAS".chars().collect();
for x in 0..grid.len() {
for y in 0..grid[x].len() {
if grid[x][y] != 'A' {
continue;
}
let mut count = 0;
for vel in [(1, 1), (1, -1), (-1, -1), (-1, 1)] {
if let Some(pos) = next((x, y), vel, grid.len()) {
if check_mas(&grid, pos, (-1*vel.0, -1*vel.1)) {
count += 1;
}
}
}
if count == 2 {
total += 1;
}
}
}
Ok(total)
}
fn check_mas(grid: &[Vec<char>], mut pos: (usize, usize), vel: (i64, i64)) -> bool {
let mut matches = 0;
for c in "MAS".chars() {
if c != grid[pos.0][pos.1] {
break;
}
matches += 1;
if let Some(_pos) = next(pos, vel, grid.len()) {
pos = _pos;
} else {
break;
}
}
matches == "MAS".len()
}
fn next((x, y): (usize, usize), (xvel, yvel): (i64, i64), width: usize) -> Option<(usize, usize)> {
let x = x as i64 + xvel;
let y = y as i64 + yvel;
if x < 0 || y < 0 || x == width as i64 || y == width as i64 {
None
} else {
Some((x as usize, y as usize))
}
}
#[cfg(test)]
mod tests {
use advent_of_code_2024::input;
use super::*;
#[test]
fn sample_input() {
let strings: Vec<String> = input!("d4p1.txt");
let got = solve(strings).unwrap();
assert_eq!(got, 9);
}
}