From cd08ef848be9318ae00d440c975e8bb0005264b7 Mon Sep 17 00:00:00 2001 From: Daniel Flanagan Date: Tue, 21 Dec 2021 13:19:41 -0600 Subject: [PATCH] Pretty naive memoization for turn outcomes to solve part 2 --- 2021/nim/day21.nim | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/2021/nim/day21.nim b/2021/nim/day21.nim index 6886fe8..be4a936 100644 --- a/2021/nim/day21.nim +++ b/2021/nim/day21.nim @@ -1,29 +1,50 @@ import ./common, std/[sequtils, algorithm, sugar, sets, strformat, strutils, tables, options, json, hashes, random] -proc p1(input: Lines): uint64 = - const DIE_FACES = 100 - const TARGET_SCORE = 1000 - const BOARD_POSITIONS = 10 +const BOARD_POSITIONS = 10 +proc p1(input: Lines): uint64 = var scores = [0, 0] var pos = [input[0].split(": ")[1].parseInt - 1, input[1].split(": ")[1].parseInt - 1] var rollNum = 1 var turn = 0 - while scores[0] < TARGET_SCORE and scores[1] < TARGET_SCORE: + while scores[0] < 1000 and scores[1] < 1000: var move = 0 for _ in 1..3: - move += rollNum mod DIE_FACES + move += rollNum mod 100 inc rollNum pos[turn] = (pos[turn] + move) mod BOARD_POSITIONS scores[turn] += pos[turn] + 1 - echo &"{move}, {pos[turn]}, {scores}" turn = (turn + 1) mod 2 - - echo rollNum, scores uint64(scores[turn mod 2] * (rollNum - 1)) +type DiracGamestate = tuple + scores: array[2, int] + positions: array[2, int] + turn: int + +var turnOutcomes = newTable[DiracGamestate, array[2, uint64]]() +proc turn(g: DiracGamestate): array[2, uint64] = + if turnOutcomes.hasKey g: return turnOutcomes[g] + if g.scores[0] >= 21: + return [1'u64, 0] + elif g.scores[1] >= 21: + return [0'u64, 1] + for r in product(@[@[1,2,3],@[1,2,3],@[1,2,3]]): + let move = r.foldl(a + b) + var ng = g + ng.positions[ng.turn] = (ng.positions[ng.turn] + move) mod BOARD_POSITIONS + ng.scores[ng.turn] += ng.positions[ng.turn] + 1 + ng.turn = (ng.turn + 1) mod 2 + let r = turn(ng) + turnOutcomes[ng] = r + result[0] += r[0] + result[1] += r[1] + proc p2(input: Lines): uint64 = - 0 + var pos = [input[0].split(": ")[1].parseInt - 1, input[1].split(": ")[1].parseInt - 1] + var g: DiracGamestate = (scores: [0, 0], positions: pos, turn: 0) + let wins = turn(g) + wins.max const input = """ Player 1 starting position: 4