123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- (import
- (except (rnrs base)
- let-values
- map
- error
- vector-map)
- (only (guile)
- lambda* λ
- simple-format
- current-output-port)
- (fileio)
- ;; (ice-9 pretty-print)
- (ice-9 peg)
- (prefix (peg-tree-utils) peg-tree:)
- ;; (ice-9 format)
- (srfi srfi-1)
- (pipeline)
- (debug)
- (list-helpers)
- (parallelism)
- (math))
- (define input-filename "input")
- (define lines (get-lines-from-file input-filename))
- (define list-groups (split-into-segments lines (λ (line) (string-null? line))))
- (assert (reduce (λ (elem acc) (and acc elem))
- #t
- (map (λ (list-group) (= (length list-group) 2))
- list-groups)))
- ;; define grammar
- (define-peg-pattern COMMA none ",")
- (define-peg-pattern NUMBER all (+ (range #\0 #\9)))
- (define-peg-pattern QOPEN none "[")
- (define-peg-pattern QCLOSE none "]")
- (define-peg-pattern QLIST-ITEM body (or NUMBER QLIST))
- (define-peg-pattern QLIST-ALL-ITEMS all (* (and QLIST-ITEM (? COMMA))))
- (define-peg-pattern QLIST all (and QOPEN QLIST-ALL-ITEMS QCLOSE))
- (define parse-string-list
- (λ (str)
- (let ([tree (peg:tree (match-pattern QLIST str))])
- tree)))
- (assert (reduce (λ (elem acc) (and acc elem))
- #t
- (map (λ (list-group)
- (and (parse-string-list (first list-group))
- (parse-string-list (second list-group))))
- list-groups)))
- (define parsed-list->list
- (λ (plist)
- (let ([label (first plist)])
- (cond
- [(eq? label 'NUMBER)
- (string->number (second plist))]
- [(eq? label 'QLIST)
- (map parsed-list->list
- (peg-tree:tree-refs plist '(QLIST-ALL-ITEMS) #:equal-test eq?))]
- [else (error "unrecognized parsed list" plist)]))))
- (define list-transformer
- (λ (list-str)
- (-> list-str parse-string-list parsed-list->list)))
- (define translated-list-groups
- (parallel-map (λ (group _ind)
- (cons (list-transformer (first group))
- (list-transformer (second group))))
- list-groups))
- (for-each (λ (list-group)
- (assert (or (pair? (car list-group)) (null? (car list-group))))
- (assert (or (pair? (cdr list-group)) (null? (cdr list-group)))))
- translated-list-groups)
- (define less
- (λ (lst1 lst2)
- (define compare
- ;; Usage of a continuation for the equals case avoids having to
- ;; encode the results of <, =, > in 3 values like 1, 0, -1.
- (λ (lst1° lst2° equal-case-cont)
- ;; (simple-format #t "comparing:\n~a\n~a\n" lst1° lst2°)
- (cond
- [(and (null? lst1°) (null? lst2°)) (equal-case-cont)]
- [(null? lst2°) #f]
- [(null? lst1°) #t]
- ;; no list ran out of elements yet -- OK!
- [else
- (let ([elem1 (first lst1°)] [elem2 (first lst2°)])
- (cond
- ;; both contain a list as first element
- [(and (or (pair? elem1) (null? elem1))
- (or (pair? elem2) (null? elem2)))
- (compare elem1
- elem2
- ;; Build a new continuation. Compare this cdr,
- ;; but also keep the outer cdr compare
- ;; continuation.
- (λ ()
- (compare (cdr lst1°)
- (cdr lst2°)
- equal-case-cont)))]
- ;; both a number
- [(and (number? elem1) (number? elem2))
- ;; need to distinguish equals case
- (cond
- [(< elem1 elem2) #t]
- [(= elem1 elem2)
- (compare (cdr lst1°) (cdr lst2°) equal-case-cont)]
- [(> elem1 elem2) #f])]
- ;; transform into a list if not both a list
- [(and (number? elem1) (not (number? elem2)))
- (less (cons (list elem1) (cdr lst1°)) lst2°)]
- [(and (not (number? elem1)) (number? elem2))
- (less lst1° (cons (list elem2) (cdr lst2°)))]
- ;; both a list
- [(and (pair? elem1) (pair? elem2))
- (compare elem1
- elem2
- (λ () (less (cdr lst1°) (cdr lst2°))))]
- [else
- (simple-format #t "unrecognized situation while comparing: ~a with ~a\n" lst1 lst2)
- (error "unrecognized situation" lst1 lst2)]))])))
- (compare lst1
- lst2
- (λ () (less (cdr lst1) (cdr lst2))))))
- (define identity (λ (x) x))
- (simple-format
- #t "~a\n"
- (sum (filter identity
- (parallel-map
- (λ (group group-index)
- ;; (simple-format #t "comparing group ~a\n" (+ group-index 1))
- (cond [(less (car group) (cdr group))
- ;; (simple-format #t " -> ~a\n" #t)
- (+ group-index 1)]
- [else
- ;; (simple-format #t " -> ~a\n" #f)
- #f]))
- translated-list-groups))))
|