Skip to content

Instantly share code, notes, and snippets.

@JoshCheek
Created November 20, 2015 17:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JoshCheek/617fb3c63bdcc4f048ae to your computer and use it in GitHub Desktop.
Save JoshCheek/617fb3c63bdcc4f048ae to your computer and use it in GitHub Desktop.
Project Euler #84 (Monopoly)
# 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