all tasks
This commit is contained in:
parent
b83f433714
commit
68f8f3e56b
14735 changed files with 178959 additions and 0 deletions
67
Task/Zeckendorf-arithmetic/0DESCRIPTION
Normal file
67
Task/Zeckendorf-arithmetic/0DESCRIPTION
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
This task is a total immersion zeckendorf task, using decimal numbers will attract serious disapprobation.
|
||||
|
||||
The task is to implement addition, subtraction, multiplication, and division using [[Zeckendorf number representation]]. [[Zeckendorf number representation#Using_a_C.2B.2B11_User_Defined_Literal|Optionally]] provide decrement, increment and comparitive operation functions.
|
||||
|
||||
;Addition
|
||||
Like binary 1 + 1 = 10, note carry 1 left. There the similarity ends. 10 + 10 = 101, note carry 1 left and 1 right. 100 + 100 = 1001, note carry 1 left and 2 right, this is the general case.
|
||||
|
||||
Occurrences of 11 must be changed to 100. Occurrences of 111 may be changed from the right by replacing 11 with 100, or from the left converting 111 to 100 + 100;
|
||||
|
||||
;Subtraction
|
||||
10 - 1 = 1. The general rule is borrow 1 right carry 1 left. eg:
|
||||
<pre>
|
||||
abcde
|
||||
10100 -
|
||||
1000
|
||||
_____
|
||||
100 borrow 1 from a leaves 100
|
||||
+ 100 add the carry
|
||||
_____
|
||||
1001
|
||||
</pre>
|
||||
A larger example:
|
||||
<pre>
|
||||
abcdef
|
||||
100100 -
|
||||
1000
|
||||
______
|
||||
1*0100 borrow 1 from b
|
||||
+ 100 add the carry
|
||||
______
|
||||
1*1001
|
||||
|
||||
Sadly we borrowed 1 from b which didn't have it to lend. So now b borrows from a:
|
||||
|
||||
1001
|
||||
+ 1000 add the carry
|
||||
____
|
||||
10100
|
||||
</pre>
|
||||
|
||||
;Multiplication
|
||||
Here you teach your computer its zeckendorf tables. eg. 101 * 1001:
|
||||
<pre>
|
||||
a = 1 * 101 = 101
|
||||
b = 10 * 101 = a + a = 10000
|
||||
c = 100 * 101 = b + a = 10101
|
||||
d = 1000 * 101 = c + b = 101010
|
||||
|
||||
1001 = d + a therefore 101 * 1001 =
|
||||
|
||||
101010
|
||||
+ 101
|
||||
______
|
||||
1000100
|
||||
</pre>
|
||||
|
||||
;Division
|
||||
Lets try 1000101 divided by 101, so we can use the same table used for addition.
|
||||
<pre>
|
||||
1000101 -
|
||||
101010 subtract d (1000 * 101)
|
||||
_______
|
||||
1000 -
|
||||
101 b and c are too large to subtract, so subtract a
|
||||
____
|
||||
1 so 1000101 divided by 101 is d + a (1001) remainder 1
|
||||
</pre>
|
||||
72
Task/Zeckendorf-arithmetic/C++/zeckendorf-arithmetic-1.cpp
Normal file
72
Task/Zeckendorf-arithmetic/C++/zeckendorf-arithmetic-1.cpp
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
// For a class N which implements Zeckendorf numbers:
|
||||
// I define an increment operation ++()
|
||||
// I define a comparison operation <=(other N)
|
||||
// I define an addition operation +=(other N)
|
||||
// I define a subtraction operation -=(other N)
|
||||
// Nigel Galloway October 28th., 2012
|
||||
#include <iostream>
|
||||
enum class zd {N00,N01,N10,N11};
|
||||
class N {
|
||||
private:
|
||||
int dVal = 0, dLen;
|
||||
void _a(int i) {
|
||||
for (;; i++) {
|
||||
if (dLen < i) dLen = i;
|
||||
switch ((zd)((dVal >> (i*2)) & 3)) {
|
||||
case zd::N00: case zd::N01: return;
|
||||
case zd::N10: if (((dVal >> ((i+1)*2)) & 1) != 1) return;
|
||||
dVal += (1 << (i*2+1)); return;
|
||||
case zd::N11: dVal &= ~(3 << (i*2)); _b((i+1)*2);
|
||||
}}}
|
||||
void _b(int pos) {
|
||||
if (pos == 0) {++*this; 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;
|
||||
return;
|
||||
}
|
||||
public:
|
||||
N(char const* x = "0") {
|
||||
int i = 0, q = 1;
|
||||
for (; x[i] > 0; i++);
|
||||
for (dLen = --i/2; i >= 0; i--) {dVal+=(x[i]-48)*q; q*=2;
|
||||
}}
|
||||
const N& operator++() {dVal += 1; _a(0); return *this;}
|
||||
const N& operator+=(const N& other) {
|
||||
for (int GN = 0; GN < (other.dLen + 1) * 2; GN++) if ((other.dVal >> GN) & 1 == 1) _b(GN);
|
||||
return *this;
|
||||
}
|
||||
const N& operator-=(const N& other) {
|
||||
for (int GN = 0; GN < (other.dLen + 1) * 2; GN++) if ((other.dVal >> GN) & 1 == 1) _c(GN);
|
||||
for (;((dVal >> dLen*2) & 3) == 0 or dLen == 0; dLen--);
|
||||
return *this;
|
||||
}
|
||||
const N& operator*=(const N& other) {
|
||||
N Na = other, Nb = other, Nt, Nr;
|
||||
for (int i = 0; i <= (dLen + 1) * 2; i++) {
|
||||
if (((dVal >> i) & 1) > 0) Nr += Nb;
|
||||
Nt = Nb; Nb += Na; Na = Nt;
|
||||
}
|
||||
return *this = Nr;
|
||||
}
|
||||
const bool operator<=(const N& other) const {return dVal <= other.dVal;}
|
||||
friend std::ostream& operator<<(std::ostream&, const N&);
|
||||
};
|
||||
N operator "" N(char const* x) {return N(x);}
|
||||
std::ostream &operator<<(std::ostream &os, const N &G) {
|
||||
const static std::string dig[] {"00","01","10"}, dig1[] {"","1","10"};
|
||||
if (G.dVal == 0) return os << "0";
|
||||
os << dig1[(G.dVal >> (G.dLen*2)) & 3];
|
||||
for (int i = G.dLen-1; i >= 0; i--) os << dig[(G.dVal >> (i*2)) & 3];
|
||||
return os;
|
||||
}
|
||||
15
Task/Zeckendorf-arithmetic/C++/zeckendorf-arithmetic-2.cpp
Normal file
15
Task/Zeckendorf-arithmetic/C++/zeckendorf-arithmetic-2.cpp
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
int main(void) {
|
||||
N G;
|
||||
G = 10N;
|
||||
G += 10N;
|
||||
std::cout << G << std::endl;
|
||||
G += 10N;
|
||||
std::cout << G << std::endl;
|
||||
G += 1001N;
|
||||
std::cout << G << std::endl;
|
||||
G += 1000N;
|
||||
std::cout << G << std::endl;
|
||||
G += 10101N;
|
||||
std::cout << G << std::endl;
|
||||
return 0;
|
||||
}
|
||||
10
Task/Zeckendorf-arithmetic/C++/zeckendorf-arithmetic-3.cpp
Normal file
10
Task/Zeckendorf-arithmetic/C++/zeckendorf-arithmetic-3.cpp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
int main(void) {
|
||||
N G;
|
||||
G = 1000N;
|
||||
G -= 101N;
|
||||
std::cout << G << std::endl;
|
||||
G = 10101010N;
|
||||
G -= 1010101N;
|
||||
std::cout << G << std::endl;
|
||||
return 0;
|
||||
}
|
||||
10
Task/Zeckendorf-arithmetic/C++/zeckendorf-arithmetic-4.cpp
Normal file
10
Task/Zeckendorf-arithmetic/C++/zeckendorf-arithmetic-4.cpp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
int main(void) {
|
||||
N G = 1001N;
|
||||
G *= 101N;
|
||||
std::cout << G << std::endl;
|
||||
|
||||
G = 101010N;
|
||||
G += 101N;
|
||||
std::cout << G << std::endl;
|
||||
return 0;
|
||||
}
|
||||
100
Task/Zeckendorf-arithmetic/Perl-6/zeckendorf-arithmetic.pl6
Normal file
100
Task/Zeckendorf-arithmetic/Perl-6/zeckendorf-arithmetic.pl6
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
my $z1 = '1'; # glyph to use for a '1'
|
||||
my $z0 = '0'; # glyph to use for a '0'
|
||||
|
||||
# helper sub to translate constants into the particular glyphs you used
|
||||
sub z($a) { $a.trans([<1 0>] => [$z1, $z0]) };
|
||||
|
||||
######## Zeckendorf comparison operators #########
|
||||
|
||||
# less than
|
||||
sub infix:<ltz>($a, $b) { ($z0 lt $z1) ?? ($a lt $b) !!
|
||||
($a.trans([$z1, $z0] => [<1 0>]) lt $b.trans([$z1, $z0] => [<1 0>]))
|
||||
};
|
||||
|
||||
# greater than
|
||||
sub infix:<gtz>($a, $b) { ($z0 lt $z1) ?? ($a gt $b) !!
|
||||
($a.trans([$z1, $z0] => [<1 0>]) gt $b.trans([$z1, $z0] => [<1 0>]))
|
||||
};
|
||||
|
||||
# equal
|
||||
sub infix:<eqz>($a, $b) { $a eq $b };
|
||||
|
||||
# not equal
|
||||
sub infix:<nez>($a, $b) { $a ne $b };
|
||||
|
||||
|
||||
######## Operators for Zeckendorf arithmetic ########
|
||||
|
||||
# post increment
|
||||
sub postfix:<++z>($a is rw) {
|
||||
$a = ("$z0$z0"~$a).subst(/("$z0$z0")($z1+ %% $z0)?$/, -> $/ { "$z0$z1" ~ $z0 x $1.chars });
|
||||
$a ~~ s/^$z0+//;
|
||||
$a
|
||||
}
|
||||
|
||||
# post decrement
|
||||
sub postfix:<--z>($a is rw) {
|
||||
$a.=subst(/$z1($z0*)$/, -> $/ {$z0 ~ "$z1$z0" x $0.chars div 2 ~ $z1 x $0.chars mod 2});
|
||||
$a ~~ s/^$z0+(.+)$/$0/;
|
||||
$a
|
||||
}
|
||||
|
||||
# addition
|
||||
sub infix:<+z>($a is copy, $b is copy) { $a++z while $b--z nez $z0; $a };
|
||||
|
||||
# subtraction
|
||||
sub infix:<-z>($a is copy, $b is copy) { $a--z while $b--z nez $z0; $a };
|
||||
|
||||
# multiplication
|
||||
sub infix:<*z>($a, $b) {
|
||||
return $z0 if $a eq $z0 or $b eq $z0;
|
||||
return $a if $b eq $z1;
|
||||
return $b if $a eq $z1;
|
||||
my $c = $a;
|
||||
my $d = $z1;
|
||||
repeat {
|
||||
my $e = $z0;
|
||||
repeat { $c++z; $e++z } until $e eqz $a;
|
||||
$d++z;
|
||||
} until $d eqz $b;
|
||||
$c
|
||||
};
|
||||
|
||||
# division (really more of a div mod)
|
||||
sub infix:</z>($a is copy, $b is copy) {
|
||||
fail "Divide by zero" if $b eqz $z0;
|
||||
return $a if $a eqz $z0 or $b eqz $z1;
|
||||
my $c = $z0;
|
||||
repeat {
|
||||
my $d = $b +z ($z1 ~ $z0);
|
||||
$c++z;
|
||||
$a--z while $d--z nez $z0
|
||||
} until $a ltz $b;
|
||||
$c ~= " remainder $a" if $a nez $z0;
|
||||
$c
|
||||
};
|
||||
|
||||
|
||||
###################### Testing ######################
|
||||
|
||||
say "Using the glyph '$z1' for 1 and '$z0' for 0\n";
|
||||
|
||||
my $fmt = "%-22s = %15s %s\n";
|
||||
|
||||
my $zeck = $z1;
|
||||
|
||||
printf( $fmt, "$zeck++z", $zeck++z, '# increment' ) for 1 .. 10;
|
||||
|
||||
printf $fmt, "$zeck +z {z('1010')}", $zeck +z= z('1010'), '# addition';
|
||||
|
||||
printf $fmt, "$zeck -z {z('100')}", $zeck -z= z('100'), '# subtraction';
|
||||
|
||||
printf $fmt, "$zeck *z {z('100101')}", $zeck *z= z('100101'), '# multiplication';
|
||||
|
||||
printf $fmt, "$zeck /z {z('100')}", $zeck /z= z('100'), '# division';
|
||||
|
||||
printf( $fmt, "$zeck--z", $zeck--z, '# decrement' ) for 1 .. 5;
|
||||
|
||||
printf $fmt, "$zeck *z {z('101001')}", $zeck *z= z('101001'), '# multiplication';
|
||||
|
||||
printf $fmt, "$zeck /z {z('100')}", $zeck /z= z('100'), '# division';
|
||||
Loading…
Add table
Add a link
Reference in a new issue