mirror of
https://github.com/wezm/advent-of-code.git
synced 2024-11-14 03:28:01 +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