Zeckendorf arithmetic: Difference between revisions
m
→{{header|11l}}: Void
m (→{{header|Quackery}}: another typo) |
Alextretyak (talk | contribs) m (→{{header|11l}}: Void) |
||
(9 intermediate revisions by 5 users not shown) | |||
Line 134:
.inc()
F inc() ->
.dVal = .dVal + 1
.a(0)
Line 972:
1000100
1000100</pre>
=={{header|Dart}}==
{{trans|Kotlin}}
<syntaxhighlight lang="Dart">
class Zeckendorf {
int dVal = 0;
int dLen = 0;
Zeckendorf(String x) {
var q = 1;
var i = x.length - 1;
dLen = i ~/ 2;
while (i >= 0) {
dVal += (x[i].codeUnitAt(0) - '0'.codeUnitAt(0)) * q;
q *= 2;
i--;
}
}
void a(int n) {
var i = n;
while (true) {
if (dLen < i) dLen = i;
var j = (dVal >> (i * 2)) & 3;
switch (j) {
case 0:
case 1:
return;
case 2:
if (((dVal >> ((i + 1) * 2)) & 1) != 1) return;
dVal += 1 << (i * 2 + 1);
return;
case 3:
dVal &= ~(3 << (i * 2));
b((i + 1) * 2);
break;
}
i++;
}
}
void b(int pos) {
if (pos == 0) {
this.increment();
return;
}
if (((dVal >> pos) & 1) == 0) {
dVal += 1 << pos;
a(pos ~/ 2);
if (pos > 1) a(pos ~/ 2 - 1);
} else {
dVal &= ~(1 << pos);
b(pos + 1);
b(pos - (pos > 1 ? 2 : 1));
}
}
void c(int pos) {
if (((dVal >> pos) & 1) == 1) {
dVal &= ~(1 << pos);
return;
}
c(pos + 1);
if (pos > 0)
b(pos - 1);
else
this.increment();
}
Zeckendorf increment() {
dVal += 1;
a(0);
return this;
}
void operator + (Zeckendorf other) {
for (var gn = 0; gn < (other.dLen + 1) * 2; gn++) {
if (((other.dVal >> gn) & 1) == 1) b(gn);
}
}
void operator - (Zeckendorf other) {
for (var gn = 0; gn < (other.dLen + 1) * 2; gn++) {
if (((other.dVal >> gn) & 1) == 1) c(gn);
}
while (dLen > 0 && (((dVal >> dLen * 2) & 3) == 0)) dLen--;
}
void operator * (Zeckendorf other) {
var na = other.copy();
var nb = other.copy();
Zeckendorf nt;
var nr = Zeckendorf("0");
for (var i = 0; i <= (dLen + 1) * 2; i++) {
if (((dVal >> i) & 1) > 0) nr + nb;
nt = nb.copy();
nb + na;
na = nt.copy();
}
dVal = nr.dVal;
dLen = nr.dLen;
}
int compareTo(Zeckendorf other) {
return dVal.compareTo(other.dVal);
}
@override
String toString() {
if (dVal == 0) return "0";
var sb = StringBuffer(dig1[(dVal >> (dLen * 2)) & 3]);
for (var i = dLen - 1; i >= 0; i--) {
sb.write(dig[(dVal >> (i * 2)) & 3]);
}
return sb.toString();
}
Zeckendorf copy() {
var z = Zeckendorf("0");
z.dVal = dVal;
z.dLen = dLen;
return z;
}
static final List<String> dig = ["00", "01", "10"];
static final List<String> dig1 = ["", "1", "10"];
}
void main() {
print("Addition:");
var g = Zeckendorf("10");
g + Zeckendorf("10");
print(g);
g + Zeckendorf("10");
print(g);
g + Zeckendorf("1001");
print(g);
g + Zeckendorf("1000");
print(g);
g + Zeckendorf("10101");
print(g);
print("\nSubtraction:");
g = Zeckendorf("1000");
g - Zeckendorf("101");
print(g);
g = Zeckendorf("10101010");
g - Zeckendorf("1010101");
print(g);
print("\nMultiplication:");
g = Zeckendorf("1001");
g * Zeckendorf("101");
print(g);
g = Zeckendorf("101010");
g + Zeckendorf("101");
print(g);
}
</syntaxhighlight>
{{out}}
<pre>
Addition:
101
1001
10101
100101
1010000
Subtraction:
1
1000000
Multiplication:
1000100
1000100
</pre>
=={{header|Elena}}==
{{trans|C++}}
ELENA
<syntaxhighlight lang="elena">import extensions;
Line 1,023 ⟶ 1,202:
};
int v := (dVal $shr (i * 2))
v =>
0 { ^ self }
1 { ^ self }
2 {
ifnot ((dVal $shr ((i + 1) * 2)).allMask
{
^ self
Line 1,039 ⟶ 1,218:
3 {
int tmp := 3 $shl (i * 2);
tmp := tmp.
dVal := dVal
self.b((i+1)*2)
Line 1,059 ⟶ 1,238:
if (pos == 0) { ^ self.inc() };
ifnot((dVal $shr pos).allMask
{
dVal += (1 $shl pos);
Line 1,067 ⟶ 1,246:
else
{
dVal := dVal
self.b(pos + 1);
int arg := pos - ((pos > 1) ? 2 : 1);
Line 1,076 ⟶ 1,255:
private c(int pos)
{
if ((dVal $shr pos).allMask
{
int tmp := 1 $shl pos;
tmp := tmp.
dVal := dVal
^ self
Line 1,103 ⟶ 1,282:
int mLen := 0;
n.readContent(ref
m.readContent(ref mVal, ref mLen);
dLen := l;
for(int GN := 0; GN < (mLen + 1) * 2; GN += 1)
{
if ((mVal $shr GN).allMask
{
self.b(GN)
Line 1,120 ⟶ 1,302:
int mLen := 0;
n.readContent(ref
m.readContent(ref mVal, ref mLen);
dLen := l;
for(int GN := 0; GN < (mLen + 1) * 2; GN += 1)
{
if ((mVal $shr GN).allMask
{
self.c(GN)
Line 1,131 ⟶ 1,316:
};
while (((dVal $shr (dLen*2))
{
dLen -= 1
Line 1,139 ⟶ 1,324:
internal constructor product(ZeckendorfNumber n, ZeckendorfNumber m)
{
n.readContent(ref
dVal := v;
dLen := l;
ZeckendorfNumber Na := m;
Line 1,146 ⟶ 1,334:
ZeckendorfNumber Nt := 0n;
for(int i := 0
{
if (((dVal $shr i)
{
Nr += Nb
Line 1,157 ⟶ 1,345:
};
Nr.readContent(ref
dVal := v;
dLen := l;
}
Line 1,171 ⟶ 1,362:
{ ^ "0" };
string s := dig1[(dVal $shr (dLen * 2))
int i := dLen - 1;
while (i >= 0)
{
s := s + dig[(dVal $shr (i * 2))
i-=1
Line 2,449 ⟶ 2,640:
=={{header|Perl}}==
<syntaxhighlight lang="perl">
package Zeckendorf;
use overload qw("" zstring + zadd - zsub ++ zinc -- zdec * zmul / zdiv ge zge);
sub new ($class, $value) {
bless \$value, ref $class || $class;
}
sub zinc ($self, $, $) {
local $_ = $$self;
s/0$/1/ or s/(?:^|0)1$/10/;
1 while s/(?:^|0)11/100/;
$$self = $self->new( s/^0+\B//r )
}
sub zdec ($self, $, $) {
local $_ = $$self;
1 while s/100(?=0*$)/011/;
s/1$/0/ || s/10$/01/;
$$self = $self->new( s/^0+\B//r )
}
sub zadd ($self, $other, $) {
my ($x, $y) = map $self->new($$_), $self, $other;
$x++, $y-- while $$y;
$x
}
sub zsub ($self, $other, $) {
my ($x, $y) = map $self->new($$_), $self, $other;
$x--, $y-- while $$y;
$x
}
sub zmul ($self, $other, $) {
my ($x, $y) = map $self->new($$_), $self, $other;
my $product = Zeckendorf->new(0);
$product = $product + $x, $y-- while $y;
$product
}
sub zdiv ($self, $other, $) {
my ($x, $y) = map $self->new($$_), $self, $other;
my $quotient = Zeckendorf->new(0);
$quotient++, $x = $x - $y while $x ge $y;
$quotient
}
sub zge ($self, $other, $) {
my $l; $l = length $$other if length $other > ($l = length $$self);
0 x ($l - length $$self) . $$self ge 0 x ($l - length $$other) . $$other;
}
sub asdecimal ($self) {
my($aa, $bb, $n) = (1, 1, 0);
for ( reverse split '', $$self ) {
$n += $bb * $_;
($aa, $bb) = ($bb, $aa + $bb);
}
$n
}
sub fromdecimal ($self, $value) {
my $z = $self->new(0);
$z++ for 1 .. $value;
$z
}
sub zstring { ${ shift() } }
package main;
for ( split /\n/, <<END ) # test cases
Line 2,475 ⟶ 2,734:
$op eq '/' ? $x / $y :
die "bad op <$op>";
printf "%12s %s %-9s => %12s in Zeckendorf\n", $x, $op, $y, $answer;
printf "%12d %s %-9d => %12d in decimal\n\n",
$x->asdecimal, $op, $y->asdecimal, $answer->asdecimal;
}</syntaxhighlight>
{{out}}
<pre> 1 + 1 => 10 in Zeckendorf
1 + 1 => 2 in decimal
Line 2,600 ⟶ 2,767:
100001000001 / 100101 => 100010 in Zeckendorf
255 / 17 => 15 in decimal</pre>
=={{header|Phix}}==
Line 3,258 ⟶ 3,423:
Subtraction is implemented as ''difference'' (i.e. abs(a-b) as this is an unsigned implementation.) The process is to reduce both numbers in value until the smaller one equals zero. Continuing the naming theme established by <code>canonise</code> and <code>defrock</code>, the word that removes the bits that are set to 1 in both arguments is called <code>exorcise</code>. The appropriate sequence of exorcisms and defrockings will reduce the smaller argument to zero much of the time.
However, numbers which alternate 1s and 0s (e.g. ...01010101...) are immune to both canonisation and defrocking
Division is basic binary long division with a twist; instead of multiplying the divisor by 2 until it's large enough, use it to make a fibonacci style sequence, except starting with a couple of copies of the divisor rather than 1s.
Line 3,429 ⟶ 3,594:
else drop ] ] is zdivmod ( z z --> z z )
[ 2dup and iff
Line 3,693 ⟶ 3,858:
=={{header|Raku}}==
(formerly Perl 6)
This is a somewhat limited implementation of Zeckendorf arithmetic operators. They only handle positive integer values. There are no actual calculations, everything is done with string manipulations, so it doesn't matter what glyphs you use for 1 and 0.
Implemented arithmetic operators:
Comparison operators:
<syntaxhighlight lang="raku" line>my $z1 = '1'; # glyph to use for a '1'
my $z0 = '0'; # glyph to use for a '0'
sub zorder($a) { ($z0 lt $z1) ?? $a !! $a.trans([$z0, $z1] => [$z1, $z0]) }
######## Zeckendorf comparison operators #########
# less than
sub infix:<ltz>($a, $b) { $a.&zorder lt $b.&zorder }
# greater than
sub infix:<gtz>($a, $b) { $a.&zorder gt $b.&zorder }
# equal
sub infix:<eqz>($a, $b) { $a eq $b }
# not equal
sub infix:<nez>($a, $b) { $a ne $b }
######## Operators for Zeckendorf arithmetic ########
Line 3,748 ⟶ 3,913:
# addition
sub infix:<+z>($a is copy, $b is copy) { $a++z; $a++z while $b--z nez $z0; $a }
# subtraction
sub infix:<-z>($a is copy, $b is copy) { $a--z; $a--z while $b--z nez $z0; $a }
# multiplication
sub infix:<
return $z0 if $a eqz $z0 or $b eqz $z0;
return $a if $b eqz $z1;
Line 3,766 ⟶ 3,931:
} until $d eqz $b;
$c
}
# division (really more of a div mod)
Line 3,781 ⟶ 3,946:
$c ~= " remainder $a" if $a nez $z0;
$c
}
###################### Testing ######################
# helper sub to translate constants into the particular glyphs you used
sub z($a) { $a.trans([<1 0>] => [$z1, $z0]) }
say "Using the glyph '$z1' for 1 and '$z0' for 0\n";
Line 3,800 ⟶ 3,965:
printf $fmt, "$zeck -z {z('100')}", $zeck -z= z('100'), '# subtraction';
printf $fmt, "$zeck
printf $fmt, "$zeck /z {z('100')}", $zeck /z= z('100'), '# division';
Line 3,806 ⟶ 3,971:
printf( $fmt, "$zeck--z", $zeck--z, '# decrement' ) for 1 .. 5;
printf $fmt, "$zeck
printf $fmt, "$zeck /z {z('100')}", $zeck /z= z('100'), '# division';</syntaxhighlight>
Line 3,826 ⟶ 3,991:
10100 +z 1010 = 101000 # addition
101000 -z 100 = 100010 # subtraction
100010
100001000001 /z 100 = 101010001 # division
101010001--z = 101010000 # decrement
Line 3,833 ⟶ 3,998:
101001001--z = 101001000 # decrement
101001000--z = 101000101 # decrement
101000101
101010000010101 /z 100 = 1001010001001 remainder 10 # division</pre>
Using alternate glyphs:
<pre>
Using the glyph 'X' for 1 and 'O' for 0
Line 3,851 ⟶ 4,016:
XOXOO +z XOXO = XOXOOO # addition
XOXOOO -z XOO = XOOOXO # subtraction
XOOOXO
XOOOOXOOOOOX /z XOO = XOXOXOOOX # division
XOXOXOOOX--z = XOXOXOOOO # decrement
Line 3,858 ⟶ 4,023:
XOXOOXOOX--z = XOXOOXOOO # decrement
XOXOOXOOO--z = XOXOOOXOX # decrement
XOXOOOXOX
XOXOXOOOOOXOXOX /z XOO = XOOXOXOOOXOOX remainder XO # division</pre>
=={{header|Rust}}==
{{trans|C#}}
<syntaxhighlight lang="Rust">
struct Zeckendorf {
d_val: i32,
d_len: i32,
}
impl Zeckendorf {
fn new(x: &str) -> Zeckendorf {
let mut d_val = 0;
let mut q = 1;
let mut i = x.len() as i32 - 1;
let d_len = i / 2;
while i >= 0 {
d_val += (x.chars().nth(i as usize).unwrap() as i32 - '0' as i32) * q;
q *= 2;
i -= 1;
}
Zeckendorf { d_val, d_len }
}
fn a(&mut self, n: i32) {
let mut i = n;
loop {
if self.d_len < i {
self.d_len = i;
}
let j = (self.d_val >> (i * 2)) & 3;
match j {
0 | 1 => return,
2 => {
if ((self.d_val >> ((i + 1) * 2)) & 1) != 1 {
return;
}
self.d_val += 1 << (i * 2 + 1);
return;
}
3 => {
let temp = 3 << (i * 2);
let temp = !temp;
self.d_val &= temp;
self.b((i + 1) * 2);
}
_ => (),
}
i += 1;
}
}
fn b(&mut self, pos: i32) {
if pos == 0 {
self.inc();
return;
}
if ((self.d_val >> pos) & 1) == 0 {
self.d_val += 1 << pos;
self.a(pos / 2);
if pos > 1 {
self.a(pos / 2 - 1);
}
} else {
let temp = 1 << pos;
let temp = !temp;
self.d_val &= temp;
self.b(pos + 1);
self.b(pos - if pos > 1 { 2 } else { 1 });
}
}
fn c(&mut self, pos: i32) {
if ((self.d_val >> pos) & 1) == 1 {
let temp = 1 << pos;
let temp = !temp;
self.d_val &= temp;
return;
}
self.c(pos + 1);
if pos > 0 {
self.b(pos - 1);
} else {
self.inc();
}
}
fn inc(&mut self) -> &mut Self {
self.d_val += 1;
self.a(0);
self
}
fn copy(&self) -> Zeckendorf {
Zeckendorf {
d_val: self.d_val,
d_len: self.d_len,
}
}
fn plus_assign(&mut self, other: &Zeckendorf) {
for gn in 0..(other.d_len + 1) * 2 {
if ((other.d_val >> gn) & 1) == 1 {
self.b(gn);
}
}
}
fn minus_assign(&mut self, other: &Zeckendorf) {
for gn in 0..(other.d_len + 1) * 2 {
if ((other.d_val >> gn) & 1) == 1 {
self.c(gn);
}
}
while (((self.d_val >> self.d_len * 2) & 3) == 0) || (self.d_len == 0) {
self.d_len -= 1;
}
}
fn times_assign(&mut self, other: &Zeckendorf) {
let mut na = other.copy();
let mut nb = other.copy();
let mut nt;
let mut nr = Zeckendorf::new("0");
for i in 0..(self.d_len + 1) * 2 {
if ((self.d_val >> i) & 1) > 0 {
nr.plus_assign(&nb);
}
nt = nb.copy();
nb.plus_assign(&na);
na = nt.copy(); // `na` is now mutable, so this reassignment is allowed
}
self.d_val = nr.d_val;
self.d_len = nr.d_len;
}
fn to_string(&self) -> String {
if self.d_val == 0 {
return "0".to_string();
}
let dig = ["00", "01", "10"];
let dig1 = ["", "1", "10"];
let idx = (self.d_val >> (self.d_len * 2)) & 3;
let mut sb = String::from(dig1[idx as usize]);
for i in (0..self.d_len).rev() {
let idx = (self.d_val >> (i * 2)) & 3;
sb.push_str(dig[idx as usize]);
}
sb
}
}
fn main() {
println!("Addition:");
let mut g = Zeckendorf::new("10");
g.plus_assign(&Zeckendorf::new("10"));
println!("{}", g.to_string());
g.plus_assign(&Zeckendorf::new("10"));
println!("{}", g.to_string());
g.plus_assign(&Zeckendorf::new("1001"));
println!("{}", g.to_string());
g.plus_assign(&Zeckendorf::new("1000"));
println!("{}", g.to_string());
g.plus_assign(&Zeckendorf::new("10101"));
println!("{}", g.to_string());
println!();
println!("Subtraction:");
g = Zeckendorf::new("1000");
g.minus_assign(&Zeckendorf::new("101"));
println!("{}", g.to_string());
g = Zeckendorf::new("10101010");
g.minus_assign(&Zeckendorf::new("1010101"));
println!("{}", g.to_string());
println!();
println!("Multiplication:");
g = Zeckendorf::new("1001");
g.times_assign(&Zeckendorf::new("101"));
println!("{}", g.to_string());
g = Zeckendorf::new("101010");
g.plus_assign(&Zeckendorf::new("101"));
println!("{}", g.to_string());
}
</syntaxhighlight>
{{out}}
<pre>
Addition:
101
1001
10101
100101
1010000
Subtraction:
1
1000000
Multiplication:
1000100
1000100
</pre>
=={{header|Scala}}==
{{works with|Scala|2.13.1}}
Line 4,751 ⟶ 5,119:
{{trans|Kotlin}}
{{libheader|Wren-trait}}
<syntaxhighlight lang="
class Zeckendorf is Comparable {
|