Created
November 20, 2015 17:24
-
-
Save JoshCheek/617fb3c63bdcc4f048ae to your computer and use it in GitHub Desktop.
Project Euler #84 (Monopoly)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# https://projecteuler.net/problem=84 | |
# (solved at the airport) | |
do_print = false | |
num_trials = 1000 | |
first, *mids, last = | |
"GO A1 CC1 A2 T1 R1 B1 CH1 B2 B3 JAIL | |
H2 C1 | |
T2 U1 | |
H1 C2 | |
CH3 C3 | |
R4 R2 | |
G3 D1 | |
CC3 CC2 | |
G2 D2 | |
G1 D3 | |
G2J F3 U2 F2 F1 R3 E3 E2 CH2 E1 FP" | |
.downcase.lines.map(&:split) | |
index_to_name = [first, mids.transpose.last, last.reverse, mids.transpose.first.reverse].flatten.map(&:intern) | |
name_to_index = index_to_name.map.with_index { |name, i| [name, i] }.to_h | |
landings = name_to_index.map { |n, *| [n, 0] }.to_h | |
define_method :p do |*args| | |
return unless do_print | |
super(*args) | |
end | |
define_method :print_board do |dice:, index:| | |
return unless do_print | |
to_display = name_to_index.to_a.map(&:first) | |
top = to_display.shift 11 | |
right = to_display.shift 9 | |
bot = to_display.shift(11).reverse | |
left = to_display.shift 9 | |
rows = left.reverse.zip(right).flatten | |
format = 11.times.map { '%4s' }.join(' ') << | |
("\n%4s " + " "*5*9 + "%4s")*9 << "\n" << | |
11.times.map { '%4s' }.join(' ') << "\n" | |
board = sprintf format, *top, *rows, *bot | |
p dice: dice, square: index, name: index_to_name[index] | |
puts board.sub(/.?\b#{index_to_name[index]}\b.?/) { |name| "\e[42;30m#{name}\e[0m" } | |
end | |
num_trials.times do |i| | |
$stdout.puts({index: i}.inspect) if i % 10 == 0 | |
cc_stack = [ *14.times.map { :ignore }, | |
:go_to_go, | |
:go_to_jail, | |
].shuffle | |
ch_stack = [ :go, | |
:jail, | |
:c1, | |
:e3, | |
:h2, | |
:r1, | |
:next_rail, | |
:next_rail, | |
:next_util, | |
:back_3, | |
:ignore, | |
:ignore, | |
:ignore, | |
:ignore, | |
:ignore, | |
:ignore, | |
].shuffle | |
current = name_to_index.fetch :go | |
num_doubles = 0 | |
1000.times do | |
die1 = rand(4).next | |
die2 = rand(4).next | |
# print_board dice: [], index: current | |
# die1, die2, * = [*gets.split.map(&:to_i), 0, 0] | |
spaces = die1 + die2 | |
current += spaces | |
current %= index_to_name.length | |
if die1 == die2 | |
num_doubles += 1 | |
else | |
num_doubles = 0 | |
end | |
if num_doubles == 3 | |
current = name_to_index.fetch :jail | |
num_doubles = 0 | |
end | |
case current | |
when name_to_index[:g2j] | |
p g2j: current | |
current = name_to_index.fetch :jail | |
when name_to_index[:ch1], name_to_index[:ch2], name_to_index[:ch3] | |
card = ch_stack.first | |
ch_stack.rotate! | |
p chance: card | |
case card | |
when :go then current = name_to_index.fetch :go | |
when :jail then current = name_to_index.fetch :jail | |
when :c1 then current = name_to_index.fetch :c1 | |
when :e3 then current = name_to_index.fetch :e3 | |
when :h2 then current = name_to_index.fetch :h2 | |
when :r1 then current = name_to_index.fetch :r1 | |
when :next_rail then current = (current+1)%index_to_name.length until [:r1, :r2, :r3, :r4].include? index_to_name.fetch(current) | |
when :next_util then current = (current+1)%index_to_name.length until [:u1, :u2].include? index_to_name.fetch(current) | |
when :back_3 then current -= 3 | |
current += index_to_name.length if current < 0 | |
when :ignore then :noop | |
else raise "WHAT IS #{card.inspect}" | |
end | |
when name_to_index[:cc1], name_to_index[:cc2], name_to_index[:cc3] | |
card = cc_stack.first | |
cc_stack.rotate! | |
p community_chest: card | |
case card | |
when :ignore then :noop | |
when :go_to_go then current = name_to_index.fetch :go | |
when :go_to_jail then current = name_to_index.fetch :jail | |
else raise "WHAT IS #{card.inspect}" | |
end | |
end | |
# print_board dice: [die1, die2], index: current | |
landings[index_to_name.fetch(current)] += 1 | |
end | |
end | |
total_landings = landings.map(&:last).inject(0, :+) | |
modal_string = landings.map { |name, landed_here| [name, 100.0*landed_here/total_landings] } | |
.sort_by(&:last) | |
.each { |name, percentage| puts "#{name}: #{percentage}" } | |
.last(3) | |
.reverse | |
.map { |name, percentage| '%02d' % name_to_index[name] } | |
.join("") | |
$stdout.puts({modal_string: modal_string}.inspect) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment