Skip to content

Commit a70e1f7

Browse files
committed
add negafibonacci encoding
1 parent ab883c0 commit a70e1f7

File tree

2 files changed

+104
-29
lines changed

2 files changed

+104
-29
lines changed

index.html

+40-7
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,56 @@
11
<!DOCTYPE html>
22
<meta charset="utf-8">
3-
3+
<style>
4+
input {
5+
margin-top: 5px;
6+
}
7+
</style>
48
<body>
59
<div>
10+
<h1>Online Fibonacci Coding Converter</h1>
611
<p>
7-
A simple online tool for converting between decimal numbers and their <a
8-
href="https://en.wikipedia.org/wiki/Fibonacci_coding">Fibonacci coding</a>.
12+
A simple online tool for converting between decimal numbers, <a
13+
href="https://en.wikipedia.org/wiki/Fibonacci_coding">Fibonacci coding</a>, and <a
14+
href="https://en.wikipedia.org/wiki/Negafibonacci_coding">Negafibonacci coding</a>.
915
</p>
16+
<div>
17+
<fieldset>
18+
<legend>From</legend>
19+
<div><input type="radio" id="fibonacci" name="from" value="fibonacci">
20+
<label for="fibonacci">fibonacci</label>
21+
</div>
22+
<div><input type="radio" id="negafibonacci" name="from" value="negafibonacci">
23+
<label for="negafibonacci">negafibonacci</label>
24+
</div>
25+
<div>
26+
<input type="radio" id="decimal" name="from" value="decimal" checked>
27+
<label for="decimal">decimal</label>
28+
</div>
29+
</fieldset>
30+
<fieldset>
31+
<legend>To</legend>
32+
<div><input type="radio" id="fibonacci-to" name="to" value="fibonacci" checked>
33+
<label for="fibonacci">fibonacci</label>
34+
</div>
35+
<div><input type="radio" id="negafibonacci-to" name="to" value="negafibonacci">
36+
<label for="negafibonacci">negafibonacci</label>
37+
</div>
38+
<div>
39+
<input type="radio" id="decimal-to" name="to" value="decimal">
40+
<label for="decimal">decimal</label>
41+
</div>
42+
</fieldset>
43+
</div>
1044
<br>
1145
<div>
12-
Input:
1346
<input type="text" id="input" size="50">
14-
<button id="d2f">Decimal to Fibonacci</button>
15-
<button id="f2d">Fibonacci to Decimal</button>
47+
<label for="input">Input</label>
48+
<button id="convert">Convert</button>
1649
</div>
1750
<br>
1851
<div>
19-
Output:
2052
<input type="text" id="output" size="50">
53+
<label for="output">Output</label>
2154
</div>
2255
</div>
2356
<script src="./script.js"></script>

script.js

+64-22
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const d2f = num => {
1+
const d2f = (num, neg) => {
22
const helper = (f1, f2, n) => {
33
if (f2 > n) {
44
return [n, "1"];
@@ -10,46 +10,88 @@ const d2f = num => {
1010
return [rem, "0" + b];
1111
}
1212
}
13-
if (num <= 0) {
14-
return "Number must be greater than 0";
13+
14+
const negHelper = (f1, f2, sum, n) => {
15+
if (Math.abs(sum) > Math.abs(n)) {
16+
return [n, "1"];
17+
}
18+
if ((n < 0 && f1 < 0) || (n > 0 && f1 > 0)) {
19+
sum += f1;
20+
}
21+
[rem, b] = negHelper(f2, f1 + -f2, sum, n);
22+
const canBe1 = b.charAt(0) !== '1' || b.length === 1;
23+
if (Math.abs(rem - f1) < Math.abs(rem) && canBe1) {
24+
return [rem - f1, "1" + b];
25+
} else {
26+
return [rem, "0" + b];
27+
}
28+
}
29+
30+
if (neg) {
31+
if (num === 0) {
32+
return "Number cannot be 0";
33+
}
34+
return negHelper(1, -1, 0, num)[1];
35+
} else {
36+
if (num <= 0) {
37+
return "Number must be greater than 0";
38+
}
39+
return helper(1, 1, num)[1];
1540
}
16-
return helper(1, 1, num)[1];
1741
};
1842

19-
const f2d = b => {
43+
const f2d = (enc, neg) => {
44+
const n = neg ? -1 : 1;
2045
const helper = (f1, f2, i) => {
21-
if (i >= b.length - 1) {
46+
if (i >= enc.length - 1) {
2247
return 0;
2348
}
24-
const char = b.charAt(i);
49+
const char = enc.charAt(i);
2550
if (char == '1') {
26-
return f2 + helper(f2, f1 + f2, i + 1);
51+
return (neg ? f1 : f2) + helper(f2, f1 + n * f2, i + 1);
2752
} else if (char == '0') {
28-
return helper(f2, f1 + f2, i + 1);
53+
return helper(f2, f1 + n * f2, i + 1);
2954
}
3055
}
31-
for (var i = 0; i < b.length; i++) {
32-
switch (b.charAt(i)) {
56+
for (var i = 0; i < enc.length; i++) {
57+
switch (enc.charAt(i)) {
3358
case '1':
3459
case '0':
3560
break;
3661
default:
37-
return `Invalid character at position ${i}: ${b.charAt(i)}`;
62+
return `Invalid character at position ${i}: ${enc.charAt(i)}`;
3863
}
3964
}
40-
if (b.length < 2 || b.charAt(b.length - 1) != '1' || b.charAt(b.length - 2) != '1') {
65+
if (enc.length < 2 || enc.charAt(enc.length - 1) != '1' || enc.charAt(enc.length - 2) != '1') {
4166
return "Last two bits must be 1";
4267
}
43-
return helper(1, 1, 0);
68+
return helper(1, n * 1, 0);
4469
};
4570

46-
document.getElementById("d2f").addEventListener("click", () => {
47-
const input = document.getElementById("input").value;
48-
const output = d2f(parseInt(input));
49-
document.getElementById("output").value = output;
50-
});
51-
document.getElementById("f2d").addEventListener("click", () => {
52-
const input = document.getElementById("input").value;
53-
const output = f2d(input);
71+
document.getElementById("convert").addEventListener("click", () => {
72+
const inputEncoding = document.querySelector('input[name="from"]:checked').value;
73+
const outputEncoding = document.querySelector('input[name="to"]:checked').value;
74+
75+
const input = document.getElementById("input").value.trim();
76+
var output;
77+
if (inputEncoding === outputEncoding) {
78+
output = input;
79+
} else if (inputEncoding === "fibonacci") {
80+
const decimal = f2d(input, false);
81+
if (outputEncoding === "decimal") {
82+
output = decimal;
83+
} else {
84+
output = (/^\d+$/.test(decimal)) ? d2f(decimal, true) : decimal;
85+
}
86+
} else if (inputEncoding === "decimal") {
87+
output = d2f(input, outputEncoding === "negafibonacci");
88+
} else if (inputEncoding === "negafibonacci") {
89+
const decimal = f2d(input, true);
90+
if (outputEncoding === "decimal") {
91+
output = decimal
92+
} else {
93+
output = (/^\d+$/.test(decimal)) ? d2f(decimal, false) : decimal;
94+
}
95+
}
5496
document.getElementById("output").value = output.toString();
5597
});

0 commit comments

Comments
 (0)