CDE
This commit is contained in:
parent
518da4a923
commit
764da6cbbb
6144 changed files with 83610 additions and 11 deletions
93
Task/Balanced-ternary/Common-Lisp/balanced-ternary-1.lisp
Normal file
93
Task/Balanced-ternary/Common-Lisp/balanced-ternary-1.lisp
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
;;; balanced ternary
|
||||
;;; represented as a list of 0, 1 or -1s, with least significant digit first
|
||||
|
||||
;;; convert ternary to integer
|
||||
(defun bt-integer (b)
|
||||
(reduce (lambda (x y) (+ x (* 3 y))) b :from-end t :initial-value 0))
|
||||
|
||||
;;; convert integer to ternary
|
||||
(defun integer-bt (n)
|
||||
(if (zerop n) nil
|
||||
(case (mod n 3)
|
||||
(0 (cons 0 (integer-bt (/ n 3))))
|
||||
(1 (cons 1 (integer-bt (floor n 3))))
|
||||
(2 (cons -1 (integer-bt (floor (1+ n) 3)))))))
|
||||
|
||||
;;; convert string to ternary
|
||||
(defun string-bt (s)
|
||||
(loop with o = nil for c across s do
|
||||
(setf o (cons (case c (#\+ 1) (#\- -1) (#\0 0)) o))
|
||||
finally (return o)))
|
||||
|
||||
;;; convert ternary to string
|
||||
(defun bt-string (bt)
|
||||
(if (not bt) "0"
|
||||
(let* ((l (length bt))
|
||||
(s (make-array l :element-type 'character)))
|
||||
(mapc (lambda (b)
|
||||
(setf (aref s (decf l))
|
||||
(case b (-1 #\-) (0 #\0) (1 #\+))))
|
||||
bt)
|
||||
s)))
|
||||
|
||||
;;; arithmetics
|
||||
(defun bt-neg (a) (map 'list #'- a))
|
||||
(defun bt-sub (a b) (bt-add a (bt-neg b)))
|
||||
|
||||
(let ((tbl #((0 -1) (1 -1) (-1 0) (0 0) (1 0) (-1 1) (0 1))))
|
||||
(defun bt-add-digits (a b c)
|
||||
(values-list (aref tbl (+ 3 a b c)))))
|
||||
|
||||
(defun bt-add (a b &optional (c 0))
|
||||
(if (not (and a b))
|
||||
(if (zerop c) (or a b)
|
||||
(bt-add (list c) (or a b)))
|
||||
(multiple-value-bind (d c)
|
||||
(bt-add-digits (if a (car a) 0) (if b (car b) 0) c)
|
||||
(let ((res (bt-add (cdr a) (cdr b) c)))
|
||||
;; trim leading zeros
|
||||
(if (or res (not (zerop d)))
|
||||
(cons d res))))))
|
||||
|
||||
(defun bt-mul (a b)
|
||||
(if (not (and a b))
|
||||
nil
|
||||
(bt-add (case (car a)
|
||||
(-1 (bt-neg b))
|
||||
( 0 nil)
|
||||
( 1 b))
|
||||
(cons 0 (bt-mul (cdr a) b)))))
|
||||
|
||||
;;; division with quotient/remainder, for completeness
|
||||
(defun bt-truncate (a b)
|
||||
(let ((n (- (length a) (length b)))
|
||||
(d (car (last b))))
|
||||
(if (minusp n)
|
||||
(values nil a)
|
||||
(labels ((recur (a b x)
|
||||
(multiple-value-bind (quo rem)
|
||||
(if (plusp x) (recur a (cons 0 b) (1- x))
|
||||
(values nil a))
|
||||
|
||||
(loop with g = (car (last rem))
|
||||
with quo = (cons 0 quo)
|
||||
while (= (length rem) (length b)) do
|
||||
(cond ((= g d) (setf rem (bt-sub rem b)
|
||||
quo (bt-add '(1) quo)))
|
||||
((= g (- d)) (setf rem (bt-add rem b)
|
||||
quo (bt-add '(-1) quo))))
|
||||
(setf x (car (last rem)))
|
||||
finally (return (values quo rem))))))
|
||||
|
||||
(recur a b n)))))
|
||||
|
||||
;;; test case
|
||||
(let* ((a (string-bt "+-0++0+"))
|
||||
(b (integer-bt -436))
|
||||
(c (string-bt "+-++-"))
|
||||
(d (bt-mul a (bt-sub b c))))
|
||||
(format t "a~5d~8t~a~%b~5d~8t~a~%c~5d~8t~a~%a × (b − c) = ~d ~a~%"
|
||||
(bt-integer a) (bt-string a)
|
||||
(bt-integer b) (bt-string b)
|
||||
(bt-integer c) (bt-string c)
|
||||
(bt-integer d) (bt-string d)))
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
a 523 +-0++0+
|
||||
b -436 -++-0--
|
||||
c 65 +-++-
|
||||
a × (b − c) = -262023 ----0+--0++0
|
||||
142
Task/Balanced-ternary/D/balanced-ternary.d
Normal file
142
Task/Balanced-ternary/D/balanced-ternary.d
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
import std.stdio, std.bigint, std.range, std.algorithm, std.array,
|
||||
std.conv, std.exception;
|
||||
|
||||
struct BalancedTernary {
|
||||
enum Dig : byte { N=-1, Z=0, P=+1 } // digits
|
||||
Dig[] digits;
|
||||
// Represented as a list of 0, 1 or -1s,
|
||||
// with least significant digit first.
|
||||
|
||||
static string dig2str = "-0+";
|
||||
|
||||
const static Dig[dchar] str2dig; // = ['+': Dig.P, ...];
|
||||
static this() {
|
||||
str2dig = ['+': Dig.P, '-': Dig.N, '0': Dig.Z];
|
||||
}
|
||||
|
||||
immutable static Dig[2][] table =
|
||||
[[Dig.Z, Dig.N], [Dig.P, Dig.N], [Dig.N, Dig.Z],
|
||||
[Dig.Z, Dig.Z], [Dig.P, Dig.Z], [Dig.N, Dig.P],
|
||||
[Dig.Z, Dig.P]];
|
||||
|
||||
this(string inp) {
|
||||
this.digits = map!(c => cast()str2dig[c])(retro(inp)).array();
|
||||
}
|
||||
|
||||
this(long inp) {
|
||||
this.digits = _bint2ternary(BigInt(inp));
|
||||
}
|
||||
|
||||
this(BigInt inp) {
|
||||
this.digits = _bint2ternary(inp);
|
||||
}
|
||||
|
||||
this(BalancedTernary inp) {
|
||||
// no need to dup, they are virtually immutable
|
||||
this.digits = inp.digits;
|
||||
}
|
||||
|
||||
private this(Dig[] inp) {
|
||||
this.digits = inp;
|
||||
}
|
||||
|
||||
static Dig[] _bint2ternary(/*in*/ BigInt n) {
|
||||
static py_div(T1, T2)(T1 a, T2 b) {
|
||||
if (a < 0)
|
||||
if (b < 0)
|
||||
return -a / -b;
|
||||
else
|
||||
return -(-a / b) - (-a % b != 0 ? 1 : 0);
|
||||
else if (b < 0)
|
||||
return -(a / -b) - (a % -b != 0 ? 1 : 0);
|
||||
else
|
||||
return a / b;
|
||||
}
|
||||
|
||||
if (n == 0) return [];
|
||||
switch (((n % 3) + 3) % 3) { // (n % 3) is the remainder
|
||||
case 0: return Dig.Z ~ _bint2ternary(py_div(n, 3));
|
||||
case 1: return Dig.P ~ _bint2ternary(py_div(n, 3));
|
||||
case 2: return Dig.N ~ _bint2ternary(py_div(n + 1, 3));
|
||||
default: assert(0, "Can't happen");
|
||||
}
|
||||
}
|
||||
|
||||
@property BigInt toBint() const {
|
||||
return reduce!((y,x) => x + 3 * y)(BigInt(0), retro(digits));
|
||||
}
|
||||
|
||||
string toString() const {
|
||||
if (digits.empty) return "0";
|
||||
//return map!(d => dig2str[d + 1])(retro(digits)).array();
|
||||
auto r = map!(d => cast()dig2str[d+1])(retro(digits)).array();
|
||||
return assumeUnique(r); ///
|
||||
}
|
||||
|
||||
static Dig[] neg_(Dig[] digs) {
|
||||
return map!(d => -d)(digs).array();
|
||||
}
|
||||
|
||||
BalancedTernary opUnary(string op:"-")() {
|
||||
return BalancedTernary(neg_(this.digits));
|
||||
}
|
||||
|
||||
static Dig[] add_(Dig[] a, Dig[] b, Dig c=Dig.Z) {
|
||||
auto a_or_b = a.length ? a : b;
|
||||
if (a.empty || b.empty) {
|
||||
if (c == Dig.Z)
|
||||
return a_or_b;
|
||||
else
|
||||
return BalancedTernary.add_([c], a_or_b);
|
||||
} else {
|
||||
// (const d, c) = table[...];
|
||||
const dc = table[3 + (a.length ? a[0] : 0) +
|
||||
(b.length ? b[0] : 0) + c];
|
||||
auto res = add_(a[1 .. $], b[1 .. $], dc[1]);
|
||||
// trim leading zeros
|
||||
if (res.length || dc[0] != Dig.Z)
|
||||
return [dc[0]] ~ res;
|
||||
else
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
BalancedTernary opBinary(string op:"+")(BalancedTernary b) {
|
||||
return BalancedTernary(add_(this.digits, b.digits));
|
||||
}
|
||||
|
||||
BalancedTernary opBinary(string op:"-")(BalancedTernary b) {
|
||||
return this + (-b);
|
||||
}
|
||||
|
||||
static Dig[] mul_(in Dig[] a, /*in*/ Dig[] b) {
|
||||
if (a.empty || b.empty) {
|
||||
return [];
|
||||
} else {
|
||||
Dig[] y = Dig.Z ~ mul_(a[1 .. $], b);
|
||||
final switch (a[0]) {
|
||||
case Dig.N: return add_(neg_(b), y);
|
||||
case Dig.Z: return add_([], y);
|
||||
case Dig.P: return add_(b, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BalancedTernary opBinary(string op:"*")(BalancedTernary b) {
|
||||
return BalancedTernary(mul_(this.digits, b.digits));
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
auto a = BalancedTernary("+-0++0+");
|
||||
writeln("a: ", a.toBint, " ", a);
|
||||
|
||||
auto b = BalancedTernary(-436);
|
||||
writeln("b: ", b.toBint, " ", b);
|
||||
|
||||
auto c = BalancedTernary("+-++-");
|
||||
writeln("c: ", c.toBint, " ", c);
|
||||
|
||||
auto r = a * (b - c);
|
||||
writeln("a * (b - c): ", r.toBint, " ", r);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue