Something went wrong. Try again.
retroactive, to derust my rust
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532pub fn day1_preprocess(input: &str) -> (Vec<u32>, Vec<u32>) { let pairs: Vec<Vec<u32>> = input .lines() .map(|line| { line.split_ascii_whitespace() .map(|location_id| location_id.parse().unwrap()) .collect() }) .collect();
let mut left = pairs.iter().map(|pair| pair[0]).collect::<Vec<_>>(); let mut right = pairs.iter().map(|pair| pair[1]).collect::<Vec<_>>(); left.sort(); right.sort(); (left, right)}pub fn day1_part1(input: &str) -> String { let (left, right) = day1_preprocess(input); let sum: u32 = left .iter() .zip(right) .map(|(left, right)| left.abs_diff(right)) .sum(); sum.to_string()}
pub fn day1_part2(input: &str) -> String { let (left, right) = day1_preprocess(input); let similarity_score: u32 = left .into_iter() .map(|left_location| { left_location * right .iter() .filter(|&&right_location| right_location == left_location) .count() as u32 }) .sum(); similarity_score.to_string()}
pub mod day2 { fn day2_preprocess(input: &str) -> Vec<Vec<u32>> { input .lines() .map(|report| { report .split_ascii_whitespace() .map(|level| level.parse().unwrap()) .collect() }) .collect() } pub fn day2_part1(input: &str) -> String { let reports = day2_preprocess(input); reports .into_iter() .filter(gradual) .filter(monotonic) .count() .to_string() } pub fn day2_part2(input: &str) -> String { let reports = day2_preprocess(input); reports .into_iter() .filter(should_filter_out_part2) .count() .to_string() } fn should_filter_out_part2(report: &Vec<u32>) -> bool { if gradual(report) && monotonic(report) { return true; } for index_to_skip in 0..report.len() { let skipped_report: Vec<u32> = report .iter() .enumerate() .filter(|(i, _)| *i != index_to_skip) .map(|(_, elem)| *elem) .collect(); if gradual(&skipped_report) && monotonic(&skipped_report) { return true; } } false }
fn gradual(report: &Vec<u32>) -> bool { for i in 1..report.len() { let diff = report[i].abs_diff(report[i - 1]); if !(1..=3).contains(&diff) { return false; } } true }
//fails if not gradual fn monotonic(report: &Vec<u32>) -> bool { let increasing = report[0] < report[1]; for i in 1..report.len() { if increasing { if report[i] < report[i - 1] { return false; } } else if report[i] > report[i - 1] { return false; } } true }}
pub mod day3 { use regex::Regex;
pub fn day3_part1(input: &str) -> String { let r = Regex::new(r"mul\((\d+),(\d+)\)").unwrap(); let multiplicands: Vec<(u32, u32)> = r .captures_iter(input) .map(|captures| { dbg!(&captures); (captures[1].parse().unwrap(), captures[2].parse().unwrap()) }) .collect(); let products: u32 = multiplicands.into_iter().map(|(l, r)| l * r).sum(); products.to_string() }
pub fn day3_part2(input: &str) -> String { let r = Regex::new(r"(?:do\(\))|(?:don't\(\))|(?:mul\((\d+),(\d+)\))").unwrap(); let mut multiply = true; let mut products: Vec<(u32, u32)> = vec![]; for captures in r.captures_iter(input) { dbg!(&captures); if &captures[0] == "do()" { multiply = true; } else if &captures[0] == "don't()" { multiply = false; } else if multiply { products.push((captures[1].parse().unwrap(), captures[2].parse().unwrap())); } } let sum: u32 = products.into_iter().map(|(l, r)| l * r).sum(); sum.to_string() }}
pub mod day4 { use regex::Regex;
pub fn day4_part1(input: &str) -> String { let pattern = Regex::new(r"XMAS").unwrap(); let reverse_pattern = Regex::new(r"SAMX").unwrap(); let mut count = 0;
count += pattern.find_iter(input).count(); count += reverse_pattern.find_iter(input).count(); dbg!(count);
let transposed = dbg!(transpose_string(input));
count += pattern.find_iter(&transposed).count(); count += reverse_pattern.find_iter(&transposed).count();
dbg!(count); let diag1 = dbg!(rotate_string_45degrees_counterclockwise(input)); count += pattern.find_iter(&diag1).count(); count += reverse_pattern.find_iter(&diag1).count();
dbg!(count); let diag2 = dbg!(rotate_string_45degrees_clockwise(input)); count += pattern.find_iter(&diag2).count(); count += reverse_pattern.find_iter(&diag2).count();
dbg!(count); count.to_string() }
pub fn day4_part2(input: &str) -> String{ let input = string_to_array(input); let mut count = 0; for row in 1..input.len()-1 { for col in 1..input.len()-1 { if is_x_mas(&input, row, col) { count += 1; } } } count.to_string() }
/* S&M combinations for X-MAS MS MS SM SM
MM SS
SS MM */ //precondition: row and col are one away from the edge fn is_x_mas(input: &Vec<Vec<char>>, row: usize, col: usize) -> bool { if input[row][col] != 'A' { return false; } if input[row-1][col-1] == 'M' { if input[row-1][col+1] == 'M' { input[row+1][col+1] == 'S' && input[row+1][col-1] == 'S' } else if input[row+1][col-1] == 'M' { input[row+1][col+1] == 'S' && input[row-1][col+1] == 'S' } else { false } } else if input[row-1][col-1] == 'S' { if input[row-1][col+1] == 'S' { input[row+1][col+1] == 'M' && input[row+1][col-1] == 'M' } else if input[row+1][col-1] == 'S' { input[row+1][col+1] == 'M' && input[row-1][col+1] == 'M' } else { false } } else { false }
}
//squares only fn rotate_string_45degrees_counterclockwise(input: &str) -> String { let array_input = string_to_array(input); assert_eq!(array_input.len(), array_input[0].len()); let mut array_output = vec![vec!['\0'; array_input.len()]; array_input.len() * 2 - 1];
// [(0, 5)] // [(0, 4), (1, 5)] // [(0, 3), (1, 4), (2, 5)] // [(0, 2), (1, 3), (2, 4), (3, 5)] // [(0, 1), (1, 2), (2, 3), (3, 4), (4, 5)] // [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)] // [(1, 0), (2, 1), (3, 2), (4, 3), (5, 4)] // [(2, 0), (3, 1), (4, 2), (5, 3)] // [(3, 0), (4, 1), (5, 2)] // [(4, 0), (5, 1)] // [(5, 0)]
for input_row in 0..array_input.len() { for input_col in 0..array_input.len() { let output_row = (array_input.len() - 1) as isize + (input_row as isize - input_col as isize); array_output[output_row as usize].push(array_input[input_row][input_col]); } }
let horistrings = array_output .into_iter() .map(|row| row.iter().filter(|&&c| c != '\0').collect::<String>()) .collect::<Vec<_>>(); horistrings.join("\n") }
fn rotate_string_45degrees_clockwise(input: &str) -> String { let mut unstrung = string_to_array(input); flip_horizontal(&mut unstrung); let restrung = horizontal_strings(&unstrung); rotate_string_45degrees_counterclockwise(&restrung.join("\n")) }
#[cfg(test)] #[test] fn string_rotation_tests() { let square_string = "AB\nCD"; let rotated = rotate_string_45degrees_counterclockwise(square_string); // B //A D // C assert_eq!(rotated, "B\nAD\nC");
/* ABCDE FGHIJ KLMNO PQRST UVWXY
rotated counterclockwise:
E D J C I O B H N T A G M S Y F L R X K Q W P V U
*/ let square_5x = "ABCDE\nFGHIJ\nKLMNO\nPQRST\nUVWXY"; let rotated = rotate_string_45degrees_counterclockwise(square_5x); day4_part1(square_5x); dbg!(rotated); // panic!() }
fn transpose_string(input: &str) -> String { let unstrung = string_to_array(input); let transposed = transpose(&unstrung); let horistrings = horizontal_strings(&transposed); horistrings.join("\n") }
fn string_to_array(input: &str) -> Vec<Vec<char>> { input.lines().map(|line| line.chars().collect()).collect() }
fn horizontal_strings(input: &Vec<Vec<char>>) -> Vec<String> { input.iter().map(|row| row.iter().collect()).collect() }
fn transpose(input: &Vec<Vec<char>>) -> Vec<Vec<char>> { let mut output = vec![vec!['\0'; input.len()]; input[0].len()];
for col in 0..input[0].len() { for row in 0..input.len() { output[col][row] = input[row][col] } } output }
fn flip_horizontal(input: &mut Vec<Vec<char>>) { for row in 0..input.len() { input[row].reverse() } }}
pub mod day5;pub mod day6;pub mod day7;pub mod day8;pub mod day9;pub mod day10;pub mod spatial;
#[cfg(test)]mod tests { use super::*;
#[test] fn day10_part1_test() { let test_result = day10::day10_part1(include_str!("../input/day10.test.txt")); assert_eq!(test_result, "36"); let result = day10::day10_part1(include_str!("../input/day10.txt")); assert_eq!(result, "820"); } #[test] fn day10_part2_test() { let test_result = day10::day10_part2(include_str!("../input/day10_simple2.test.txt")); assert_eq!(test_result, "3"); let test_result = day10::day10_part2(include_str!("../input/day10_simple.test.txt")); assert_eq!(test_result, "13"); let test_result = day10::day10_part2(include_str!("../input/day10.test.txt")); assert_eq!(test_result, "81"); let result = day10::day10_part2(include_str!("../input/day10.txt")); assert_eq!(result, "1786"); }
#[test] fn day9_part1_test() { let test_result = day9::day9_part1(include_str!("../input/day9.test.txt")); assert_eq!(test_result, "1928"); let result = day9::day9_part1(include_str!("../input/day9.txt")); assert_eq!(result, "6448989155953"); } #[test] fn day9_part2_test() { let test_result = day9::day9_part2(include_str!("../input/day9.test.txt")); assert_eq!(test_result, "2858"); let result = day9::day9_part2(include_str!("../input/day9.txt")); assert_eq!(result, "6476642796832"); }
#[test] fn day8_part1_test() { let simple_result = day8::day8_part1(include_str!("../input/day8.simple.test.txt")); assert_eq!(simple_result, "2"); let simple2_result = day8::day8_part1(include_str!("../input/day8.simple2.test.txt")); assert_eq!(simple2_result, "4"); let test_result = day8::day8_part1(include_str!("../input/day8.test.txt")); assert_eq!(test_result, "14"); let result = day8::day8_part1(include_str!("../input/day8.txt")); // assert!(result.parse::<u64>().unwrap() < 414); //too high assert_eq!(result, "369"); } #[test] fn day8_part2_test() { let test_result = day8::day8_part2(include_str!("../input/day8.test.txt")); assert_eq!(test_result, "34"); let result = day8::day8_part2(include_str!("../input/day8.txt")); assert_eq!(result, "1169"); }
#[test] fn day7_part1_test() { let test_result = day7::day7_part1(include_str!("../input/day7.test.txt")); assert_eq!(test_result, "3749"); let result = day7::day7_part1(include_str!("../input/day7.txt")); assert_eq!(result, "3598800864292"); }
#[ignore] #[test] fn day7_part2_test() { let simple_result = day7::day7_part2(include_str!("../input/day7_custom.test.txt")); assert_eq!(simple_result, (12345 + 12034050 + 15 + 120).to_string());
let test_result = day7::day7_part2(include_str!("../input/day7.test.txt")); assert_eq!(test_result, "11387"); let result = day7::day7_part2(include_str!("../input/day7.txt")); let parsed_result: u64 = result.parse::<u64>().unwrap(); assert!(parsed_result > 318_910_516_761_637, "{parsed_result} was too low"); assert_eq!(parsed_result, 340_362_529_351_427); }
#[test] fn day6_part1_test() { let test_result = day6::day6_part1(include_str!("../input/day6.test.txt")); assert_eq!(test_result, "41"); let result = day6::day6_part1(include_str!("../input/day6.txt")); assert_eq!(result, "5131"); }
#[ignore] #[test] fn day6_part2_test() { let test_result = day6::day6_part2(include_str!("../input/day6.test.txt")); assert_eq!(test_result, "6"); let result = day6::day6_part2(include_str!("../input/day6.txt")); assert_eq!(result, "1784"); }
#[test] fn day5_part1_test() { let test_result = day5::day5_part1(include_str!("../input/day5.test.txt")); assert_eq!(test_result, "143"); let result = day5::day5_part1(include_str!("../input/day5.txt")); assert_eq!(result, "5452"); }
#[test] fn day5_part2_test() { let test_result = day5::day5_part2(include_str!("../input/day5.test.txt")); assert_eq!(test_result, "123"); let result = day5::day5_part2(include_str!("../input/day5.txt")); assert_eq!(result, "4598"); }
#[test] fn day4_part1_test() { let simplest = "..X...\n.SAMX.\n.A..A.\nXMAS.S\n.X....\n......"; let test_result = day4::day4_part1(simplest); assert_eq!(test_result, "4");
let test_result = day4::day4_part1(include_str!("../input/day4.test.txt")); assert_eq!(test_result, "18"); let result = day4::day4_part1(include_str!("../input/day4.txt")); assert_ne!(result, "2092"); //too low assert_eq!(result, "2493"); }
#[test] fn day4_part2_test() { let test_result = day4::day4_part2(include_str!("../input/day4.test.txt")); assert_eq!(test_result, "9"); let result = day4::day4_part2(include_str!("../input/day4.txt")); assert_eq!(result, "1890"); }
#[test] fn day3_part1_test() { let test_result = day3::day3_part1(include_str!("../input/day3.test.txt")); assert_eq!(test_result, "161"); let result = day3::day3_part1(include_str!("../input/day3.txt")); assert_eq!(result, "183788984"); }
#[test] fn day3_part2_test() { let test_result = day3::day3_part2(include_str!("../input/day3_part2.test.txt")); assert_eq!(test_result, "48"); let result = day3::day3_part2(include_str!("../input/day3.txt")); assert_eq!(result, "62098619"); }
#[test] fn day2_part1_test() { let test_result = day2::day2_part1(include_str!("../input/day2.test.txt")); assert_eq!(test_result, "2"); let result = day2::day2_part1(include_str!("../input/day2.txt")); assert_eq!(result, "213"); } #[test] fn day2_part2_test() { let test_result = day2::day2_part2(include_str!("../input/day2.test.txt")); assert_eq!(test_result, "4"); let result = day2::day2_part2(include_str!("../input/day2.txt")); assert_eq!(result, "285"); }
#[test] fn day1_part1_test() { let test_result = day1_part1(include_str!("../input/day1_part1.test.txt")); assert_eq!(test_result, "11"); let result = day1_part1(include_str!("../input/day1.txt")); assert_eq!(result, "2742123"); }
#[test] fn day1_part2_test() { let test_result = day1_part2(include_str!("../input/day1_part1.test.txt")); assert_eq!(test_result, "31"); let result = day1_part2(include_str!("../input/day1.txt")); assert_eq!(result, "21328497"); }}