aoc-2023

My solutions in CHICKEN scheme to Advent of Code 2023
git clone https://git.instinctive.eu/aoc-2023.git
Log | Files | Refs | README | LICENSE

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))))