summaryrefslogtreecommitdiffstats
path: root/2023/rs/code/seven/src/main.rs
blob: 132a779c6d19cd6e891c22084aaf58f05399dc68 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#![feature(iter_array_chunks)]

use std::collections::BTreeMap;

static INPUT: &str = include_str!("input.txt");

static MAPPING1: &[u8] = &[
  0,
  b'2',
  b'3',
  b'4',
  b'5',
  b'6',
  b'7',
  b'8',
  b'9',
  b'T',
  b'J',
  b'Q',
  b'K',
  b'A'
];
static MAPPING2: &[u8] = &[
  0,
  b'J',
  b'2',
  b'3',
  b'4',
  b'5',
  b'6',
  b'7',
  b'8',
  b'9',
  b'T',
  b'Q',
  b'K',
  b'A'
];

#[derive(Ord, PartialOrd, Eq, PartialEq, Debug, Copy, Clone)]
enum Hand {
  HighCard = 0,
  OnePair,
  TwoPair,
  ThreeOfAKind,
  FullHouse,
  FourOfAKind,
  FiveOfAKind
}

fn from_analyzer(analyzer: &BTreeMap<u8, u8>) -> Hand {
  match analyzer.len() {
      1 => Hand::FiveOfAKind,
      2 if analyzer.values().any(|a| *a == 4) => Hand::FourOfAKind,
      2 => Hand::FullHouse,
      3 if analyzer.values().any(|a| *a == 3) => Hand::ThreeOfAKind,
      3 => Hand::TwoPair,
      4 => Hand::OnePair,
      5 => Hand::HighCard,
      _ => unreachable!()
    }
}

fn main() {
  let valueified_1 = INPUT.split_ascii_whitespace().array_chunks::<2>().map(|[hand, bid]| {
    let bid = bid.parse::<u32>().unwrap();
    let mut analyzer = BTreeMap::new();
    for c in hand.bytes() { *analyzer.entry(c).or_insert(0) += 1; }
    let handtype = from_analyzer(&analyzer);
    ((handtype, hand.bytes().map(|b| MAPPING1.iter().position(|i| *i == b).unwrap()).collect::<Vec<_>>()), bid)
  });
  let total_winnings = valueified_1.collect::<BTreeMap<_, _>>().into_iter().enumerate().map(|(n, (_, b))| (n + 1) as u32 * b).sum::<u32>();
  println!("Total Winnings: {total_winnings}");


  let mut valueified_2 = INPUT.split_ascii_whitespace().array_chunks::<2>().map(|[hand, bid]| {
    let bid = bid.parse::<u32>().unwrap();
    let mut analyzer = BTreeMap::new();
    for c in hand.bytes() { *analyzer.entry(c).or_insert(0) += 1; }
    let mut hand = hand.bytes().collect::<Vec<_>>();
    if analyzer.contains_key(&b'J') {
      let (hichar, _) = analyzer.iter().fold((0, 0), |(a, b), (c, n)| if *n > b && *c != b'J' { (*c, *n) } else { (a, b) });
      if hichar != 0 {
        *analyzer.get_mut(&hichar).unwrap() += analyzer[&b'J'];
        analyzer.remove(&b'J');
      }
    }
    let handtype = from_analyzer(&analyzer);
    for c in &mut hand { *c = MAPPING2.iter().position(|i| *i == *c).unwrap() as u8 }
    ((handtype, hand), bid)
  }).collect::<Vec<_>>();
  valueified_2.sort_by(|a, b| a.0.cmp(&b.0));
  let total_winnings = valueified_2.into_iter().enumerate().map(|(n, (_, b))| (n + 1) as u32 * b).sum::<u32>();
  println!("Total Winnings 2: {total_winnings}");
}