aboutsummaryrefslogtreecommitdiff
path: root/2022/day-21/day-21.rkt
blob: 612c7f1548ea3d745f796b740283c75e973f1c07 (plain)
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
#lang racket

(require advent-of-code
         threading
         (only-in relation ->number ->symbol))

(struct monkey (name op) #:transparent)
(struct op (f first second) #:transparent)

(define (parse-monkey str)
  (match (string-split str " ")
    [(list (app (curryr string-trim ":") name) name1 (app ->symbol f) name2)
     (monkey name (op f name1 name2))]
    [(list (app (curryr string-trim ":") name) (app ->number int))
     (monkey name (op 'constant int #f))]))

(define raw-monkeys (port->lines (open-aoc-input (find-session) 2022 21 #:cache #true)))

(define monkey-table
  (for/hash ([m raw-monkeys] #:do [(match-define (monkey name op) (parse-monkey m))])
    (values name op)))

;; part 1
(define (evaluate-monkey m-name)
  (match-define (op f name1 name2) (hash-ref monkey-table m-name))
  (match f
    ['constant name1]
    ['+ (+ (evaluate-monkey name1) (evaluate-monkey name2))]
    ['- (- (evaluate-monkey name1) (evaluate-monkey name2))]
    ['* (* (evaluate-monkey name1) (evaluate-monkey name2))]
    ['/ (/ (evaluate-monkey name1) (evaluate-monkey name2))]))

(evaluate-monkey "root")

;; part 2
(match-define (op _ branch-1 branch-2) (hash-ref monkey-table "root"))

(define (evaluate-monkey* m-name guess)
  (match-define (op f name1 name2)
    (if (equal? m-name "humn") (op 'constant guess #f) (hash-ref monkey-table m-name)))
  (match f
    ['constant name1]
    ['+ (+ (evaluate-monkey* name1 guess) (evaluate-monkey* name2 guess))]
    ['- (- (evaluate-monkey* name1 guess) (evaluate-monkey* name2 guess))]
    ['* (* (evaluate-monkey* name1 guess) (evaluate-monkey* name2 guess))]
    ['/ (/ (evaluate-monkey* name1 guess) (evaluate-monkey* name2 guess))]))

;; part 2
;; I plugged in numbers for guess to find a suitable starting range and settled on the first one
;; that I found that got me within a million
(for/first ([guess (in-naturals 3059361690000)]
            #:do [(define result-1 (evaluate-monkey* branch-1 guess))
                  (define result-2 (evaluate-monkey* branch-2 guess))
                  (println (~a "Guess: "
                               guess
                               " result 1: "
                               (~r (exact->inexact result-1) #:notation 'exponential)
                               " result 2: "
                               (~r (exact->inexact result-2) #:notation 'exponential)
                               " diff: "
                               (~r (exact->inexact (- result-1 result-2)) #:notation 'exponential)))]
            #:when (= result-1 result-2))
  guess)