185 lines
5.9 KiB
Scheme
185 lines
5.9 KiB
Scheme
;; Puzzle Solution
|
|
|
|
;; #+NAME: day6-part1-imports
|
|
|
|
;; [[file:chicken-src.org::day6-part1-imports][day6-part1-imports]]
|
|
;; -*- geiser-scheme-implementation: chicken -*-
|
|
(import (chicken string)
|
|
(chicken irregex))
|
|
;; day6-part1-imports ends here
|
|
|
|
|
|
|
|
;; #+NAME: day6-input-scm
|
|
|
|
;; [[file:chicken-src.org::day6-input-scm][day6-input-scm]]
|
|
;; -*- geiser-scheme-implementation: chicken -*-
|
|
(define input "
|
|
Time: 58 81 96 76
|
|
Distance: 434 1041 2219 1218")
|
|
;; day6-input-scm ends here
|
|
|
|
;; Data Extraction
|
|
|
|
;; First, we need to define the record for the race data.
|
|
|
|
;; #+NAME: day6-part1-race-record
|
|
|
|
;; [[file:chicken-src.org::day6-part1-race-record][day6-part1-race-record]]
|
|
;; -*- geiser-scheme-implementation: chicken -*-
|
|
(define-record race time-limit record-distance winning-distances losing-distances)
|
|
;; day6-part1-race-record ends here
|
|
|
|
|
|
|
|
;; The solution starts with the usual data extraction using ~irregex~.
|
|
|
|
;; #+NAME: day6-part1-input-extraction-irregex
|
|
|
|
;; [[file:chicken-src.org::day6-part1-input-extraction-irregex][day6-part1-input-extraction-irregex]]
|
|
;; -*- geiser-scheme-implementation: chicken -*-
|
|
(define input-extraction-irregex
|
|
'(: "Time:"
|
|
(submatch-named time-vals (+ (or numeric whitespace)))
|
|
"Distance:"
|
|
(submatch-named distance-vals (+ (or numeric whitespace)))))
|
|
;; day6-part1-input-extraction-irregex ends here
|
|
|
|
|
|
|
|
;; Next, the data is converted into ~race~ records.
|
|
|
|
;; #+NAME: day6-part1-input--race-records
|
|
|
|
;; [[file:chicken-src.org::day6-part1-input--race-records][day6-part1-input--race-records]]
|
|
;; -*- geiser-scheme-implementation: chicken -*-
|
|
(define (input->race-records input)
|
|
(let ((match (irregex-search input-extraction-irregex
|
|
input)))
|
|
(map (lambda (time distance)
|
|
(make-race time distance #f #f))
|
|
(map string->number (string-split (irregex-match-substring match 'time-vals)))
|
|
(map string->number (string-split (irregex-match-substring match 'distance-vals))))))
|
|
;; day6-part1-input--race-records ends here
|
|
|
|
;; Race Calculations
|
|
|
|
;; #+NAME: day6-part1-get-distance
|
|
|
|
;; [[file:chicken-src.org::day6-part1-get-distance][day6-part1-get-distance]]
|
|
;; -*- geiser-scheme-implementation: chicken -*-
|
|
(define (get-distance race hold-time)
|
|
(let ((time-remaining (- (race-time-limit race) hold-time)))
|
|
(* time-remaining hold-time)))
|
|
;; day6-part1-get-distance ends here
|
|
|
|
|
|
|
|
;; #+NAME: day6-part1-calc-race-distances
|
|
|
|
;; [[file:chicken-src.org::day6-part1-calc-race-distances][day6-part1-calc-race-distances]]
|
|
;; -*- geiser-scheme-implementation: chicken -*-
|
|
(define (calc-race-distances race
|
|
#!optional (hold-time 1) (winning-distances '()) (losing-distances '()))
|
|
(let* ((record-distance (race-record-distance race))
|
|
(new-distance (get-distance race hold-time))
|
|
(is-new-record? (> new-distance record-distance)))
|
|
(cond
|
|
((= new-distance 0)
|
|
(begin
|
|
(race-winning-distances-set! race winning-distances)
|
|
(race-losing-distances-set! race losing-distances)
|
|
race))
|
|
(else
|
|
(calc-race-distances
|
|
race (+ hold-time 1)
|
|
(if is-new-record? (cons new-distance winning-distances) winning-distances)
|
|
(if is-new-record? losing-distances (cons new-distance losing-distances)))))))
|
|
;; day6-part1-calc-race-distances ends here
|
|
|
|
;; Getting The Result
|
|
|
|
;; #+NAME: day6-part1-calc-fn
|
|
|
|
;; [[file:chicken-src.org::day6-part1-calc-fn][day6-part1-calc-fn]]
|
|
;; -*- geiser-scheme-implementation: chicken -*-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define (calc-part-1)
|
|
(foldl *
|
|
1 (map (compose length race-winning-distances)
|
|
(map calc-race-distances (input->race-records input)))))
|
|
;; day6-part1-calc-fn ends here
|
|
|
|
;; Code Changes
|
|
|
|
;; The ~input->race-records~ function has to be rewritten:
|
|
|
|
;; #+NAME: day6-part2-input--race-record
|
|
|
|
;; [[file:chicken-src.org::day6-part2-input--race-record][day6-part2-input--race-record]]
|
|
;; -*- geiser-scheme-implementation: chicken -*-
|
|
(define (input->race-record input)
|
|
(let* ((match (irregex-search input-extraction-irregex input))
|
|
(time-val ((compose string->number
|
|
(cut foldl string-append "" <>)
|
|
string-split
|
|
(cut irregex-match-substring <> 'time-vals))
|
|
match))
|
|
(distance-val ((compose string->number
|
|
(cut foldl string-append "" <>)
|
|
string-split
|
|
(cut irregex-match-substring <> 'distance-vals))
|
|
match)))
|
|
(make-race time-val distance-val #f #f)))
|
|
;; day6-part2-input--race-record ends here
|
|
|
|
|
|
|
|
;; And instead of keeping a list of all winning and losing distances, I use a counter.
|
|
|
|
;; #+NAME: day6-part2-calc-race-distances
|
|
|
|
;; [[file:chicken-src.org::day6-part2-calc-race-distances][day6-part2-calc-race-distances]]
|
|
;; -*- geiser-scheme-implementation: chicken -*-
|
|
(define (calc-race-distances-with-counter race
|
|
#!optional (hold-time 1) (winning-distances 0) (losing-distances 0))
|
|
(let* ((record-distance (race-record-distance race))
|
|
(new-distance (get-distance race hold-time))
|
|
(is-new-record? (> new-distance record-distance)))
|
|
(cond
|
|
((= new-distance 0)
|
|
(begin
|
|
(race-winning-distances-set! race winning-distances)
|
|
(race-losing-distances-set! race losing-distances)
|
|
race))
|
|
(else
|
|
(calc-race-distances-with-counter
|
|
race (+ hold-time 1)
|
|
(if is-new-record? (+ 1 winning-distances) winning-distances)
|
|
(if is-new-record? losing-distances (+ 1 losing-distances)))))))
|
|
;; day6-part2-calc-race-distances ends here
|
|
|
|
;; Race Variant Results
|
|
|
|
;; #+NAME: day6-part2-calc-fn
|
|
|
|
;; [[file:chicken-src.org::day6-part2-calc-fn][day6-part2-calc-fn]]
|
|
;; -*- geiser-scheme-implementation: chicken -*-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
(define (calc-part-2)
|
|
(race-winning-distances
|
|
(calc-race-distances-with-counter (input->race-record input))))
|
|
;; day6-part2-calc-fn ends here
|