#!/usr/bin/env -S guile -s !# (use-modules (ice-9 regex) (ice-9 textual-ports) (srfi srfi-1)) (define (read-lines port) (letrec ((loop (lambda (l ls) (if (eof-object? l) ls (loop (get-line port) (cons l ls)))))) (reverse (loop (get-line port) '())))) (define (split-up nums) (map string->number (filter (lambda (x) (not (string-null? x))) (string-split nums char-set:whitespace)))) (define (perform-mapping val map) (let* ((mapping (filter (lambda (x) (and (>= val (cadr x)) (< val (+ (cadr x) (caddr x))))) map))) (if (null? mapping) val (+ val (- (caar mapping) (cadar mapping)))))) (define (perform-all-mappings val maps) (do ((i 0 (1+ i))) ((= i (length maps))) (set! val (perform-mapping val (list-ref maps i)))) val) (define (parse-next-map lines) (let ((map-started #f) (map-parsed #f) (current-map '())) (while (not map-parsed) (if (and (not map-started) (string-match "map" (car lines))) (set! map-started #t) (when map-started (if (string-match "[0-9]" (car lines)) (set! current-map (append current-map `(,(split-up (car lines))))) (set! map-parsed #t)))) (set! lines (cdr lines))) `(,current-map ,lines))) (define (in-ranges ranges val) (let ((found #f)) (while (and (not (null? ranges)) (not found)) (if (and (>= val (car ranges)) (< val (+ (car ranges) (cadr ranges)))) (set! found #t) (set! ranges (cddr ranges)))) found)) (let* ((port (open-input-file "5.txt")) (lines (read-lines port)) (seeds (split-up (match:substring (string-match ": ([0-9| ]+)" (car lines)) 1))) (lines (cdr lines)) (maps '()) (index 0)) (close-port port) (do ((i 0 (1+ i))) ((= i 7)) (let ((res (parse-next-map lines))) (set! maps (append maps `(,(car res)))) (set! lines (cadr res)))) (set! maps (reverse (map (lambda (x) (map (lambda (y) `(,(cadr y) ,(car y) ,(caddr y))) x)) maps))) (while (not (in-ranges seeds (perform-all-mappings index maps))) (set! index (1+ index))) (display index))