advent of code 2023 edition
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
aoc_2023/day07/boc.rs

149 lines
2.9 KiB

10 months ago
use std::iter::*;
use std::cmp::*;
use std::collections::HashMap;
use std::fs;
use std::env;
type Hand = [usize;5];
fn main() {
let card_value: HashMap<char, usize> = zip(['J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A'], 0..13).collect();
println!("Hello, AoC day 7!");
let args: Vec<String> = env::args().collect();
if args.len() != 2 {
println!("wrong number of arguments!");
std::process::exit(1);
}
let file_path = &args[1];
let binding = fs::read_to_string(file_path)
.expect("Should have been able to read the file");
let contents = binding.lines();
let mut hands: Vec<(Hand, u32)> = Vec::new();
for line in contents {
if !line.is_empty() {
hands.push(parse(line, &card_value));
}
}
hands.sort_by(|(ha, _), (hb, _)| hand_compare(*ha, *hb));
println!("and now, the sorted:");
for (hand, value) in hands.iter() {
let ran = match rank(*hand) {
6 => "five of a kind",
5 => "four of a kind",
4 => "full house",
3 => "three of a kind",
2 => "two pair",
1 => "one pair",
0 => "card high",
_ => "mystery to us all"
};
println!("{:?}, which is a {}, for {}", hand, ran, value);
}
let mut sum = 0;
for (index, (_hand, bet)) in hands.iter().enumerate() {
let score = ((index as u32) + 1) * bet;
sum += score;
}
println!("total scores was: {}", sum);
}
fn parse(line: &str, dictionary: &HashMap<char, usize>) -> (Hand, u32) {
let (hand, value) = line.split_once(" ").expect("expected a line to have the format 'AAAAA ###'");
let mut m: [usize;5] = [0;5];
for (i, character) in hand.chars().enumerate() {
m[i] = *dictionary.get(&character).expect(&format!("expected a card in {}", line));
}
return (m, value.parse().unwrap());
}
fn rank(hand: Hand) -> u32 {
let mut a = [0; 13];
for letter in hand {
a[letter] += 1;
}
let mut fives = 0;
let mut fours = 0;
let mut threes = 0;
let mut twos = 0;
let mut _ones = 0;
for number in &a[1..] {
match number {
5 => fives += 1,
4 => fours += 1,
3 => threes += 1,
2 => twos += 1,
1 => _ones += 1,
_ => ()
}
}
if (fives > 0) ||
((fours == 1) && (a[0] == 1)) ||
((threes == 1) && (a[0] == 2)) ||
((twos == 1) && (a[0] == 3)) ||
(a[0] == 4) ||
(a[0] == 5) {
return 6;
}
if (fours > 0) ||
((threes == 1) && (a[0] == 1)) ||
((twos == 1) && (a[0] == 2)) ||
(a[0] == 3) ||
(a[0] == 4) {
return 5;
}
if (threes == 1 && twos == 1) ||
((twos == 2) && (a[0] == 1)) {
return 4;
}
if (threes == 1) ||
((twos == 1) && (a[0] == 1)) ||
(a[0] == 2) {
return 3;
}
if twos == 2 {
return 2;
}
if (twos == 1) ||
(a[0] == 1) {
return 1;
}
return 0;
}
fn hand_compare(a: Hand, b: Hand) -> Ordering {
let bs_a = rank(a);
let bs_b = rank(b);
if bs_a > bs_b {
return Ordering::Greater;
} else if bs_a < bs_b {
return Ordering::Less;
}
if a > b {
return Ordering::Greater;
} else if a < b {
return Ordering::Less;
}
return Ordering::Equal;
}