diff options
Diffstat (limited to 'report-repair/rr.scm')
-rw-r--r-- | report-repair/rr.scm | 100 |
1 files changed, 42 insertions, 58 deletions
diff --git a/report-repair/rr.scm b/report-repair/rr.scm index b327d3c..6adee86 100644 --- a/report-repair/rr.scm +++ b/report-repair/rr.scm @@ -2,64 +2,48 @@ -e main -s !# (define-module (rr) + #:use-module (combinations) #:use-module (srfi srfi-1) + #:use-module (ice-9 format) #:use-module (ice-9 exceptions) #:export (rr - multiply-pair - return-equivalent-pair - equivalent-pair? - return-friendship-pair - report->pairs)) - - -(define (rr str) - (multiply-pair - (return-equivalent-pair - (report->pairs str)))) - -(define (multiply-pair pair) - (* (car pair) - (cdr pair))) - -(define (return-equivalent-pair pairs) - "Given PAIRS friendship pairs, returns the -ones that are found to be friends. Throws -friendship-exception if no friends are found. - -We do NOT care if there are multiple pairs. -Return the first one." - (let loop ((pair (car pairs)) (pairs (cdr pairs))) - (if (null? pairs) - (raise-exception - (make-exception-with-message - "Concerning lack of friendship!")) - (if (equivalent-pair? pair pairs) - pair - (loop (car pairs) (cdr pairs)))))) - -(define (equivalent-pair? pair pairs) - "Given friendship pair PAIR and a list -of other PAIRS, determines if PAIR is -contained in PAIRS, irrespective of order" - (let ((r-pair (cons (cdr pair) - (car pair)))) - (any (lambda (pair) - (equal? r-pair pair)) - pairs))) - -(define (report->pairs str) - "Given a report, convert it to a -list of friendship pairs." - (let ((lst (string-split - (string-trim-both str char-set:whitespace) - char-set:whitespace))) - (map (lambda (str) - (return-friendship-pair - (string->number str))) - lst))) - -(define (return-friendship-pair num) - "Given NUM, returns a cons pair with -CAR as the original number and CDR as -the companion number." - (cons num (- 2020 num))) + 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)) |