-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinputs.lisp
62 lines (52 loc) · 1.99 KB
/
inputs.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
(in-package :aoc)
(defun call-with-input (year in function)
(typecase in
(stream (funcall function in))
(t (with-open-file (stream (fetch-input year in nil))
(funcall function stream)))))
(defmacro with-input ((stream name) &body body)
(input-bind (year in) name
`(call-with-input ,year ,in (lambda (,stream) ,@body))))
(defmacro do-input-lines ((line name &optional result) &body body)
(with-gensyms (stream)
`(with-input (,stream ,name)
(loop :for ,line := (read-line ,stream nil nil)
:while ,line
:do (progn ,@body)
:finally (return ,result)))))
(defmacro map-input (in &key (transform nil) (reader '#'read-line) (type ''vector))
(with-gensyms (s)
(let ((scanner `(z:scan-stream ,s ,reader)))
`(with-input (,s ,in)
(z:collect ,type
,(if transform
`(z:map-fn t ,transform ,scanner)
scanner))))))
(defun fold-input-lines (input function &optional accumulator)
(do-input-lines (line input accumulator)
(setf accumulator (funcall function line accumulator))))
(defun slurp-line (input)
(with-input (s input)
(read-line s)))
(defmacro do-integers ((var string &optional result) &body body)
(with-gensyms (Z S E)
`(let ((,Z ,string))
(do-matches (,S ,E '(:greedy-repetition 1 () :digit-class) ,Z ,result)
(let ((,var (parse-integer ,Z :start ,S :end ,E)))
,@body)))))
(defun map-all-integers (string function)
(do-integers (integer string)
(funcall function integer)))
(defun all-integers (string)
(with-buffer (b)
(map-all-integers string #'b)))
(defun map-line-chunks (in function &aux stack)
"Read consecutive non-empty lines and call FUNCTION on their concatenation."
(flet ((emit ()
(when stack
(let ((lines (nreverse (shiftf stack nil))))
(funcall function lines)))))
(do-input-lines (line in (emit))
(if (string= line "")
(emit)
(push line stack)))))