2018-12-09 - Marble Mania
(original .ipynb)
class Marble(object):
def __init__(self, value):
self.value = value
self.previous_marble = None
self.next_marble = None
class MarbleGame(object):
def __init__(self, players):
self.players = [0] * players
self.current_value = 0
self.current_player = 0
# initialize the zero marble
zero_marble = Marble(self.current_value)
zero_marble.next_marble = zero_marble
zero_marble.previous_marble = zero_marble
self.head_marble = zero_marble
self.current_marble = self.head_marble
def advance_turn(self):
self.current_player = (self.current_player + 1) % len(self.players)
self.current_value += 1
def add_marble(self):
clockwise_one_marble = self.current_marble.next_marble
clockwise_two_marble = clockwise_one_marble.next_marble
new_marble = Marble(self.current_value + 1)
if new_marble.value % 23 == 0:
self.add_to_score(new_marble.value)
self.advance_turn()
return
# connect clockwise_one_marble and new marble
clockwise_one_marble.next_marble = new_marble
new_marble.previous_marble = clockwise_one_marble
# connect new_marble and clockwise_two_marble
new_marble.next_marble = clockwise_two_marble
clockwise_two_marble.previous_marble = new_marble
self.current_marble = new_marble
self.advance_turn()
def add_to_score(self, marble_value):
# first add new new marble's value to the new player's score
self.players[self.current_player] += marble_value
# next find the 7th counter-clockwise marble
marble = self.current_marble
for i in range(7):
marble = marble.previous_marble
# then add its value to the player's score
self.players[self.current_player] += marble.value
# and connect them up
previous_marble = marble.previous_marble
next_marble = marble.next_marble
previous_marble.next_marble = next_marble
next_marble.previous_marble = previous_marble
# can we delete the marble? it shouldn't have any references so should be GC'd, but it
# should be safe to do this anyway
del marble
self.current_marble = next_marble
def dump_marbles(self):
marbles = [ 0 ]
marble = self.head_marble.next_marble
while marble.value != 0:
marbles.append(marble.value)
marble = marble.next_marble
print(marbles)
print(this.current_marble.value)
def run_game(players, last_marble):
game = MarbleGame(players)
while game.current_value < last_marble:
game.add_marble()
return max(game.players)
# test input
assert 32 == run_game(9, 25)
assert 8317 == run_game(10, 1618)
assert 146373 == run_game(13, 7999)
assert 2764 == run_game(17, 1104)
assert 54718 == run_game(21, 6111)
assert 37305 == run_game(30, 5807)
# Part 1
print("part one:", run_game(403, 71920))
# Part 2
print("part two:", run_game(403, 71920 * 100))
part one: 439089
part two: 3668541094