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.
advent-of-code/2023/ruby/day_07.rb

78 lines
2.1 KiB

module PartOne
CARD_ORDER = ((?2..?9).to_a + %w[ T J Q K A ]).each.with_index.to_h
Card = Data.define(:rank) do
def <=>(other)
CARD_ORDER.fetch(self.rank) <=> CARD_ORDER.fetch(other.rank)
end
end
Hand = Data.define(:cards) do
def type
tally = self.cards.tally
case tally.values.sort
when [5] then 5 # five of a kind
when [1, 4] then 4 # four of a kind
when [2, 3] then 3.5 # full house
when [1, 1, 3] then 3 # three of a kind
when [1, 2, 2] then 2.5 # two pair
when [1, 1, 1, 2] then 2 # one pair
when [1, 1, 1, 1, 1] then 1 # high card
else fail "couldn't calculate type: #{self.inspect}"
end
end
def <=>(other)
v = self.type <=> other.type
v.zero? ? self.cards <=> other.cards : v
end
end
end
module PartTwo
CARD_ORDER = ([?J] + (?2..?9).to_a + %w[ T Q K A ]).each.with_index.to_h
Card = Data.define(:rank) do
def <=>(other)
CARD_ORDER.fetch(self.rank) <=> CARD_ORDER.fetch(other.rank)
end
end
Hand = Data.define(:cards) do
def type
tally = self.cards.map(&:rank).tally
jokers = tally.delete(?J) || 0
counts = tally.values.sort
if counts.empty?
counts = [5]
else
counts[-1] += jokers
end
case counts
when [5] then 5 # five of a kind
when [1, 4] then 4 # four of a kind
when [2, 3] then 3.5 # full house
when [1, 1, 3] then 3 # three of a kind
when [1, 2, 2] then 2.5 # two pair
when [1, 1, 1, 2] then 2 # one pair
when [1, 1, 1, 1, 1] then 1 # high card
else fail "couldn't calculate type: #{self.inspect}"
end
end
def <=>(other)
v = self.type <=> other.type
v.zero? ? self.cards <=> other.cards : v
end
end
end
hands = ARGF.read.scan(/(\w+)\s+(\d+)/).to_h {|hand, bid|
[PartTwo::Hand.new(hand.chars.map { PartTwo::Card.new(_1) }), bid.to_i]
}
p hands
.sort_by(&:first)
.map.with_index {|(_,bid),i| bid * (i+1) }
.sum