-
Notifications
You must be signed in to change notification settings - Fork 0
/
util.lisp
47 lines (35 loc) · 1.57 KB
/
util.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
;;; Common support functions for AoC
;;;
;;; Requires split-sequence and regex
(defun process-stream (reduce-func map-func s)
"Read a stream and mapreduce it"
(funcall reduce-func
(loop for line = (read-line s nil)
while line
collect (funcall map-func line))))
(defun process-file (reduce-func map-func filename)
"Read contents of a file into a list and mapreduce it - the reduce function is called with the list as a single argument"
(with-open-file (foo filename :direction :input
:if-does-not-exist :error)
(process-stream reduce-func map-func foo)))
(defun process-file-or-string (reduce-func map-func file-or-string)
"Process a file (by name) or stream or string"
(cond
((pathnamep file-or-string) (process-file reduce-func map-func file-or-string))
((streamp file-or-string) (process-stream reduce-func map-func file-or-string))
((stringp file-or-string) (process-stream reduce-func map-func (make-string-input-stream file-or-string)))
(t (error "Cannot process type ~A" (type-of file-or-string)))))
(defun make-string-parser (&optional syntax)
"Generate a function to parse a string"
(declare (ignore syntax))
;; cheap and cheerful implementation for now
(lambda (string)
(mapcar #'read-from-string (split-sequence:split-sequence #\Space string))))
(defun integer-digits (n &optional (radix 10))
"Split a non-negative integer into its digits"
(declare (type unsigned-byte n))
(labels ((i-dig (n)
(if (< n radix) (list n)
(multiple-value-bind (q r) (floor n radix)
(cons r (i-dig q))))))
(nreverse (i-dig n))))