Rust
I’m a day behind on this one due to a lot of work with my job and school.
use std::iter::zip;
use crate::utils::read_lines;
pub fn solution1() {
let puzzle = read_puzzle();
let horizontal_sum = puzzle
.iter()
.map(|line| {
line.windows(4)
.filter(|window| {
matches!(window, [b'X', b'M', b'A', b'S'] | [b'S', b'A', b'M', b'X'])
})
.count() as u32
})
.sum::<u32>();
let vertical_and_diagonal_sum = puzzle
.windows(4)
.map(|window| {
count_xmas(window, (0, 0, 0, 0))
+ count_xmas(window, (0, 1, 2, 3))
+ count_xmas(window, (3, 2, 1, 0))
})
.sum::<u32>();
println!(
"XMAS count = {}",
horizontal_sum + vertical_and_diagonal_sum
);
}
pub fn solution2() {
let puzzle = read_puzzle();
let sum = puzzle
.windows(3)
.map(|window| {
zip(
window[0].windows(3),
zip(window[1].windows(3), window[2].windows(3)),
)
.map(|(a, (b, c))| (a, b, c))
.filter(|tuple| {
matches!(
tuple,
([b'M', _, b'M'], [_, b'A', _], [b'S', _, b'S'])
| ([b'S', _, b'M'], [_, b'A', _], [b'S', _, b'M'])
| ([b'M', _, b'S'], [_, b'A', _], [b'M', _, b'S'])
| ([b'S', _, b'S'], [_, b'A', _], [b'M', _, b'M'])
)
})
.count() as u32
})
.sum::<u32>();
println!("X-MAS count = {sum}");
}
fn count_xmas(
window: &[Vec<u8>],
(skip0, skip1, skip2, skip3): (usize, usize, usize, usize),
) -> u32 {
zip(
window[0].iter().skip(skip0),
zip(
window[1].iter().skip(skip1),
zip(window[2].iter().skip(skip2), window[3].iter().skip(skip3)),
),
)
.map(|(a, (b, (c, d)))| (a, b, c, d))
.filter(|tup| matches!(tup, (b'X', b'M', b'A', b'S') | (b'S', b'A', b'M', b'X')))
.count() as u32
}
fn read_puzzle() -> Vec<Vec<u8>> {
read_lines("src/day4/input.txt")
.map(|line| line.into_bytes())
.collect()
}
The standard library windows
method and pattern matching have been carrying me this year so far.
Rust
Kinda sorta got day 5 done on time.
use std::cmp::Ordering; use crate::utils::{bytes_to_num, read_lines}; pub fn solution1() { let mut lines = read_input(); let rules = parse_rules(&mut lines); let middle_rules_sum = lines .filter_map(|line| { let line_nums = rule_line_to_list(&line); line_nums .is_sorted_by(|&a, &b| is_sorted(&rules, (a, b))) .then_some(line_nums[line_nums.len() / 2]) }) .sum::<usize>(); println!("Sum of in-order middle rules = {middle_rules_sum}"); } pub fn solution2() { let mut lines = read_input(); let rules = parse_rules(&mut lines); let middle_rules_sum = lines .filter_map(|line| { let mut line_nums = rule_line_to_list(&line); (!line_nums.is_sorted_by(|&a, &b| is_sorted(&rules, (a, b)))).then(|| { line_nums.sort_by(|&a, &b| { is_sorted(&rules, (a, b)) .then_some(Ordering::Less) .unwrap_or(Ordering::Greater) }); line_nums[line_nums.len() / 2] }) }) .sum::<usize>(); println!("Sum of middle rules = {middle_rules_sum}"); } fn read_input() -> impl Iterator<Item = String> { read_lines("src/day5/input.txt") } fn parse_rules(lines: &mut impl Iterator<Item = String>) -> Vec<(usize, usize)> { lines .take_while(|line| !line.is_empty()) .fold(Vec::new(), |mut rules, line| { let (a, b) = line.as_bytes().split_at(2); let a = bytes_to_num(a); let b = bytes_to_num(&b[1..]); rules.push((a, b)); rules }) } fn rule_line_to_list(line: &str) -> Vec<usize> { line.split(',') .map(|s| bytes_to_num(s.as_bytes())) .collect::<Vec<_>>() } fn is_sorted(rules: &[(usize, usize)], tuple: (usize, usize)) -> bool { rules.iter().any(|&r| r == tuple) }
Reusing my
bytes_to_num
function from day 3 feels nice. Pretty fun challenge.