Day 7 part 1
This commit is contained in:
parent
958a8f29e2
commit
d7c0ce9190
|
|
@ -60,17 +60,10 @@ pub fn solve(lines: Vec<String>, part: Part) -> u64 {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use log::info;
|
||||
|
||||
use crate::{day6::solve_race, utils::init_logger_test};
|
||||
fn init(){
|
||||
init_logger_test();
|
||||
}
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_solve_race() {
|
||||
init();
|
||||
|
||||
assert_eq!(solve_race(9, 7), 4);
|
||||
assert_eq!(solve_race(40, 15), 8);
|
||||
assert_eq!(solve_race(200, 30), 9);
|
||||
|
|
|
|||
283
src/day7/mod.rs
283
src/day7/mod.rs
|
|
@ -1,23 +1,298 @@
|
|||
use std::{cmp::Ordering, collections::HashMap};
|
||||
|
||||
use super::Part;
|
||||
use log::{debug, info, trace};
|
||||
use regex::Regex;
|
||||
|
||||
pub fn solve(lines: Vec<String>, part: Part) -> u64 {
|
||||
todo!()
|
||||
#[allow(dead_code)]
|
||||
#[derive(PartialEq, Eq, Debug, Hash, Clone)]
|
||||
enum Value {
|
||||
A,
|
||||
K,
|
||||
Q,
|
||||
J,
|
||||
T,
|
||||
Number(u8)
|
||||
}
|
||||
|
||||
impl PartialOrd for Value {
|
||||
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
match (self, other) {
|
||||
(Self::A, Self::A) => Some(Ordering::Equal),
|
||||
(_, Self::A) => Some(Ordering::Less),
|
||||
(Self::A, _) => Some(Ordering::Greater),
|
||||
|
||||
(Self::K, Self::K) => Some(Ordering::Equal),
|
||||
(_, Self::K) => Some(Ordering::Less),
|
||||
(Self::K, _) => Some(Ordering::Greater),
|
||||
|
||||
(Self::Q, Self::Q) => Some(Ordering::Equal),
|
||||
(_, Self::Q) => Some(Ordering::Less),
|
||||
(Self::Q, _) => Some(Ordering::Greater),
|
||||
|
||||
(Self::J, Self::J) => Some(Ordering::Equal),
|
||||
(_, Self::J) => Some(Ordering::Less),
|
||||
(Self::J, _) => Some(Ordering::Greater),
|
||||
|
||||
(Self::T, Self::T) => Some(Ordering::Equal),
|
||||
(_, Self::T) => Some(Ordering::Less),
|
||||
(Self::T, _) => Some(Ordering::Greater),
|
||||
|
||||
(Self::Number(n_self), Self::Number(n_other)) => n_self.partial_cmp(n_other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Value {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug)]
|
||||
enum Type {
|
||||
FiveOfAKind(Value),
|
||||
FourOfAKind(Value),
|
||||
FullHouse(Value, Value),
|
||||
ThreeOfAKind(Value),
|
||||
TwoPair(Value, Value),
|
||||
Pair(Value),
|
||||
HighCard(Value)
|
||||
}
|
||||
impl PartialEq for Type {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
matches!((self, other), (Self::FiveOfAKind(_), Self::FiveOfAKind(_)) | (Self::FourOfAKind(_), Self::FourOfAKind(_)) | (Self::ThreeOfAKind(_), Self::ThreeOfAKind(_)) | (Self::Pair(_), Self::Pair(_)) | (Self::HighCard(_), Self::HighCard(_)) | (Self::FullHouse(_, _), Self::FullHouse(_, _)) | (Self::TwoPair(_, _), Self::TwoPair(_, _)))
|
||||
}
|
||||
}
|
||||
impl Eq for Type {
|
||||
|
||||
}
|
||||
impl PartialOrd for Type {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
match (self, other) {
|
||||
(Self::FiveOfAKind(v), Self::FiveOfAKind(o)) => v.partial_cmp(o),
|
||||
(Self::FiveOfAKind(_), _) => Some(Ordering::Greater),
|
||||
(_, Self::FiveOfAKind(_)) => Some(Ordering::Less),
|
||||
|
||||
(Self::FourOfAKind(v), Self::FourOfAKind(o)) => v.partial_cmp(o),
|
||||
(Self::FourOfAKind(_), _) => Some(Ordering::Greater),
|
||||
(_, Self::FourOfAKind(_)) => Some(Ordering::Less),
|
||||
|
||||
(Self::FullHouse(v, v2), Self::FullHouse(o, o2)) => {
|
||||
let cmp = v.partial_cmp(o);
|
||||
if let Some(Ordering::Equal) = cmp {
|
||||
v2.partial_cmp(o2)
|
||||
}else{
|
||||
cmp
|
||||
}
|
||||
},
|
||||
(Self::FullHouse(_, _), _) => Some(Ordering::Greater),
|
||||
(_, Self::FullHouse(_, _)) => Some(Ordering::Less),
|
||||
|
||||
(Self::ThreeOfAKind(v), Self::ThreeOfAKind(o)) => v.partial_cmp(o),
|
||||
(Self::ThreeOfAKind(_), _) => Some(Ordering::Greater),
|
||||
(_, Self::ThreeOfAKind(_)) => Some(Ordering::Less),
|
||||
|
||||
(Self::TwoPair(v, v2), Self::TwoPair(o, o2)) => {
|
||||
let cmp = v.partial_cmp(o);
|
||||
if let Some(Ordering::Equal) = cmp {
|
||||
v2.partial_cmp(o2)
|
||||
}else{
|
||||
cmp
|
||||
}
|
||||
},
|
||||
(Self::TwoPair(_, _), _) => Some(Ordering::Greater),
|
||||
(_, Self::TwoPair(_, _)) => Some(Ordering::Less),
|
||||
|
||||
(Self::Pair(v), Self::Pair(o)) => v.partial_cmp(o),
|
||||
(Self::Pair(_), _) => Some(Ordering::Greater),
|
||||
(_, Self::Pair(_)) => Some(Ordering::Less),
|
||||
|
||||
(Self::HighCard(v), Self::HighCard(o)) => v.partial_cmp(o),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct Hand {
|
||||
cards: [Value; 5],
|
||||
kind: Type,
|
||||
bid: u64,
|
||||
}
|
||||
|
||||
impl PartialOrd for Hand {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
if self.kind == other.kind {
|
||||
for (v, o) in self.cards.iter().zip(other.cards.iter()) {
|
||||
match v.cmp(o) {
|
||||
Ordering::Greater => return Some(Ordering::Greater),
|
||||
Ordering::Less => return Some(Ordering::Less),
|
||||
_ => {},
|
||||
}
|
||||
};
|
||||
Some(Ordering::Equal)
|
||||
}else{
|
||||
self.kind.partial_cmp(&other.kind)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Hand {
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
self.partial_cmp(other).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
fn parse_char(c: char) -> Option<Value> {
|
||||
match c {
|
||||
'A' => Some(Value::A),
|
||||
'K' => Some(Value::K),
|
||||
'Q' => Some(Value::Q),
|
||||
'J' => Some(Value::J),
|
||||
'T' => Some(Value::T),
|
||||
'2'..='9' => Some(Value::Number(c.to_digit(10).unwrap() as u8)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_type_hand(cards: &[Value; 5]) -> Type {
|
||||
// Get the count of each type of card
|
||||
let counts = cards.iter().fold(HashMap::new(), |mut acc, e| {
|
||||
let counter = acc.entry(e).or_insert(0);
|
||||
*counter += 1;
|
||||
|
||||
acc
|
||||
});
|
||||
|
||||
let mut counts : Vec<_> = counts.iter().collect();
|
||||
counts.sort_by(|a,b| a.1.cmp(b.1));
|
||||
counts.reverse();
|
||||
debug!("# Cards {:?}", counts);
|
||||
|
||||
let (v, c) = counts.first().unwrap();
|
||||
// TODO: make it an accumulator ?
|
||||
|
||||
if **c == 5 {
|
||||
Type::FiveOfAKind((***v).clone())
|
||||
}else if **c == 4 {
|
||||
Type::FourOfAKind((***v).clone())
|
||||
}else if let Some(second_part) = counts.get(1) && **c == 3 && *second_part.1 == 2{
|
||||
Type::FullHouse((***v).clone(), (**second_part.0).clone())
|
||||
}else if **c == 3 {
|
||||
Type::ThreeOfAKind((***v).clone())
|
||||
}else if let Some(second_part) = counts.get(1) && **c == 2 && *second_part.1 == 2 {
|
||||
Type::TwoPair((***v).clone(), (**second_part.0).clone())
|
||||
}else if **c == 2 {
|
||||
Type::Pair((***v).clone())
|
||||
}else{
|
||||
Type::HighCard((***v).clone())
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(line: &str) -> Hand {
|
||||
let (hand, bid) = line.split_once(' ').unwrap();
|
||||
|
||||
let cards = hand.chars().map(|c| Value::parse_char(c).unwrap()).collect::<Vec<Value>>().try_into().unwrap();
|
||||
let bid = bid.parse().unwrap();
|
||||
|
||||
let kind = get_type_hand(&cards);
|
||||
|
||||
Hand {
|
||||
cards,
|
||||
kind,
|
||||
bid
|
||||
}
|
||||
}
|
||||
|
||||
pub fn solve(lines: Vec<String>, _: Part) -> u64 {
|
||||
let mut list : Vec<Hand> = lines.iter().map(|v| parse(v)).collect();
|
||||
list.sort();
|
||||
debug!("{:?}", list);
|
||||
|
||||
let mut sum: u64 = 0;
|
||||
for (rank, card) in list.iter().enumerate() {
|
||||
sum += (rank as u64 + 1 ) * card.bid;
|
||||
}
|
||||
|
||||
sum
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use log::info;
|
||||
|
||||
use crate::{day6::solve_race, utils::init_logger_test};
|
||||
use crate::utils::init_logger_test;
|
||||
use super::*;
|
||||
use super::Value::*;
|
||||
fn init(){
|
||||
init_logger_test();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_solve() {
|
||||
fn test_parse_hands() {
|
||||
init();
|
||||
|
||||
let h1 = "32T3K 765";
|
||||
let o1 = Hand{
|
||||
cards: [
|
||||
Number(3),
|
||||
Number(2),
|
||||
T,
|
||||
Number(3),
|
||||
K
|
||||
],
|
||||
kind: Type::Pair(Number(3)),
|
||||
bid: 765,
|
||||
};
|
||||
let h2 = "T55J5 684";
|
||||
let o2 = Hand {
|
||||
cards: [
|
||||
T,
|
||||
Number(5),
|
||||
Number(5),
|
||||
J,
|
||||
Number(5),
|
||||
],
|
||||
bid: 684,
|
||||
kind: Type::ThreeOfAKind(Number(5))
|
||||
};
|
||||
let h3 = "QQQJA 483";
|
||||
|
||||
let o3 = Hand {
|
||||
cards: [
|
||||
Q, Q, Q, J, A
|
||||
],
|
||||
kind: Type::ThreeOfAKind(Q),
|
||||
bid: 483
|
||||
};
|
||||
|
||||
let h4 = "KK677 28";
|
||||
let o4 = Hand {
|
||||
cards: [
|
||||
K, K, Number(6), Number(7), Number(7)
|
||||
],
|
||||
kind: Type::TwoPair(K, Number(7)),
|
||||
bid: 28
|
||||
};
|
||||
|
||||
info!("Hand 1 parsed {:?}", parse(h1));
|
||||
info!("Hand 1 reference {:?}", o1);
|
||||
assert_eq!(parse(h1), o1);
|
||||
|
||||
assert_eq!(parse(h2), o2);
|
||||
assert_eq!(parse(h3), o3);
|
||||
assert_eq!(parse(h4), o4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_lines_and_all() {
|
||||
let lines = "32T3K 765\nT55J5 684\nKK677 28\nKTJJT 220\nQQQJA 483".split('\n').map(|v| v.to_owned()).collect();
|
||||
let result = solve(lines, Part::One);
|
||||
|
||||
assert_eq!(result, 6440);
|
||||
}
|
||||
}
|
||||
26
src/main.rs
26
src/main.rs
|
|
@ -1,4 +1,5 @@
|
|||
#![feature(let_chains)]
|
||||
#![feature(array_zip)]
|
||||
#![feature(string_remove_matches)]
|
||||
|
||||
mod day1;
|
||||
|
|
@ -9,6 +10,7 @@ mod day5;
|
|||
mod day6;
|
||||
mod day7;
|
||||
mod utils;
|
||||
use log::info;
|
||||
use utils::Part;
|
||||
|
||||
|
||||
|
|
@ -21,7 +23,9 @@ fn main() {
|
|||
.init();
|
||||
|
||||
let data = utils::lines_from_file("./datasets/adventofcode.com_2023_day_7_input.txt").expect("Can't load the data");
|
||||
//let data = utils::lines_from_file("./datasets/test.txt").expect("Can't load the data");
|
||||
let result = day7::solve(data, Part::One);
|
||||
|
||||
info!("Result : {}", result);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -53,8 +57,8 @@ mod tests {
|
|||
#[test]
|
||||
fn day3() {
|
||||
let data_path = "./datasets/adventofcode.com_2023_day_3_input.txt";
|
||||
let result = day3::solve(utils::lines_from_file(data_path).expect("Could not load the dataset for day 3"), Part::One);
|
||||
let result2 = day3::solve(utils::lines_from_file(data_path).expect("Could not load the dataset for day 3"), Part::Two);
|
||||
let result = day3::solve(utils::lines_from_file(data_path).expect("Could not load the dataset"), Part::One);
|
||||
let result2 = day3::solve(utils::lines_from_file(data_path).expect("Could not load the dataset"), Part::Two);
|
||||
|
||||
assert_eq!(result, 522726);
|
||||
assert_eq!(result2, 81721933);
|
||||
|
|
@ -63,8 +67,8 @@ mod tests {
|
|||
#[test]
|
||||
fn day4() {
|
||||
let data_path = "./datasets/adventofcode.com_2023_day_4_input.txt";
|
||||
let result = day4::solve(utils::lines_from_file(data_path).expect("Could not load the dataset for day 3"), Part::One);
|
||||
let result2 = day4::solve(utils::lines_from_file(data_path).expect("Could not load the dataset for day 3"), Part::Two);
|
||||
let result = day4::solve(utils::lines_from_file(data_path).expect("Could not load the dataset"), Part::One);
|
||||
let result2 = day4::solve(utils::lines_from_file(data_path).expect("Could not load the dataset"), Part::Two);
|
||||
assert_eq!(result, 20407);
|
||||
assert_eq!(result2, 23806951);
|
||||
}
|
||||
|
|
@ -72,9 +76,17 @@ mod tests {
|
|||
#[test]
|
||||
fn day6() {
|
||||
let data_path = "./datasets/adventofcode.com_2023_day_6_input.txt";
|
||||
let result = day6::solve(utils::lines_from_file(data_path).expect("Could not load the dataset for day 3"), Part::One);
|
||||
let result2 = day6::solve(utils::lines_from_file(data_path).expect("Could not load the dataset for day 3"), Part::Two);
|
||||
let result = day6::solve(utils::lines_from_file(data_path).expect("Could not load the dataset"), Part::One);
|
||||
let result2 = day6::solve(utils::lines_from_file(data_path).expect("Could not load the dataset"), Part::Two);
|
||||
assert_eq!(result, 2612736);
|
||||
assert_eq!(result2, 29891250);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn day7() {
|
||||
let data_path = "./datasets/adventofcode.com_2023_day_7_input.txt";
|
||||
let result = day7::solve(utils::lines_from_file(data_path).expect("Could not load the dataset"), Part::One);
|
||||
|
||||
assert_eq!(result, 253866470);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue