aboutsummaryrefslogtreecommitdiff
path: root/05/2.scm
blob: 9a59bb6f5296baff9a2f387582c4f7497292be95 (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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
(import (chicken io))
(import (chicken string))
(import srfi-69)
(import srfi-1)

(define (read-input)
  (with-input-from-file "input"
    (lambda ()
      (define part1
        (let loop ((ret '()))
          (let ((line (read-line)))
            (if (= 0 (string-length line))
                (reverse ret)
                (loop (cons line ret))))))
      (define part2
        (let loop ((ret '()))
          (let ((line (read-line)))
            (if (eof-object? line)
                (reverse ret)
                (loop (cons line ret))))))
      (values part1 part2))))

(define-values (part1 part2) (read-input))

(set! part1 (map (lambda (x) (string-split x "|")) part1))
(set! part1 (map (lambda (x) (map string->number x)) part1))

(define rules (make-hash-table))

(map (lambda (x)
       (hash-table-set! rules x #t) '())
     part1)

(define updates (map (lambda (x) (string-split x ",")) part2))
(set! updates (map (lambda (x) (map string->number x)) updates))

(define (check-rules x lst)
  (if (null? lst)
      #t
      (and (not (hash-table-ref/default rules (list (car lst) x) #f))
           (check-rules x (cdr lst)))))

(define (find-failed x lst)
  (if (null? lst)
      #f
      (if (hash-table-ref/default rules (list (car lst) x) #f)
          lst
          (find-failed x (cdr lst)))))

(define (check-update update)
  (if (null? update)
      #t
      (and (check-rules (car update) (cdr update))
           (check-update (cdr update)))))

(define (correct-update! update)
  (if (null? update)
      '()
      (let ()
        (define failed (find-failed (car update) (cdr update)))
        (if failed
            (let ()
              (define tmp (car failed))
              (set-car! failed (car update))
              (set-car! update tmp))
            (correct-update! (cdr update))))))

(define (median lst)
  (list-ref lst (quotient (length lst) 2)))

(define incorrect (filter (lambda (x) (not (check-update x))) updates))

(define (do-correction! lst)
  (if (check-update lst)
      '()
      (let ()
        (correct-update! lst)
        (do-correction! lst))))

(map do-correction! incorrect)

(display (apply + (map median incorrect)))