Skip to content

Instantly share code, notes, and snippets.

@tomaspavlic
Created December 10, 2024 16:40
Show Gist options
  • Save tomaspavlic/13d04e31710cf83694bbd85177e2416a to your computer and use it in GitHub Desktop.
Save tomaspavlic/13d04e31710cf83694bbd85177e2416a to your computer and use it in GitHub Desktop.
use itertools::Itertools;
use nom::{
bytes::complete::take_while1,
character::complete::{i32, newline},
multi::separated_list1,
IResult,
};
use std::collections::HashMap;
fn parse_row_numbers(s: &str) -> IResult<&str, (i32, i32)> {
let (s, n) = i32(s)?;
let (s, _) = take_while1(char::is_whitespace)(s)?;
let (s, n2) = i32(s)?;
Ok((s, (n, n2)))
}
fn parse_numbers(s: &str) -> IResult<&str, Vec<(i32, i32)>> {
separated_list1(newline, parse_row_numbers)(s)
}
fn solve_part1(left_list_sorted: &[i32], right_list_sorted: &[i32]) -> u32 {
left_list_sorted
.iter()
.zip(right_list_sorted)
.map(|(a, &b)| a.abs_diff(b))
.sum()
}
fn solve_part2(left_list: &[i32], right_list_sorted: &[i32]) -> i32 {
let r: HashMap<i32, i32> = right_list_sorted
.into_iter()
.chunk_by(|&a| a)
.into_iter()
.map(|(&k, g)| (k, g.count() as i32))
.collect();
left_list
.into_iter()
.map(|l| r.get(l).unwrap_or(&0) * l)
.sum()
}
fn main() -> anyhow::Result<()> {
let input = include_str!("../input/day1.txt");
let (_, numbers) = parse_numbers(&input)?;
let left_list = numbers.iter().map(|(n, _)| *n).sorted().collect_vec();
let right_list = numbers.into_iter().map(|(_, n)| n).sorted().collect_vec();
let part1 = solve_part1(&left_list, &right_list);
dbg!(part1);
let part2 = solve_part2(&left_list, &right_list);
dbg!(part2);
Ok(())
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn parse_numbers_works() {
let s = r"3 4
4 3
2 5
1 3
3 9
3 3";
let actual = parse_numbers(s);
let expected = IResult::Ok(("", vec![(3, 4), (4, 3), (2, 5), (1, 3), (3, 9), (3, 3)]));
assert_eq!(expected, actual);
}
#[test]
fn parse_row_numbers_works() {
let s = "3 4";
let actual = parse_row_numbers(s);
let expected = IResult::Ok(("", (3, 4)));
assert_eq!(expected, actual);
}
#[test]
fn solve_part1_works() {
let actual = solve_part1(&[1, 2, 3, 3, 3, 4], &[3, 3, 3, 4, 5, 9]);
assert_eq!(11, actual);
}
#[test]
fn solve_part2_works() {
let actual = solve_part2(&[3, 4, 2, 1, 3, 3], &[3, 3, 3, 4, 5, 9]);
assert_eq!(31, actual);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment