Skip to content

Instantly share code, notes, and snippets.

@Karamell
Last active December 22, 2020 06:30
Show Gist options
  • Select an option

  • Save Karamell/209e76b968326b0e4e3ff01195efa1e9 to your computer and use it in GitHub Desktop.

Select an option

Save Karamell/209e76b968326b0e4e3ff01195efa1e9 to your computer and use it in GitHub Desktop.
Advent of Code 2020 day 22 in F#
#time "on"
let txt = System.IO.File.ReadAllText( __SOURCE_DIRECTORY__ + "/input.txt").Trim()
let player1, player2 =
let m = txt.Split("\n\n") |> Array.map(fun s -> s.Split("\n") |> Array.tail |> Array.map int |> Array.toList)
m.[0], m.[1]
let pressPlay1 () =
let rec play p1 p2 =
match p1, p2 with
| [], p -> p
| p, [] -> p
| h1::t1, h2::t2 ->
let t1', t2' =
if h1 > h2 then
t1 @ [h1; h2], t2
else
t1, t2 @ [h2;h1]
play t1' t2'
play player1 player2
let pressPlay2 () =
let isnewmatch h1 t1 h2 t2 =
h1 <= List.length t1 && h2 <= List.length t2
let rec play rounds g p1 p2 =
let rounds' = rounds |> Set.add (p1, p2)
let r = rounds' |> Set.count
//printfn "-- Round %d (Game %d) --" r g
//printfn "Player1's deck: %A" p1
//printfn "Player2's deck: %A" p2
match p1, p2 with
| p, [] ->
//printfn "Player1 wins round %d of game %d" r g
p, []
| [], p ->
//printfn "Player2 wins round %d of game %d" r g
[], p
| _ when rounds |> Set.contains (p1, p2) ->
//printfn "SAME ROUND DETECTED: The winner of game %d is player 1!" g
[0xFFFFFFFF], []
| h1::t1, h2::t2 when isnewmatch h1 t1 h2 t2 ->
//printfn "Player1 plays: %A" h1
//printfn "Player2 plays: %A" h2
//printfn "Playing a sub-game to determine the winner..."
let t1' = t1 |> List.take h1
let t2' = t2 |> List.take h2
let g' = g + 1
let t1'', t2'' =
match play Set.empty g' t1' t2' with
| p, [] ->
//printfn "The winner of game %d is player 1!" g
t1 @ [h1; h2], t2
| [], p ->
//printfn "The winner of game %d is player 2!" g
t1, t2 @ [h2;h1]
play rounds' g t1'' t2''
| h1::t1, h2::t2 ->
//printfn "Player1 plays: %A" h1
//printfn "Player2 plays: %A" h2
let t1', t2' =
if h1 > h2 then
//printfn "Player 1 wins round %d of game %d!" r g
t1 @ [h1; h2], t2
else
//printfn "Player 2 wins round %d of game %d!" r g
t1, t2 @ [h2;h1]
play rounds' g t1' t2'
play Set.empty 1 player1 player2 |> fun (a, b) -> max a b
let countHand hand = hand |> List.rev |> List.mapi(fun i c -> (i + 1) * c) |> List.sum
pressPlay1() |> countHand |> printfn "part 1: %d"
pressPlay2() |> countHand |> printfn "part 2: %d"
// Real: 00:00:11.261, CPU: 00:00:11.513, GC gen0: 758, gen1: 86, gen2: 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment