add: more days
This commit is contained in:
Generated
+47
@@ -5,3 +5,50 @@ version = 3
|
||||
[[package]]
|
||||
name = "advent-of-code-2024"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||
|
||||
@@ -4,3 +4,4 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
regex = "1.11.1"
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import re
|
||||
with open("input-xlarge", "r") as inputFile:
|
||||
memory = inputFile.read()
|
||||
do_memory = memory.split("don't()")
|
||||
|
||||
|
||||
# part 1
|
||||
def apply_multipliers(s: str):
|
||||
prods = []
|
||||
multipliers = re.findall("mul\(\d{1,3},\d{1,3}\)", s)
|
||||
for m in multipliers:
|
||||
nums = list(map(int, re.findall("\d+", m)))
|
||||
prods.append(nums[0] * nums[1])
|
||||
return sum(prods)
|
||||
|
||||
|
||||
# part 2
|
||||
sum_dos = apply_multipliers(do_memory[0])
|
||||
for line in do_memory[1:]:
|
||||
if "do()" in line:
|
||||
split_line = "".join(line.split('do()')[1:])
|
||||
sum_dos += apply_multipliers(split_line)
|
||||
print(sum_dos)
|
||||
@@ -1,9 +0,0 @@
|
||||
# Advent of code 2024
|
||||
|
||||
Usage:
|
||||
|
||||
rustc dp1.rs
|
||||
cat input.txt | dp1.rs
|
||||
|
||||
## Day
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
use std::collections::BinaryHeap;
|
||||
use std::io;
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
let mut l1 = BinaryHeap::<u64>::new();
|
||||
let mut l2 = BinaryHeap::<u64>::new();
|
||||
for line in io::stdin().lines() {
|
||||
let line = line?;
|
||||
let parts: Vec<&str> = line.trim().split_whitespace().collect();
|
||||
let (n1, n2) = (parts[0], parts[1]);
|
||||
l1.push(n1.parse().unwrap());
|
||||
l2.push(n2.parse().unwrap());
|
||||
}
|
||||
let l1 = l1.into_sorted_vec();
|
||||
let l2 = l2.into_sorted_vec();
|
||||
let mut sum = 0;
|
||||
for (n1, n2) in l1.into_iter().zip(l2.into_iter()) {
|
||||
sum += n1.abs_diff(n2);
|
||||
}
|
||||
println!("{}", sum);
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
3 4
|
||||
4 3
|
||||
2 5
|
||||
1 3
|
||||
3 9
|
||||
3 3
|
||||
@@ -1,21 +0,0 @@
|
||||
use std::collections::HashMap;
|
||||
use std::io;
|
||||
|
||||
fn main() -> io::Result<()> {
|
||||
let mut l1: Vec<u64> = vec!();
|
||||
let mut l2: HashMap<u64, u64> = HashMap::default();
|
||||
for line in io::stdin().lines() {
|
||||
let line = line?;
|
||||
let parts: Vec<&str> = line.trim().split_whitespace().collect();
|
||||
let (n1, n2) = (parts[0], parts[1]);
|
||||
l1.push(n1.parse().unwrap());
|
||||
let v = l2.entry(n2.parse::<u64>().unwrap()).or_insert(0);
|
||||
*v += 1;
|
||||
}
|
||||
let mut sum = 0;
|
||||
for n1 in l1.into_iter() {
|
||||
sum += n1*l2.get(&n1).unwrap_or(&0);
|
||||
}
|
||||
println!("{}", sum);
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
use advent_of_code_2024::{make_main, SResult};
|
||||
|
||||
make_main!();
|
||||
|
||||
// CODE
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum Direction {
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
fn from(a: usize, b: usize) -> Self {
|
||||
if a > b {
|
||||
Direction::Down
|
||||
} else {
|
||||
Direction::Up
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn solve(lines: Vec<String>) -> SResult<usize> {
|
||||
let mut failed = 0;
|
||||
for line in lines.iter() {
|
||||
let reports: Vec<usize> = line.split_whitespace().map(|v| v.parse::<usize>().unwrap()).collect();
|
||||
let mut i = 0;
|
||||
let direction = Direction::from(reports[0], reports[1]);
|
||||
while i + 1 < reports.len() {
|
||||
let delta = reports[i].abs_diff(reports[i+1]);
|
||||
if delta < 1 || delta > 3 {
|
||||
failed += 1;
|
||||
break;
|
||||
}
|
||||
if direction != Direction::from(reports[i], reports[i+1]) {
|
||||
failed += 1;
|
||||
break;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
Ok(lines.len() - failed)
|
||||
}
|
||||
|
||||
// CODE
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use advent_of_code_2024::input;
|
||||
|
||||
use super::*;
|
||||
#[test]
|
||||
fn sample_input() {
|
||||
let strings: Vec<String> = input!("d2p1.txt");
|
||||
let got = solve(strings).unwrap();
|
||||
assert_eq!(got, 2);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
7 6 4 2 1
|
||||
1 2 7 8 9
|
||||
9 7 6 2 1
|
||||
1 3 2 4 5
|
||||
8 6 4 4 1
|
||||
1 3 6 7 9
|
||||
@@ -1,78 +0,0 @@
|
||||
use advent_of_code_2024::{make_main, SResult};
|
||||
|
||||
make_main!();
|
||||
|
||||
#[derive(PartialEq, Clone, Copy)]
|
||||
enum Direction {
|
||||
Up,
|
||||
Down,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
fn from(a: usize, b: usize) -> Self {
|
||||
if a > b {
|
||||
Direction::Down
|
||||
} else {
|
||||
Direction::Up
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn solve(lines: Vec<String>) -> SResult<usize> {
|
||||
let mut fail_count = 0;
|
||||
for line in lines.iter() {
|
||||
let reports: Vec<usize> = line
|
||||
.split_whitespace()
|
||||
.map(|v| v.parse::<usize>().unwrap())
|
||||
.collect();
|
||||
let problems = match test(&reports) {
|
||||
// Cool, nothing to see here
|
||||
Ok(_) => continue,
|
||||
Err(e) => e,
|
||||
};
|
||||
let mut pass = false;
|
||||
for problem in problems {
|
||||
let mut l1 = reports.clone();
|
||||
l1.remove(problem);
|
||||
if test(&l1).is_ok() {
|
||||
pass = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !pass {
|
||||
fail_count += 1;
|
||||
}
|
||||
}
|
||||
Ok(lines.len() - fail_count)
|
||||
}
|
||||
|
||||
// Tests the report, and returns indexes around where a failure is detected.
|
||||
fn test(reports: &[usize]) -> Result<(), Vec<usize>> {
|
||||
let mut i = 0;
|
||||
let direction = Direction::from(reports[0], reports[1]);
|
||||
while i + 1 < reports.len() {
|
||||
let delta = reports[i].abs_diff(reports[i + 1]);
|
||||
if delta < 1 || delta > 3 || direction != Direction::from(reports[i], reports[i + 1]) {
|
||||
let mut errs = vec![i, i + 1];
|
||||
if i > 0 {
|
||||
errs.push(i - 1);
|
||||
}
|
||||
return Err(errs);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use advent_of_code_2024::input;
|
||||
|
||||
use super::*;
|
||||
#[test]
|
||||
fn sample_input() {
|
||||
let strings: Vec<String> = input!("d2p1.txt");
|
||||
let got = solve(strings).unwrap();
|
||||
assert_eq!(got, 4);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
MMMSXXMASM
|
||||
MSAMXMSMSA
|
||||
AMXSXMAAMM
|
||||
MSAMASMSMX
|
||||
XMASAMXAMM
|
||||
XXAMMXXAMA
|
||||
SMSMSASXSS
|
||||
SAXAMASAAA
|
||||
MAMMMXMMMM
|
||||
MXMXAXMASX
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
+12
@@ -19,3 +19,15 @@ macro_rules! input {
|
||||
}
|
||||
|
||||
pub type SResult<T> = Result<T, Box<dyn std::error::Error>>;
|
||||
|
||||
pub type Pair<T = usize> = (T, T);
|
||||
|
||||
pub fn next((x, y): Pair, (xvel, yvel): Pair<i64>, width: usize) -> Option<Pair> {
|
||||
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))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user