-
Notifications
You must be signed in to change notification settings - Fork 2
/
ternary-print.lisp
59 lines (47 loc) · 1.85 KB
/
ternary-print.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
(in-package :cl-nutes)
;; A couple of simple functions to represent numbers in balanced 3, 9 and 27 base.
;; Requires Unicode, because negative digits are overlined (perfectly works in Emacs)
;; Balanced version of modulo
(defun bmod (n b)
(let ((a (floor b 2)))
(- (mod (+ n a) b) a)))
;; Getting the sequence of digits in 3^n balanced base
(defun 3n-split (n &key (b 3))
(labels ((f1 (n &key b)
(let ((bmod (bmod n b)))
(unless (zerop n)
(cons bmod (f1 (floor (- n bmod) b) :b b ))))))
(if (zerop n) '(0) (f1 n :b b))))
;; "Little-endian" version of the same
(defun 3n-digits (n &key (b 3) (l nil))
(let* ((res (reverse (3n-split n :b b)))
(ln (length res)))
(when l
(if (<= l ln)
(setf res (subseq res (- ln l) ln))
(setf res (append (make-list (- l ln) :initial-element 0) res))))
res))
(defun ternary-list
(n &optional (b 3))
(let
((b3 #("1̅" "0" "1"))
(b9 #("4̅" "3̅" "2̅" "1̅" "0" "1" "2" "3" "4"))
(b27 #("D̅" "C̅" "B̅" "A̅" "9̅" "8̅" "7̅" "6̅" "5̅" "4̅" "3̅" "2̅" "1̅" "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" ))
(digits nil))
(setf digits (3n-digits n :b b))
(case b
(3 (mapcar (lambda (x) (elt b3 (+ x 1))) digits))
(9 (mapcar (lambda (x) (elt b9 (+ x 4))) digits))
(27 (mapcar (lambda (x) (elt b27 (+ x 13))) digits)))))
;; Produce a string representing a balanced 3,9 or 27-base number
(defun ternary-string (n &key (b 27)(l nil))
(let* ((lst (ternary-list n b))
(ln (length lst)))
(if l
(if (< l ln)
(setf lst (subseq lst (- ln l) ln))
(setf lst (append (make-list (- l ln) :initial-element "0") lst))))
(apply #'concatenate 'string lst)))
;; Print a number in 3,9 or 27 balanced base
(defun ternary-print (n &key (b 27) (l nil) (stream t))
(format stream "~a" (ternary-string n :b b :l l)))