123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 |
- (import
- (except (rnrs base) let-values map error)
- (only (guile) lambda* λ command-line string-null?)
- (srfi srfi-1)
- (fileio))
- (define concat-lines
- (lambda* (lines #:key (separator-test string-null?))
- (let next-line ([remaining-lines lines] [combined-line ""])
- (cond
- [(null? remaining-lines)
- (list (string-trim-both combined-line))]
- [else
- (let ([cur-line (first remaining-lines)])
- (cond
- ;; The passport-separator finishes an entry in
- ;; the lines. We cons the single passport data
- ;; onto the recursion and start collecting data
- ;; for the next single passport.
- [(separator-test cur-line)
- (cons (string-trim-both combined-line)
- (next-line (cdr remaining-lines) ""))]
- ;; If more data for a single passport follows, we
- ;; append it onto the single passport data and
- ;; look at the next line.
- [else
- (next-line (cdr remaining-lines)
- (string-append combined-line cur-line))]))]))))
- (define unique-chars
- (λ (str)
- (define look-at-next-char
- (λ (remaining-chars previous-char unique-chars)
- (cond
- [(null? remaining-chars)
- unique-chars]
- [(char=? previous-char (first remaining-chars))
- (look-at-next-char (cdr remaining-chars)
- previous-char
- unique-chars)]
- [else
- (look-at-next-char (cdr remaining-chars)
- (first remaining-chars)
- (cons (first remaining-chars) unique-chars))])))
- (let ([sorted-chars (sort (string->list str) char<?)])
- (look-at-next-char (cdr sorted-chars)
- (first sorted-chars)
- (list (first sorted-chars))))))
- (define main
- (λ (cmd-line-args)
- (let* ([lines (concat-lines (get-lines-from-file (second cmd-line-args)))])
- (apply + (map length (map unique-chars lines))))))
- (simple-format (current-output-port)
- "~a\n"
- (main (command-line)))
|