From 9be3674f73f4a5902616f71909826a4c0cca4f52 Mon Sep 17 00:00:00 2001 From: Greg Woods Date: Thu, 7 Dec 2023 10:05:14 -0500 Subject: [PATCH] day 7 --- examples/07.txt | 5 +++ lib/days/07.rb | 96 +++++++++++++++++++++++++++++++++++++++++++++++++ test/07_test.rb | 18 ++++++++++ 3 files changed, 119 insertions(+) create mode 100644 examples/07.txt create mode 100644 lib/days/07.rb create mode 100644 test/07_test.rb diff --git a/examples/07.txt b/examples/07.txt new file mode 100644 index 0000000..e3500c3 --- /dev/null +++ b/examples/07.txt @@ -0,0 +1,5 @@ +32T3K 765 +T55J5 684 +KK677 28 +KTJJT 220 +QQQJA 483 diff --git a/lib/days/07.rb b/lib/days/07.rb new file mode 100644 index 0000000..9c0c807 --- /dev/null +++ b/lib/days/07.rb @@ -0,0 +1,96 @@ +class Day07 + + # LABELS = ['High Card', 'Pair', 'Two Pair', 'Three of a Kind', 'Full House', 'Four of a Kind', 'Five of a Kind'] + CARD_VALUES = ['2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K', 'A'].freeze + + HandP1 = Struct.new(:cards, :bid) do + def hand_value + counts = cards.chars.group_by(&:to_s).values.map(&:length) + + if counts == [5] + 6 + elsif counts.include?(4) + 5 + elsif counts.include?(3) && counts.include?(2) + 4 + elsif counts.include?(3) + 3 + elsif counts.select { |c| c == 2 }.length == 2 + 2 + elsif counts.include?(2) + 1 + else + 0 + end + end + + def card_value + cards.chars.map { |c| CARD_VALUES.index(c).to_s.rjust(2, '0') }.join + end + + def value + "#{hand_value}.#{card_value}".to_f + end + end + + def part1(input) + hands = input.split("\n").map do |line| + args = line.split.map(&:strip) + HandP1.new(args.first, args.last.to_i) + end + + hands.sort_by(&:value).each_with_index.map do |h, index| + h.bid * (index + 1) + end.sum + end + + CARD_VALUES_2 = ['J', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'Q', 'K', 'A'].freeze + + HandP2 = Struct.new(:cards, :bid) do + def hand_value + jokers = cards.scan('J').length + counts = cards.delete('J').chars.group_by(&:to_s).values.map(&:length) + + if counts.length == 1 || jokers == 5 # 5 of a kind + 6 + elsif counts.max == 4 || counts.max + jokers == 4 || jokers == 4 # 4 of a kind + 5 + elsif (counts.include?(3) && counts.include?(2)) || # full house + jokers == 3 || + (jokers == 2 && counts.length == 2) || + (jokers == 1 && counts.length == 2) + 4 + elsif counts.max == 3 || jokers == 3 || counts.max + jokers == 3 # 3 of a kind + 3 + elsif counts.select { |c| c == 2 }.length == 2 || jokers >= 2 # 2 pair + 2 + elsif counts.include?(2) || jokers.positive? # pair + 1 + else + 0 + end + end + + def card_value + cards.chars.map do |c| + CARD_VALUES_2.index(c).to_s.rjust(2, '0') + end.join + end + + def value + "#{hand_value}.#{card_value}".to_f + end + end + + def part2(input) + hands = input.split("\n").map do |line| + args = line.split.map(&:strip) + HandP2.new(args.first, args.last.to_i) + end + + hands.sort_by(&:value).each_with_index.map do |h, index| + h.bid * (index + 1) + end.sum + end + +end diff --git a/test/07_test.rb b/test/07_test.rb new file mode 100644 index 0000000..ea6a1c3 --- /dev/null +++ b/test/07_test.rb @@ -0,0 +1,18 @@ +require 'minitest/autorun' +require 'minitest/pride' +require_relative '../app' + +class TestDay07 < Minitest::Test + def setup + @data = File.read(File.join(APP_ROOT, 'examples', '07.txt')).rstrip + @day = Day07.new + end + + def test_part1 + assert_equal @day.part1(@data), 6440 + end + + def test_part2 + assert_equal @day.part2(@data), 5905 + end +end