This repository was archived by the owner on Dec 2, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDay4.fsx
More file actions
93 lines (81 loc) · 2.88 KB
/
Day4.fsx
File metadata and controls
93 lines (81 loc) · 2.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
open System
let parse (s : string) =
s.Split("\r\n\r\n")
|> Array.map (fun s ->
s.Split([|'\n'; '\r'|], StringSplitOptions.RemoveEmptyEntries)
|> Array.map (fun s ->
s.Split([|' '; ','|], StringSplitOptions.RemoveEmptyEntries)
|> Array.map Int32.Parse
)
)
let input = System.IO.File.ReadAllText "Day4.txt" |> parse
let drawn_numbers = Array.exactlyOne input.[0] |> Array.toList
type BoardSquare = {
Value : int
mutable Marked : bool
}
type Board = {
Squares : BoardSquare[,]
mutable Score : int option
}
let getInitialBoards =
fun () ->
input.[1..]
|> Array.map (fun arr ->
arr
|> array2D
|> Array2D.map (fun x ->
{Value = x; Marked = false})
|> fun x -> {Squares = x; Score = None}
) |> Array.toList
let playTurn (drawn_number : int) (boards: Board list)=
let isWinningTurn (board : Board) (i : int) (j : int) =
let isWinningLine (line : BoardSquare[]) =
Array.forall (fun square -> square.Marked) line
isWinningLine board.Squares.[i, *] || isWinningLine board.Squares.[*, j]
let score (board : Board) (drawn_number : int) =
let mutable sum = 0
board.Squares
|> Array2D.iter (fun v ->
if not v.Marked then
sum <- sum + v.Value)
sum * drawn_number
for board in boards do
board.Squares
|> Array2D.iteri (fun i j v ->
if v.Value = drawn_number then
v.Marked <- true
if isWinningTurn board i j && board.Score = None then board.Score <- Some (score board drawn_number))
boards
let problem1 =
let boards = getInitialBoards()
let rec loop (numbers : int list) (boards : Board list)=
match numbers with
| drawn_number :: rest ->
boards
|> playTurn drawn_number
|> List.choose (fun board -> board.Score)
|> List.tryExactlyOne
|> fun x ->
match x with
| Some result -> result
| None -> loop rest boards
| [] -> failwith "Problem1 ran out of numbers"
loop drawn_numbers boards
let problem2 =
let initial_boards = getInitialBoards()
let rec loop (numbers : int list) (boards : Board list) =
match numbers with
| drawn_number :: rest ->
boards
|> List.filter (fun board -> board.Score = None)
|> playTurn drawn_number
|> fun x ->
match x with
| [finalBoard] ->
match finalBoard.Score with
| Some score -> score
| None -> loop rest x
| _ -> loop rest x
| [] -> failwith "Problem2 ran out of numbers"
loop drawn_numbers initial_boards