summary refs log tree commit diff stats
path: root/solutions/day11.fs
blob: 2b93042984d93491790806a5ce6308a37983dcc3 (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
107
108
namespace Solutions

module 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