mirror of
https://github.com/wezm/advent-of-code.git
synced 2024-12-18 18:29:55 +00:00
2023: Day 7, part 1
This commit is contained in:
parent
87c5a2c02c
commit
8fcfb3c01a
8 changed files with 1251 additions and 0 deletions
7
2023/day7/Cargo.lock
generated
Normal file
7
2023/day7/Cargo.lock
generated
Normal 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
8
2023/day7/Cargo.toml
Normal 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
2
2023/day7/Makefile
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
day7: day7.cpp
|
||||||
|
c++ -Wall -fsanitize=address day7.cpp -o day7
|
7
2023/day7/compile_commands.json
Normal file
7
2023/day7/compile_commands.json
Normal 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
105
2023/day7/day7.cpp
Normal 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
116
2023/day7/src/main.rs
Normal 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
6
2023/input/day7.sample
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
32T3K 765
|
||||||
|
T55J5 684
|
||||||
|
KK677 28
|
||||||
|
KTJJT 220
|
||||||
|
QQQJA 483
|
||||||
|
|
1000
2023/input/day7.txt
Normal file
1000
2023/input/day7.txt
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue