From 1c4bf97e07d666f6e6952bf5a9bfbb102a72d55b Mon Sep 17 00:00:00 2001 From: Andrew Glaze Date: Mon, 18 Dec 2023 09:38:38 -0500 Subject: [PATCH] update day7 --- Cargo.lock | 7 ++ Cargo.toml | 1 + old/day07/Cargo.lock | 7 -- old/day07/Cargo.toml | 8 -- old/day07/src/main.rs | 183 ------------------------------------- src/day7.rs | 207 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 7 files changed, 216 insertions(+), 198 deletions(-) delete mode 100644 old/day07/Cargo.lock delete mode 100644 old/day07/Cargo.toml delete mode 100644 old/day07/src/main.rs create mode 100644 src/day7.rs diff --git a/Cargo.lock b/Cargo.lock index 70fa963..67a0b69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,7 @@ version = "0.1.0" dependencies = [ "aoc-runner", "aoc-runner-derive", + "array2d", "itertools", "rust-crypto", ] @@ -41,6 +42,12 @@ dependencies = [ "serde_json", ] +[[package]] +name = "array2d" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b39cb2c1bf5a7c0dd097aa95ab859cf87dab5a4328900f5388942dc1889f74" + [[package]] name = "either" version = "1.9.0" diff --git a/Cargo.toml b/Cargo.toml index 86c1333..225963e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,3 +11,4 @@ rust-crypto = "0.2.36" aoc-runner = "0.3.0" aoc-runner-derive = "0.3.0" itertools = "0.12.0" +array2d = "0.3.0" \ No newline at end of file diff --git a/old/day07/Cargo.lock b/old/day07/Cargo.lock deleted file mode 100644 index cf14c74..0000000 --- a/old/day07/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "day07" -version = "0.1.0" diff --git a/old/day07/Cargo.toml b/old/day07/Cargo.toml deleted file mode 100644 index 682e4ad..0000000 --- a/old/day07/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "day07" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/old/day07/src/main.rs b/old/day07/src/main.rs deleted file mode 100644 index d7d3eae..0000000 --- a/old/day07/src/main.rs +++ /dev/null @@ -1,183 +0,0 @@ -use std::{fs, collections::HashMap}; - -fn main() { - let input = fs::read_to_string("input.txt").unwrap(); - let mut input: Vec<_> = input.split('\n') - .map(|line| line.split(' ').collect::>()) - .collect(); - - for line in 0..input.len() { - let hand = input[line][0]; - if hand == "JJJJJ" { - input[line].push("7"); - continue; - } - let mut card_freq: HashMap = HashMap::new(); - let joker_count: i16 = hand.chars().filter(|c| c == &'J').count().try_into().unwrap(); - for card in hand.chars().filter(|c| c != &'J') { - card_freq.entry(card) - .and_modify(|count| *count += 1) - .or_insert(1); - } - - // The most helpful place for the jokers will always be with the max card count - let max = card_freq.clone().into_iter().max_by(|a, b| a.1.cmp(&b.1)).unwrap(); - card_freq.entry(max.0) - .and_modify(|count| *count += joker_count); - - let mut set_count: HashMap = HashMap::new(); - for i in 1..=5 { - let card_count = card_freq.values().filter(|x| **x == i).count().try_into().unwrap(); - if card_count != 0 { - set_count.insert(i, card_count); - } - } - - let power = match set_count { - x if x.contains_key(&5) => "7", - x if x.contains_key(&4) => "6", - x if x.contains_key(&3) && x.contains_key(&2) => "5", - x if x.contains_key(&3) => "4", - x if x.get(&2).unwrap_or(&0) >= &2 => "3", - x if x.get(&2).unwrap_or(&0) == &1 => "2", - HashMap { .. } => "1" - }; - - input[line].push(power); - } - - input.sort_by(|lhs, rhs| { - let lhs_power: i32 = lhs[2].parse().unwrap(); - let rhs_power: i32 = rhs[2].parse().unwrap(); - if lhs_power != rhs_power { - return lhs_power.cmp(&rhs_power); - } - - let lhs_hand: Vec = lhs[0].chars().map(card_value).collect(); - let rhs_hand: Vec = rhs[0].chars().map(card_value).collect(); - for i in 0..5 { - if lhs_hand[i] == rhs_hand[i] { continue; } - return lhs_hand[i].cmp(&rhs_hand[i]); - } - - panic!("Should not be reachable"); - }); - - - let mut total_winnings = 0; - for i in 0..input.len() { - let bid: usize = input[i][1].parse().unwrap(); - total_winnings += (i + 1) * bid; - } - - println!("{}", total_winnings); - - -} - - -fn card_value(card: char) -> i32 { - match card { - 'A' => 13, - 'K' => 12, - 'Q' => 11, - 'T' => 10, - '9' => 9, - '8' => 8, - '7' => 7, - '6' => 6, - '5' => 5, - '4' => 4, - '3' => 3, - '2' => 2, - 'J' => 1, - _ => panic!("invalid card") - } -} - -// use std::{fs, collections::HashMap}; - -// fn main() { -// let input = fs::read_to_string("input.txt").unwrap(); -// let mut input: Vec<_> = input.split('\n') -// .map(|line| line.split(' ').collect::>()) -// .collect(); - -// for line in 0..input.len() { -// let hand = input[line][0]; -// let mut card_freq: HashMap = HashMap::new(); -// for card in hand.chars() { -// card_freq.entry(card) -// .and_modify(|count| *count += 1) -// .or_insert(1); -// } - -// let mut set_count: HashMap = HashMap::new(); -// for i in 1..=5 { -// let card_count = card_freq.values().filter(|x| **x == i).count().try_into().unwrap(); -// if card_count != 0 { -// set_count.insert(i, card_count); -// } -// } - -// let power = match set_count { -// x if x.contains_key(&5) => "7", -// x if x.contains_key(&4) => "6", -// x if x.contains_key(&3) && x.contains_key(&2) => "5", -// x if x.contains_key(&3) => "4", -// x if x.get(&2).unwrap_or(&0) >= &2 => "3", -// x if x.get(&2).unwrap_or(&0) == &1 => "2", -// HashMap { .. } => "1" -// }; - -// input[line].push(power); -// } - -// input.sort_by(|lhs, rhs| { -// let lhs_power: i32 = lhs[2].parse().unwrap(); -// let rhs_power: i32 = rhs[2].parse().unwrap(); -// if lhs_power != rhs_power { -// return lhs_power.cmp(&rhs_power); -// } - -// let lhs_hand: Vec = lhs[0].chars().map(card_value).collect(); -// let rhs_hand: Vec = rhs[0].chars().map(card_value).collect(); -// for i in 0..5 { -// if lhs_hand[i] == rhs_hand[i] { continue; } -// return lhs_hand[i].cmp(&rhs_hand[i]); -// } - -// panic!("Should not be reachable"); -// }); - - -// let mut total_winnings = 0; -// for i in 0..input.len() { -// let bid: usize = input[i][1].parse().unwrap(); -// total_winnings += (i + 1) * bid; -// } - -// println!("{}", total_winnings); - - -// } - - -// fn card_value(card: char) -> i32 { -// match card { -// 'A' => 13, -// 'K' => 12, -// 'Q' => 11, -// 'J' => 10, -// 'T' => 9, -// '9' => 8, -// '8' => 7, -// '7' => 6, -// '6' => 5, -// '5' => 4, -// '4' => 3, -// '3' => 2, -// '2' => 1, -// _ => panic!("invalid card") -// } -// } \ No newline at end of file diff --git a/src/day7.rs b/src/day7.rs new file mode 100644 index 0000000..f754ce4 --- /dev/null +++ b/src/day7.rs @@ -0,0 +1,207 @@ +use std::collections::HashMap; + +use aoc_runner_derive::{aoc, aoc_generator}; +#[aoc_generator(day7)] +fn parse(input: &str) -> Vec> { + let input: Vec> = input.split('\n') + .map(|line| line.split(' ').map(|x| x.into()).collect::>()) + .collect::>(); + + input +} + +#[aoc(day7, part1)] +fn part1(input: &Vec>) -> usize { + let mut tmp: Vec> = Vec::new(); + input.clone_into(&mut tmp); + let mut input = tmp; + + for line in 0..input.len() { + let hand = &input[line][0]; + let mut card_freq: HashMap = HashMap::new(); + for card in hand.chars() { + card_freq.entry(card) + .and_modify(|count| *count += 1) + .or_insert(1); + } + + let mut set_count: HashMap = HashMap::new(); + for i in 1..=5 { + let card_count = card_freq.values().filter(|x| **x == i).count().try_into().unwrap(); + if card_count != 0 { + set_count.insert(i, card_count); + } + } + + let power = match set_count { + x if x.contains_key(&5) => "7", + x if x.contains_key(&4) => "6", + x if x.contains_key(&3) && x.contains_key(&2) => "5", + x if x.contains_key(&3) => "4", + x if x.get(&2).unwrap_or(&0) >= &2 => "3", + x if x.get(&2).unwrap_or(&0) == &1 => "2", + HashMap { .. } => "1" + }; + + input[line].push(power.into()); + } + + input.sort_by(|lhs, rhs| { + let lhs_power: i32 = lhs[2].parse().unwrap(); + let rhs_power: i32 = rhs[2].parse().unwrap(); + if lhs_power != rhs_power { + return lhs_power.cmp(&rhs_power); + } + + let lhs_hand: Vec = lhs[0].chars().map(card_value).collect(); + let rhs_hand: Vec = rhs[0].chars().map(card_value).collect(); + for i in 0..5 { + if lhs_hand[i] == rhs_hand[i] { continue; } + return lhs_hand[i].cmp(&rhs_hand[i]); + } + + panic!("Should not be reachable"); + }); + + + let mut total_winnings = 0; + for i in 0..input.len() { + let bid: usize = input[i][1].parse().unwrap(); + total_winnings += (i + 1) * bid; + } + + total_winnings +} + +fn card_value(card: char) -> i32 { + match card { + 'A' => 13, + 'K' => 12, + 'Q' => 11, + 'J' => 10, + 'T' => 9, + '9' => 8, + '8' => 7, + '7' => 6, + '6' => 5, + '5' => 4, + '4' => 3, + '3' => 2, + '2' => 1, + _ => panic!("invalid card") + } +} + +#[aoc(day7, part2)] +fn part2(input: &Vec>) -> usize { + let mut tmp: Vec> = Vec::new(); + input.clone_into(&mut tmp); + let mut input = tmp; + + for line in 0..input.len() { + let hand = &input[line][0]; + if hand == "JJJJJ" { + input[line].push("7".to_string()); + continue; + } + let mut card_freq: HashMap = HashMap::new(); + let joker_count: i16 = hand.chars().filter(|c| c == &'J').count().try_into().unwrap(); + for card in hand.chars().filter(|c| c != &'J') { + card_freq.entry(card) + .and_modify(|count| *count += 1) + .or_insert(1); + } + + // The most helpful place for the jokers will always be with the max card count + let max = card_freq.clone().into_iter().max_by(|a, b| a.1.cmp(&b.1)).unwrap(); + card_freq.entry(max.0) + .and_modify(|count| *count += joker_count); + + let mut set_count: HashMap = HashMap::new(); + for i in 1..=5 { + let card_count = card_freq.values().filter(|x| **x == i).count().try_into().unwrap(); + if card_count != 0 { + set_count.insert(i, card_count); + } + } + + let power = match set_count { + x if x.contains_key(&5) => "7", + x if x.contains_key(&4) => "6", + x if x.contains_key(&3) && x.contains_key(&2) => "5", + x if x.contains_key(&3) => "4", + x if x.get(&2).unwrap_or(&0) >= &2 => "3", + x if x.get(&2).unwrap_or(&0) == &1 => "2", + HashMap { .. } => "1" + }; + + input[line].push(power.to_string()); + } + + input.sort_by(|lhs, rhs| { + let lhs_power: i32 = lhs[2].parse().unwrap(); + let rhs_power: i32 = rhs[2].parse().unwrap(); + if lhs_power != rhs_power { + return lhs_power.cmp(&rhs_power); + } + + let lhs_hand: Vec = lhs[0].chars().map(card_value_pt2).collect(); + let rhs_hand: Vec = rhs[0].chars().map(card_value_pt2).collect(); + for i in 0..5 { + if lhs_hand[i] == rhs_hand[i] { continue; } + return lhs_hand[i].cmp(&rhs_hand[i]); + } + + panic!("Should not be reachable"); + }); + + + let mut total_winnings = 0; + for i in 0..input.len() { + let bid: usize = input[i][1].parse().unwrap(); + total_winnings += (i + 1) * bid; + } + + total_winnings +} + +fn card_value_pt2(card: char) -> i32 { + match card { + 'A' => 13, + 'K' => 12, + 'Q' => 11, + 'T' => 10, + '9' => 9, + '8' => 8, + '7' => 7, + '6' => 6, + '5' => 5, + '4' => 4, + '3' => 3, + '2' => 2, + 'J' => 1, + _ => panic!("invalid card") + } +} + + +#[cfg(test)] +mod tests { + use super::*; + + const EX: &str = r"32T3K 765 +T55J5 684 +KK677 28 +KTJJT 220 +QQQJA 483"; + + #[test] + fn part1_example() { + assert_eq!(part1(&parse(EX)), 6440); + } + + #[test] + fn part2_example() { + assert_eq!(part2(&parse(EX)), 5905); + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 88d157d..64d52d5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ +mod day7; mod day6; mod day5; mod day3;