advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

day05.scm (6660B)

    1 (use-modules (ice-9 popen))
    2 (use-modules (ice-9 rdelim))
    3 (use-modules (ice-9 format))
    4 (use-modules (ice-9 receive))
    5 (use-modules (srfi srfi-1))
    6 
    7 (define (parse-numbers numbers)
    8   (filter (lambda (x) x) (map string->number (string-split numbers #\ ))))
    9 
   10 (define (parse-map file)
   11   (let ((parsed-map '()))
   12     (while #t
   13            (let ((line (car (%read-line file))))
   14              (cond ((or (eof-object? line) (string-null? line)) (break))
   15                    (#t (set! parsed-map (cons (parse-numbers line) parsed-map))))))
   16     (reverse parsed-map)))
   17 
   18 (define (parse-input filename)
   19   (let ((file (open-input-file filename))
   20         (seeds '())
   21         (seed-to-soil-map '())
   22         (soil-to-fertilizer-map '())
   23         (fertilizer-to-water-map '())
   24         (water-to-light-map '())
   25         (light-to-temperature-map '())
   26         (temperature-to-humidity-map '())
   27         (humidity-to-location-map '()))
   28     (let ((line (car (%read-line file))))
   29       (set! seeds (parse-numbers (car (cdr (string-split line #\:))))))
   30     (%read-line file)
   31     (while #t
   32            (let ((line (car (%read-line file))))
   33              (cond ((eof-object? line) (break))
   34                    ((string-prefix? line "seed-to-soil map:") (set! seed-to-soil-map (parse-map file)))
   35                    ((string-prefix? line "soil-to-fertilizer map:") (set! soil-to-fertilizer-map (parse-map file)))
   36                    ((string-prefix? line "fertilizer-to-water map:") (set! fertilizer-to-water-map (parse-map file)))
   37                    ((string-prefix? line "soil-to-fertilizer map:") (set! soil-to-fertilizer-map (parse-map file)))
   38                    ((string-prefix? line "fertilizer-to-water map:") (set! fertilizer-to-water-map (parse-map file)))
   39                    ((string-prefix? line "water-to-light map:") (set! water-to-light-map (parse-map file)))
   40                    ((string-prefix? line "light-to-temperature map:") (set! light-to-temperature-map (parse-map file)))
   41                    ((string-prefix? line "temperature-to-humidity map:") (set! temperature-to-humidity-map (parse-map file)))
   42                    ((string-prefix? line "humidity-to-location map:") (set! humidity-to-location-map (parse-map file))))))
   43     (values seeds seed-to-soil-map soil-to-fertilizer-map fertilizer-to-water-map water-to-light-map light-to-temperature-map temperature-to-humidity-map humidity-to-location-map)))
   44 
   45 (define (convert-number x maps)
   46   (let ((dest-start (car maps))
   47         (src-start (car (cdr maps)))
   48         (map-length (car (cdr (cdr maps)))))
   49     (if (and (>= x src-start) (< x (+ src-start map-length)))
   50         (+ dest-start (- x src-start))
   51         #f)))
   52 
   53 (define (src-to-dest src maps)
   54   (if (null? maps)
   55       src
   56       (let ((res (convert-number src (car maps))))
   57         (if (not res)
   58             (src-to-dest src (cdr maps))
   59             res))))
   60 
   61 (define (srcs-to-dests srcs maps)
   62   (map (lambda (src) (src-to-dest src maps)) srcs))
   63 
   64 (receive (seeds seed-to-soil-map soil-to-fertilizer-map fertilizer-to-water-map water-to-light-map light-to-temperature-map temperature-to-humidity-map humidity-to-location-map)
   65     (parse-input "input.txt")
   66   (let* ((curr seeds)
   67          (curr (srcs-to-dests curr seed-to-soil-map))
   68          (curr (srcs-to-dests curr soil-to-fertilizer-map))
   69          (curr (srcs-to-dests curr fertilizer-to-water-map))
   70          (curr (srcs-to-dests curr water-to-light-map))
   71          (curr (srcs-to-dests curr light-to-temperature-map))
   72          (curr (srcs-to-dests curr temperature-to-humidity-map))
   73          (curr (srcs-to-dests curr humidity-to-location-map))
   74          (lowest-location (reduce (lambda (x y) (min x y)) #nil curr)))
   75     ;; 175622908
   76     (format #t "Part 1: ~d" lowest-location)
   77     (newline)))
   78 
   79 (define (between x a b)
   80   (and (>= x a) (<= x b)))
   81 
   82 (define (startend-to-range start end)
   83   (cons start (1+ (- end start))))
   84 
   85 (define (range-intersect a-start a-length b-start b-length)
   86   (let ((a-end (1- (+ a-start a-length)))
   87         (b-end (1- (+ b-start b-length))))
   88     (cond ((or (< a-end b-start) (> a-start b-end))
   89            (values #nil (list (cons a-start a-length))))
   90           ((and (< a-start b-start) (between a-end b-start b-end))
   91            (values (startend-to-range b-start a-end) (list (startend-to-range a-start (1- b-start)))))
   92           ((and (between a-start b-start b-end) (> a-end b-end))
   93            (values (startend-to-range a-start b-end) (list (startend-to-range (1+ b-end) a-end))))
   94           ((and (>= a-start b-start) (<= a-end b-end))
   95            (values (startend-to-range a-start a-end) '()))
   96           ((and (< a-start b-start) (> a-end b-end))
   97            (values (startend-to-range b-start b-end) (list (startend-to-range a-start (1- b-start)) (startend-to-range (1+ b-end) a-end)))))))
   98 
   99 (define (src-range-to-dest-ranges x-range maps)
  100   (if (null? maps)
  101       (list x-range)
  102       (let ((x-start (car x-range))
  103             (x-length (cdr x-range))
  104             (dest-start (car (car maps)))
  105             (src-start (car (cdr (car maps))))
  106             (map-length (car (cdr (cdr (car maps)))))
  107             (res '()))
  108         (receive (mapped unmapped) (range-intersect x-start x-length src-start map-length)
  109           (if (not (null? mapped))
  110               (set! res (cons (cons (+ dest-start (- (car mapped) src-start)) (cdr mapped)) res)))
  111           (fold append res (map (lambda (r) (src-range-to-dest-ranges r (cdr maps))) unmapped))))))
  112 
  113 (define (src-ranges-to-dest-ranges srcs maps)
  114   (fold append '() (map (lambda (src) (src-range-to-dest-ranges src maps)) srcs)))
  115 
  116 (define (make-pairs inputs)
  117   (if (null? inputs)
  118       '()
  119       (cons (cons (car inputs) (car (cdr inputs))) (make-pairs (cdr (cdr inputs))))))
  120 
  121 (receive (seed-ranges-raw seed-to-soil-map soil-to-fertilizer-map fertilizer-to-water-map water-to-light-map light-to-temperature-map temperature-to-humidity-map humidity-to-location-map)
  122     (parse-input "input.txt")
  123   (let* ((curr (make-pairs seed-ranges-raw))
  124          (curr (src-ranges-to-dest-ranges curr seed-to-soil-map))
  125          (curr (src-ranges-to-dest-ranges curr soil-to-fertilizer-map))
  126          (curr (src-ranges-to-dest-ranges curr fertilizer-to-water-map))
  127          (curr (src-ranges-to-dest-ranges curr water-to-light-map))
  128          (curr (src-ranges-to-dest-ranges curr light-to-temperature-map))
  129          (curr (src-ranges-to-dest-ranges curr temperature-to-humidity-map))
  130          (curr (src-ranges-to-dest-ranges curr humidity-to-location-map))
  131          (curr-starts (map (lambda (x) (car x)) curr))
  132          (lowest-location (reduce (lambda (x y) (min x y)) #nil curr-starts)))
  133     ;; 5200543
  134     (format #t "Part 2: ~d" lowest-location)
  135     (newline)))