diff --git a/2021/ruby/day_21.rb b/2021/ruby/day_21.rb new file mode 100644 index 0000000..497b33e --- /dev/null +++ b/2021/ruby/day_21.rb @@ -0,0 +1,76 @@ +# Player = Struct.new(:space, :score) +# one = Player.new(7, 0) +# two = Player.new(3, 0) + +# class Die +# def initialize +# @value = 0 +# @rolls = 0 +# end + +# attr_reader :rolls + +# def roll +# value = @value + +# @value += 1 +# @value %= 100 + +# @rolls += 1 + +# value +# end +# end +# die = Die.new + +# loop do +# one.space += 3.times.sum { die.roll + 1 } +# one.space %= 10 +# one.score += one.space + 1 +# break if one.score >= 1000 + +# two.space += 3.times.sum { die.roll + 1 } +# two.space %= 10 +# two.score += two.space + 1 +# break if two.score >= 1000 +# end + +# p [one, two].map(&:score).min * die.rolls + +ROLLS = (1..3).flat_map {|a| (1..3).flat_map {|b| (1..3).map {|c| + [a, b, c].sum +}}}.tally +Player = Struct.new(:score, :space, keyword_init: true) +wins = Hash.new {|h,k| + one, two = k + + multiverse = ROLLS.map {|delta,n| + space = (one.space + delta) % 10 + [Player.new(score: one.score + space + 1, space: space), n] + } + one_wins, one_ongoing = multiverse.partition {|player,_| player.score >= 21 } + one_wins = one_wins.sum(&:last) + + multiverse = ROLLS.map {|delta,n| + space = (two.space + delta) % 10 + [Player.new(score: two.score + space + 1, space: space), n] + } + + wins = one_ongoing.flat_map {|one, n_one| multiverse.map {|two, n_two| + n = n_one * n_two + if two.score >= 21 + { one: 0, two: n } + else + h[[one, two]].map { [_1, _2 * n] }.to_h + end + }} + wins = wins.inject({one: 0, two: 0}) {|acc,wins| acc.merge(wins) { _2 + _3 }} + + h[k] = { + one: one_wins + wins.fetch(:one), + two: wins.fetch(:two), + } +} + +# p wins[[Player.new(score: 0, space: 3), Player.new(score: 0, space: 7)]] +p wins[[Player.new(score: 0, space: 7), Player.new(score: 0, space: 3)]].values.max