2023: Day 7, part 1

This commit is contained in:
Wesley Moore 2023-12-08 08:27:25 +10:00
parent 87c5a2c02c
commit 8fcfb3c01a
No known key found for this signature in database
8 changed files with 1251 additions and 0 deletions

7
2023/day7/Cargo.lock generated Normal file
View file

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "day7"
version = "0.1.0"

8
2023/day7/Cargo.toml Normal file
View file

@ -0,0 +1,8 @@
[package]
name = "day7"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

2
2023/day7/Makefile Normal file
View file

@ -0,0 +1,2 @@
day7: day7.cpp
c++ -Wall -fsanitize=address day7.cpp -o day7

View file

@ -0,0 +1,7 @@
[
{
"directory": "/home/wmoore/Projects/advent-of-code/2023/day7",
"command": "c++ -Wall -fsanitize=address day7.cpp -o day7",
"file": "day7.cpp"
}
]

105
2023/day7/day7.cpp Normal file
View file

@ -0,0 +1,105 @@
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <map>
using std::cout, std::cerr, std::endl;
// From strongest to weakest
enum class Type {
// Five of a kind, where all five cards have the same label: AAAAA
FiveOfAKind = 7,
// Four of a kind, where four cards have the same label and one card has a
// different label: AA8AA
FourOfAKind = 6,
// Full house, where three cards have the same label, and the remaining two
// cards share a different label: 23332
FullHouse = 5,
// Three of a kind, where three cards have the same label, and the remaining
// two cards are each different from any other card in the hand: TTT98
ThreeOfAKind = 4,
// Two pair, where two cards share one label, two other cards share a second
// label, and the remaining card has a third label: 23432
TwoPair = 3,
// One pair, where two cards share one label, and the other three cards have a
// different label from the pair and each other: A23A4
OnePair = 2,
// High card, where all cards' labels are distinct: 23456
HighCard = 1,
Nothing = 0,
};
class Hand {
Hand(std::string, int);
Type type();
std::string hand;
int bid;
};
Hand::Hand(std::string s, int n) : hand{s}, bid{n} {
if (hand.length() != 5) {
throw "hand length != 5";
}
}
Type Hand::type() {
std::unordered_map<char, int> counts;
for(auto c : hand) {
counts[c] += 1;
}
if (counts.size() == 1) {
return Type::FiveOfAKind;
}
else if (counts.size() == 2) {
const auto it{counts.begin()};
auto count{it->second};
switch (count) {
case 1:
case 4:
return Type::FourOfAKind;
case 2:
case 3:
return Type::FullHouse;
}
for (const auto p : counts) {
}
}
return Type::Nothing;
}
int main(int argc, char **argv) {
if (argc < 2) {
cerr << "Usage: day7 input.txt" << endl;
return 1;
}
std::ifstream ifs{argv[1]};
std::string input{(std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>())};
std::istringstream iss{input};
for (std::string line; std::getline(iss, line);) {
if (line.empty()) {
continue;
}
std::istringstream liness{line};
std::string hand;
int bid;
liness >> hand >> bid;
cout << hand << ": " << bid << endl;
}
return 0;
}

116
2023/day7/src/main.rs Normal file
View file

@ -0,0 +1,116 @@
use std::cmp::Ordering;
use std::collections::HashMap;
use std::{env, fs};
type BoxError = Box<dyn std::error::Error>;
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Copy, Clone)]
enum Type {
// Five of a kind, where all five cards have the same label: AAAAA
FiveOfAKind = 7,
// Four of a kind, where four cards have the same label and one card has a
// different label: AA8AA
FourOfAKind = 6,
// Full house, where three cards have the same label, and the remaining two
// cards share a different label: 23332
FullHouse = 5,
// Three of a kind, where three cards have the same label, and the remaining
// two cards are each different from any other card in the hand: TTT98
ThreeOfAKind = 4,
// Two pair, where two cards share one label, two other cards share a second
// label, and the remaining card has a third label: 23432
TwoPair = 3,
// One pair, where two cards share one label, and the other three cards have a
// different label from the pair and each other: A23A4
OnePair = 2,
// High card, where all cards' labels are distinct: 23456
HighCard = 1,
Nothing = 0,
}
#[derive(Debug)]
struct Hand {
hand: String,
bid: u32,
}
fn main() -> Result<(), BoxError> {
let input_path = env::args_os()
.skip(1)
.next()
.ok_or("missing input file path")?;
let input = fs::read_to_string(input_path)?;
let mut hands = Vec::new();
for line in input.lines() {
if line.is_empty() {
continue;
}
let (hand, bid) = line.split_once(' ').ok_or("unable to split line")?;
hands.push(Hand {
hand: hand.to_string(),
bid: bid.parse()?,
});
}
let mut ranked = hands
.iter()
.map(|hand| (hand.hand_type(), hand))
.collect::<Vec<_>>();
ranked.sort_by(|(a_ty, a_hand), (b_ty, b_hand)| match a_ty.cmp(b_ty) {
Ordering::Equal => {
// println!("tie break {} {}", a_hand.hand, b_hand.hand);
for (ach, bch) in a_hand.hand.chars().zip(b_hand.hand.chars()) {
let ord = cmp_card(ach, bch);
if ord != Ordering::Equal {
return ord;
}
}
// All chars the same
return Ordering::Equal;
}
ord => ord,
});
let mut total_winnings = 0;
for (i, (_ty, hand)) in ranked.iter().enumerate() {
// println!("{} * {} = {}", (i as u32 + 1), hand.bid, (i as u32 + 1) * hand.bid);
total_winnings += (i as u32 + 1) * hand.bid;
}
// dbg!(&ranked);
println!("Part 1: {total_winnings}");
Ok(())
}
impl Hand {
fn hand_type(&self) -> Type {
let mut map = HashMap::with_capacity(5);
for c in self.hand.chars() {
*map.entry(c).or_insert(0) += 1;
}
let mut counts = map.values().collect::<Vec<_>>();
counts.sort_unstable();
counts.reverse();
match counts[..] {
[5] => Type::FiveOfAKind,
[4, 1] => Type::FourOfAKind,
[3, 2] => Type::FullHouse,
[3, 1, 1] => Type::ThreeOfAKind,
[2, 2, 1] => Type::TwoPair,
[1, 1, 1, 1, 1] => Type::HighCard,
_ if *counts[0] == 2 => Type::OnePair,
_ => Type::Nothing,
}
}
}
fn cmp_card(a: char, b: char) -> Ordering {
let sort = [
'A', 'K', 'Q', 'J', 'T', '9', '8', '7', '6', '5', '4', '3', '2',
];
let ai = sort.iter().position(|&c| a == c).expect("invalid char");
let bi = sort.iter().position(|&c| b == c).expect("invalid char");
bi.cmp(&ai)
}

6
2023/input/day7.sample Normal file
View file

@ -0,0 +1,6 @@
32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483

1000
2023/input/day7.txt Normal file

File diff suppressed because it is too large Load diff