summary refs log tree commit diff stats
path: root/solutions/day11.fs
blob: d9a9d178726a3669b726d402909861eee116734e (plain) (blame)
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
94
95
96
97
98
99
100
101
102
103
104
105
106
module Solutions.Day11
type Monkey = {
    Items: int64 list
    Operation: int64 -> int64
    Test: int64
    TrueMonkey: int
    FalseMonkey: int
    Inspections: int64
}

let monkeys = 
    [ { Items = [89; 95; 92; 64; 87; 68]
        Operation = (*) 11L
        Test = 2
        TrueMonkey = 7
        FalseMonkey = 4
        Inspections = 0 }
      { Items = [87; 67]
        Operation = (+) 1L;
        Test = 13;
        TrueMonkey = 3
        FalseMonkey = 6
        Inspections = 0 }
      { Items = [95; 79; 92; 82; 60]
        Operation = (+) 6L
        Test = 3
        TrueMonkey = 1
        FalseMonkey = 6
        Inspections = 0 }
      { Items = [67; 97; 56]
        Operation = fun x -> x * x
        Test = 17
        TrueMonkey = 7
        FalseMonkey = 0
        Inspections = 0 }
      { Items = [80; 68; 87; 94; 61; 59; 50; 68]
        Operation = (*) 7L
        Test = 19
        TrueMonkey = 5
        FalseMonkey = 2
        Inspections = 0 }
      { Items = [73; 51; 76; 59]
        Operation = (+) 8L
        Test = 7
        TrueMonkey = 2
        FalseMonkey = 1
        Inspections = 0 }
      { Items = [92]
        Operation = (+) 5L
        Test = 11
        TrueMonkey = 3
        FalseMonkey = 0
        Inspections = 0 }
      { Items = [99; 76; 78; 76; 79; 90; 89]
        Operation = (+) 7L
        Test = 5
        TrueMonkey = 4
        FalseMonkey = 5
        Inspections = 0 } ]

let throw item target monkeys =
    let monkey = List.item target monkeys
    
    List.updateAt target {monkey with Items = (List.append monkey.Items [item])} monkeys

let doItem operation monkey monkeys item =
    let worryLevel = monkey.Operation item
    let boredLevel = operation worryLevel
    let target = if boredLevel % monkey.Test = 0L then monkey.TrueMonkey else monkey.FalseMonkey
    throw boredLevel target monkeys

let playTurn operation monkeys id =
    let monkey = List.item id monkeys

    let cleared = monkeys 
                  |> List.updateAt 
                            id 
                            {monkey with Items = []
                                         Inspections = monkey.Inspections + (int64 monkey.Items.Length)}
    
    monkey.Items |> List.fold (doItem operation monkey) cleared

let playRound operation monkeys =
    let players = [ 0 .. (List.length monkeys - 1)]
    List.fold (playTurn operation) monkeys players

let rec playRounds operation nb monkeys =
    if nb = 0 then monkeys
    else
        let next = playRound operation monkeys
        playRounds operation (nb - 1) next

let solve operation count =
    monkeys
    |> playRounds operation count
    |> List.map (fun m -> m.Inspections)
    |> List.sortDescending
    |> List.take 2
    |> List.reduce (*)

let part1 () = 
    solve (fun x -> x / 3L) 20

let part2 () = 
    let safeMod = monkeys |> Seq.map (fun m -> m.Test) |> Seq.reduce (*)
    solve (fun x -> x % safeMod) 10_000