feat: 2023 day seven
This commit is contained in:
parent
0f5138df92
commit
27eb39cc0f
1000
src/aoc2023/day07/input.txt
Normal file
1000
src/aoc2023/day07/input.txt
Normal file
File diff suppressed because it is too large
Load Diff
270
src/aoc2023/day07/mod.rs
Normal file
270
src/aoc2023/day07/mod.rs
Normal file
@ -0,0 +1,270 @@
|
||||
pub fn task_one(input: &str) -> String {
|
||||
let mut hands = parse_input_task_one(&input);
|
||||
hands.sort_by_key(|hand| hand.hand_type);
|
||||
|
||||
loop {
|
||||
let mut swap_occured = false;
|
||||
|
||||
for i in 0..(hands.len() - 1) {
|
||||
let current_element = hands[i].clone();
|
||||
let next_element = &hands[i + 1].clone();
|
||||
|
||||
if current_element.hand_type != next_element.hand_type {
|
||||
continue;
|
||||
}
|
||||
|
||||
for j in 0..5 {
|
||||
match current_element.cards[j].cmp(&next_element.cards[j]) {
|
||||
std::cmp::Ordering::Greater => {
|
||||
hands.swap(i, i + 1);
|
||||
swap_occured = true;
|
||||
break;
|
||||
},
|
||||
std::cmp::Ordering::Equal => continue,
|
||||
std::cmp::Ordering::Less => break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !swap_occured {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hands.iter()
|
||||
.enumerate()
|
||||
.fold(0, |sum, (rank, hand)| sum + ((rank + 1) * hand.bid as usize))
|
||||
.to_string()
|
||||
}
|
||||
|
||||
pub fn task_two(input: &str) -> String {
|
||||
let mut hands = parse_input_task_two(&input);
|
||||
hands.sort_by_key(|hand| hand.hand_type);
|
||||
|
||||
loop {
|
||||
let mut swap_occured = false;
|
||||
|
||||
for i in 0..(hands.len() - 1) {
|
||||
let current_element = hands[i].clone();
|
||||
let next_element = &hands[i + 1].clone();
|
||||
|
||||
if current_element.hand_type != next_element.hand_type {
|
||||
continue;
|
||||
}
|
||||
|
||||
for j in 0..5 {
|
||||
match current_element.cards[j].cmp(&next_element.cards[j]) {
|
||||
std::cmp::Ordering::Greater => {
|
||||
hands.swap(i, i + 1);
|
||||
swap_occured = true;
|
||||
break;
|
||||
},
|
||||
std::cmp::Ordering::Equal => continue,
|
||||
std::cmp::Ordering::Less => break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !swap_occured {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hands.iter()
|
||||
.enumerate()
|
||||
.fold(0, |sum, (rank, hand)| sum + ((rank + 1) * hand.bid as usize))
|
||||
.to_string()
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||
enum HandType {
|
||||
FiveOfAKind = 6,
|
||||
FourOfAKind = 5,
|
||||
FullHouse = 4,
|
||||
ThreeOfAKind = 3,
|
||||
TwoPair = 2,
|
||||
OnePair = 1,
|
||||
HighCard = 0
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
enum Card {
|
||||
Ass = 14,
|
||||
King = 13,
|
||||
Queen = 12,
|
||||
Junior = 11,
|
||||
Ten = 10,
|
||||
Nine = 9,
|
||||
Eight = 8,
|
||||
Seven = 7,
|
||||
Six = 6,
|
||||
Five = 5,
|
||||
Four = 4,
|
||||
Three = 3,
|
||||
Two = 2
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
|
||||
enum JokerCard {
|
||||
Ass = 14,
|
||||
King = 13,
|
||||
Queen = 12,
|
||||
Ten = 10,
|
||||
Nine = 9,
|
||||
Eight = 8,
|
||||
Seven = 7,
|
||||
Six = 6,
|
||||
Five = 5,
|
||||
Four = 4,
|
||||
Three = 3,
|
||||
Two = 2,
|
||||
Joker = 1
|
||||
}
|
||||
|
||||
impl From<char> for Card {
|
||||
fn from(value: char) -> Self {
|
||||
match value {
|
||||
'A' => Card::Ass,
|
||||
'K' => Card::King,
|
||||
'Q' => Card::Queen,
|
||||
'J' => Card::Junior,
|
||||
'T' => Card::Ten,
|
||||
'9' => Card::Nine,
|
||||
'8' => Card::Eight,
|
||||
'7' => Card::Seven,
|
||||
'6' => Card::Six,
|
||||
'5' => Card::Five,
|
||||
'4' => Card::Four,
|
||||
'3' => Card::Three,
|
||||
'2' => Card::Two,
|
||||
_ => panic!("Found {}", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<char> for JokerCard{
|
||||
fn from(value: char) -> Self {
|
||||
match value {
|
||||
'A' => JokerCard::Ass,
|
||||
'K' => JokerCard::King,
|
||||
'Q' => JokerCard::Queen,
|
||||
'T' => JokerCard::Ten,
|
||||
'9' => JokerCard::Nine,
|
||||
'8' => JokerCard::Eight,
|
||||
'7' => JokerCard::Seven,
|
||||
'6' => JokerCard::Six,
|
||||
'5' => JokerCard::Five,
|
||||
'4' => JokerCard::Four,
|
||||
'3' => JokerCard::Three,
|
||||
'2' => JokerCard::Two,
|
||||
'J' => JokerCard::Joker,
|
||||
_ => panic!("Found {}", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Hand {
|
||||
cards: Vec<Card>,
|
||||
bid: u32,
|
||||
hand_type: HandType
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct JokerHand {
|
||||
cards: Vec<JokerCard>,
|
||||
bid: u32,
|
||||
hand_type: HandType
|
||||
}
|
||||
|
||||
fn parse_input_task_one(input: &str) -> Vec<Hand> {
|
||||
let mut hands = Vec::new();
|
||||
|
||||
for line in input.lines() {
|
||||
let (cards, bid_string) = line.split_once(" ").unwrap();
|
||||
let mut hand_type = HandType::HighCard;
|
||||
|
||||
let pairs = count_cards(cards);
|
||||
|
||||
if pairs.iter().find(|pair| pair.1 == 5).is_some() {
|
||||
hand_type = HandType::FiveOfAKind;
|
||||
} else if pairs.iter().find(|pair| pair.1 == 4).is_some() {
|
||||
hand_type = HandType::FourOfAKind;
|
||||
} else if pairs.iter().find(|pair| pair.1 == 3).is_some() && pairs.iter().find(|pair| pair.1 == 2).is_some() {
|
||||
hand_type = HandType::FullHouse;
|
||||
} else if pairs.iter().find(|pair| pair.1 == 3).is_some() {
|
||||
hand_type = HandType::ThreeOfAKind;
|
||||
} else if pairs.iter().filter(|pair| pair.1 == 2).count() == 2 {
|
||||
hand_type = HandType::TwoPair;
|
||||
} else if pairs.iter().filter(|pair| pair.1 == 2).count() == 1 {
|
||||
hand_type = HandType::OnePair;
|
||||
}
|
||||
|
||||
hands.push(Hand { cards: cards.chars().into_iter().map(|c| c.into()).collect(), bid: bid_string.parse().unwrap(), hand_type })
|
||||
}
|
||||
|
||||
hands
|
||||
}
|
||||
|
||||
fn parse_input_task_two(input: &str) -> Vec<JokerHand> {
|
||||
let mut hands = Vec::new();
|
||||
|
||||
for line in input.lines() {
|
||||
let (cards, bid_string) = line.split_once(" ").unwrap();
|
||||
let mut hand_type = HandType::HighCard;
|
||||
|
||||
let mut pairs = count_cards(cards);
|
||||
let amount_of_joker = pairs.iter().find(|pair| pair.0 == 'J').unwrap_or(&('J', 0)).1;
|
||||
pairs.retain(|pair| pair.0 != 'J');
|
||||
pairs.sort_by_key(|pair| pair.1);
|
||||
pairs.reverse();
|
||||
|
||||
if let Some(first_pair) = pairs.first_mut() {
|
||||
first_pair.1 += amount_of_joker;
|
||||
}
|
||||
|
||||
if amount_of_joker == 5 || pairs.iter().find(|pair| pair.1 == 5).is_some() {
|
||||
hand_type = HandType::FiveOfAKind;
|
||||
} else if pairs.iter().find(|pair| pair.1 == 4).is_some() {
|
||||
hand_type = HandType::FourOfAKind;
|
||||
} else if pairs.iter().find(|pair| pair.1 == 3).is_some() && pairs.iter().find(|pair| pair.1 == 2).is_some() {
|
||||
hand_type = HandType::FullHouse;
|
||||
} else if pairs.iter().find(|pair| pair.1 == 3).is_some() {
|
||||
hand_type = HandType::ThreeOfAKind;
|
||||
} else if pairs.iter().filter(|pair| pair.1 == 2).count() == 2 {
|
||||
hand_type = HandType::TwoPair;
|
||||
} else if pairs.iter().filter(|pair| pair.1 == 2).count() == 1 {
|
||||
hand_type = HandType::OnePair;
|
||||
}
|
||||
|
||||
hands.push(JokerHand { cards: cards.chars().into_iter().map(|c| c.into()).collect(), bid: bid_string.parse().unwrap(), hand_type })
|
||||
}
|
||||
|
||||
hands
|
||||
}
|
||||
|
||||
fn count_cards(input: &str) -> Vec<(char, u8)> {
|
||||
let mut result: Vec<(char, u8)> = Vec::new();
|
||||
|
||||
for char in input.chars() {
|
||||
if let Some(entry) = result.iter_mut().find(|pair| pair.0 == char) {
|
||||
entry.1 += 1;
|
||||
} else {
|
||||
result.push((char, 1));
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_task_two() {
|
||||
let input = r##"32T3K 765
|
||||
T55J5 684
|
||||
KK677 28
|
||||
KTJJT 220
|
||||
QQQJA 483"##;
|
||||
|
||||
let result = task_two(&input);
|
||||
assert_eq!(result, "5905");
|
||||
}
|
@ -3,3 +3,4 @@ pub mod day02;
|
||||
pub mod day03;
|
||||
pub mod day04;
|
||||
pub mod day06;
|
||||
pub mod day07;
|
||||
|
@ -50,6 +50,7 @@ fn main() {
|
||||
puzzles.push(Puzzle { day: 3, year: 2023, task_one: aoc2023::day03::task_one, task_two: aoc2023::day03::task_two });
|
||||
puzzles.push(Puzzle { day: 4, year: 2023, task_one: aoc2023::day04::task_one, task_two: aoc2023::day04::task_two });
|
||||
puzzles.push(Puzzle { day: 6, year: 2023, task_one: aoc2023::day06::task_one, task_two: aoc2023::day06::task_two });
|
||||
puzzles.push(Puzzle { day: 7, year: 2023, task_one: aoc2023::day07::task_one, task_two: aoc2023::day07::task_two });
|
||||
|
||||
puzzles.iter().for_each(|puzzle| puzzle.solve_and_print());
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user