Data update
This commit is contained in:
parent
4bb20c9b71
commit
cbaf4c4b64
12390 changed files with 318560 additions and 27248 deletions
47
Task/Balanced-ternary/Ada/balanced-ternary-1.adb
Normal file
47
Task/Balanced-ternary/Ada/balanced-ternary-1.adb
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.adb
Normal file
181
Task/Balanced-ternary/Ada/balanced-ternary-2.adb
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.adb
Normal file
19
Task/Balanced-ternary/Ada/balanced-ternary-3.adb
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;
|
||||
79
Task/Balanced-ternary/Quackery/balanced-ternary.quackery
Normal file
79
Task/Balanced-ternary/Quackery/balanced-ternary.quackery
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
[ -1 1 clamp 1+ ]'[ swap peek do ] is sif ( n --> )
|
||||
|
||||
[ $ "" swap witheach
|
||||
[ sif [ char - char 0 char + ]
|
||||
swap join ] ] is t->$ ( t --> )
|
||||
|
||||
[ [] swap witheach
|
||||
[ char - - sif [ 1 -1 0 ]
|
||||
swap join ] ] is $->t ( $ --> t )
|
||||
|
||||
[ 0 swap reverse witheach [ swap 3 * + ] ] is t->n ( $ --> t )
|
||||
|
||||
[ [] swap
|
||||
[ 3 /mod [ table 0 1 [ 1+ -1 ] ] do
|
||||
swap dip join dup 0 = until ]
|
||||
drop ] is n->t ( n --> t )
|
||||
|
||||
[ -1 peek ] is tsign ( t --> n )
|
||||
|
||||
[ ' [ 0 ] = ] is tzero ( t --> b )
|
||||
|
||||
[ tsign -1 = ] is tneg ( t --> b )
|
||||
|
||||
[ tsign 1 = ] is tpos ( t --> b )
|
||||
|
||||
[ [] swap witheach [ negate join ] ] is -t ( t --> t )
|
||||
|
||||
[ 0 over size times
|
||||
[ 1 - 2dup peek if conclude ]
|
||||
1+ dup if split drop ] is tnorm ( t --> t )
|
||||
|
||||
[ [] 0 2swap
|
||||
over size over size - dup 0 <
|
||||
if [ dip swap negate ]
|
||||
0 swap of join temp put
|
||||
witheach
|
||||
[ temp share i^ peek
|
||||
+ + 3 +
|
||||
[ table
|
||||
[ 0 -1 ] [ 1 -1 ] [ -1 0 ]
|
||||
[ 0 0 ] [ 1 0 ] [ -1 1 ]
|
||||
[ 0 1 ] ] do
|
||||
dip join ]
|
||||
join tnorm
|
||||
temp release ] is t+ ( t t --> t )
|
||||
|
||||
[ -t t+ ] is t- ( t t --> t )
|
||||
|
||||
[ t- tneg ] is t< ( t t --> b )
|
||||
|
||||
[ t- tpos ] is t> ( t t --> b )
|
||||
|
||||
[ behead swap witheach
|
||||
[ 2dup t> if swap
|
||||
drop ] ] is tmin ( [ --> t )
|
||||
|
||||
[ behead swap witheach
|
||||
[ 2dup t< if swap
|
||||
drop ] ] is tmax ( [ --> t )
|
||||
|
||||
[ dup t+ ] is twice ( t --> t )
|
||||
|
||||
[ 0 swap join ] is thrice ( t --> t )
|
||||
|
||||
[ ' [ 0 ] swap witheach
|
||||
[ dip over
|
||||
sif [ t- drop t+ ]
|
||||
dip thrice ]
|
||||
nip ] is t* ( t t --> t )
|
||||
|
||||
say "a: " $ "+-0++0+" dup echo$ say " = " $->t t->n echo cr
|
||||
say "b: " -436 dup echo say " = " n->t t->$ echo$ cr
|
||||
say "c: " $ "+-++-" dup echo$ say " = " $->t t->n echo cr
|
||||
say "a*(b-c): = "
|
||||
$ "+-0++0+" $->t
|
||||
-436 n->t
|
||||
$ "+-++-" $->t
|
||||
t- t*
|
||||
dup t->$ echo$ say " = " t->n echo cr
|
||||
138
Task/Balanced-ternary/R/balanced-ternary.r
Normal file
138
Task/Balanced-ternary/R/balanced-ternary.r
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
## BalancedTernary in R (S3)
|
||||
|
||||
## Constructor helpers ----
|
||||
new_BalancedTernary <- function(digits) {
|
||||
# digits are least-significant first, values in {-1,0,1}
|
||||
structure(list(digits = as.integer(digits)), class = "BalancedTernary")
|
||||
}
|
||||
|
||||
BalancedTernary <- function(x = 0L) {
|
||||
if (inherits(x, "BalancedTernary")) return(x)
|
||||
if (is.character(x)) return(BalancedTernary_from_string(x))
|
||||
if (length(x) != 1 || !is.finite(x)) stop("BalancedTernary: need a single finite number or a string.")
|
||||
BalancedTernary_from_int(as.integer(x))
|
||||
}
|
||||
|
||||
BalancedTernary_zero <- function() new_BalancedTernary(0L)
|
||||
|
||||
## Conversions ----
|
||||
BalancedTernary_from_int <- function(n) {
|
||||
n <- as.integer(n)
|
||||
if (n == 0L) return(new_BalancedTernary(0L))
|
||||
digs <- integer(0)
|
||||
while (n != 0L) {
|
||||
r <- n %% 3L
|
||||
if (r == 0L) {
|
||||
digs <- c(digs, 0L); n <- n %/% 3L
|
||||
} else if (r == 1L) {
|
||||
digs <- c(digs, 1L); n <- n %/% 3L
|
||||
} else { # r == 2 -> digit -1 and carry +1 (i.e., add 1 then divide)
|
||||
digs <- c(digs, -1L); n <- (n + 1L) %/% 3L
|
||||
}
|
||||
}
|
||||
new_BalancedTernary(digs)
|
||||
}
|
||||
|
||||
BalancedTernary_from_string <- function(s) {
|
||||
# string is most-significant first with '-', '0', '+'
|
||||
map <- c("-" = -1L, "0" = 0L, "+" = 1L)
|
||||
chs <- strsplit(s, "", fixed = TRUE)[[1]]
|
||||
if (!all(chs %in% names(map))) stop("String may only contain '-', '0', '+'.")
|
||||
# reverse to least-significant first
|
||||
new_BalancedTernary(unname(map[rev(chs)]))
|
||||
}
|
||||
|
||||
bt <- function(s) BalancedTernary_from_string(s) # macro-ish convenience
|
||||
|
||||
## Printing & coercion ----
|
||||
print.BalancedTernary <- function(x, ...) {
|
||||
cat(as.character(x), "\n", sep = "")
|
||||
invisible(x)
|
||||
}
|
||||
|
||||
as.character.BalancedTernary <- function(x, ...) {
|
||||
map <- c(`-1` = "-", `0` = "0", `1` = "+")
|
||||
# display most-significant first
|
||||
paste0(rev(map[as.character(x$digits)]), collapse = "")
|
||||
}
|
||||
|
||||
as.integer.BalancedTernary <- function(x, ...) {
|
||||
s <- x$digits
|
||||
if (length(s) == 1L && s[1] == 0L) return(0L)
|
||||
ex <- seq_along(s) - 1L
|
||||
# use double accumulate then coerce to integer (safe for moderate sizes)
|
||||
val <- sum((3 ^ ex) * s)
|
||||
as.integer(val)
|
||||
}
|
||||
|
||||
## Unary minus ----
|
||||
`-.BalancedTernary` <- function(e1) new_BalancedTernary(-e1$digits)
|
||||
|
||||
## Core arithmetic helpers ----
|
||||
# Addition table for (a1 + b1 + c) -> (digit, carry),
|
||||
# indexed by 4 + a1 + b1 + c where a1,b1,c in {-1,0,1} gives 1..7
|
||||
.bt_table_digit <- c( 0, 1, -1, 0, 1, -1, 0) # d
|
||||
.bt_table_carry <- c(-1, -1, 0, 0, 0, 1, 1) # c
|
||||
|
||||
.bt_add <- function(a, b, c = 0L) {
|
||||
# a,b are integer vectors of digits (LSB first) in {-1,0,1}
|
||||
if (length(a) == 0L || length(b) == 0L) {
|
||||
if (c == 0L) return(if (length(a) == 0L) b else a)
|
||||
return(.bt_add(c(c), if (length(a) == 0L) b else a))
|
||||
} else {
|
||||
a1 <- a[1]; b1 <- b[1]
|
||||
idx <- 4L + a1 + b1 + c
|
||||
d <- .bt_table_digit[idx]
|
||||
c2 <- .bt_table_carry[idx]
|
||||
r <- .bt_add(a[-1], b[-1], c2)
|
||||
if (length(r) != 0L || d != 0L) {
|
||||
return(c(d, r)) # unshift
|
||||
} else {
|
||||
return(r)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bt_mul <- function(a, b) {
|
||||
# schoolbook recursion with balanced digits
|
||||
if (length(a) == 0L || length(b) == 0L) return(integer(0))
|
||||
a1 <- a[1]
|
||||
if (a1 == -1L) x <- (-BalancedTernary(new_BalancedTernary(b)))$digits
|
||||
else if (a1 == 0L) x <- integer(0)
|
||||
else if (a1 == 1L) x <- b
|
||||
# shift (multiply by 3) = prepend a 0 digit to recursive product
|
||||
y <- c(0L, .bt_mul(a[-1], b))
|
||||
.bt_add(x, y)
|
||||
}
|
||||
|
||||
.normalize_zero <- function(v) if (length(v) == 0L) 0L else v
|
||||
|
||||
## Binary operators ----
|
||||
`+.BalancedTernary` <- function(e1, e2) {
|
||||
v <- .bt_add(e1$digits, e2$digits)
|
||||
new_BalancedTernary(.normalize_zero(v))
|
||||
}
|
||||
|
||||
`-.BalancedTernary` # already defined (unary)
|
||||
|
||||
`%minus_bt%` <- function(a, b) a + (-b) # internal helper if needed
|
||||
|
||||
`*.BalancedTernary` <- function(e1, e2) {
|
||||
v <- .bt_mul(e1$digits, e2$digits)
|
||||
new_BalancedTernary(.normalize_zero(v))
|
||||
}
|
||||
|
||||
## Demo / tests ----
|
||||
a <- bt("+-0++0+")
|
||||
cat("a: ", as.integer(a), ", ", as.character(a), "\n", sep = "")
|
||||
|
||||
b <- BalancedTernary(-436L)
|
||||
cat("b: ", as.integer(b), ", ", as.character(b), "\n", sep = "")
|
||||
|
||||
c <- BalancedTernary("+-++-")
|
||||
cat("c: ", as.integer(c), ", ", as.character(c), "\n", sep = "")
|
||||
|
||||
r <- a * (b + (-c)) # a * (b - c)
|
||||
cat("a * (b - c): ", as.integer(r), ", ", as.character(r), "\n", sep = "")
|
||||
|
||||
stopifnot(as.integer(r) == as.integer(a) * (as.integer(b) - as.integer(c)))
|
||||
297
Task/Balanced-ternary/Zig/balanced-ternary.zig
Normal file
297
Task/Balanced-ternary/Zig/balanced-ternary.zig
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
const std = @import("std");
|
||||
const ArrayList = std.ArrayList;
|
||||
const Allocator = std.mem.Allocator;
|
||||
|
||||
pub fn main() !void {
|
||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||
defer _ = gpa.deinit();
|
||||
const allocator = gpa.allocator();
|
||||
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
|
||||
var a = try BalancedTernary.fromString(allocator, "+-0++0+");
|
||||
defer a.deinit();
|
||||
const a_val = try a.toI128();
|
||||
const a_str = try a.toString(allocator);
|
||||
defer allocator.free(a_str);
|
||||
try stdout.print("a = {s} = {d}\n", .{ a_str, a_val });
|
||||
|
||||
var b = try BalancedTernary.fromI128(allocator, -436);
|
||||
defer b.deinit();
|
||||
const b_val = try b.toI128();
|
||||
const b_str = try b.toString(allocator);
|
||||
defer allocator.free(b_str);
|
||||
try stdout.print("b = {s} = {d}\n", .{ b_str, b_val });
|
||||
|
||||
var c = try BalancedTernary.fromString(allocator, "+-++-");
|
||||
defer c.deinit();
|
||||
const c_val = try c.toI128();
|
||||
const c_str = try c.toString(allocator);
|
||||
defer allocator.free(c_str);
|
||||
try stdout.print("c = {s} = {d}\n", .{ c_str, c_val });
|
||||
|
||||
var c_neg = try c.clone(allocator);
|
||||
defer c_neg.deinit();
|
||||
c_neg.negate();
|
||||
|
||||
var b_plus_neg_c = try b.add(allocator, c_neg);
|
||||
defer b_plus_neg_c.deinit();
|
||||
|
||||
var d = try a.mul(allocator, b_plus_neg_c);
|
||||
defer d.deinit();
|
||||
const d_val = try d.toI128();
|
||||
const d_str = try d.toString(allocator);
|
||||
defer allocator.free(d_str);
|
||||
try stdout.print("a * (b - c) = {s} = {d}\n", .{ d_str, d_val });
|
||||
|
||||
var e = try BalancedTernary.fromString(allocator, "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
|
||||
defer e.deinit();
|
||||
const e_result = e.toI128();
|
||||
try std.testing.expect(e_result == error.Overflow);
|
||||
}
|
||||
|
||||
const Trit = enum {
|
||||
Zero,
|
||||
Pos,
|
||||
Neg,
|
||||
|
||||
fn fromChar(c: u8) !Trit {
|
||||
return switch (c) {
|
||||
'0' => .Zero,
|
||||
'+' => .Pos,
|
||||
'-' => .Neg,
|
||||
else => error.InvalidCharacter,
|
||||
};
|
||||
}
|
||||
|
||||
fn toChar(self: Trit) u8 {
|
||||
return switch (self) {
|
||||
.Zero => '0',
|
||||
.Pos => '+',
|
||||
.Neg => '-',
|
||||
};
|
||||
}
|
||||
|
||||
fn add(self: Trit, rhs: Trit) struct { carry: Trit, current: Trit } {
|
||||
return switch (self) {
|
||||
.Zero => .{ .carry = .Zero, .current = rhs },
|
||||
.Pos => switch (rhs) {
|
||||
.Zero => .{ .carry = .Zero, .current = .Pos },
|
||||
.Neg => .{ .carry = .Zero, .current = .Zero },
|
||||
.Pos => .{ .carry = .Pos, .current = .Neg },
|
||||
},
|
||||
.Neg => switch (rhs) {
|
||||
.Zero => .{ .carry = .Zero, .current = .Neg },
|
||||
.Pos => .{ .carry = .Zero, .current = .Zero },
|
||||
.Neg => .{ .carry = .Neg, .current = .Pos },
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn mul(self: Trit, rhs: Trit) Trit {
|
||||
return switch (self) {
|
||||
.Zero => .Zero,
|
||||
.Pos => switch (rhs) {
|
||||
.Zero => .Zero,
|
||||
.Pos => .Pos,
|
||||
.Neg => .Neg,
|
||||
},
|
||||
.Neg => switch (rhs) {
|
||||
.Zero => .Zero,
|
||||
.Pos => .Neg,
|
||||
.Neg => .Pos,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
fn negate(self: Trit) Trit {
|
||||
return switch (self) {
|
||||
.Zero => .Zero,
|
||||
.Pos => .Neg,
|
||||
.Neg => .Pos,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const BalancedTernary = struct {
|
||||
digits: ArrayList(Trit),
|
||||
|
||||
fn deinit(self: *BalancedTernary) void {
|
||||
self.digits.deinit();
|
||||
}
|
||||
|
||||
fn clone(self: BalancedTernary, allocator: Allocator) !BalancedTernary {
|
||||
var new_digits = try ArrayList(Trit).initCapacity(allocator, self.digits.items.len);
|
||||
try new_digits.appendSlice(self.digits.items);
|
||||
return BalancedTernary{ .digits = new_digits };
|
||||
}
|
||||
|
||||
fn fromString(allocator: Allocator, s: []const u8) !BalancedTernary {
|
||||
var digits = ArrayList(Trit).init(allocator);
|
||||
errdefer digits.deinit();
|
||||
|
||||
var i: usize = s.len;
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
const trit = try Trit.fromChar(s[i]);
|
||||
try digits.append(trit);
|
||||
}
|
||||
|
||||
return BalancedTernary{ .digits = digits };
|
||||
}
|
||||
|
||||
fn fromI128(allocator: Allocator, x: i128) !BalancedTernary {
|
||||
var digits = ArrayList(Trit).init(allocator);
|
||||
errdefer digits.deinit();
|
||||
|
||||
var curr = x;
|
||||
|
||||
while (true) {
|
||||
const rem = @rem(curr, 3);
|
||||
|
||||
const trit: Trit = switch (rem) {
|
||||
0 => .Zero,
|
||||
1, -2 => .Pos,
|
||||
2, -1 => .Neg,
|
||||
else => unreachable,
|
||||
};
|
||||
try digits.append(trit);
|
||||
|
||||
const offset = @as(i128, @intFromFloat(@round(@as(f64, @floatFromInt(rem)) / 3.0)));
|
||||
curr = @divTrunc(curr, 3) + offset;
|
||||
|
||||
if (curr == 0) break;
|
||||
}
|
||||
|
||||
return BalancedTernary{ .digits = digits };
|
||||
}
|
||||
|
||||
fn toString(self: BalancedTernary, allocator: Allocator) ![]const u8 {
|
||||
var result = try ArrayList(u8).initCapacity(allocator, self.digits.items.len);
|
||||
defer result.deinit();
|
||||
|
||||
var i: usize = self.digits.items.len;
|
||||
while (i > 0) {
|
||||
i -= 1;
|
||||
try result.append(self.digits.items[i].toChar());
|
||||
}
|
||||
|
||||
return result.toOwnedSlice();
|
||||
}
|
||||
|
||||
fn toI128(self: BalancedTernary) !i128 {
|
||||
var acc: i128 = 0;
|
||||
|
||||
for (self.digits.items, 0..) |trit, i| {
|
||||
const index: u32 = std.math.cast(u32, i) orelse return error.Overflow;
|
||||
|
||||
switch (trit) {
|
||||
.Zero => {},
|
||||
.Pos => {
|
||||
const power = std.math.powi(i128, 3, index) catch return error.Overflow;
|
||||
acc = std.math.add(i128, acc, power) catch return error.Overflow;
|
||||
},
|
||||
.Neg => {
|
||||
const power = std.math.powi(i128, 3, index) catch return error.Overflow;
|
||||
acc = std.math.sub(i128, acc, power) catch return error.Overflow;
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
fn trim(digits: *ArrayList(Trit)) void {
|
||||
while (digits.items.len > 0) {
|
||||
const last = digits.items[digits.items.len - 1];
|
||||
if (last != .Zero) {
|
||||
break;
|
||||
}
|
||||
_ = digits.pop();
|
||||
}
|
||||
}
|
||||
|
||||
fn add(self: BalancedTernary, allocator: Allocator, rhs: BalancedTernary) !BalancedTernary {
|
||||
if (rhs.digits.items.len == 0) {
|
||||
if (self.digits.items.len == 0) {
|
||||
var digits = ArrayList(Trit).init(allocator);
|
||||
try digits.append(.Zero);
|
||||
return BalancedTernary{ .digits = digits };
|
||||
}
|
||||
return try self.clone(allocator);
|
||||
}
|
||||
|
||||
const length = @min(self.digits.items.len, rhs.digits.items.len);
|
||||
var sum = ArrayList(Trit).init(allocator);
|
||||
errdefer sum.deinit();
|
||||
|
||||
var carry = ArrayList(Trit).init(allocator);
|
||||
errdefer carry.deinit();
|
||||
try carry.append(.Zero);
|
||||
|
||||
for (0..length) |i| {
|
||||
const result = self.digits.items[i].add(rhs.digits.items[i]);
|
||||
try sum.append(result.current);
|
||||
try carry.append(result.carry);
|
||||
}
|
||||
|
||||
if (self.digits.items.len > length) {
|
||||
try sum.appendSlice(self.digits.items[length..]);
|
||||
}
|
||||
if (rhs.digits.items.len > length) {
|
||||
try sum.appendSlice(rhs.digits.items[length..]);
|
||||
}
|
||||
|
||||
trim(&sum);
|
||||
trim(&carry);
|
||||
|
||||
var sum_bt = BalancedTernary{ .digits = sum };
|
||||
const carry_bt = BalancedTernary{ .digits = carry };
|
||||
//defer carry_bt.deinit();
|
||||
|
||||
return try sum_bt.add(allocator, carry_bt);
|
||||
}
|
||||
|
||||
fn mul(self: BalancedTernary, allocator: Allocator, rhs: BalancedTernary) !BalancedTernary {
|
||||
var results = ArrayList(BalancedTernary).init(allocator);
|
||||
defer {
|
||||
for (results.items) |*item| {
|
||||
item.deinit();
|
||||
}
|
||||
results.deinit();
|
||||
}
|
||||
|
||||
for (rhs.digits.items, 0..) |rhs_trit, i| {
|
||||
var digits = ArrayList(Trit).init(allocator);
|
||||
errdefer digits.deinit();
|
||||
|
||||
for (0..i) |_| {
|
||||
try digits.append(.Zero);
|
||||
}
|
||||
|
||||
for (self.digits.items) |self_trit| {
|
||||
try digits.append(self_trit.mul(rhs_trit));
|
||||
}
|
||||
|
||||
try results.append(BalancedTernary{ .digits = digits });
|
||||
}
|
||||
|
||||
var acc_digits = ArrayList(Trit).init(allocator);
|
||||
try acc_digits.append(.Zero);
|
||||
var acc = BalancedTernary{ .digits = acc_digits };
|
||||
|
||||
for (results.items) |item| {
|
||||
const new_acc = try acc.add(allocator, item);
|
||||
acc.deinit();
|
||||
acc = new_acc;
|
||||
}
|
||||
|
||||
return acc;
|
||||
}
|
||||
|
||||
fn negate(self: *BalancedTernary) void {
|
||||
for (self.digits.items) |*trit| {
|
||||
trit.* = trit.negate();
|
||||
}
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue