Missed several updates. Working on 8 pt 2

This commit is contained in:
Connor Johnstone
2023-12-07 23:51:02 -07:00
parent 1793b37364
commit 58e0f7fcea
22 changed files with 4230 additions and 12 deletions

171
day_07/src/lib.rs Normal file
View File

@@ -0,0 +1,171 @@
use nom::{
bytes::complete::take,
character::complete::{
self, space1,
},
sequence::preceded,
IResult,
};
use std::collections::HashMap;
// 393J3 50208020002 836
// 3TJAJ 50209001200 837
fn is_five_of_a_kind(card: &str, match_numbers: Vec<usize>) -> bool {
if match_numbers.iter().any(|x| {x==&5}) {
true
} else if match_numbers.iter().any(|x| {x==&4}) && card.matches("J").count() == 1 {
true
} else if match_numbers.iter().any(|x| {x==&3}) && card.matches("J").count() == 2 {
true
} else if match_numbers.iter().any(|x| {x==&2}) && card.matches("J").count() == 3 {
true
} else if match_numbers.iter().any(|x| {x==&1}) && card.matches("J").count() == 4 {
true
} else if card.matches("J").count() == 5 {
true
} else {
false
}
}
fn is_four_of_a_kind(card: &str, match_numbers: Vec<usize>) -> bool {
if match_numbers.iter().any(|x| {x==&4}) {
true
} else if match_numbers.iter().any(|x| {x==&3}) && card.matches("J").count() == 1 {
true
} else if match_numbers.iter().any(|x| {x==&2}) && card.matches("J").count() == 2 {
true
} else if card.matches("J").count() == 3 {
true
} else {
false
}
}
fn is_full_house(card: &str, match_numbers: Vec<usize>) -> bool {
if match_numbers.iter().filter(|x| x > &&0).count() == 2 && match_numbers.iter().sum::<usize>() == 5 {
true
} else if match_numbers.iter().filter(|x| x == &&2).count() == 2 && card.matches("J").count() == 1 {
true
} else {
false
}
}
fn is_three_of_a_kind(card: &str, match_numbers: Vec<usize>) -> bool {
if match_numbers.iter().any(|x| {x==&3}) {
true
} else if match_numbers.iter().any(|x| {x==&2}) && card.matches("J").count() == 1 {
true
} else if card.matches("J").count() == 2 {
true
} else {
false
}
}
fn is_two_pair(_card: &str, match_numbers: Vec<usize>) -> bool {
if match_numbers.iter().filter(|x| x == &&2).count() == 2 {
true
} else {
false
}
}
fn is_pair(card: &str, match_numbers: Vec<usize>) -> bool {
if match_numbers.iter().any(|x| {x==&2}) {
true
} else if card.matches("J").count() == 1 {
true
} else {
false
}
}
fn score_card_pt2(card: &str) -> u64 {
let values = HashMap::from(
[('2', 1),('3', 2),('4', 3),('5', 4),('6', 5),('7', 6),('8', 7),('9', 8),('T', 9),('J', 0),('Q', 10),('K', 11),('A', 12)]
);
let values_without_joker = HashMap::from(
[('2', 1),('3', 2),('4', 3),('5', 4),('6', 5),('7', 6),('8', 7),('9', 8),('T', 9),('Q', 10),('K', 11),('A', 12)]
);
let sub_score = card.chars().enumerate().fold(0, |acc, (i, character)| {
acc + values.get(&character).unwrap() * 10_u64.pow(8 - 2*i as u32)
});
let match_numbers = values_without_joker.keys().map(|value| { card.matches(*value).count() }).collect::<Vec<usize>>();
if is_five_of_a_kind(card, match_numbers.clone()) {
6 * 10_u64.pow(10) + sub_score
} else if is_four_of_a_kind(card, match_numbers.clone()) {
5 * 10_u64.pow(10) + sub_score
} else if is_full_house(card, match_numbers.clone()) {
4 * 10_u64.pow(10) + sub_score
} else if is_three_of_a_kind(card, match_numbers.clone()) {
3 * 10_u64.pow(10) + sub_score
} else if is_two_pair(card, match_numbers.clone()) {
2 * 10_u64.pow(10) + sub_score
} else if is_pair(card, match_numbers.clone()) {
1 * 10_u64.pow(10) + sub_score
} else {
sub_score
}
}
fn score_card(card: &str) -> u64 {
let values = HashMap::from(
[('2', 0),('3', 1),('4', 2),('5', 3),('6', 4),('7', 5),('8', 6),('9', 7),('T', 8),('J', 9),('Q', 10),('K', 11),('A', 12)]
);
let sub_score = card.chars().enumerate().fold(0, |acc, (i, character)| {
acc + values.get(&character).unwrap() * 10_u64.pow(8 - 2*i as u32)
});
let match_numbers = values.keys().map(|value| { card.matches(*value).count() });
if match_numbers.clone().any(|x| {x==5}) {
6 * 10_u64.pow(10) + sub_score
} else if match_numbers.clone().any(|x| {x==4}) {
5 * 10_u64.pow(10) + sub_score
} else if match_numbers.clone().filter(|x| x > &0).count() == 2 && match_numbers.clone().sum::<usize>() == 5 {
4 * 10_u64.pow(10) + sub_score
} else if match_numbers.clone().any(|x| {x==3}) {
3 * 10_u64.pow(10) + sub_score
} else if match_numbers.clone().filter(|x| x > &0).count() == 3 {
2 * 10_u64.pow(10) + sub_score
} else if match_numbers.clone().any(|x| {x==2}) {
1 * 10_u64.pow(10) + sub_score
} else {
sub_score
}
}
fn parse_card(input: &str) -> IResult<&str, (&str, u64)> {
let (input, card) = take(5 as usize)(input)?;
let (input, bid) = preceded(space1, complete::u64)(input)?;
Ok((input, (card, bid)))
}
pub fn part1(input: &str) -> String {
let mut scored_hands = input.lines().map(|line| {
let (_, (card, bid)) = parse_card(line).unwrap();
let score = score_card(card);
(card, score, bid)
}).collect::<Vec<_>>();
scored_hands.sort_by_key(|x| {x.1});
scored_hands.into_iter().enumerate().map(|(i, (_, _, bid))| { (i as u64 + 1) * bid }).sum::<u64>().to_string()
}
pub fn part2(input: &str) -> String {
let mut scored_hands = input.lines().map(|line| {
let (_, (card, bid)) = parse_card(line).unwrap();
let score = score_card_pt2(card);
(card, score, bid)
}).collect::<Vec<_>>();
scored_hands.sort_by_key(|x| {x.1});
scored_hands.iter().enumerate().for_each(|(i, (card, score, _))| {println!("{} {} {}", card, score, i);});
scored_hands.into_iter().enumerate().map(|(i, (_, _, bid))| { (i as u64 + 1) * bid }).sum::<u64>().to_string()
}
pub mod prelude {
pub use super::part1;
pub use super::part2;
}

33
day_07/src/main.rs Normal file
View File

@@ -0,0 +1,33 @@
use day_07::prelude::*;
fn main() {
let input = include_str!("../input.txt");
println!("{}", part1(input));
println!("{}", part2(input));
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_part1() {
let test_input = "32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483";
assert_eq!(part1(test_input), "6440".to_string());
}
#[test]
fn test_part2() {
let test_input = "32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483";
assert_eq!(part2(test_input), "5905".to_string());
}
}