(define-module (rr) #:use-module (combinations) #:use-module (srfi srfi-1) #:use-module (ice-9 format) #:use-module (ice-9 exceptions) #:export (rr get-2020-terms includes-all? generate-sets make-complete-set)) (define (rr str len) (apply * (get-2020-terms (map string->number (string-split (string-trim-both str char-set:whitespace) char-set:whitespace)) len))) (define (get-2020-terms lst len) "Given a list of numbers, returns a list of length LEN whose contents add up to 2020. Throws input-exception if none are found." (let loop ((sets (generate-sets lst len))) (cond ((null? sets) (raise-exception (make-exception-with-message (format #f "Could not find ~s arguments that add to 2020 in inputs!" len)))) ((includes-all? (car sets) lst) (car sets)) (#t (loop (cdr sets)))))) (define (includes-all? lst1 lst2) "Returns #t if all elements in LST1 are present in LST2, #f otherwise." (equal? lst1 (lset-intersection eqv? lst1 lst2))) (define (generate-sets lst len) (map make-complete-set (combinations lst (1- len)))) (define (make-complete-set lst) "Given a LST of numbers, i.e. '(979 366) returns a list of one greater length such that all numbers add up to 2020." (append (list (- 2020 (apply + lst))) lst))