Time for an 2014 update…
This commit is contained in:
parent
372c577f83
commit
09687c4926
2520 changed files with 34227 additions and 7318 deletions
|
|
@ -1,47 +1,47 @@
|
|||
import std.stdio, std.bigint, std.range, std.algorithm, std.array,
|
||||
std.conv, std.exception;
|
||||
import std.stdio, std.bigint, std.range, std.algorithm;
|
||||
|
||||
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.
|
||||
enum Dig : byte { N=-1, Z=0, P=+1 } // Digit.
|
||||
const Dig[] digits;
|
||||
|
||||
static string dig2str = "-0+";
|
||||
// This could also be a BalancedTernary template argument.
|
||||
static immutable string dig2str = "-0+";
|
||||
|
||||
const static Dig[dchar] str2dig; // = ['+': Dig.P, ...];
|
||||
static this() {
|
||||
immutable static Dig[dchar] str2dig; // = ['+': Dig.P, ...];
|
||||
nothrow static this() {
|
||||
str2dig = ['+': Dig.P, '-': Dig.N, '0': Dig.Z];
|
||||
}
|
||||
|
||||
immutable static Dig[2][] table =
|
||||
immutable pure nothrow 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 = inp.retro().map!(c => cast()str2dig[c]).array;
|
||||
this(in string inp) const pure {
|
||||
this.digits = inp.retro.map!(c => str2dig[c]).array;
|
||||
}
|
||||
|
||||
this(long inp) {
|
||||
this(in long inp) const pure /*nothrow*/ {
|
||||
this.digits = _bint2ternary(inp.BigInt);
|
||||
}
|
||||
|
||||
this(BigInt inp) {
|
||||
this(in BigInt inp) const pure /*nothrow*/ {
|
||||
this.digits = _bint2ternary(inp);
|
||||
}
|
||||
|
||||
this(BalancedTernary inp) {
|
||||
this(in BalancedTernary inp) const pure nothrow {
|
||||
// No need to dup, they are virtually immutable.
|
||||
this.digits = inp.digits;
|
||||
}
|
||||
|
||||
private this(Dig[] inp) {
|
||||
private this(in Dig[] inp) /*inout*/ pure nothrow {
|
||||
this.digits = inp;
|
||||
}
|
||||
|
||||
static Dig[] _bint2ternary(/*in*/ BigInt n) {
|
||||
static py_div(T1, T2)(T1 a, T2 b) {
|
||||
static Dig[] _bint2ternary(in BigInt n) pure /*nothrow*/ {
|
||||
static py_div(T1, T2)(in T1 a, in T2 b) pure /*nothrow*/ {
|
||||
if (a < 0) {
|
||||
return (b < 0) ?
|
||||
-a / -b :
|
||||
|
|
@ -54,33 +54,34 @@ struct BalancedTernary {
|
|||
}
|
||||
|
||||
if (n == 0) return [];
|
||||
switch (((n % 3) + 3) % 3) { // (n % 3) is the remainder.
|
||||
// This final switch in D v.2.064 is fake, not enforced.
|
||||
final 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 {
|
||||
@property BigInt toBint() const pure /*nothrow*/ {
|
||||
return reduce!((y, x) => x + 3 * y)(0.BigInt, digits.retro);
|
||||
}
|
||||
|
||||
string toString() const {
|
||||
string toString() const pure nothrow {
|
||||
if (digits.empty) return "0";
|
||||
return digits.retro.map!(d => dig2str[d + 1]).array;
|
||||
}
|
||||
|
||||
static Dig[] neg_(Dig[] digs) {
|
||||
return digs.map!q{ -a }.array;
|
||||
static const(Dig)[] neg_(in Dig[] digs) pure nothrow {
|
||||
return digs.map!(a => -a).array;
|
||||
}
|
||||
|
||||
BalancedTernary opUnary(string op:"-")() {
|
||||
BalancedTernary opUnary(string op:"-")() const pure nothrow {
|
||||
return BalancedTernary(neg_(this.digits));
|
||||
}
|
||||
|
||||
static Dig[] add_(Dig[] a, Dig[] b, Dig c=Dig.Z) {
|
||||
auto a_or_b = a.length ? a : b;
|
||||
static const(Dig)[] add_(in Dig[] a, in Dig[] b, in Dig c=Dig.Z)
|
||||
pure nothrow {
|
||||
const a_or_b = a.length ? a : b;
|
||||
if (a.empty || b.empty) {
|
||||
if (c == Dig.Z)
|
||||
return a_or_b;
|
||||
|
|
@ -90,7 +91,7 @@ struct BalancedTernary {
|
|||
// (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]);
|
||||
const res = add_(a[1 .. $], b[1 .. $], dc[1]);
|
||||
// Trim leading zeros.
|
||||
if (res.length || dc[0] != Dig.Z)
|
||||
return [dc[0]] ~ res;
|
||||
|
|
@ -99,19 +100,21 @@ struct BalancedTernary {
|
|||
}
|
||||
}
|
||||
|
||||
BalancedTernary opBinary(string op:"+")(BalancedTernary b) {
|
||||
BalancedTernary opBinary(string op:"+")(in BalancedTernary b)
|
||||
const pure nothrow {
|
||||
return BalancedTernary(add_(this.digits, b.digits));
|
||||
}
|
||||
|
||||
BalancedTernary opBinary(string op:"-")(BalancedTernary b) {
|
||||
BalancedTernary opBinary(string op:"-")(in BalancedTernary b)
|
||||
const pure nothrow {
|
||||
return this + (-b);
|
||||
}
|
||||
|
||||
static Dig[] mul_(in Dig[] a, /*in*/ Dig[] b) {
|
||||
static const(Dig)[] mul_(in Dig[] a, in Dig[] b) pure nothrow {
|
||||
if (a.empty || b.empty) {
|
||||
return [];
|
||||
} else {
|
||||
Dig[] y = Dig.Z ~ mul_(a[1 .. $], b);
|
||||
const 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);
|
||||
|
|
@ -120,21 +123,22 @@ struct BalancedTernary {
|
|||
}
|
||||
}
|
||||
|
||||
BalancedTernary opBinary(string op:"*")(BalancedTernary b) {
|
||||
BalancedTernary opBinary(string op:"*")(in BalancedTernary b)
|
||||
const pure nothrow {
|
||||
return BalancedTernary(mul_(this.digits, b.digits));
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
auto a = BalancedTernary("+-0++0+");
|
||||
writeln("a: ", a.toBint, " ", a);
|
||||
immutable a = BalancedTernary("+-0++0+");
|
||||
writeln("a: ", a.toBint, ' ', a);
|
||||
|
||||
auto b = BalancedTernary(-436);
|
||||
writeln("b: ", b.toBint, " ", b);
|
||||
immutable b = BalancedTernary(-436);
|
||||
writeln("b: ", b.toBint, ' ', b);
|
||||
|
||||
auto c = BalancedTernary("+-++-");
|
||||
writeln("c: ", c.toBint, " ", c);
|
||||
immutable c = BalancedTernary("+-++-");
|
||||
writeln("c: ", c.toBint, ' ', c);
|
||||
|
||||
auto r = a * (b - c);
|
||||
writeln("a * (b - c): ", r.toBint, " ", r);
|
||||
immutable r = a * (b - c);
|
||||
writeln("a * (b - c): ", r.toBint, ' ', r);
|
||||
}
|
||||
|
|
|
|||
160
Task/Balanced-ternary/Groovy/balanced-ternary-1.groovy
Normal file
160
Task/Balanced-ternary/Groovy/balanced-ternary-1.groovy
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
enum T {
|
||||
m('-', -1), z('0', 0), p('+', 1)
|
||||
|
||||
final String symbol
|
||||
final int value
|
||||
|
||||
private T(String symbol, int value) {
|
||||
this.symbol = symbol
|
||||
this.value = value
|
||||
}
|
||||
|
||||
static T get(Object key) {
|
||||
switch (key) {
|
||||
case [m.value, m.symbol] : return m
|
||||
case [z.value, z.symbol] : return z
|
||||
case [p.value, p.symbol] : return p
|
||||
default: return null
|
||||
}
|
||||
}
|
||||
|
||||
T negative() {
|
||||
T.get(-this.value)
|
||||
}
|
||||
|
||||
String toString() { this.symbol }
|
||||
}
|
||||
|
||||
|
||||
class BalancedTernaryInteger {
|
||||
|
||||
static final MINUS = new BalancedTernaryInteger(T.m)
|
||||
static final ZERO = new BalancedTernaryInteger(T.z)
|
||||
static final PLUS = new BalancedTernaryInteger(T.p)
|
||||
private static final LEADING_ZEROES = /^0+/
|
||||
|
||||
final String value
|
||||
|
||||
BalancedTernaryInteger(String bt) {
|
||||
assert bt && bt.toSet().every { T.get(it) }
|
||||
value = bt ==~ LEADING_ZEROES ? T.z : bt.replaceAll(LEADING_ZEROES, '');
|
||||
}
|
||||
|
||||
BalancedTernaryInteger(BigInteger i) {
|
||||
this(i == 0 ? T.z.symbol : valueFromInt(i));
|
||||
}
|
||||
|
||||
BalancedTernaryInteger(T...tArray) {
|
||||
this(tArray.sum{ it.symbol });
|
||||
}
|
||||
|
||||
BalancedTernaryInteger(List<T> tList) {
|
||||
this(tList.sum{ it.symbol });
|
||||
}
|
||||
|
||||
private static String valueFromInt(BigInteger i) {
|
||||
assert i != null
|
||||
if (i < 0) return negate(valueFromInt(-i))
|
||||
if (i == 0) return ''
|
||||
int bRem = (((i % 3) - 2) ?: -3) + 2
|
||||
valueFromInt((i - bRem).intdiv(3)) + T.get(bRem)
|
||||
}
|
||||
|
||||
private static String negate(String bt) {
|
||||
bt.collect{ T.get(it) }.inject('') { str, t ->
|
||||
str + (-t)
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map INITIAL_SUM_PARTS = [carry:T.z, sum:[]]
|
||||
private static final prepValueLen = { int len, String s ->
|
||||
s.padLeft(len + 1, T.z.symbol).collect{ T.get(it) }
|
||||
}
|
||||
private static final partCarrySum = { partialSum, carry, trit ->
|
||||
[carry: carry, sum: [trit] + partialSum]
|
||||
}
|
||||
private static final partSum = { parts, trits ->
|
||||
def carrySum = partCarrySum.curry(parts.sum)
|
||||
switch ((trits + parts.carry).sort()) {
|
||||
case [[T.m, T.m, T.m]]: return carrySum(T.m, T.z) //-3
|
||||
case [[T.m, T.m, T.z]]: return carrySum(T.m, T.p) //-2
|
||||
case [[T.m, T.z, T.z], [T.m, T.m, T.p]]: return carrySum(T.z, T.m) //-1
|
||||
case [[T.z, T.z, T.z], [T.m, T.z, T.p]]: return carrySum(T.z, T.z) //+0
|
||||
case [[T.z, T.z, T.p], [T.m, T.p, T.p]]: return carrySum(T.z, T.p) //+1
|
||||
case [[T.z, T.p, T.p]]: return carrySum(T.p, T.m) //+2
|
||||
case [[T.p, T.p, T.p]]: default: return carrySum(T.p, T.z) //+3
|
||||
}
|
||||
}
|
||||
|
||||
BalancedTernaryInteger plus(BalancedTernaryInteger that) {
|
||||
assert that != null
|
||||
if (this == ZERO) return that
|
||||
if (that == ZERO) return this
|
||||
def prep = prepValueLen.curry([value.size(), that.value.size()].max())
|
||||
List values = [prep(value), prep(that.value)].transpose()
|
||||
new BalancedTernaryInteger(values[-1..(-values.size())].inject(INITIAL_SUM_PARTS, partSum).sum)
|
||||
}
|
||||
|
||||
BalancedTernaryInteger negative() {
|
||||
!this ? this : new BalancedTernaryInteger(negate(value))
|
||||
}
|
||||
|
||||
BalancedTernaryInteger minus(BalancedTernaryInteger that) {
|
||||
assert that != null
|
||||
this + -that
|
||||
}
|
||||
|
||||
private static final INITIAL_PRODUCT_PARTS = [sum:ZERO, pad:'']
|
||||
private static final sigTritCount = { it.value.replaceAll(T.z.symbol,'').size() }
|
||||
|
||||
private BalancedTernaryInteger paddedValue(String pad) {
|
||||
new BalancedTernaryInteger(value + pad)
|
||||
}
|
||||
|
||||
private BalancedTernaryInteger partialProduct(T multiplier, String pad){
|
||||
switch (multiplier) {
|
||||
case T.z: return ZERO
|
||||
case T.m: return -paddedValue(pad)
|
||||
case T.p: default: return paddedValue(pad)
|
||||
}
|
||||
}
|
||||
|
||||
BalancedTernaryInteger multiply(BalancedTernaryInteger that) {
|
||||
assert that != null
|
||||
if (that == ZERO) return ZERO
|
||||
if (that == PLUS) return this
|
||||
if (that == MINUS) return -this
|
||||
if (this.value.size() == 1 || sigTritCount(this) < sigTritCount(that)) {
|
||||
return that.multiply(this)
|
||||
}
|
||||
that.value.collect{ T.get(it) }[-1..(-value.size())].inject(INITIAL_PRODUCT_PARTS) { parts, multiplier ->
|
||||
[sum: parts.sum + partialProduct(multiplier, parts.pad), pad: parts.pad + T.z]
|
||||
}.sum
|
||||
}
|
||||
|
||||
BigInteger asBigInteger() {
|
||||
value.collect{ T.get(it) }.inject(0) { i, trit -> i * 3 + trit.value }
|
||||
}
|
||||
|
||||
def asType(Class c) {
|
||||
switch (c) {
|
||||
case Integer: return asBigInteger() as Integer
|
||||
case Long: return asBigInteger() as Long
|
||||
case [BigInteger, Number]: return asBigInteger()
|
||||
case Boolean: return this != ZERO
|
||||
case String: return toString()
|
||||
default: return super.asType(c)
|
||||
}
|
||||
}
|
||||
|
||||
boolean equals(Object that) {
|
||||
switch (that) {
|
||||
case BalancedTernaryInteger: return this.value == that?.value
|
||||
default: return super.equals(that)
|
||||
}
|
||||
}
|
||||
|
||||
int hashCode() { this.value.hashCode() }
|
||||
|
||||
String toString() { value }
|
||||
}
|
||||
16
Task/Balanced-ternary/Groovy/balanced-ternary-2.groovy
Normal file
16
Task/Balanced-ternary/Groovy/balanced-ternary-2.groovy
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
BalancedTernaryInteger a = new BalancedTernaryInteger('+-0++0+')
|
||||
BalancedTernaryInteger b = new BalancedTernaryInteger(-436)
|
||||
BalancedTernaryInteger c = new BalancedTernaryInteger(T.p, T.m, T.p, T.p, T.m)
|
||||
BalancedTernaryInteger bmc = new BalancedTernaryInteger(-436 - (c as Integer))
|
||||
BalancedTernaryInteger atbmc = new BalancedTernaryInteger((a as Integer) * (-436 - (c as Integer)))
|
||||
|
||||
printf ("%9s = %12s %8d\n", 'a', "${a}", a as Number)
|
||||
printf ("%9s = %12s %8d\n", 'b', "${b}", b as Number)
|
||||
printf ("%9s = %12s %8d\n", 'c', "${c}", c as Number)
|
||||
assert (b-c) == bmc
|
||||
printf ("%9s = %12s %8d\n", 'b-c', "${b-c}", (b-c) as Number)
|
||||
assert (a * (b-c)) == atbmc
|
||||
printf ("%9s = %12s %8d\n", 'a * (b-c)', "${a * (b-c)}", (a * (b-c)) as Number)
|
||||
|
||||
println "\nDemonstrate failure:"
|
||||
assert (a * (b-c)) == a
|
||||
137
Task/Balanced-ternary/Liberty-BASIC/balanced-ternary.liberty
Normal file
137
Task/Balanced-ternary/Liberty-BASIC/balanced-ternary.liberty
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
global tt$
|
||||
tt$="-0+" '-1 0 1; +2 -> 1 2 3, instr
|
||||
|
||||
'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.
|
||||
|
||||
a$="+-0++0+"
|
||||
a=deci(a$)
|
||||
print "a",a, a$
|
||||
|
||||
b=-436
|
||||
b$=ternary$(b)
|
||||
print "b",b, b$
|
||||
|
||||
c$="+-++-"
|
||||
c=deci(c$)
|
||||
print "c",c, c$
|
||||
|
||||
'calculate in ternary
|
||||
|
||||
res$=multTernary$(a$, subTernary$(b$, c$))
|
||||
print "a * (b - c)", res$
|
||||
print "In decimal:",deci(res$)
|
||||
|
||||
print "Check:"
|
||||
print "a * (b - c)", a * (b - c)
|
||||
end
|
||||
|
||||
function deci(s$)
|
||||
pow = 1
|
||||
for i = len(s$) to 1 step -1
|
||||
c$ = mid$(s$,i,1)
|
||||
'select case c$
|
||||
' case "+":sign= 1
|
||||
' case "-":sign=-1
|
||||
' case "0":sign= 0
|
||||
'end select
|
||||
sign = instr(tt$,c$)-2
|
||||
deci = deci+pow*sign
|
||||
pow = pow*3
|
||||
next
|
||||
end function
|
||||
|
||||
function ternary$(n)
|
||||
while abs(n)>3^k/2
|
||||
k=k+1
|
||||
wend
|
||||
k=k-1
|
||||
|
||||
pow = 3^k
|
||||
for i = k to 0 step -1
|
||||
sign = (n>0) - (n<0)
|
||||
sign = sign * (abs(n)>pow/2)
|
||||
ternary$ = ternary$+mid$(tt$,sign+2,1)
|
||||
n = n - sign*pow
|
||||
pow = pow/3
|
||||
next
|
||||
if ternary$ = "" then ternary$ ="0"
|
||||
end function
|
||||
|
||||
function multTernary$(a$, b$)
|
||||
|
||||
c$ = ""
|
||||
t$ = ""
|
||||
shift$ = ""
|
||||
for i = len(a$) to 1 step -1
|
||||
|
||||
select case mid$(a$,i,1)
|
||||
case "+": t$ = b$
|
||||
case "0": t$ = "0"
|
||||
case "-": t$ = negate$(b$)
|
||||
end select
|
||||
|
||||
c$ = addTernary$(c$, t$+shift$)
|
||||
|
||||
shift$ = shift$ +"0"
|
||||
'print d, t$, c$
|
||||
next
|
||||
multTernary$ = c$
|
||||
end function
|
||||
|
||||
function subTernary$(a$, b$)
|
||||
subTernary$ = addTernary$(a$, negate$(b$))
|
||||
end function
|
||||
|
||||
function negate$(s$)
|
||||
negate$=""
|
||||
for i = 1 to len(s$)
|
||||
'print mid$(s$,i,1), instr(tt$, mid$(s$,i,1)), 4-instr(tt$, mid$(s$,i,1))
|
||||
negate$=negate$+mid$(tt$, 4-instr(tt$, mid$(s$,i,1)), 1)
|
||||
next
|
||||
end function
|
||||
|
||||
function addTernary$(a$, b$)
|
||||
'add a$ + b$, for now only positive
|
||||
l = max(len(a$), len(b$))
|
||||
a$=pad$(a$,l)
|
||||
b$=pad$(b$,l)
|
||||
c$ = "" 'result
|
||||
carry = 0
|
||||
for i = l to 1 step -1
|
||||
a = instr(tt$,mid$(a$,i,1))-2
|
||||
b = instr(tt$,mid$(b$,i,1))-2 '-1 0 1
|
||||
c = a+b+carry
|
||||
|
||||
select case
|
||||
case abs(c)<2
|
||||
carry = 0
|
||||
case c>0
|
||||
carry =1: c=c-3
|
||||
case c<0
|
||||
carry =-1: c=c+3
|
||||
end select
|
||||
|
||||
'print a, b, c
|
||||
c$ = mid$(tt$,c+2,1)+c$
|
||||
next
|
||||
if carry<>0 then c$ = mid$(tt$,carry+2,1) +c$
|
||||
'print c$
|
||||
'have to trim leading 0's
|
||||
i=0
|
||||
while mid$(c$,i+1,1)="0"
|
||||
i=i+1
|
||||
wend
|
||||
c$=mid$(c$,i+1)
|
||||
if c$="" then c$="0"
|
||||
addTernary$ = c$
|
||||
end function
|
||||
|
||||
function pad$(a$,n) 'pad from right with 0 to length n
|
||||
pad$ = a$
|
||||
while len(pad$)<n
|
||||
pad$ = "0"+pad$
|
||||
wend
|
||||
end function
|
||||
74
Task/Balanced-ternary/Perl/balanced-ternary.pl
Normal file
74
Task/Balanced-ternary/Perl/balanced-ternary.pl
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
my @d = qw( 0 + - );
|
||||
my @v = qw( 0 1 -1 );
|
||||
|
||||
sub to_bt {
|
||||
my $n = shift;
|
||||
my $b = '';
|
||||
while( $n ) {
|
||||
my $r = $n%3;
|
||||
$b .= $d[$r];
|
||||
$n -= $v[$r];
|
||||
$n /= 3;
|
||||
}
|
||||
return scalar reverse $b;
|
||||
}
|
||||
|
||||
sub from_bt {
|
||||
my $n = 0;
|
||||
for( split //, shift ) { # Horner
|
||||
$n *= 3;
|
||||
$n += "${_}1" if $_;
|
||||
}
|
||||
return $n;
|
||||
}
|
||||
|
||||
my %addtable = (
|
||||
'-0' => [ '-', '' ],
|
||||
'+0' => [ '+', '' ],
|
||||
'+-' => [ '0', '' ],
|
||||
'00' => [ '0', '' ],
|
||||
'--' => [ '+', '-' ],
|
||||
'++' => [ '-', '+' ],
|
||||
);
|
||||
|
||||
sub add {
|
||||
my ($b1, $b2) = @_;
|
||||
return ($b1 or $b2 ) unless ($b1 and $b2);
|
||||
my $d = $addtable{ join '', sort substr( $b1, -1, 1, '' ), substr( $b2, -1, 1, '' ) };
|
||||
return add( add($b1, $d->[1]), $b2 ).$d->[0];
|
||||
}
|
||||
|
||||
sub unary_minus {
|
||||
my $b = shift;
|
||||
$b =~ tr/-+/+-/;
|
||||
return $b;
|
||||
}
|
||||
|
||||
sub subtract {
|
||||
my ($b1, $b2) = @_;
|
||||
return add( $b1, unary_minus $b2 );
|
||||
}
|
||||
|
||||
sub mult {
|
||||
my ($b1, $b2) = @_;
|
||||
my $r = '0';
|
||||
for( reverse split //, $b2 ){
|
||||
$r = add $r, $b1 if $_ eq '+';
|
||||
$r = subtract $r, $b1 if $_ eq '-';
|
||||
$b1 .= '0';
|
||||
}
|
||||
$r =~ s/^0+//;
|
||||
return $r;
|
||||
}
|
||||
|
||||
my $a = "+-0++0+";
|
||||
my $b = to_bt( -436 );
|
||||
my $c = "+-++-";
|
||||
my $d = mult( $a, subtract( $b, $c ) );
|
||||
printf " a: %14s %10d\n", $a, from_bt( $a );
|
||||
printf " b: %14s %10d\n", $b, from_bt( $b );
|
||||
printf " c: %14s %10d\n", $c, from_bt( $c );
|
||||
printf "a*(b-c): %14s %10d\n", $d, from_bt( $d );
|
||||
104
Task/Balanced-ternary/Scala/balanced-ternary-1.scala
Normal file
104
Task/Balanced-ternary/Scala/balanced-ternary-1.scala
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
object TernaryBit {
|
||||
val P = TernaryBit(+1)
|
||||
val M = TernaryBit(-1)
|
||||
val Z = TernaryBit( 0)
|
||||
|
||||
implicit def asChar(t: TernaryBit): Char = t.charValue
|
||||
implicit def valueOf(c: Char): TernaryBit = {
|
||||
c match {
|
||||
case '0' => 0
|
||||
case '+' => 1
|
||||
case '-' => -1
|
||||
case nc => throw new IllegalArgumentException("Illegal ternary symbol " + nc)
|
||||
}
|
||||
}
|
||||
implicit def asInt(t: TernaryBit): Int = t.intValue
|
||||
implicit def valueOf(i: Int): TernaryBit = TernaryBit(i)
|
||||
}
|
||||
|
||||
case class TernaryBit(val intValue: Int) {
|
||||
|
||||
def inverse: TernaryBit = TernaryBit(-intValue)
|
||||
|
||||
def charValue = intValue match {
|
||||
case 0 => '0'
|
||||
case 1 => '+'
|
||||
case -1 => '-'
|
||||
}
|
||||
}
|
||||
|
||||
class Ternary(val bits: List[TernaryBit]) {
|
||||
|
||||
def + (b: Ternary) = {
|
||||
val sumBits: List[Int] = bits.map(_.intValue).zipAll(b.bits.map(_.intValue), 0, 0).map(p => p._1 + p._2)
|
||||
|
||||
// normalize
|
||||
val iv: Tuple2[List[Int], Int] = (List(), 0)
|
||||
val (revBits, carry) = sumBits.foldLeft(iv)((accu: Tuple2[List[Int], Int], e: Int) => {
|
||||
val s = e + accu._2
|
||||
(((s + 1 + 3 * 100) % 3 - 1) :: accu._1 , (s + 1 + 3 * 100) / 3 - 100)
|
||||
})
|
||||
|
||||
new Ternary(( TernaryBit(carry) :: revBits.map(TernaryBit(_))).reverse )
|
||||
}
|
||||
|
||||
def - (b: Ternary) = {this + (-b)}
|
||||
def <<<(a: Int): Ternary = { List.fill(a)(TernaryBit.Z) ++ bits}
|
||||
def >>>(a: Int): Ternary = { bits.drop(a) }
|
||||
def unary_- = { bits.map(_.inverse) }
|
||||
|
||||
def ** (b: TernaryBit): Ternary = {
|
||||
b match {
|
||||
case TernaryBit.P => this
|
||||
case TernaryBit.M => - this
|
||||
case TernaryBit.Z => 0
|
||||
}
|
||||
}
|
||||
|
||||
def * (mul: Ternary): Ternary = {
|
||||
// might be done more efficiently - perform normalize only once
|
||||
mul.bits.reverse.foldLeft(new Ternary(Nil))((a: Ternary, b: TernaryBit) => (a <<< 1) + (this ** b))
|
||||
}
|
||||
|
||||
def intValue = bits.foldRight(0)((c, a) => a*3 + c.intValue)
|
||||
|
||||
override def toString = new String(bits.reverse.map(_.charValue).toArray)
|
||||
}
|
||||
|
||||
object Ternary {
|
||||
|
||||
implicit def asString(t: Ternary): String = t.toString()
|
||||
implicit def valueOf(s: String): Ternary = new Ternary(s.toList.reverse.map(TernaryBit.valueOf(_)))
|
||||
|
||||
implicit def asBits(t: Ternary): List[TernaryBit] = t.bits
|
||||
implicit def valueOf(l: List[TernaryBit]): Ternary = new Ternary(l)
|
||||
|
||||
implicit def asInt(t: Ternary): BigInt = t.intValue
|
||||
// XXX not tail recursive
|
||||
implicit def valueOf(i: BigInt): Ternary = {
|
||||
if (i < 0) -valueOf(-i)
|
||||
else if (i == 0) new Ternary(List())
|
||||
else if (i % 3 == 0) TernaryBit.Z :: valueOf(i / 3)
|
||||
else if (i % 3 == 1) TernaryBit.P :: valueOf(i / 3)
|
||||
else /*(i % 3 == 2)*/ TernaryBit.M :: valueOf((i + 1) / 3)
|
||||
}
|
||||
implicit def intToTernary(i: Int): Ternary = valueOf(i)
|
||||
}
|
||||
</scala>
|
||||
|
||||
Then these classes can be used in the following way:
|
||||
<lang scala>
|
||||
object Main {
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
val a: Ternary = "+-0++0+"
|
||||
val b: Ternary = -436
|
||||
val c: Ternary = "+-++-"
|
||||
println(a.toString + " " + a.intValue)
|
||||
println(b.toString + " " + b.intValue)
|
||||
println(c.toString + " " + c.intValue)
|
||||
val res = a * (b - c)
|
||||
println(res.toString + " " + res.intValue)
|
||||
}
|
||||
|
||||
}
|
||||
15
Task/Balanced-ternary/Scala/balanced-ternary-2.scala
Normal file
15
Task/Balanced-ternary/Scala/balanced-ternary-2.scala
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
object TernarySpecification extends Properties("Ternary") {
|
||||
|
||||
property("sum") = forAll { (a: Int, b: Int) =>
|
||||
val at: Ternary = a
|
||||
val bt: Ternary = b
|
||||
(at+bt).intValue == (at.intValue + bt.intValue)
|
||||
}
|
||||
|
||||
property("multiply") = forAll { (a: Int, b: Int) =>
|
||||
val at: Ternary = a
|
||||
val bt: Ternary = b
|
||||
(at*bt).intValue == (at.intValue * bt.intValue)
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue