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.
149 lines
2.9 KiB
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;
|
||
|
}
|