-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day03.fs
80 lines (60 loc) · 2.22 KB
/
Day03.fs
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
namespace AdventOfCode.Solution
open AdventOfCode
module Day03 =
let rows = Input.Day03.input.Length
let columns = Input.Day03.input.[0].Length
let parseList =
Input.Day03.input
|> Array.map (fun str ->
str |> Seq.map (fun c -> c.ToString() |> int)
|> Array.ofSeq
)
type Strategy = (int [] [] * int [] []) -> int [] []
let oxygen (zeros: int [] [], ones: int [] []) =
match ones.Length >= zeros.Length with
| true -> ones
| false -> zeros
let carbon (zeros: int [] [], ones: int [] []) =
match ones.Length >= zeros.Length with
| true -> zeros
| false -> ones
let getOnes (column: int) (candidates: int [] []) =
candidates |> Array.filter (fun c -> c[column] = 1)
let getZeros (column: int) (candidates: int [] []) =
candidates |> Array.filter (fun c -> c[column] = 0)
let separateIntoOneAndZeros (column: int) (candidates: int [] []) =
(candidates |> getZeros column, candidates |> getOnes column)
let binaryStringToInt b = System.Convert.ToInt32(b, 2)
// Step one column at the time and filter out ones or zeros
let rec selectCandidate (selector: Strategy) (column: int) (candidates: int [] []) =
match candidates with
| [||] -> failwith "should not happen"
| [| last |] -> last |> Array.fold (fun binary number -> binary + string number) "" |> binaryStringToInt
| candidates ->
candidates
|> separateIntoOneAndZeros column
|> selector
|> selectCandidate selector (column + 1)
let calcOxygen =
parseList
|> selectCandidate oxygen 0
let calcCarbon =
parseList
|> selectCandidate carbon 0
// Part1
let sumList =
parseList
|> Array.transpose
|> Array.map Array.sum
let gamma_rate =
sumList
|> Array.map (fun number -> if (rows / 2) < number then 1 else 0)
|> Array.fold (fun state item -> state + (string item)) ""
|> fun str -> System.Convert.ToInt32(str, 2)
let epsilon_rate =
sumList
|> Array.map (fun number -> if (rows / 2) > number then 1 else 0)
|> Array.fold (fun state item -> state + (string item)) ""
|> fun str -> System.Convert.ToInt32(str, 2)
let part1 = gamma_rate * epsilon_rate
let part2 = calcCarbon * calcOxygen