This commit is contained in:
Ingy döt Net 2013-10-27 22:24:23 +00:00
parent 6f050a029e
commit 776bba907c
3887 changed files with 59894 additions and 7280 deletions

View file

@ -0,0 +1,211 @@
/*
* Test case
* With balanced ternaries a from string "+-0++0+", b from native integer -436, c "+-++-":
* Write out a, b and c in decimal notation;
* Calculate a × (b c), write out the result in both ternary and decimal notations.
*/
public class BalancedTernary
{
public static void main(String[] args)
{
BTernary a=new BTernary("+-0++0+");
BTernary b=new BTernary(-436);
BTernary c=new BTernary("+-++-");
System.out.println("a="+a.intValue());
System.out.println("b="+b.intValue());
System.out.println("c="+c.intValue());
System.out.println();
//result=a*(b-c)
BTernary result=a.mul(b.sub(c));
System.out.println("result= "+result+" "+result.intValue());
}
public static class BTernary
{
String value;
public BTernary(String s)
{
int i=0;
while(s.charAt(i)=='0')
i++;
this.value=s.substring(i);
}
public BTernary(int v)
{
this.value="";
this.value=convertToBT(v);
}
private String convertToBT(int v)
{
if(v<0)
return flip(convertToBT(-v));
if(v==0)
return "";
int rem=mod3(v);
if(rem==0)
return convertToBT(v/3)+"0";
if(rem==1)
return convertToBT(v/3)+"+";
if(rem==2)
return convertToBT((v+1)/3)+"-";
return "You can't see me";
}
private String flip(String s)
{
String flip="";
for(int i=0;i<s.length();i++)
{
if(s.charAt(i)=='+')
flip+='-';
else if(s.charAt(i)=='-')
flip+='+';
else
flip+='0';
}
return flip;
}
private int mod3(int v)
{
if(v>0)
return v%3;
v=v%3;
return (v+3)%3;
}
public int intValue()
{
int sum=0;
String s=this.value;
for(int i=0;i<s.length();i++)
{
char c=s.charAt(s.length()-i-1);
int dig=0;
if(c=='+')
dig=1;
else if(c=='-')
dig=-1;
sum+=dig*Math.pow(3, i);
}
return sum;
}
public BTernary add(BTernary that)
{
String a=this.value;
String b=that.value;
String longer=a.length()>b.length()?a:b;
String shorter=a.length()>b.length()?b:a;
while(shorter.length()<longer.length())
shorter=0+shorter;
a=longer;
b=shorter;
char carry='0';
String sum="";
for(int i=0;i<a.length();i++)
{
int place=a.length()-i-1;
String digisum=addDigits(a.charAt(place),b.charAt(place),carry);
if(digisum.length()!=1)
carry=digisum.charAt(0);
else
carry='0';
sum=digisum.charAt(digisum.length()-1)+sum;
}
sum=carry+sum;
return new BTernary(sum);
}
private String addDigits(char a,char b,char carry)
{
String sum1=addDigits(a,b);
String sum2=addDigits(sum1.charAt(sum1.length()-1),carry);
//System.out.println(carry+" "+sum1+" "+sum2);
if(sum1.length()==1)
return sum2;
if(sum2.length()==1)
return sum1.charAt(0)+sum2;
return sum1.charAt(0)+"";
}
private String addDigits(char a,char b)
{
String sum="";
if(a=='0')
sum=b+"";
else if (b=='0')
sum=a+"";
else if(a=='+')
{
if(b=='+')
sum="+-";
else
sum="0";
}
else
{
if(b=='+')
sum="0";
else
sum="-+";
}
return sum;
}
public BTernary neg()
{
return new BTernary(flip(this.value));
}
public BTernary sub(BTernary that)
{
return this.add(that.neg());
}
public BTernary mul(BTernary that)
{
BTernary one=new BTernary(1);
BTernary zero=new BTernary(0);
BTernary mul=new BTernary(0);
int flipflag=0;
if(that.compareTo(zero)==-1)
{
that=that.neg();
flipflag=1;
}
for(BTernary i=new BTernary(1);i.compareTo(that)<1;i=i.add(one))
mul=mul.add(this);
if(flipflag==1)
mul=mul.neg();
return mul;
}
public boolean equals(BTernary that)
{
return this.value.equals(that.value);
}
public int compareTo(BTernary that)
{
if(this.intValue()>that.intValue())
return 1;
else if(this.equals(that))
return 0;
return -1;
}
public String toString()
{
return value;
}
}
}

View file

@ -0,0 +1,75 @@
#lang racket
;; Represent a balanced-ternary number as a list of 0's, 1's and -1's.
;;
;; e.g. 11 = 3^2 + 3^1 - 3^0 ~ "++-" ~ '(-1 1 1)
;; 6 = 3^2 - 3^1 ~ "+-0" ~ '(0 -1 1)
;;
;; Note: the list-rep starts with the least signifcant tert, while
;; the string-rep starts with the most significsnt tert.
(define (bt->integer t)
(if (null? t)
0
(+ (first t) (* 3 (bt->integer (rest t))))))
(define (integer->bt n)
(letrec ([recur (λ (b r) (cons b (convert (floor (/ r 3)))))]
[convert (λ (n) (if (zero? n) null
(case (modulo n 3)
[(0) (recur 0 n)]
[(1) (recur 1 n)]
[(2) (recur -1 (add1 n))])))])
(convert n)))
(define (bt->string t)
(define (strip-leading-zeroes a)
(if (or (null? a) (not (= (first a) 0))) a (strip-leading-zeroes (rest a))))
(string-join (map (λ (u)
(case u
[(1) "+"]
[(-1) "-"]
[(0) "0"]))
(strip-leading-zeroes (reverse t))) ""))
(define (string->bt s)
(reverse
(map (λ (c)
(case c
[(#\+) 1]
[(#\-) -1]
[(#\0) 0]))
(string->list s))))
(define (bt-negate t)
(map (λ (u) (- u)) t))
(define (bt-add a b [c 0])
(cond [(and (null? a) (null? b)) (if (zero? c) null (list c))]
[(null? b) (if (zero? c) a (bt-add a (list c)))]
[(null? a) (bt-add b a c)]
[else (let* ([t (+ (first a) (first b) c)]
[carry (if (> (abs t) 1) (sgn t) 0)]
[v (case (abs t)
[(3) 0]
[(2) (- (sgn t))]
[else t])])
(cons v (bt-add (rest a) (rest b) carry)))]))
(define (bt-multiply a b)
(cond [(null? a) null]
[(null? b) null]
[else (bt-add (case (first a)
[(-1) (bt-negate b)]
[(0) null]
[(1) b])
(cons 0 (bt-multiply (rest a) b)))]))
; test case
(let* ([a (string->bt "+-0++0+")]
[b (integer->bt -436)]
[c (string->bt "+-++-")]
[d (bt-multiply a (bt-add b (bt-negate c)))])
(for ([bt (list a b c d)]
[description (list 'a 'b 'c "a×(bc)")])
(printf "~a = ~a or ~a\n" description (bt->integer bt) (bt->string bt))))

View file

@ -1,67 +1,62 @@
class BalancedTernary
include Comparable
def initialize(str = "")
if str !~ /^[-+0]+$/
if str =~ /[^-+0]+/
raise ArgumentError, "invalid BalancedTernary number: #{str}"
end
@digits = trim0(str)
end
I2BT = {0 => ["0",0], 1 => ["+",0], 2 => ["-",1]}
def self.from_int(value)
n = value
n = value.to_i
digits = ""
while n != 0
quo, rem = n.divmod(3)
case rem
when 0
digits = "0" + digits
n = quo
when 1
digits = "+" + digits
n = quo
when 2
digits = "-" + digits
n = quo + 1
end
bt, carry = I2BT[rem]
digits = bt + digits
n = quo + carry
end
new(digits)
end
BT2I = {"-" => -1, "0" => 0, "+" => 1}
def to_int
@digits.chars.inject(0) do |sum, char|
sum *= 3
case char
when "+"
sum += 1
when "-"
sum -= 1
end
sum
sum = 3 * sum + BT2I[char]
end
end
alias :to_i :to_int
def to_s
@digits
@digits.dup # String is mutable
end
alias :inspect :to_s
def <=>(other)
to_i <=> other.to_i
end
ADDITION_TABLE = {
"-" => {"-" => ["-","+"], "0" => ["0","-"], "+" => ["0","0"]},
"0" => {"-" => ["0","-"], "0" => ["0","0"], "+" => ["0","+"]},
"+" => {"-" => ["0","0"], "0" => ["0","+"], "+" => ["+","-"]},
"---" => ["-","0"], "--0" => ["-","+"], "--+" => ["0","-"],
"-0-" => ["-","+"], "-00" => ["0","-"], "-0+" => ["0","0"],
"-+-" => ["0","-"], "-+0" => ["0","0"], "-++" => ["0","+"],
"0--" => ["-","+"], "0-0" => ["0","-"], "0-+" => ["0","0"],
"00-" => ["0","-"], "000" => ["0","0"], "00+" => ["0","+"],
"0+-" => ["0","0"], "0+0" => ["0","+"], "0++" => ["+","-"],
"+--" => ["0","-"], "+-0" => ["0","0"], "+-+" => ["0","+"],
"+0-" => ["0","0"], "+00" => ["0","+"], "+0+" => ["+","-"],
"++-" => ["0","+"], "++0" => ["+","-"], "+++" => ["+","0"],
}
def +(other)
maxl = [to_s, other.to_s].collect {|s| s.length}.max
a = pad0(to_s, maxl)
b = pad0(other.to_s, maxl)
maxl = [to_s.length, other.to_s.length].max
a = pad0_reverse(to_s, maxl)
b = pad0_reverse(other.to_s, maxl)
carry = "0"
sum = a.reverse.chars.zip( b.reverse.chars ).inject("") do |sum, (c1, c2)|
carry1, digit1 = ADDITION_TABLE[c1][c2]
carry2, digit2 = ADDITION_TABLE[carry][digit1]
sum = digit2 + sum
carry = ADDITION_TABLE[carry1][carry2][1]
sum
sum = a.zip( b ).inject("") do |sum, (c1, c2)|
carry, digit = ADDITION_TABLE[carry + c1 + c2]
sum = digit + sum
end
self.class.new(carry + sum)
end
@ -73,7 +68,7 @@ class BalancedTernary
}
def *(other)
product = self.class.new("0")
product = self.class.new
other.to_s.each_char do |bdigit|
row = to_s.tr("-0+", MULTIPLICATION_TABLE[bdigit])
product += self.class.new(row)
@ -84,7 +79,7 @@ class BalancedTernary
# negation
def -@()
self * BalancedTernary.new("-")
self.class.new(@digits.tr('-+','+-'))
end
# subtraction
@ -113,16 +108,16 @@ class BalancedTernary
str
end
def pad0(str, len)
str.rjust(len, "0")
def pad0_reverse(str, len)
str.rjust(len, "0").reverse.chars
end
end
a = BalancedTernary.new("+-0++0+")
b = BalancedTernary.from_int(-436)
c = BalancedTernary.new("+-++-")
calc = a * (b - c)
puts "%s\t%d\t%s\n" % ['a', a.to_i, a]
puts "%s\t%d\t%s\n" % ['b', b.to_i, b]
puts "%s\t%d\t%s\n" % ['c', c.to_i, c]
puts "%s\t%d\t%s\n" % ['a*(b-c)', calc.to_i, calc]
%w[a b c a*(b-c)].each do |exp|
val = eval(exp)
puts "%8s :%13s,%8d" % [exp, val, val.to_i]
end