part-01.scm 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. (import
  2. (except (rnrs base)
  3. let-values
  4. map
  5. error
  6. vector-map)
  7. (only (guile)
  8. lambda* λ
  9. simple-format
  10. current-output-port)
  11. (fileio)
  12. ;; (ice-9 pretty-print)
  13. (ice-9 peg)
  14. (prefix (peg-tree-utils) peg-tree:)
  15. ;; (ice-9 format)
  16. (srfi srfi-1)
  17. (pipeline)
  18. (debug)
  19. (list-helpers)
  20. (parallelism)
  21. (math))
  22. (define input-filename "input")
  23. (define lines (get-lines-from-file input-filename))
  24. (define list-groups (split-into-segments lines (λ (line) (string-null? line))))
  25. (assert (reduce (λ (elem acc) (and acc elem))
  26. #t
  27. (map (λ (list-group) (= (length list-group) 2))
  28. list-groups)))
  29. ;; define grammar
  30. (define-peg-pattern COMMA none ",")
  31. (define-peg-pattern NUMBER all (+ (range #\0 #\9)))
  32. (define-peg-pattern QOPEN none "[")
  33. (define-peg-pattern QCLOSE none "]")
  34. (define-peg-pattern QLIST-ITEM body (or NUMBER QLIST))
  35. (define-peg-pattern QLIST-ALL-ITEMS all (* (and QLIST-ITEM (? COMMA))))
  36. (define-peg-pattern QLIST all (and QOPEN QLIST-ALL-ITEMS QCLOSE))
  37. (define parse-string-list
  38. (λ (str)
  39. (let ([tree (peg:tree (match-pattern QLIST str))])
  40. tree)))
  41. (assert (reduce (λ (elem acc) (and acc elem))
  42. #t
  43. (map (λ (list-group)
  44. (and (parse-string-list (first list-group))
  45. (parse-string-list (second list-group))))
  46. list-groups)))
  47. (define parsed-list->list
  48. (λ (plist)
  49. (let ([label (first plist)])
  50. (cond
  51. [(eq? label 'NUMBER)
  52. (string->number (second plist))]
  53. [(eq? label 'QLIST)
  54. (map parsed-list->list
  55. (peg-tree:tree-refs plist '(QLIST-ALL-ITEMS) #:equal-test eq?))]
  56. [else (error "unrecognized parsed list" plist)]))))
  57. (define list-transformer
  58. (λ (list-str)
  59. (-> list-str parse-string-list parsed-list->list)))
  60. (define translated-list-groups
  61. (parallel-map (λ (group _ind)
  62. (cons (list-transformer (first group))
  63. (list-transformer (second group))))
  64. list-groups))
  65. (for-each (λ (list-group)
  66. (assert (or (pair? (car list-group)) (null? (car list-group))))
  67. (assert (or (pair? (cdr list-group)) (null? (cdr list-group)))))
  68. translated-list-groups)
  69. (define less
  70. (λ (lst1 lst2)
  71. (define compare
  72. ;; Usage of a continuation for the equals case avoids having to
  73. ;; encode the results of <, =, > in 3 values like 1, 0, -1.
  74. (λ (lst1° lst2° equal-case-cont)
  75. ;; (simple-format #t "comparing:\n~a\n~a\n" lst1° lst2°)
  76. (cond
  77. [(and (null? lst1°) (null? lst2°)) (equal-case-cont)]
  78. [(null? lst2°) #f]
  79. [(null? lst1°) #t]
  80. ;; no list ran out of elements yet -- OK!
  81. [else
  82. (let ([elem1 (first lst1°)] [elem2 (first lst2°)])
  83. (cond
  84. ;; both contain a list as first element
  85. [(and (or (pair? elem1) (null? elem1))
  86. (or (pair? elem2) (null? elem2)))
  87. (compare elem1
  88. elem2
  89. ;; Build a new continuation. Compare this cdr,
  90. ;; but also keep the outer cdr compare
  91. ;; continuation.
  92. (λ ()
  93. (compare (cdr lst1°)
  94. (cdr lst2°)
  95. equal-case-cont)))]
  96. ;; both a number
  97. [(and (number? elem1) (number? elem2))
  98. ;; need to distinguish equals case
  99. (cond
  100. [(< elem1 elem2) #t]
  101. [(= elem1 elem2)
  102. (compare (cdr lst1°) (cdr lst2°) equal-case-cont)]
  103. [(> elem1 elem2) #f])]
  104. ;; transform into a list if not both a list
  105. [(and (number? elem1) (not (number? elem2)))
  106. (less (cons (list elem1) (cdr lst1°)) lst2°)]
  107. [(and (not (number? elem1)) (number? elem2))
  108. (less lst1° (cons (list elem2) (cdr lst2°)))]
  109. ;; both a list
  110. [(and (pair? elem1) (pair? elem2))
  111. (compare elem1
  112. elem2
  113. (λ () (less (cdr lst1°) (cdr lst2°))))]
  114. [else
  115. (simple-format #t "unrecognized situation while comparing: ~a with ~a\n" lst1 lst2)
  116. (error "unrecognized situation" lst1 lst2)]))])))
  117. (compare lst1
  118. lst2
  119. (λ () (less (cdr lst1) (cdr lst2))))))
  120. (define identity (λ (x) x))
  121. (simple-format
  122. #t "~a\n"
  123. (sum (filter identity
  124. (parallel-map
  125. (λ (group group-index)
  126. ;; (simple-format #t "comparing group ~a\n" (+ group-index 1))
  127. (cond [(less (car group) (cdr group))
  128. ;; (simple-format #t " -> ~a\n" #t)
  129. (+ group-index 1)]
  130. [else
  131. ;; (simple-format #t " -> ~a\n" #f)
  132. #f]))
  133. translated-list-groups))))