day05.scm (5607B)
1 ; Copyright (c) 2023, Natacha Porté 2 ; 3 ; Permission to use, copy, modify, and distribute this software for any 4 ; purpose with or without fee is hereby granted, provided that the above 5 ; copyright notice and this permission notice appear in all copies. 6 ; 7 ; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 ; WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 ; MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 ; ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 ; WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 ; ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 ; OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 15 (import (chicken io) (chicken string) 16 comparse 17 srfi-1 18 srfi-14) 19 20 ;;;;;;;;;;;;;;;;; 21 ;; Input parsing 22 23 (define (as-number parser) 24 (bind (as-string parser) 25 (lambda (s) 26 (result (string->number s))))) 27 28 (define spaces 29 (zero-or-more (is #\space))) 30 31 (define digit 32 (in char-set:digit)) 33 34 (define digits 35 (as-number (one-or-more digit))) 36 37 (define word 38 (as-string (one-or-more (in char-set:letter)))) 39 40 (define range 41 (sequence* ((data (repeated (preceded-by spaces digits) 3)) 42 (_ (is #\newline))) 43 (result data))) 44 45 (define number-map 46 (sequence* ((_ (zero-or-more (is #\newline))) 47 (from-type word) 48 (_ (char-seq "-to-")) 49 (to-type word) 50 (_ (char-seq " map:\n")) 51 (ranges (zero-or-more range))) 52 (result (cons (list from-type to-type) ranges)))) 53 54 (define seed-list 55 (preceded-by (char-seq "seeds:") 56 (zero-or-more (preceded-by spaces digits)))) 57 58 (define all-data 59 (sequence* ((seeds seed-list) 60 (maps (one-or-more number-map))) 61 (result (cons seeds maps)))) 62 63 (define data (parse all-data (read-string))) 64 65 ;;;;;;;;;;;;;;;;; 66 ;; Second Puzzle 67 68 (define (apply-map n ranges) 69 (if (null? ranges) 70 n 71 (let ((cur-range (car ranges)) 72 (rest (cdr ranges))) 73 (let ((dest-start (car cur-range)) 74 (src-start (cadr cur-range)) 75 (size (caddr cur-range))) 76 (if (<= src-start n (+ src-start size -1)) 77 (+ dest-start (- n src-start)) 78 (apply-map n rest)))))) 79 80 (define (multi-apply-map n-list num-map) 81 (map (lambda (n) (apply-map n (cdr num-map))) n-list)) 82 83 (define (answer-1 nums maps) 84 (if (null? maps) 85 nums 86 (answer-1 (multi-apply-map nums (car maps)) (cdr maps)))) 87 88 (write-line (conc "First puzzle: " 89 (apply min (answer-1 (car data) (cdr data))))) 90 91 ;;;;;;;;;;;;;;;;; 92 ;; Second Puzzle 93 94 (define (bounds->range range-first range-last) 95 (list range-first (- range-last range-first -1))) 96 97 (define (transform-range range transform) 98 ; (write-line (conc "transform-range " range " " transform)) 99 (let ((range-first (car range)) 100 (range-length (cadr range)) 101 (dest-first (car transform)) 102 (src-first (cadr transform)) 103 (size (caddr transform))) 104 (let ((range-last (+ range-first range-length -1)) 105 (src-last (+ src-first size -1))) 106 ; (write-line (conc "range: " range-first " .. " range-last)) 107 ; (write-line (conc "src: " src-first " .. " src-last)) 108 (list (if (and (<= range-first src-last) (>= range-last src-first)) 109 (list (list 110 (+ (max range-first src-first) (- dest-first src-first)) 111 (- (min range-last src-last) (max range-first src-first) -1))) 112 '()) 113 (filter (lambda (l) (not (null? l))) 114 (list (if (< range-first src-first) 115 (bounds->range range-first 116 (min (sub1 src-first) range-last)) 117 '()) 118 (if (> range-last src-last) 119 (bounds->range (max (add1 src-last) range-first) 120 range-last) 121 '()))))))) 122 123 (define (transform-ranges todo transformed unchanged transform) 124 ; (write-line (conc "transform-ranges " todo " / " transformed " / " unchanged " / " transform)) 125 (if (null? todo) 126 (list transformed unchanged) 127 (let ((tmp (transform-range (car todo) transform))) 128 (transform-ranges (cdr todo) 129 (append (car tmp) transformed) 130 (append (cadr tmp) unchanged) 131 transform)))) 132 133 (define (map-ranges transformed unchanged transform-list) 134 ; (write-line (conc "map-ranges " transformed " / " unchanged " / " transform-list)) 135 (if (null? transform-list) 136 (append unchanged transformed) 137 (let ((tmp (transform-ranges unchanged '() '() (car transform-list)))) 138 (map-ranges (append (car tmp) transformed) 139 (cadr tmp) 140 (cdr transform-list))))) 141 142 (define (seed-ranges cur input) 143 (if (null? input) 144 cur 145 (seed-ranges (cons (list (car input) (cadr input)) cur) 146 (cddr input)))) 147 148 (define (ranges-total-size ranges) 149 (apply + (map cadr ranges))) 150 151 (define (multi-map-ranges ranges maps) 152 ; (write-line (conc "multi-map-ranges total size: " (ranges-total-size ranges))) 153 (if (null? maps) 154 ranges 155 (multi-map-ranges (map-ranges '() ranges (cdar maps)) (cdr maps)))) 156 157 (define result-2 158 (multi-map-ranges (seed-ranges '() (car data)) 159 (cdr data))) 160 161 (write-line (conc "Second puzzle: " (apply min (map car result-2))))