new files
This commit is contained in:
parent
3af7344581
commit
86c034bb8b
1364 changed files with 21352 additions and 0 deletions
16
Task/Balanced-ternary/0DESCRIPTION
Normal file
16
Task/Balanced-ternary/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
[[wp:Balanced ternary|Balanced ternary]] is a way of representing numbers. Unlike the prevailing binary representation, a balanced ternary integer is in base 3, and each digit can have the values 1, 0, or −1. For example, decimal 11 = 3<sup>2</sup> + 3<sup>1</sup> − 3<sup>0</sup>, thus can be written as "++−", while 6 = 3<sup>2</sup> − 3<sup>1</sup> + 0 × 3<sup>0</sup>, i.e., "+−0".
|
||||
|
||||
For this task, implement balanced ternary representation of integers with the following
|
||||
|
||||
'''Requirements'''
|
||||
# Support arbitrarily large integers, both positive and negative;
|
||||
# Provide ways to convert to and from text strings, using digits '+', '-' and '0' (unless you are already using strings to represent balanced ternary; but see requirement 5).
|
||||
# Provide ways to convert to and from native integer type (unless, improbably, your platform's native integer type ''is'' balanced ternary). If your native integers can't support arbitrary length, overflows during conversion must be indicated.
|
||||
# Provide ways to perform addition, negation and multiplication directly on balanced ternary integers; do ''not'' convert to native integers first.
|
||||
# Make your implementation efficient, with a reasonable definition of "effcient" (and with a reasonable definition of "reasonable").
|
||||
|
||||
'''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.
|
||||
|
||||
'''Note:''' The pages [[generalised floating point addition]] and [[generalised floating point multiplication]] have code implementing [[wp:arbitrary precision|arbitrary precision]] [[wp:floating point|floating point]] balanced ternary.
|
||||
47
Task/Balanced-ternary/Ada/balanced-ternary-1.ada
Normal file
47
Task/Balanced-ternary/Ada/balanced-ternary-1.ada
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
with Ada.Finalization;
|
||||
|
||||
package BT is
|
||||
|
||||
type Balanced_Ternary is private;
|
||||
|
||||
-- conversions
|
||||
function To_Balanced_Ternary (Num : Integer) return Balanced_Ternary;
|
||||
function To_Balanced_Ternary (Str : String) return Balanced_Ternary;
|
||||
function To_Integer (Num : Balanced_Ternary) return Integer;
|
||||
function To_string (Num : Balanced_Ternary) return String;
|
||||
|
||||
-- Arithmetics
|
||||
-- unary minus
|
||||
function "-" (Left : in Balanced_Ternary)
|
||||
return Balanced_Ternary;
|
||||
|
||||
-- subtraction
|
||||
function "-" (Left, Right : in Balanced_Ternary)
|
||||
return Balanced_Ternary;
|
||||
|
||||
-- addition
|
||||
function "+" (Left, Right : in Balanced_Ternary)
|
||||
return Balanced_Ternary;
|
||||
-- multiplication
|
||||
function "*" (Left, Right : in Balanced_Ternary)
|
||||
return Balanced_Ternary;
|
||||
|
||||
private
|
||||
-- a balanced ternary number is a unconstrained array of (1,0,-1)
|
||||
-- dinamically allocated, least significant trit leftmost
|
||||
type Trit is range -1..1;
|
||||
type Trit_Array is array (Positive range <>) of Trit;
|
||||
pragma Pack(Trit_Array);
|
||||
|
||||
type Trit_Access is access Trit_Array;
|
||||
|
||||
type Balanced_Ternary is new Ada.Finalization.Controlled
|
||||
with record
|
||||
Ref : Trit_access;
|
||||
end record;
|
||||
|
||||
procedure Initialize (Object : in out Balanced_Ternary);
|
||||
procedure Adjust (Object : in out Balanced_Ternary);
|
||||
procedure Finalize (Object : in out Balanced_Ternary);
|
||||
|
||||
end BT;
|
||||
181
Task/Balanced-ternary/Ada/balanced-ternary-2.ada
Normal file
181
Task/Balanced-ternary/Ada/balanced-ternary-2.ada
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
with Ada.Unchecked_Deallocation;
|
||||
|
||||
package body BT is
|
||||
|
||||
procedure Free is new Ada.Unchecked_Deallocation (Trit_Array, Trit_Access);
|
||||
|
||||
-- Conversions
|
||||
-- String to BT
|
||||
function To_Balanced_Ternary (Str: String) return Balanced_Ternary is
|
||||
J : Positive := 1;
|
||||
Tmp : Trit_Access;
|
||||
begin
|
||||
Tmp := new Trit_Array (1..Str'Last);
|
||||
for I in reverse Str'Range loop
|
||||
case Str(I) is
|
||||
when '+' => Tmp (J) := 1;
|
||||
when '-' => Tmp (J) := -1;
|
||||
when '0' => Tmp (J) := 0;
|
||||
when others => raise Constraint_Error;
|
||||
end case;
|
||||
J := J + 1;
|
||||
end loop;
|
||||
return (Ada.Finalization.Controlled with Ref => Tmp);
|
||||
end To_Balanced_Ternary;
|
||||
|
||||
-- Integer to BT
|
||||
function To_Balanced_Ternary (Num: Integer) return Balanced_Ternary is
|
||||
K : Integer := 0;
|
||||
D : Integer;
|
||||
Value : Integer := Num;
|
||||
Tmp : Trit_Array(1..19); -- 19 trits is enough to contain
|
||||
-- a 32 bits signed integer
|
||||
begin
|
||||
loop
|
||||
D := (Value mod 3**(K+1))/3**K;
|
||||
if D = 2 then D := -1; end if;
|
||||
Value := Value - D*3**K;
|
||||
K := K + 1;
|
||||
Tmp(K) := Trit(D);
|
||||
exit when Value = 0;
|
||||
end loop;
|
||||
return (Ada.Finalization.Controlled
|
||||
with Ref => new Trit_Array'(Tmp(1..K)));
|
||||
end To_Balanced_Ternary;
|
||||
|
||||
-- BT to Integer --
|
||||
-- If the BT number is too large Ada will raise CONSTRAINT ERROR
|
||||
function To_Integer (Num : Balanced_Ternary) return Integer is
|
||||
Value : Integer := 0;
|
||||
Pos : Integer := 1;
|
||||
begin
|
||||
for I in Num.Ref.all'Range loop
|
||||
Value := Value + Integer(Num.Ref(I)) * Pos;
|
||||
Pos := Pos * 3;
|
||||
end loop;
|
||||
return Value;
|
||||
end To_Integer;
|
||||
|
||||
-- BT to String --
|
||||
function To_String (Num : Balanced_Ternary) return String is
|
||||
I : constant Integer := Num.Ref.all'Last;
|
||||
Result : String (1..I);
|
||||
begin
|
||||
for J in Result'Range loop
|
||||
case Num.Ref(I-J+1) is
|
||||
when 0 => Result(J) := '0';
|
||||
when -1 => Result(J) := '-';
|
||||
when 1 => Result(J) := '+';
|
||||
end case;
|
||||
end loop;
|
||||
return Result;
|
||||
end To_String;
|
||||
|
||||
-- unary minus --
|
||||
function "-" (Left : in Balanced_Ternary)
|
||||
return Balanced_Ternary is
|
||||
Result : constant Balanced_Ternary := Left;
|
||||
begin
|
||||
for I in Result.Ref.all'Range loop
|
||||
Result.Ref(I) := - Result.Ref(I);
|
||||
end loop;
|
||||
return Result;
|
||||
end "-";
|
||||
|
||||
-- addition --
|
||||
Carry : Trit;
|
||||
|
||||
function Add (Left, Right : in Trit)
|
||||
return Trit is
|
||||
begin
|
||||
if Left /= Right then
|
||||
Carry := 0;
|
||||
return Left + Right;
|
||||
else
|
||||
Carry := Left;
|
||||
return -Right;
|
||||
end if;
|
||||
end Add;
|
||||
pragma Inline (Add);
|
||||
|
||||
function "+" (Left, Right : in Trit_Array)
|
||||
return Balanced_Ternary is
|
||||
Max_Size : constant Integer :=
|
||||
Integer'Max(Left'Last, Right'Last);
|
||||
Tmp_Left, Tmp_Right : Trit_Array(1..Max_Size) := (others => 0);
|
||||
Result : Trit_Array(1..Max_Size+1) := (others => 0);
|
||||
begin
|
||||
Tmp_Left (1..Left'Last) := Left;
|
||||
Tmp_Right(1..Right'Last) := Right;
|
||||
for I in Tmp_Left'Range loop
|
||||
Result(I) := Add (Result(I), Tmp_Left(I));
|
||||
Result(I+1) := Carry;
|
||||
Result(I) := Add(Result(I), Tmp_Right(I));
|
||||
Result(I+1) := Add(Result(I+1), Carry);
|
||||
end loop;
|
||||
-- remove trailing zeros
|
||||
for I in reverse Result'Range loop
|
||||
if Result(I) /= 0 then
|
||||
return (Ada.Finalization.Controlled
|
||||
with Ref => new Trit_Array'(Result(1..I)));
|
||||
end if;
|
||||
end loop;
|
||||
return (Ada.Finalization.Controlled
|
||||
with Ref => new Trit_Array'(1 => 0));
|
||||
end "+";
|
||||
|
||||
function "+" (Left, Right : in Balanced_Ternary)
|
||||
return Balanced_Ternary is
|
||||
begin
|
||||
return Left.Ref.all + Right.Ref.all;
|
||||
end "+";
|
||||
|
||||
-- Subtraction
|
||||
function "-" (Left, Right : in Balanced_Ternary)
|
||||
return Balanced_Ternary is
|
||||
begin
|
||||
return Left + (-Right);
|
||||
end "-";
|
||||
|
||||
-- multiplication
|
||||
function "*" (Left, Right : in Balanced_Ternary)
|
||||
return Balanced_Ternary is
|
||||
A, B : Trit_Access;
|
||||
Result : Balanced_Ternary;
|
||||
begin
|
||||
if Left.Ref.all'Length > Right.Ref.all'Length then
|
||||
A := Right.Ref; B := Left.Ref;
|
||||
else
|
||||
B := Right.Ref; A := Left.Ref;
|
||||
end if;
|
||||
for I in A.all'Range loop
|
||||
if A(I) /= 0 then
|
||||
declare
|
||||
Tmp_Result : Trit_Array (1..I+B.all'Length-1) := (others => 0);
|
||||
begin
|
||||
for J in B.all'Range loop
|
||||
Tmp_Result(I+J-1) := B(J) * A(I);
|
||||
end loop;
|
||||
Result := Result.Ref.all + Tmp_Result;
|
||||
end;
|
||||
end if;
|
||||
end loop;
|
||||
return Result;
|
||||
end "*";
|
||||
|
||||
procedure Adjust (Object : in out Balanced_Ternary) is
|
||||
begin
|
||||
Object.Ref := new Trit_Array'(Object.Ref.all);
|
||||
end Adjust;
|
||||
|
||||
procedure Finalize (Object : in out Balanced_Ternary) is
|
||||
begin
|
||||
Free (Object.Ref);
|
||||
end Finalize;
|
||||
|
||||
procedure Initialize (Object : in out Balanced_Ternary) is
|
||||
begin
|
||||
Object.Ref := new Trit_Array'(1 => 0);
|
||||
end Initialize;
|
||||
|
||||
end BT;
|
||||
19
Task/Balanced-ternary/Ada/balanced-ternary-3.ada
Normal file
19
Task/Balanced-ternary/Ada/balanced-ternary-3.ada
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
with Ada.Text_Io; use Ada.Text_Io;
|
||||
with Ada.Integer_Text_Io; use Ada.Integer_Text_Io;
|
||||
with BT; use BT;
|
||||
|
||||
procedure TestBT is
|
||||
Result, A, B, C : Balanced_Ternary;
|
||||
begin
|
||||
A := To_Balanced_Ternary("+-0++0+");
|
||||
B := To_Balanced_Ternary(-436);
|
||||
C := To_Balanced_Ternary("+-++-");
|
||||
|
||||
Result := A * (B - C);
|
||||
|
||||
Put("a = "); Put(To_integer(A), 4); New_Line;
|
||||
Put("b = "); Put(To_integer(B), 4); New_Line;
|
||||
Put("c = "); Put(To_integer(C), 4); New_Line;
|
||||
Put("a * (b - c) = "); Put(To_integer(Result), 4);
|
||||
Put_Line (" " & To_String(Result));
|
||||
end TestBT;
|
||||
89
Task/Balanced-ternary/Erlang/balanced-ternary-1.erl
Normal file
89
Task/Balanced-ternary/Erlang/balanced-ternary-1.erl
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
-module(ternary).
|
||||
-compile(export_all).
|
||||
|
||||
test() ->
|
||||
AS = "+-0++0+", AT = from_string(AS), A = from_ternary(AT),
|
||||
B = -436, BT = to_ternary(B), BS = to_string(BT),
|
||||
CS = "+-++-", CT = from_string(CS), C = from_ternary(CT),
|
||||
RT = mul(AT,sub(BT,CT)),
|
||||
R = from_ternary(RT),
|
||||
RS = to_string(RT),
|
||||
io:fwrite("A = ~s -> ~b~n",[AS, A]),
|
||||
io:fwrite("B = ~s -> ~b~n",[BS, B]),
|
||||
io:fwrite("C = ~s -> ~b~n",[CS, C]),
|
||||
io:fwrite("A x (B - C) = ~s -> ~b~n", [RS, R]).
|
||||
|
||||
to_string(T) -> [to_char(X) || X <- T].
|
||||
|
||||
from_string(S) -> [from_char(X) || X <- S].
|
||||
|
||||
to_char(-1) -> $-;
|
||||
to_char(0) -> $0;
|
||||
to_char(1) -> $+.
|
||||
|
||||
from_char($-) -> -1;
|
||||
from_char($0) -> 0;
|
||||
from_char($+) -> 1.
|
||||
|
||||
to_ternary(N) when N > 0 ->
|
||||
to_ternary(N,[]);
|
||||
to_ternary(N) ->
|
||||
neg(to_ternary(-N)).
|
||||
|
||||
to_ternary(0,Acc) ->
|
||||
Acc;
|
||||
to_ternary(N,Acc) when N rem 3 == 0 ->
|
||||
to_ternary(N div 3, [0|Acc]);
|
||||
to_ternary(N,Acc) when N rem 3 == 1 ->
|
||||
to_ternary(N div 3, [1|Acc]);
|
||||
to_ternary(N,Acc) ->
|
||||
to_ternary((N+1) div 3, [-1|Acc]).
|
||||
|
||||
from_ternary(T) -> from_ternary(T,0).
|
||||
|
||||
from_ternary([],Acc) ->
|
||||
Acc;
|
||||
from_ternary([H|T],Acc) ->
|
||||
from_ternary(T,Acc*3 + H).
|
||||
|
||||
mul(A,B) -> mul(B,A,[]).
|
||||
|
||||
mul(_,[],Acc) ->
|
||||
Acc;
|
||||
mul(B,[A|As],Acc) ->
|
||||
BP = case A of
|
||||
-1 -> neg(B);
|
||||
0 -> [0];
|
||||
1 -> B
|
||||
end,
|
||||
A1 = Acc++[0],
|
||||
A2=add(BP,A1),
|
||||
mul(B,As,A2).
|
||||
|
||||
|
||||
neg(T) -> [ -H || H <- T].
|
||||
|
||||
sub(A,B) -> add(A,neg(B)).
|
||||
|
||||
add(A,B) when length(A) < length(B) ->
|
||||
add(lists:duplicate(length(B)-length(A),0)++A,B);
|
||||
add(A,B) when length(A) > length(B) ->
|
||||
add(B,A);
|
||||
add(A,B) ->
|
||||
add(lists:reverse(A),lists:reverse(B),0,[]).
|
||||
|
||||
add([],[],0,Acc) ->
|
||||
Acc;
|
||||
add([],[],C,Acc) ->
|
||||
[C|Acc];
|
||||
add([A|As],[B|Bs],C,Acc) ->
|
||||
[C1,D] = add_util(A+B+C),
|
||||
add(As,Bs,C1,[D|Acc]).
|
||||
|
||||
add_util(-3) -> [-1,0];
|
||||
add_util(-2) -> [-1,1];
|
||||
add_util(-1) -> [0,-1];
|
||||
add_util(3) -> [1,0];
|
||||
add_util(2) -> [1,-1];
|
||||
add_util(1) -> [0,1];
|
||||
add_util(0) -> [0,0].
|
||||
6
Task/Balanced-ternary/Erlang/balanced-ternary-2.erl
Normal file
6
Task/Balanced-ternary/Erlang/balanced-ternary-2.erl
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
234> ternary:test().
|
||||
A = +-0++0+ -> 523
|
||||
B = -++-0-- -> -436
|
||||
C = +-++- -> 65
|
||||
A x (B - C) = 0----0+--0++0 -> -262023
|
||||
ok
|
||||
224
Task/Balanced-ternary/Go/balanced-ternary.go
Normal file
224
Task/Balanced-ternary/Go/balanced-ternary.go
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// R1: representation is a slice of int8 digits of -1, 0, or 1.
|
||||
// digit at index 0 is least significant. zero value of type is
|
||||
// representation of the number 0.
|
||||
type bt []int8
|
||||
|
||||
// R2: string conversion:
|
||||
|
||||
// btString is a constructor. valid input is a string of any length
|
||||
// consisting of only '+', '-', and '0' characters.
|
||||
// leading zeros are allowed but are trimmed and not represented.
|
||||
// false return means input was invalid.
|
||||
func btString(s string) (*bt, bool) {
|
||||
s = strings.TrimLeft(s, "0")
|
||||
b := make(bt, len(s))
|
||||
for i, last := 0, len(s)-1; i < len(s); i++ {
|
||||
switch s[i] {
|
||||
case '-':
|
||||
b[last-i] = -1
|
||||
case '0':
|
||||
b[last-i] = 0
|
||||
case '+':
|
||||
b[last-i] = 1
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
return &b, true
|
||||
}
|
||||
|
||||
// String method converts the other direction, returning a string of
|
||||
// '+', '-', and '0' characters representing the number.
|
||||
func (b bt) String() string {
|
||||
if len(b) == 0 {
|
||||
return "0"
|
||||
}
|
||||
last := len(b) - 1
|
||||
r := make([]byte, len(b))
|
||||
for i, d := range b {
|
||||
r[last-i] = "-0+"[d+1]
|
||||
}
|
||||
return string(r)
|
||||
}
|
||||
|
||||
// R3: integer conversion
|
||||
// int chosen as "native integer"
|
||||
|
||||
// btInt is a constructor like btString.
|
||||
func btInt(i int) *bt {
|
||||
if i == 0 {
|
||||
return new(bt)
|
||||
}
|
||||
var b bt
|
||||
var btDigit func(int)
|
||||
btDigit = func(digit int) {
|
||||
m := int8(i % 3)
|
||||
i /= 3
|
||||
switch m {
|
||||
case 2:
|
||||
m = -1
|
||||
i++
|
||||
case -2:
|
||||
m = 1
|
||||
i--
|
||||
}
|
||||
if i == 0 {
|
||||
b = make(bt, digit+1)
|
||||
} else {
|
||||
btDigit(digit + 1)
|
||||
}
|
||||
b[digit] = m
|
||||
}
|
||||
btDigit(0)
|
||||
return &b
|
||||
}
|
||||
|
||||
// Int method converts the other way, returning the value as an int type.
|
||||
// !ok means overflow occurred during conversion, not necessarily that the
|
||||
// value is not representable as an int. (Of course there are other ways
|
||||
// of doing it but this was chosen as "reasonable.")
|
||||
func (b bt) Int() (r int, ok bool) {
|
||||
pt := 1
|
||||
for _, d := range b {
|
||||
dp := int(d) * pt
|
||||
neg := r < 0
|
||||
r += dp
|
||||
if neg {
|
||||
if r > dp {
|
||||
return 0, false
|
||||
}
|
||||
} else {
|
||||
if r < dp {
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
pt *= 3
|
||||
}
|
||||
return r, true
|
||||
}
|
||||
|
||||
// R4: negation, addition, and multiplication
|
||||
|
||||
func (z *bt) Neg(b *bt) *bt {
|
||||
if z != b {
|
||||
if cap(*z) < len(*b) {
|
||||
*z = make(bt, len(*b))
|
||||
} else {
|
||||
*z = (*z)[:len(*b)]
|
||||
}
|
||||
}
|
||||
for i, d := range *b {
|
||||
(*z)[i] = -d
|
||||
}
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *bt) Add(a, b *bt) *bt {
|
||||
if len(*a) < len(*b) {
|
||||
a, b = b, a
|
||||
}
|
||||
r := *z
|
||||
r = r[:cap(r)]
|
||||
var carry int8
|
||||
for i, da := range *a {
|
||||
if i == len(r) {
|
||||
n := make(bt, len(*a)+4)
|
||||
copy(n, r)
|
||||
r = n
|
||||
}
|
||||
sum := da + carry
|
||||
if i < len(*b) {
|
||||
sum += (*b)[i]
|
||||
}
|
||||
carry = sum / 3
|
||||
sum %= 3
|
||||
switch {
|
||||
case sum > 1:
|
||||
sum -= 3
|
||||
carry++
|
||||
case sum < -1:
|
||||
sum += 3
|
||||
carry--
|
||||
}
|
||||
r[i] = sum
|
||||
}
|
||||
last := len(*a)
|
||||
if carry != 0 {
|
||||
if len(r) == last {
|
||||
n := make(bt, last+4)
|
||||
copy(n, r)
|
||||
r = n
|
||||
}
|
||||
r[last] = carry
|
||||
*z = r[:last+1]
|
||||
return z
|
||||
}
|
||||
for {
|
||||
if last == 0 {
|
||||
*z = nil
|
||||
break
|
||||
}
|
||||
last--
|
||||
if r[last] != 0 {
|
||||
*z = r[:last+1]
|
||||
break
|
||||
}
|
||||
}
|
||||
return z
|
||||
}
|
||||
|
||||
func (z *bt) Mul(a, b *bt) *bt {
|
||||
if len(*a) < len(*b) {
|
||||
a, b = b, a
|
||||
}
|
||||
var na bt
|
||||
for _, d := range *b {
|
||||
if d == -1 {
|
||||
na.Neg(a)
|
||||
break
|
||||
}
|
||||
}
|
||||
r := make(bt, len(*a)+len(*b))
|
||||
for i := len(*b) - 1; i >= 0; i-- {
|
||||
switch (*b)[i] {
|
||||
case 1:
|
||||
p := r[i:]
|
||||
p.Add(&p, a)
|
||||
case -1:
|
||||
p := r[i:]
|
||||
p.Add(&p, &na)
|
||||
}
|
||||
}
|
||||
i := len(r)
|
||||
for i > 0 && r[i-1] == 0 {
|
||||
i--
|
||||
}
|
||||
*z = r[:i]
|
||||
return z
|
||||
}
|
||||
|
||||
func main() {
|
||||
a, _ := btString("+-0++0+")
|
||||
b := btInt(-436)
|
||||
c, _ := btString("+-++-")
|
||||
show("a:", a)
|
||||
show("b:", b)
|
||||
show("c:", c)
|
||||
show("a(b-c):", a.Mul(a, b.Add(b, c.Neg(c))))
|
||||
}
|
||||
|
||||
func show(label string, b *bt) {
|
||||
fmt.Printf("%7s %12v ", label, b)
|
||||
if i, ok := b.Int(); ok {
|
||||
fmt.Printf("%7d\n", i)
|
||||
} else {
|
||||
fmt.Println("int overflow")
|
||||
}
|
||||
}
|
||||
62
Task/Balanced-ternary/Haskell/balanced-ternary.hs
Normal file
62
Task/Balanced-ternary/Haskell/balanced-ternary.hs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
data BalancedTernary = Bt [Int]
|
||||
|
||||
zeroTrim a = if null s then [0] else s where
|
||||
s = f [] [] a
|
||||
f x _ [] = x
|
||||
f x y (0:zs) = f x (y++[0]) zs
|
||||
f x y (z:zs) = f (x++y++[z]) [] zs
|
||||
|
||||
btList (Bt a) = a
|
||||
|
||||
instance Eq BalancedTernary where
|
||||
(==) a b = btList a == btList b
|
||||
|
||||
btNormalize = listBt . _carry 0 where
|
||||
_carry c [] = if c == 0 then [] else [c]
|
||||
_carry c (a:as) = r:_carry cc as where
|
||||
(cc, r) = f $ (a+c) `quotRem` 3 where
|
||||
f (x, 2) = (x + 1, -1)
|
||||
f (x, -2) = (x - 1, 1)
|
||||
f x = x
|
||||
|
||||
listBt = Bt . zeroTrim
|
||||
|
||||
instance Show BalancedTernary where
|
||||
show = reverse . map (\d->case d of -1->'-'; 0->'0'; 1->'+') . btList
|
||||
|
||||
strBt = Bt . zeroTrim.reverse.map (\c -> case c of '-' -> -1; '0' -> 0; '+' -> 1)
|
||||
|
||||
intBt :: Integral a => a -> BalancedTernary
|
||||
intBt = fromIntegral . toInteger
|
||||
|
||||
btInt = f . btList where
|
||||
f [] = 0
|
||||
f (a:as) = a + 3 * f as
|
||||
|
||||
listAdd a b = take (max (length a) (length b)) $ zipWith (+) (a++[0,0..]) (b++[0,0..])
|
||||
|
||||
-- mostly for operators, also small stuff to make GHC happy
|
||||
instance Num BalancedTernary where
|
||||
negate = Bt . map negate . btList
|
||||
(+) x y = btNormalize $ listAdd (btList x) (btList y)
|
||||
(*) x y = btNormalize $ mul_ (btList x) (btList y) where
|
||||
mul_ _ [] = []
|
||||
mul_ [] _ = []
|
||||
mul_ (a:as) b = listAdd (map (a*) b) (0:mul_ as b) where
|
||||
|
||||
-- we don't need to define binary "-" by hand
|
||||
|
||||
signum (Bt a) = if a == [0] then 0 else Bt [last a]
|
||||
abs x = if signum x == Bt [-1] then negate x else x
|
||||
|
||||
fromInteger = btNormalize . f where
|
||||
f 0 = []
|
||||
f x = fromInteger (rem x 3) : f (quot x 3)
|
||||
|
||||
|
||||
main = let (a,b,c) = (strBt "+-0++0+", intBt (-436), strBt "+-++-")
|
||||
r = a * (b - c)
|
||||
in do
|
||||
print $ map btInt [a,b,c]
|
||||
print $ r
|
||||
print $ btInt r
|
||||
67
Task/Balanced-ternary/Prolog/balanced-ternary-1.pro
Normal file
67
Task/Balanced-ternary/Prolog/balanced-ternary-1.pro
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
:- module('bt_convert.pl', [bt_convert/2,
|
||||
op(950, xfx, btconv),
|
||||
btconv/2]).
|
||||
|
||||
:- use_module(library(clpfd)).
|
||||
|
||||
:- op(950, xfx, btconv).
|
||||
|
||||
X btconv Y :-
|
||||
bt_convert(X, Y).
|
||||
|
||||
% bt_convert(?X, ?L)
|
||||
bt_convert(X, L) :-
|
||||
( (nonvar(L), \+is_list(L)) ->string_to_list(L, L1); L1 = L),
|
||||
convert(X, L1),
|
||||
( var(L) -> string_to_list(L, L1); true).
|
||||
|
||||
% map numbers toward digits +, - 0
|
||||
plus_moins( 1, 43).
|
||||
plus_moins(-1, 45).
|
||||
plus_moins( 0, 48).
|
||||
|
||||
|
||||
convert(X, [48| L]) :-
|
||||
var(X),
|
||||
( L \= [] -> convert(X, L); X = 0, !).
|
||||
|
||||
convert(0, L) :-
|
||||
var(L), !, string_to_list(L, [48]).
|
||||
|
||||
convert(X, L) :-
|
||||
( (nonvar(X), X > 0)
|
||||
; (var(X), X #> 0,
|
||||
L = [43|_],
|
||||
maplist(plus_moins, L1, L))),
|
||||
!,
|
||||
convert(X, 0, [], L1),
|
||||
( nonvar(X) -> maplist(plus_moins, L1, LL), string_to_list(L, LL)
|
||||
; true).
|
||||
|
||||
convert(X, L) :-
|
||||
( nonvar(X) -> Y is -X
|
||||
; X #< 0,
|
||||
maplist(plus_moins, L2, L),
|
||||
maplist(mult(-1), L2, L1)),
|
||||
convert(Y, 0, [], L1),
|
||||
( nonvar(X) ->
|
||||
maplist(mult(-1), L1, L2),
|
||||
maplist(plus_moins, L2, LL),
|
||||
string_to_list(L, LL)
|
||||
; X #= -Y).
|
||||
|
||||
mult(X, Y, Z) :-
|
||||
Z #= X * Y.
|
||||
|
||||
|
||||
convert(0, 0, L, L) :- !.
|
||||
|
||||
convert(0, 1, L, [1 | L]) :- !.
|
||||
|
||||
|
||||
convert(N, C, LC, LF) :-
|
||||
R #= N mod 3 + C,
|
||||
R #> 1 #<==> C1,
|
||||
N1 #= N / 3,
|
||||
R1 #= R - 3 * C1, % C1 #= 1,
|
||||
convert(N1, C1, [R1 | LC], LF).
|
||||
123
Task/Balanced-ternary/Prolog/balanced-ternary-2.pro
Normal file
123
Task/Balanced-ternary/Prolog/balanced-ternary-2.pro
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
:- module('bt_add.pl', [bt_add/3,
|
||||
bt_add1/3,
|
||||
op(900, xfx, btplus),
|
||||
op(900, xfx, btmoins),
|
||||
btplus/2,
|
||||
btmoins/2,
|
||||
strip_nombre/3
|
||||
]).
|
||||
|
||||
:- op(900, xfx, btplus).
|
||||
:- op(900, xfx, btmoins).
|
||||
|
||||
% define operator btplus
|
||||
A is X btplus Y :-
|
||||
bt_add(X, Y, A).
|
||||
|
||||
% define operator btmoins
|
||||
% no need to define a predicate for the substraction
|
||||
A is X btmoins Y :-
|
||||
X is Y btplus A.
|
||||
|
||||
|
||||
% bt_add(?X, ?Y, ?R)
|
||||
% R is X + Y
|
||||
% X, Y, R are strings
|
||||
% At least 2 args must be instantiated
|
||||
bt_add(X, Y, R) :-
|
||||
( nonvar(X) -> string_to_list(X, X1); true),
|
||||
( nonvar(Y) -> string_to_list(Y, Y1); true),
|
||||
( nonvar(R) -> string_to_list(R, R1); true),
|
||||
bt_add1(X1, Y1, R1),
|
||||
( var(X) -> string_to_list(X, X1); true),
|
||||
( var(Y) -> string_to_list(Y, Y1); true),
|
||||
( var(R) -> string_to_list(R, R1); true).
|
||||
|
||||
|
||||
|
||||
% bt_add1(?X, ?Y, ?R)
|
||||
% R is X + Y
|
||||
% X, Y, R are lists
|
||||
bt_add1(X, Y, R) :-
|
||||
% initialisation : X and Y must have the same length
|
||||
% we add zeros at the beginning of the shortest list
|
||||
( nonvar(X) -> length(X, LX); length(R, LR)),
|
||||
( nonvar(Y) -> length(Y, LY); length(R, LR)),
|
||||
( var(X) -> LX is max(LY, LR) , length(X1, LX), Y1 = Y ; X1 = X),
|
||||
( var(Y) -> LY is max(LX, LR) , length(Y1, LY), X1 = X ; Y1 = Y),
|
||||
|
||||
Delta is abs(LX - LY),
|
||||
( LX < LY -> normalise(Delta, X1, X2), Y1 = Y2
|
||||
; LY < LX -> normalise(Delta, Y1, Y2), X1 = X2
|
||||
; X1 = X2, Y1 = Y2),
|
||||
|
||||
|
||||
% if R is instancied, it must have, at least, the same length than X or Y
|
||||
Max is max(LX, LY),
|
||||
( (nonvar(R), length(R, LR), LR < Max) -> Delta1 is Max - LR, normalise(Delta1, R, R2)
|
||||
; nonvar(R) -> R = R2
|
||||
; true),
|
||||
|
||||
bt_add(X2, Y2, C, R2),
|
||||
|
||||
( C = 48 -> strip_nombre(R2, R, []),
|
||||
( var(X) -> strip_nombre(X2, X, []) ; true),
|
||||
( var(Y) -> strip_nombre(Y2, Y, []) ; true)
|
||||
; var(R) -> strip_nombre([C|R2], R, [])
|
||||
; ( select(C, [45,43], [Ca]),
|
||||
( var(X) -> strip_nombre([Ca | X2], X, [])
|
||||
; strip_nombre([Ca | Y2], Y, [])))).
|
||||
|
||||
|
||||
% here we actually compute the sum
|
||||
bt_add([], [], 48, []).
|
||||
|
||||
bt_add([H1|T1], [H2|T2], C3, [R2 | L]) :-
|
||||
bt_add(T1, T2, C, L),
|
||||
% add HH1 and H2
|
||||
ternary_sum(H1, H2, R1, C1),
|
||||
% add first carry,
|
||||
ternary_sum(R1, C, R2, C2),
|
||||
% add second carry
|
||||
ternary_sum(C1, C2, C3, _).
|
||||
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% ternary_sum
|
||||
% @arg1 : V1
|
||||
% @arg2 : V2
|
||||
% @arg3 : R is V1 + V2
|
||||
% @arg4 : Carry
|
||||
ternary_sum(43, 43, 45, 43).
|
||||
|
||||
ternary_sum(43, 45, 48, 48).
|
||||
|
||||
ternary_sum(45, 43, 48, 48).
|
||||
|
||||
ternary_sum(45, 45, 43, 45).
|
||||
|
||||
ternary_sum(X, 48, X, 48).
|
||||
|
||||
ternary_sum(48, X, X, 48).
|
||||
|
||||
|
||||
% if L has a length smaller than N, complete L with 0 (code 48)
|
||||
normalise(0, L, L) :- !.
|
||||
normalise(N, L1, L) :-
|
||||
N1 is N - 1,
|
||||
normalise(N1, [48 | L1], L).
|
||||
|
||||
|
||||
% contrary of normalise
|
||||
% remove leading zeros.
|
||||
% special case of number 0 !
|
||||
strip_nombre([48]) --> {!}, "0".
|
||||
|
||||
% enlève les zéros inutiles
|
||||
strip_nombre([48 | L]) -->
|
||||
strip_nombre(L).
|
||||
|
||||
|
||||
strip_nombre(L) -->
|
||||
L.
|
||||
170
Task/Balanced-ternary/Prolog/balanced-ternary-3.pro
Normal file
170
Task/Balanced-ternary/Prolog/balanced-ternary-3.pro
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
:- module('bt_mult.pl', [op(850, xfx, btmult),
|
||||
btmult/2,
|
||||
multiplication/3
|
||||
]).
|
||||
|
||||
:- use_module('bt_add.pl').
|
||||
|
||||
:- op(850, xfx, btmult).
|
||||
A is B btmult C :-
|
||||
multiplication(B, C, A).
|
||||
|
||||
neg(A, B) :-
|
||||
maplist(opp, A, B).
|
||||
|
||||
opp(48, 48).
|
||||
opp(45, 43).
|
||||
opp(43, 45).
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% the multiplication (efficient)
|
||||
% multiplication(+BIn, +QIn, -AOut)
|
||||
% Aout is BIn * QIn
|
||||
% BIn, QIn, AOut are strings
|
||||
multiplication(BIn, QIn, AOut) :-
|
||||
string_to_list(BIn, B),
|
||||
string_to_list(QIn, Q),
|
||||
|
||||
% We work with positive numbers
|
||||
( B = [45 | _] -> Pos0 = false, neg(B,BP) ; BP = B, Pos0 = true),
|
||||
( Q = [45 | _] -> neg(Q, QP), select(Pos0, [true, false], [Pos1]); QP = Q, Pos1 = Pos0),
|
||||
|
||||
multiplication_(BP, QP, [48], A),
|
||||
( Pos1 = false -> neg(A, A1); A1 = A),
|
||||
string_to_list(AOut, A1).
|
||||
|
||||
|
||||
multiplication_(_B, [], A, A).
|
||||
|
||||
multiplication_(B, [H | T], A, AF) :-
|
||||
multiplication_1(B, H, B1),
|
||||
append(A, [48], A1),
|
||||
bt_add1(B1, A1, A2),
|
||||
multiplication_(B, T, A2, AF).
|
||||
|
||||
% by 1 (digit '+' code 43)
|
||||
multiplication_1(B, 43, B).
|
||||
|
||||
% by 0 (digit '0' code 48)
|
||||
multiplication_1(_, 48, [48]).
|
||||
|
||||
% by -1 (digit '-' code 45)
|
||||
multiplication_1(B, 45, B1) :- neg(B, B1).
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% the division (efficient)
|
||||
% division(+AIn, +BIn, -QOut, -ROut)
|
||||
%
|
||||
division(AIn, BIn, QOut, ROut) :-
|
||||
string_to_list(AIn, A),
|
||||
string_to_list(BIn, B),
|
||||
length(B, LB),
|
||||
length(A, LA),
|
||||
Len is LA - LB,
|
||||
( Len < 0 -> Q = [48], R = A
|
||||
; neg(B, NegB), division_(A, B, NegB, LB, Len, [], Q, R)),
|
||||
string_to_list(QOut, Q),
|
||||
string_to_list(ROut, R).
|
||||
|
||||
|
||||
division_(A, B, NegB, LenB, LenA, QC, QF, R) :-
|
||||
% if the remainder R is negative (last number A), we must decrease the quotient Q, annd add B to R
|
||||
( LenA = -1 -> (A = [45 | _] -> positive(A, B, QC, QF, R) ; QF = QC, A = R)
|
||||
; extract(LenA, _, A, AR, AF),
|
||||
length(AR, LR),
|
||||
|
||||
( LR >= LenB -> ( AR = [43 | _] ->
|
||||
bt_add1(AR, NegB, S), Q0 = [43],
|
||||
% special case : R has the same length than B
|
||||
% and his first digit is + (1)
|
||||
% we must do another one substraction
|
||||
( (length(S, LenB), S = [43|_]) ->
|
||||
bt_add1(S, NegB, S1),
|
||||
bt_add1(QC, [43], QC1),
|
||||
Q00 = [45]
|
||||
; S1 = S, QC1 = QC, Q00 = Q0)
|
||||
|
||||
|
||||
; bt_add1(AR, B, S1), Q00 = [45], QC1 = QC),
|
||||
append(QC1, Q00, Q1),
|
||||
append(S1, AF, A1),
|
||||
strip_nombre(A1, A2, []),
|
||||
LenA1 is LenA - 1,
|
||||
division_(A2, B, NegB, LenB, LenA1, Q1, QF, R)
|
||||
|
||||
; append(QC, [48], Q1), LenA1 is LenA - 1,
|
||||
division_(A, B, NegB, LenB, LenA1, Q1, QF, R))).
|
||||
|
||||
% extract(+Len, ?N1, +L, -Head, -Tail)
|
||||
% remove last N digits from the list L
|
||||
% put them in Tail.
|
||||
extract(Len, Len, [], [], []).
|
||||
|
||||
extract(Len, N1, [H|T], AR1, AF1) :-
|
||||
extract(Len, N, T, AR, AF),
|
||||
N1 is N-1,
|
||||
( N > 0 -> AR = AR1, AF1 = [H | AF]; AR1 = [H | AR], AF1 = AF).
|
||||
|
||||
|
||||
|
||||
positive(R, _, Q, Q, R) :- R = [43 | _].
|
||||
|
||||
positive(S, B, Q, QF, R ) :-
|
||||
bt_add1(S, B, S1),
|
||||
bt_add1(Q, [45], Q1),
|
||||
positive(S1, B, Q1, QF, R).
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% "euclidian" division (inefficient)
|
||||
% euclide(?A, +BIn, ?Q, ?R)
|
||||
% A = B * Q + R
|
||||
euclide(A, B, Q, R) :-
|
||||
mult(A, B, Q, R).
|
||||
|
||||
|
||||
mult(AIn, BIn, QIn, RIn) :-
|
||||
( nonvar(AIn) -> string_to_list(AIn, A); A = AIn),
|
||||
( nonvar(BIn) -> string_to_list(BIn, B); B = BIn),
|
||||
( nonvar(QIn) -> string_to_list(QIn, Q); Q = QIn),
|
||||
( nonvar(RIn) -> string_to_list(RIn, R); R = RIn),
|
||||
|
||||
% we use positive numbers
|
||||
( B = [45 | _] -> Pos0 = false, neg(B,BP) ; BP = B, Pos0 = true),
|
||||
( (nonvar(Q), Q = [45 | _]) -> neg(Q, QP), select(Pos0, [true, false], [Pos1])
|
||||
; nonvar(Q) -> Q = QP , Pos1 = Pos0
|
||||
; Pos1 = Pos0),
|
||||
( (nonvar(A), A = [45 | _]) -> neg(A, AP)
|
||||
; nonvar(A) -> AP = A
|
||||
; true),
|
||||
|
||||
% is R instancied ?
|
||||
( nonvar(R) -> R1 = R; true),
|
||||
% multiplication ? we add B to A and substract 1 (digit '-') to Q
|
||||
( nonvar(Q) -> BC = BP, Ajout = [45],
|
||||
( nonvar(R) -> bt_add1(BC, R, AP) ; AP = BC)
|
||||
% division ? we substract B to A and add 1 (digit '+') to Q
|
||||
; neg(BP, BC), Ajout = [43], QP = [48]),
|
||||
|
||||
% do the real job
|
||||
mult_(BC, QP, AP, R1, Resultat, Ajout),
|
||||
|
||||
( var(QIn) -> (Pos1 = false -> neg(Resultat, QT); Resultat = QT), string_to_list(QIn, QT)
|
||||
; true),
|
||||
( var(AIn) -> (Pos1 = false -> neg(Resultat, AT); Resultat = AT), string_to_list(AIn, AT)
|
||||
; true),
|
||||
( var(RIn) -> string_to_list(RIn, R1); true).
|
||||
|
||||
% @arg1 : divisor
|
||||
% @arg2 : quotient
|
||||
% @arg3 : dividend
|
||||
% @arg4 : remainder
|
||||
% @arg5 : Result : receive either the dividend A
|
||||
% either the quotient Q
|
||||
mult_(B, Q, A, R, Resultat, Ajout) :-
|
||||
bt_add1(Q, Ajout, Q1),
|
||||
bt_add1(A, B, A1),
|
||||
( Q1 = [48] -> Resultat = A % a multiplication
|
||||
; ( A1 = [45 | _], Ajout = [43]) -> Resultat = Q, R = A % a division
|
||||
; mult_(B, Q1, A1, R, Resultat, Ajout)) .
|
||||
95
Task/Balanced-ternary/Python/balanced-ternary.py
Normal file
95
Task/Balanced-ternary/Python/balanced-ternary.py
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
class BalancedTernary:
|
||||
# Represented as a list of 0, 1 or -1s, with least significant digit first.
|
||||
|
||||
str2dig = {'+': 1, '-': -1, '0': 0} # immutable
|
||||
dig2str = {1: '+', -1: '-', 0: '0'} # immutable
|
||||
table = ((0, -1), (1, -1), (-1, 0), (0, 0), (1, 0), (-1, 1), (0, 1)) # immutable
|
||||
|
||||
def __init__(self, inp):
|
||||
if isinstance(inp, str):
|
||||
self.digits = [BalancedTernary.str2dig[c] for c in reversed(inp)]
|
||||
elif isinstance(inp, int):
|
||||
self.digits = self._int2ternary(inp)
|
||||
elif isinstance(inp, BalancedTernary):
|
||||
self.digits = list(inp.digits)
|
||||
elif isinstance(inp, list):
|
||||
if all(d in (0, 1, -1) for d in inp):
|
||||
self.digits = list(inp)
|
||||
else:
|
||||
raise ValueError("BalancedTernary: Wrong input digits.")
|
||||
else:
|
||||
raise TypeError("BalancedTernary: Wrong constructor input.")
|
||||
|
||||
@staticmethod
|
||||
def _int2ternary(n):
|
||||
if n == 0: return []
|
||||
if (n % 3) == 0: return [0] + BalancedTernary._int2ternary(n // 3)
|
||||
if (n % 3) == 1: return [1] + BalancedTernary._int2ternary(n // 3)
|
||||
if (n % 3) == 2: return [-1] + BalancedTernary._int2ternary((n + 1) // 3)
|
||||
|
||||
def to_int(self):
|
||||
return reduce(lambda y,x: x + 3 * y, reversed(self.digits), 0)
|
||||
|
||||
def __repr__(self):
|
||||
if not self.digits: return "0"
|
||||
return "".join(BalancedTernary.dig2str[d] for d in reversed(self.digits))
|
||||
|
||||
@staticmethod
|
||||
def _neg(digs):
|
||||
return [-d for d in digs]
|
||||
|
||||
def __neg__(self):
|
||||
return BalancedTernary(BalancedTernary._neg(self.digits))
|
||||
|
||||
@staticmethod
|
||||
def _add(a, b, c=0):
|
||||
if not (a and b):
|
||||
if c == 0:
|
||||
return a or b
|
||||
else:
|
||||
return BalancedTernary._add([c], a or b)
|
||||
else:
|
||||
(d, c) = BalancedTernary.table[3 + (a[0] if a else 0) + (b[0] if b else 0) + c]
|
||||
res = BalancedTernary._add(a[1:], b[1:], c)
|
||||
# trim leading zeros
|
||||
if res or d != 0:
|
||||
return [d] + res
|
||||
else:
|
||||
return res
|
||||
|
||||
def __add__(self, b):
|
||||
return BalancedTernary(BalancedTernary._add(self.digits, b.digits))
|
||||
|
||||
def __sub__(self, b):
|
||||
return self + (-b)
|
||||
|
||||
@staticmethod
|
||||
def _mul(a, b):
|
||||
if not (a and b):
|
||||
return []
|
||||
else:
|
||||
if a[0] == -1: x = BalancedTernary._neg(b)
|
||||
elif a[0] == 0: x = []
|
||||
elif a[0] == 1: x = b
|
||||
else: assert False
|
||||
y = [0] + BalancedTernary._mul(a[1:], b)
|
||||
return BalancedTernary._add(x, y)
|
||||
|
||||
def __mul__(self, b):
|
||||
return BalancedTernary(BalancedTernary._mul(self.digits, b.digits))
|
||||
|
||||
|
||||
def main():
|
||||
a = BalancedTernary("+-0++0+")
|
||||
print "a:", a.to_int(), a
|
||||
|
||||
b = BalancedTernary(-436)
|
||||
print "b:", b.to_int(), b
|
||||
|
||||
c = BalancedTernary("+-++-")
|
||||
print "c:", c.to_int(), c
|
||||
|
||||
r = a * (b - c)
|
||||
print "a * (b - c):", r.to_int(), r
|
||||
|
||||
main()
|
||||
55
Task/Balanced-ternary/REXX/balanced-ternary.rexx
Normal file
55
Task/Balanced-ternary/REXX/balanced-ternary.rexx
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*REXX pgm converts decimal ◄───► balanced ternary; also performs arith.*/
|
||||
numeric digits 10000 /*handle almost any size numbers.*/
|
||||
Ao = '+-0++0+' ; Abt = Ao /* [↓] 2 literals used by sub.*/
|
||||
Bo = '-436' ; Bbt = d2bt(Bo) ; @ = '(decimal)'
|
||||
Co = '+-++-' ; Cbt = Co ; @@ = 'balanced ternary ='
|
||||
call btShow '[a]', Abt
|
||||
call btShow '[b]', Bbt
|
||||
call btShow '[c]', Cbt
|
||||
say; $bt = btMul(Abt,btSub(Bbt,Cbt))
|
||||
call btshow '[a*(b-c)]', $bt
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*──────────────────────────────────BT2D subroutine─────────────────────*/
|
||||
d2bt: procedure; parse arg x 1; p=0; $.='-'; $.1='+'; $.0=0; #=
|
||||
x=x/1
|
||||
do until x==0; _=(x//(3**(p+1)))%3**p
|
||||
if _==2 then _=-1; if _=-2 then _=1
|
||||
x=x-_*(3**p); p=p+1; #=$._ || #
|
||||
end /*until*/
|
||||
return #
|
||||
/*──────────────────────────────────BT2D subroutine─────────────────────*/
|
||||
bt2d: procedure; parse arg x; r=reverse(x); #=0; $.=-1; $.0=0; _='+'; $._=1
|
||||
do j=1 for length(x); _=substr(r,j,1); #=#+$._*3**(j-1); end
|
||||
return #
|
||||
/*──────────────────────────────────BTADD subroutine────────────────────*/
|
||||
btAdd: procedure; parse arg x,y; rx=reverse(x); ry=reverse(y); carry=0
|
||||
$.='-'; $.0=0; $.1='+'; @.=0; _='-'; @._=-1; _="+"; @._=1; #=
|
||||
|
||||
do j=1 for max(length(x),length(y))
|
||||
x_=substr(rx,j,1); xn=@.x_
|
||||
y_=substr(ry,j,1); yn=@.y_
|
||||
s=xn+yn+carry ; carry=0
|
||||
if s== 2 then do; s=-1; carry= 1; end
|
||||
if s== 3 then do; s= 0; carry= 1; end
|
||||
if s==-2 then do; s= 1; carry=-1; end
|
||||
#=$.s || #
|
||||
end /*j*/
|
||||
if carry\==0 then #=$.carry || #; return btNorm(#)
|
||||
/*──────────────────────────────────BTMUL subroutine────────────────────*/
|
||||
btMul: procedure; parse arg x,y; if x==0 | y==0 then return 0; S=1
|
||||
x=btNorm(x); y=btNorm(y) /*handle: 0-xxx values.*/
|
||||
if left(x,1)=='-' then do; x=btNeg(x); S=-S; end /*positate.*/
|
||||
if left(y,1)=='-' then do; y=btNeg(y); S=-S; end /*positate.*/
|
||||
if length(y)>length(x) then parse value x y with y x /*optimize.*/
|
||||
P=0
|
||||
do until y==0 /*keep adding 'til done*/
|
||||
P=btAdd(P,x) /*multiple the hard way*/
|
||||
y=btSub(y,'+') /*subtract 1 from Y. */
|
||||
end /*until*/
|
||||
if S==-1 then P=btNeg(P) /*adjust product sign. */
|
||||
return P /*return the product P.*/
|
||||
/*───────────────────────────────one-line subroutines───────────────────*/
|
||||
btNeg: return translate(arg(1), '-+', "+-") /*negate the bal_tern #*/
|
||||
btNorm: _=strip(arg(1),'L',0); if _=='' then _=0; return _ /*normalize*/
|
||||
btSub: return btAdd(arg(1), btNeg(arg(2))) /*subtract two BT args.*/
|
||||
btShow: say center(arg(1),9) right(arg(2),20) @@ right(bt2d(arg(2)),9) @; return
|
||||
128
Task/Balanced-ternary/Ruby/balanced-ternary.rb
Normal file
128
Task/Balanced-ternary/Ruby/balanced-ternary.rb
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
class BalancedTernary
|
||||
def initialize(str = "")
|
||||
if str !~ /^[-+0]+$/
|
||||
raise ArgumentError, "invalid BalancedTernary number: #{str}"
|
||||
end
|
||||
@digits = trim0(str)
|
||||
end
|
||||
|
||||
def self.from_int(value)
|
||||
n = value
|
||||
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
|
||||
end
|
||||
new(digits)
|
||||
end
|
||||
|
||||
def to_int
|
||||
@digits.chars.inject(0) do |sum, char|
|
||||
sum *= 3
|
||||
case char
|
||||
when "+"
|
||||
sum += 1
|
||||
when "-"
|
||||
sum -= 1
|
||||
end
|
||||
sum
|
||||
end
|
||||
end
|
||||
alias :to_i :to_int
|
||||
|
||||
def to_s
|
||||
@digits
|
||||
end
|
||||
alias :inspect :to_s
|
||||
|
||||
ADDITION_TABLE = {
|
||||
"-" => {"-" => ["-","+"], "0" => ["0","-"], "+" => ["0","0"]},
|
||||
"0" => {"-" => ["0","-"], "0" => ["0","0"], "+" => ["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)
|
||||
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
|
||||
end
|
||||
self.class.new(carry + sum)
|
||||
end
|
||||
|
||||
MULTIPLICATION_TABLE = {
|
||||
"-" => "+0-",
|
||||
"0" => "000",
|
||||
"+" => "-0+",
|
||||
}
|
||||
|
||||
def *(other)
|
||||
product = self.class.new("0")
|
||||
other.to_s.each_char do |bdigit|
|
||||
row = to_s.tr("-0+", MULTIPLICATION_TABLE[bdigit])
|
||||
product += self.class.new(row)
|
||||
product << 1
|
||||
end
|
||||
product >> 1
|
||||
end
|
||||
|
||||
# negation
|
||||
def -@()
|
||||
self * BalancedTernary.new("-")
|
||||
end
|
||||
|
||||
# subtraction
|
||||
def -(other)
|
||||
self + (-other)
|
||||
end
|
||||
|
||||
# shift left
|
||||
def <<(count)
|
||||
@digits = trim0(@digits + "0"*count)
|
||||
self
|
||||
end
|
||||
|
||||
# shift right
|
||||
def >>(count)
|
||||
@digits[-count..-1] = "" if count > 0
|
||||
@digits = trim0(@digits)
|
||||
self
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def trim0(str)
|
||||
str = str.sub(/^0+/, "")
|
||||
str = "0" if str.empty?
|
||||
str
|
||||
end
|
||||
|
||||
def pad0(str, len)
|
||||
str.rjust(len, "0")
|
||||
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]
|
||||
57
Task/Balanced-ternary/Tcl/balanced-ternary-1.tcl
Normal file
57
Task/Balanced-ternary/Tcl/balanced-ternary-1.tcl
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
package require Tcl 8.5
|
||||
|
||||
proc bt-int b {
|
||||
set n 0
|
||||
foreach c [split $b ""] {
|
||||
set n [expr {$n * 3}]
|
||||
switch -- $c {
|
||||
+ { incr n 1 }
|
||||
- { incr n -1 }
|
||||
}
|
||||
}
|
||||
return $n
|
||||
}
|
||||
proc int-bt n {
|
||||
if {$n == 0} {
|
||||
return "0"
|
||||
}
|
||||
while {$n != 0} {
|
||||
lappend result [lindex {0 + -} [expr {$n % 3}]]
|
||||
set n [expr {$n / 3 + ($n%3 == 2)}]
|
||||
}
|
||||
return [join [lreverse $result] ""]
|
||||
}
|
||||
|
||||
proc bt-neg b {
|
||||
string map {+ - - +} $b
|
||||
}
|
||||
proc bt-sub {a b} {
|
||||
bt-add $a [bt-neg $b]
|
||||
}
|
||||
proc bt-add-digits {a b c} {
|
||||
if {$a eq ""} {set a 0}
|
||||
if {$b eq ""} {set b 0}
|
||||
if {$a ne 0} {append a 1}
|
||||
if {$b ne 0} {append b 1}
|
||||
lindex {{0 -1} {+ -1} {- 0} {0 0} {+ 0} {- 1} {0 1}} [expr {$a+$b+$c+3}]
|
||||
}
|
||||
proc bt-add {a b} {
|
||||
set c 0
|
||||
set result {}
|
||||
foreach ca [lreverse [split $a ""]] cb [lreverse [split $b ""]] {
|
||||
lassign [bt-add-digits $ca $cb $c] d c
|
||||
lappend result $d
|
||||
}
|
||||
if {$c ne "0"} {lappend result [lindex {0 + -} $c]}
|
||||
if {![llength $result]} {return "0"}
|
||||
string trimleft [join [lreverse $result] ""] 0
|
||||
}
|
||||
proc bt-mul {a b} {
|
||||
if {$a eq "0" || $a eq "" || $b eq "0"} {return "0"}
|
||||
set sub [bt-mul [string range $a 0 end-1] $b]0
|
||||
switch -- [string index $a end] {
|
||||
0 { return $sub }
|
||||
+ { return [bt-add $sub $b] }
|
||||
- { return [bt-sub $sub $b] }
|
||||
}
|
||||
}
|
||||
10
Task/Balanced-ternary/Tcl/balanced-ternary-2.tcl
Normal file
10
Task/Balanced-ternary/Tcl/balanced-ternary-2.tcl
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
for {set i 0} {$i<=10} {incr i} {puts "$i = [int-bt $i]"}
|
||||
puts "'+-+'+'+--' = [bt-add +-+ +--] = [bt-int [bt-add +-+ +--]]"
|
||||
puts "'++'*'++' = [bt-mul ++ ++] = [bt-int [bt-mul ++ ++]]"
|
||||
|
||||
set a "+-0++0+"
|
||||
set b [int-bt -436]
|
||||
set c "+-++-"
|
||||
puts "a = [bt-int $a], b = [bt-int $b], c = [bt-int $c]"
|
||||
set abc [bt-mul $a [bt-sub $b $c]]
|
||||
puts "a*(b-c) = $abc (== [bt-int $abc])"
|
||||
Loading…
Add table
Add a link
Reference in a new issue