diff --git a/algorithm.js b/algorithm.js
index ae4268a..2841188 100644
--- a/algorithm.js
+++ b/algorithm.js
@@ -234,14 +234,13 @@ const algorithm = {
delete algorithm.data[2][key];
}
}
- const sequence = sequences[sequences.current];
const colorScheme = colors[colors.current];
const color = n => ({ value: n, color: n === undefined ? undefined : colorScheme(n) });
// set first three rows
for (let x = left; x <= right; x++) {
algorithm.data[0][x] = color(0n);
algorithm.data[1][x] = color(1n);
- algorithm.data[2][x] = color(BigInt(sequence(x)));
+ algorithm.data[2][x] = color(BigInt(sequences.getFromCurrent(x)));
}
// shrink height
for (let key in algorithm.data) {
diff --git a/events.js b/events.js
index d942bdc..5f14636 100644
--- a/events.js
+++ b/events.js
@@ -105,6 +105,7 @@ const events = {
const element = ui.sections.sequence.select;
const option = element[element.selectedIndex];
sequences.current = option.value;
+ sequences.resetData();
if (option.dataset.param) {
element.dataset.requiresParam = "";
sequences.param = option.dataset.param;
diff --git a/index.html b/index.html
index e7e9a01..5494ce6 100644
--- a/index.html
+++ b/index.html
@@ -53,6 +53,7 @@
Number Walls
+
diff --git a/sequences.js b/sequences.js
index 1eae421..cd91fe6 100644
--- a/sequences.js
+++ b/sequences.js
@@ -1,6 +1,19 @@
const sequences = {
current: undefined,
param: undefined,
+ // must be an object to allow negative indeces
+ data: {},
+ getFromCurrent(n) {
+ if (n in sequences.data) {
+ return sequences.data[n];
+ }
+ const currentFunction = sequences[sequences.current];
+ sequences.data[n] = currentFunction(n);
+ return sequences.data[n];
+ },
+ resetData() {
+ sequences.data = {};
+ },
custom: () => 0,
round(n) {
return Math.round(sequences.param * n);
@@ -31,29 +44,30 @@ const sequences = {
return Number(solution == Math.floor(solution));
},
fibonacci(n) {
- // no floating point precision issues up to 60
- if (Math.abs(n) < 60) {
- return BigInt(Math.round((Math.pow(0.5 * (1 + Math.sqrt(5)), n) - Math.pow(0.5 * (1 - Math.sqrt(5)), n)) / Math.sqrt(5)));
+ if (n < 0) {
+ n = Math.abs(n);
}
- // get access to already calculated numbers
- const previous = algorithm.data[2];
- // recursive definition backward and forward
- if (n - 2 in previous && n - 1 in previous) {
- return previous[n - 2].value + previous[n - 1].value;
+ if ((n == 1) || (n==2)) {
+ return 1;
}
- if (n + 2 in previous && n + 1 in previous) {
- return previous[n + 2].value - previous[n + 1].value;
+ if (n == 0) {
+ return 0;
}
- // start from last two reliably in constant time computable terms and use the recursive formula
- let a = sequences.fibonacci(58), b = sequences.fibonacci(59);
- for (let i = 59; i < Math.abs(n); i++) {
- [a, b] = [b, a + b];
+ return sequences.getFromCurrent(n-1) + sequences.getFromCurrent(n-2);
+ },
+ hofstadterQ(n) {
+ // undefined for n < 1
+ if (n < 1) {
+ return 0;
}
- // rule for negative numbers
- if (n < 0 && n % 2 == 0) {
- b = -b;
+ if ((n == 1) || (n==2)) {
+ return 1;
}
- return b;
+ const firstTermIndex = n - sequences.getFromCurrent(n-1);
+ const secondTermIndex = n - sequences.getFromCurrent(n-2);
+ const firstTerm = sequences.getFromCurrent(firstTermIndex);
+ const secondTerm = sequences.getFromCurrent(secondTermIndex);
+ return firstTerm + secondTerm;
},
dakotaB(n) {
if (n == 0) return 0;
@@ -64,5 +78,5 @@ const sequences = {
},
dakotaC: n => n == 0 ? 1 : sequences.dakotaB(2 * n) - 2 * sequences.dakotaB(2 * n - 1) + 3,
dakotaF: n => n == 1 ? [0, 1] : n == 2 ? [1, -1] : n == 3 ? [0, -1] : [1, 0],
- dakota: n => n < 0 ? 0 : sequences.dakotaF(sequences.dakotaC(Math.floor(n / 2)))[n % 2]
+ dakota: n => n < 0 ? 0 : sequences.dakotaF(sequences.dakotaC(Math.floor(n / 2)))[n % 2],
}
\ No newline at end of file