## Bug #17427 ยป aoc22.rb

 1 ```require 'set' ``` ```class Deck ``` ``` def initialize(stack=[]) ``` ``` @stack = stack ``` ``` end ``` ``` def take ``` ``` stack.shift ``` ``` end ``` ``` def add(*cards) ``` ``` stack.concat(cards) ``` ``` end ``` ``` def max ``` ``` stack.max ``` ``` end ``` ``` def play_against!(other_deck, recursing: false) ``` ``` # smallest_cards = [*stack, *other_deck.stack].sort.first(2) ``` ``` # if smallest_cards.sum > (stack.size + other_deck.stack.size - 2) ``` ``` # \$counter += 1 ``` ``` # puts "counter1: #{\$counter}" if \$counter % 1000 == 0 ``` ``` # presumptive_winner = [max, other_deck.max].max == max ? self : other_deck ``` ``` # presumptive_winner.win! ``` ``` # return nil ``` ``` # end ``` ``` states = Set.new ``` ``` decks = [self, other_deck] ``` ``` until decks.any?(&:empty?) || decks.any?(&:winner?) ``` ``` states << [stack, other_deck.stack] ``` ``` if states.map(&:hash).uniq.size < states.size ``` ``` states.each { |state| ``` ``` p state ``` ``` } ``` ``` raise states.inspect ``` ``` end ``` ``` decks.inject(:compete!) ``` ``` if states.include?([stack, other_deck.stack]) ``` ``` win! ``` ``` return nil ``` ``` end ``` ``` end ``` ``` decks.find { |deck| !deck.empty? }.win! ``` ``` nil ``` ``` end ``` ``` def compete!(other_deck) ``` ``` mine = take ``` ``` opposing = other_deck.take ``` ``` if mine > opposing ``` ``` add(mine, opposing) ``` ``` else ``` ``` other_deck.add(opposing, mine) ``` ``` end ``` ``` end ``` ``` def win! ``` ``` @winner = true ``` ``` end ``` ``` def winner? ``` ``` !!winner ``` ``` end ``` ``` def score ``` ``` stack.reverse.map.with_index.sum(0) { |card, index| ``` ``` card * (index + 1) ``` ``` } ``` ``` end ``` ``` def empty? ``` ``` stack.empty? ``` ``` end ``` ``` protected ``` ``` attr_reader :stack, :winner ``` ```end ``` ```class RecursiveDeck < Deck ``` ``` def compete!(other_deck) ``` ``` if recurse? && other_deck.recurse? ``` ``` mine = take ``` ``` opposing = other_deck.take ``` ``` my_subdeck = recursive_duplicate(mine) ``` ``` other_subdeck = other_deck.recursive_duplicate(opposing) ``` ``` my_subdeck.play_against!(other_subdeck, recursing: true) ``` ``` if my_subdeck.winner? ``` ``` add(mine, opposing) ``` ``` else ``` ``` other_deck.add(opposing, mine) ``` ``` end ``` ``` else ``` ``` super ``` ``` end ``` ``` end ``` ``` protected ``` ``` def recurse? ``` ``` stack.first < stack.size ``` ``` end ``` ``` def recursive_duplicate(num) ``` ``` self.class.new(stack.slice(0, num)) ``` ``` end ``` ```end ``` ```input_decks = <<~INPUTS ``` ```Player 1: ``` ```12 ``` ```48 ``` ```26 ``` ```22 ``` ```44 ``` ```16 ``` ```31 ``` ```19 ``` ```30 ``` ```10 ``` ```40 ``` ```47 ``` ```21 ``` ```27 ``` ```2 ``` ```46 ``` ```9 ``` ```15 ``` ```23 ``` ```6 ``` ```50 ``` ```28 ``` ```5 ``` ```42 ``` ```34 ``` ```Player 2: ``` ```14 ``` ```45 ``` ```4 ``` ```24 ``` ```1 ``` ```7 ``` ```36 ``` ```29 ``` ```38 ``` ```33 ``` ```3 ``` ```13 ``` ```11 ``` ```17 ``` ```39 ``` ```43 ``` ```8 ``` ```41 ``` ```32 ``` ```37 ``` ```35 ``` ```49 ``` ```20 ``` ```18 ``` ```25 ``` ```INPUTS ``` ```decks = [] ``` ```input_decks.each_line do |line| ``` ``` if line =~ /Player/ ``` ``` decks << RecursiveDeck.new ``` ``` elsif line =~ /\d+/ ``` ``` decks.last.add(line.to_i) ``` ``` end ``` ```end ``` ```decks.inject(:play_against!) ``` ```p decks ``` ```puts decks.map(&:score) ```