Last active
December 22, 2020 06:30
-
-
Save Karamell/209e76b968326b0e4e3ff01195efa1e9 to your computer and use it in GitHub Desktop.
Advent of Code 2020 day 22 in F#
This file contains hidden or 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
| #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