-
Notifications
You must be signed in to change notification settings - Fork 0
/
rle.lisp
53 lines (46 loc) · 1.91 KB
/
rle.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
; Description: Assemble patterns and rules for cellular automata
; Author: Isidor Zeuner
; For license see: https://mit-license.org
; -------------------------------------------------------------------
(defvar *states* '("." "A" "B" "C"))
(defun write-rle-state (state) (elt *states* state))
(defun write-rle-row (row)
(if row
(let* ((state (car row))
(repetitions
(or (position-if-not #'(lambda (other) (eql state other)) row)
(length row))))
(concatenate 'string
(if (eql repetitions 1)
""
(format nil "~d" repetitions))
(write-rle-state state)
(write-rle-row (subseq row repetitions))))
"$
"))
(defun write-rle (grid)
(concatenate 'string "x = " (format nil "~d" (length (car grid))) ", y = "
(format nil "~d" (length grid)) ", rule = WireWorld
"
(apply #'concatenate 'string (mapcar #'write-rle-row grid)) "!
"))
(defun read-rle-line-or-more (line-or-more)
(multiple-value-bind (repetitions next)
(parse-integer line-or-more :junk-allowed t)
(let ((repetitions (or repetitions 1))
(unparsed (subseq line-or-more next)))
(if (equal "" unparsed)
(make-list repetitions)
(let ((state (position (subseq unparsed 0 1) *states* :test #'equal))
(tail (read-rle-line-or-more (subseq unparsed 1))))
(cons
(concatenate 'list (make-list repetitions :initial-element state)
(car tail))
(cdr tail)))))))
(defun read-rle (rle)
(let* ((varying-length
(mapcan #'read-rle-line-or-more
(split-by #\$ (car (split-by #\! rle)))))
(max-length (apply #'max (mapcar #'length varying-length))))
(mapcar #'(lambda (line) (rpad max-length 0 line)) varying-length)))