-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathd7_part_one.rb
89 lines (74 loc) · 1.85 KB
/
d7_part_one.rb
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
# frozen_string_literal: true
def day7_part_one(input)
# Map letters to its strength in number
strengths = {
"A" => 14,
"K" => 13,
"Q" => 12,
"J" => 11,
"T" => 10
}
# Parse the input
hands = input.map(&:split)
# Classify the hands in Five of a Kind, Four of a Kind, ...
hands.each do |hand|
cards = hand[0].chars.tally
equal_cards, *rest = cards.sort_by { |_, v| -v }.map(&:last)
hand_type =
case equal_cards
when 5
50 # Five of a Kind
when 4
40 # Four of a kind
when 3
rest.include?(2) ? 35 : 30 # "Full house" or "Three of a kind"
when 2
rest.include?(2) ? 25 : 20 # "Two pair" or "One pair"
else
10 # "High card"
end
hand << hand_type
end
# Let's play the cards
# First order by hand type desc and group them
hands_group =
hands
.sort_by! { |_, _, type| -type }
.group_by { |_, _, type| type }
# Second order, pick winner for each hand on each group
hands_group.each do |_, cards|
cards.sort! do |(ca, _, _), (cb, _, _)|
wins = 0
# Compare card by card until found a winner, tie otherwise (wins is zero)
5.times do |idx|
next if ca[idx] == cb[idx]
a = strengths.fetch(ca[idx], ca[idx]).to_i
b = strengths.fetch(cb[idx], cb[idx]).to_i
wins = a > b ? -1 : 1
break
end
wins
end
end
# Finally reverse the order (weakest to stronger) and return the sum of bid * rank
hands_group
.values
.flatten(1)
.reverse
.each_with_index
.map { |card, rank| card[1].to_i * (rank + 1) }
.sum
end
test = <<~INPUT
32T3K 765
T55J5 684
KK677 28
KTJJT 220
QQQJA 483
INPUT
.split(/\n/)
puts day7_part_one(test)
file = File.open("d7.txt")
file_data = file.readlines.map(&:chomp)
file.close
puts day7_part_one(file_data)