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

day13.scm (5732B)


      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 symbol
     24   (in #\. #\#))
     25 
     26 (define line
     27   (sequence* ((data (one-or-more symbol))
     28               (_ (is #\newline)))
     29     (result data)))
     30 
     31 (define area
     32   (sequence* ((lines (one-or-more line))
     33               (_ (zero-or-more (is #\newline))))
     34     (result lines)))
     35 
     36 (define all-data
     37   (zero-or-more area))
     38 
     39 (define data (parse all-data (read-string)))
     40 
     41 (define (draw-area prefix m)
     42   (unless (null? m)
     43     (write-line (conc prefix (list->string (car m))))
     44     (draw-area prefix (cdr m))))
     45 
     46 ;(let ((count 0))
     47 ;  (for-each (lambda (area) (set! count (add1 count)) (draw-area (conc count ": ") area)) data))
     48 
     49 ;(write-line "Input:")
     50 ;(draw-area "  " data)
     51 
     52 ;;;;;;;;;;;;;;;;;
     53 ;; First Puzzle
     54 
     55 (define (is-reflect-or-null? first second)
     56   (or (null? first)
     57       (null? second)
     58       (and (equal? (car first) (car second))
     59            (is-reflect-or-null? (cdr first) (cdr second)))))
     60 
     61 (define (is-reflect? first second)
     62   (and (not (null? first))
     63        (not (null? second))
     64        (is-reflect-or-null? first second)))
     65 
     66 (define (reflect-indices l)
     67 ;(let ((result
     68   (let loop ((reflected (list (car l)))
     69              (todo (cdr l))
     70              (acc '()))
     71     (if (null? todo)
     72         (reverse acc)
     73         (loop (cons (car todo) reflected)
     74               (cdr todo)
     75               (if (is-reflect-or-null? reflected todo)
     76                   (cons (length reflected) acc)
     77                   acc)))))
     78 ;)(write-line (conc "reflect-indices " l " -> " result)) result))
     79 
     80 (define (merge-cols left right)
     81 ;(let ((result
     82   (let loop ((todo-1 left)
     83              (todo-2 right)
     84              (acc '()))
     85     (cond ((or (null? todo-1) (null? todo-2)) (reverse acc))
     86           ((< (car todo-1) (car todo-2)) (loop (cdr todo-1) todo-2 acc))
     87           ((> (car todo-1) (car todo-2)) (loop todo-1 (cdr todo-2) acc))
     88           (else (loop (cdr todo-1) (cdr todo-2) (cons (car todo-1) acc))))))
     89 ;)(write-line (conc "result " left " " right " -> " result)) result))
     90 
     91 (define (reflect-cols area)
     92   (let loop ((todo (cdr area))
     93              (acc (reflect-indices (car area))))
     94     (if (null? todo)
     95         (begin (assert (<= (length acc) 1)) acc)
     96         (loop (cdr todo)
     97               (merge-cols acc (reflect-indices (car todo)))))))
     98 
     99 (define (term-1 area)
    100   (let ((cols (reflect-cols area))
    101         (rows (reflect-indices area)))
    102 ;   (write-line (conc "cols: " cols ", rows: " rows))
    103     (unless (= (+ (length cols) (length rows)) 1)
    104        (write-line (conc "== cols: " cols ", rows: " rows))
    105        (draw-area " " area))
    106     (assert (= 1 (+ (length cols) (length rows))))
    107     (+ (apply + cols) (* 100 (apply + rows)))))
    108 
    109 ;(let ((count 0))
    110 ;  (for-each
    111 ;    (lambda (area) (set! count (add1 count))
    112 ;                   (write-line (conc count ": " (term-1 area))))
    113 ;    data))
    114 
    115 (write-line (conc "First puzzle:  "
    116   (apply + (map (lambda (area) (term-1 area)) data))))
    117 
    118 ;;;;;;;;;;;;;;;;;
    119 ;; Second Puzzle
    120 
    121 (define (reflect-cols* area)
    122   (let loop ((todo (cdr area))
    123              (acc (reflect-indices (car area))))
    124     (if (null? todo)
    125         acc
    126         (loop (cdr todo)
    127               (merge-cols acc (reflect-indices (car todo)))))))
    128 
    129 (define (term-1* area prev-term)
    130 ;  (write-line (conc "term-1* " area))
    131 ;(let ((result
    132   (let ((cols (filter (lambda (i) (not (= i prev-term))) (reflect-cols* area)))
    133         (rows (filter (lambda (i) (not (= prev-term (* 100 i)))) (reflect-indices area))))
    134 ;(write-line (conc "  cols: " cols ", rows: " rows))
    135     (if (= (+ (length cols) (length rows)) 1)
    136         (+ (apply + cols) (* 100 (apply + rows)))
    137         0)))
    138 ;)(write-line (conc "  -> " result)) result))
    139 
    140 (define (term-2 area)
    141   (let ((prev-term (term-1 area)))
    142     (let loop ((prev-lines '())
    143                (prev-cols '())
    144                (next-cols (car area))
    145                (next-lines (cdr area)))
    146       (if (null? next-cols)
    147           (loop (append prev-lines (list (reverse prev-cols)))
    148                 '()
    149                 (car next-lines)
    150                 (cdr next-lines))
    151           (let ((try (term-1* (append prev-lines
    152                                       (list (append (reverse prev-cols)
    153                                                     (if (eqv? (car next-cols) #\#)
    154                                                         '(#\.) '(#\#))
    155                                                     (cdr next-cols)))
    156                                       next-lines)
    157                                prev-term)))
    158             (if (> try 0)
    159                 try
    160                 (loop prev-lines
    161                       (cons (car next-cols) prev-cols)
    162                       (cdr next-cols)
    163                       next-lines)))))))
    164 
    165 ;(let ((count 0))
    166 ;  (for-each
    167 ;    (lambda (area) (set! count (add1 count))
    168 ;                   (write-line (conc count ": " (term-2 area))))
    169 ;    data))
    170 
    171 (write-line (conc "Second puzzle: "
    172   (apply + (map (lambda (area) (term-2 area)) data))))