(Javascript - Arrays) Get most left and most right connected character - javascript

I have an array (2d-matrix) and I'd like to get the x/y values for the
most left & top connected '1'-character
most right & bottom connected '1'-character
EDIT 2.0:
I call my function with the parameters x/y, that are the coordinates of my start-'1'-character.
10001
00001
11111
01110 --> (x: 1, y: 3)
And my function checks the column above & and the column right so if there is a character '1' it counts x or y (wherever the column has been found) plus 1.
My function starts at a specific point (e.g. y: 2, x: 0)
var array = [
'00000',
'01111', --> get position of the most top & right '1'-character (x: 4, y: 1)
'11000',
'00000'
]
This is the function to get the top-right end of '1'-characters:
var array = [
'00000',
'01111',
'11000',
'00000'
]
Array.prototype.get_top_right = function(x_pos, y_pos) {
var matrix = this, y1= y_pos;
for (var x1 = x_pos; x1 < this[0].length; x1++) {
try {
if (matrix[(y1-1)][x1] == '1') y1--;
else if (matrix[y1][(x1+1)] != '1') break;
} catch(e) {}
}; return [x1,y1]
}
var result=array.get_top_right(0,2)
console.log(result)
Ok. The function above seems to work fine, but now I'd like to turn around the process to get the last bottom-left connected '1'-character of my array / 2D-matrix.
var array = [
'00000',
'01111',
'11000', --> get position of the most bottom & left '1'-character (x: 0, y: 2)
'00000'
]
I have no clue how to edit the function above to get the left&bottom match as result instead of the most right&top match like you can see above.
Edit 1.0 My function I've coded till yet is not working but looks like this:
Array.prototype.get_bottom_left = function(x_pos, y_pos) {
var matrix = this, y2= y_pos;
for (var x2 = x_pos; x2 > 0; x2--) {
try {
if (matrix[(y2+1)][x2] == '1') y2++;
if (matrix[y2][(x2-1)] != '1') break;
} catch(e) {}
}; return [x2,y2]
}
Using this function above and the error_array below to get the bottom left connected character of the array will lead to a browser crash. Nice!
var error_array = [
'000000',
'000011',
'111110',
'111111'
]
However, I hope somebody can help me updating my function...
Thanks a million in advance,
Greetings - hans.

I created two versions of get_bottom_left method:
bottom_left_up which traversing from (x, y) point to the left and to the up
bottom_left_down which traversing from (x, y) point to the right and to the down.
Here's the implementation:
Array.prototype.bottom_left_up = function(x, y) {
if(this[y][x] === '0') {
return;
}
while(y >= 0) {
while(--x >= 0) {
if(this[y][x] === '0') {
return [x + 1, y];
}
}
if(--y === -1 || this[y][this[y].length - 1] === '0') {
return [0, y + 1];
}
x = this[y].length;
}
};
Array.prototype.bottom_left_down = function(x, y) {
if(this[y][x] === '0') {
return;
}
while(y < this.length) {
if(this[y].indexOf('0', x) !== -1) {
return [x, y];
}
if(++y === this.length || this[y][0] === '0') {
return [x, y - 1];
}
x = 0;
}
};
You see, there are no out-of-range protections, it could be added with no problem separately. Let's test the logic:
var array = [
'00000',
'01111',
'11000',
'00000'
];
console.log(array.bottom_left_up(2, 1)); // [1, 1]
console.log(array.bottom_left_down(2, 1)); // [0, 2]
var array2 = [
'000000',
'000011',
'111110',
'111111'
];
console.log(array2.bottom_left_up(3, 3)); // [0, 3]
console.log(array2.bottom_left_down(3, 3)); // [3, 3]
Regarding methods protection, I would not use try-catch, I would suggest something like:
function(x, y) {
x = parseInt(x, 10);
y = parseInt(y, 10);
if(!this.length || isNaN(x) || isNaN(y) || x < 0 || y < 0 || x >= this.length || y >= this[0].length) {
return;
}
// ...
}
So you will get 'undefined' in 3 cases: empty array, bad params, not found.

Here is a function that seems to do the trick with any size of a matrix but I'm not quite sure if you wanted always to find the first "1" in the matrix even if it was alone on the line and on the right side..
Using your arrays as test parameters
var array = [
'00000',
'01111',
'11000',
'00100'];
var error_array = [
'000000',
'000011',
'111111',
'111111',
'000000',
'000010',
'100000'
]
getLeftBottom(error_array);
function getLeftBottom(testArray)
{
var firstFound;
for (var index = testArray.length; index > 0; index--)
{
console.log(testArray[index-1]);
str = testArray[index-1];
firstFound = str.indexOf("1");
if (firstFound !== -1)
{
console.log("Coordinates: x = {0}, y = {1}", firstFound, index) // Apparently this doesn't work as I expected in JS but you can still see the coordinates
break;
}
}
}

Related

Search coordinates in a binary not working correctly

I need to insert a lot of coordinates in a binary tree and sometimes merge them. I'm testing the program for a while and have noted that the search function doesn't work sometimes.
In this example, I created two binary trees, merged them and searched for some coordinate, but the coordinates that are inserted in the tree, were not found:
First tree:
0 2
9 8
7 0
6 0
Second tree:
3 2
8 5
4 1
5 6
Merged trees:
3 2
8 5
4 1
5 6
0 2
9 8
7 0
6 0
VALUES 8 and 5 NOT FOUND
Can someone help me with this problem?
Here is the code:
function binarytree()
{
this.root = null;
this.add = function()
{
var node = {
x : j,
y : i,
left : null,
right : null
};
var current;
if (this.root == null) this.root = node;
else {
current = this.root;
while (1)
{
if (i < current.y || j < current.x) {
if (current.left == null) {
current.left = node;
break;
}
else current = current.left;
}
else if (i > current.y || j > current.x) {
if (current.right == null) {
current.right = node;
break;
}
else current = current.right;
}
else break;
}
}
}
this.search = function(tree, i, j) {
var found = false;
current = tree.root;
while (!found && current) {
if (i < current.y || j < current.x) current = current.left;
else if (i > current.y || j > current.x) current = current.right;
else found = true;
}
return found;
}
this.print = function(no)
{
if (no)
{
this.print(no.left);
this.print(no.right);
console.log(no.x, no.y);
}
}
}
function merge(tree, tree2) {
if (tree2.x < tree.x || tree2.y < tree.y) {
if (tree.left) {
this.merge(tree.left, tree2);
} else {
tree.left = tree2;
}
} else {
if (tree.right) {
this.merge(tree.right, tree2);
} else {
tree.right = tree2;
}
}
}
var i, j;
var tree = new binarytree();
var tree2 = new binarytree();
for (x = 0; x < 4; x++)
{
i = Math.floor(Math.random() * 10);
j = Math.floor(Math.random() * 10);
tree.add();
}
for (x = 0; x < 4; x++)
{
i = Math.floor(Math.random() * 10);
j = Math.floor(Math.random() * 10);
tree2.add();
}
console.log("First tree:");
tree.print(tree.root);
console.log("Second tree:");
tree2.print(tree2.root);
merge(tree.root,tree2.root);
console.log("Merged trees:");
tree.print(tree.root);
if (tree.search(tree, i, j) == true) console.log("FOUND VALUES " + j + " AND " + i);
else console.log("VALUES " + j + " AND " + i + " NOT FOUND");
As you already mentioned in your deleted question, you need to use KD trees for this, as a normal binary search tree is intended for 1-dimensional values, not 2-dimensional values.
There are several issues in your code:
The way you split points into 2 categories is not a transitive operation. Let's say you have two points in one tree: (0, 0) and (10, -5), then the second point will be stored in the left property of the root. This is because -5 is less than 0. Now we have a second tree with two points: (4, 4) and also (10, -5). The tree will have the same structure as the first for the same reasons. Your merge function will put the second tree in the right property of the first tree's root. This is because (4, 4) is considered "right" of (0, 0). Now notice how this is inconsistent: now we have a (10, -5) sitting both in the left and the right subtree of the merged tree! This happens because the way you compare points is not a transitive comparison.
The above point is the major problem, but also notice that if (i < current.y || j < current.x) will on average be true for 75% of the cases. This is a second reason why this comparison method is not the right one.
The way to compare 2D-points in a KD tree is to alternate comparisons with either the X-coordinate or the Y-coordinate. So at the top-level of the tree you would compare Y-coordinates to decide whether to go left or right, and on the next level you would compare X-coordinates. Then again one level deeper you would compare Y-coordinates again, ...etc.
Some other remarks:
Use class syntax
Create a constructor also for the node instances
Don't print in methods, instead define a generator to produce all values, and a toString method and print that string in your main program.
Avoid using global variables: your add method should take i and j as arguments, and you should declare variables always (you didn't use var current in search, nor for x and y in the main code): this is crucial if you want to write reliable code. Consider using "use strict" which will alert you about such problems.
add and search will use a similar way to navigate through the tree, so put the code that they have in common in a separate function, which we could call locate.
As far as I know, there is no way to merge KD trees the way you have imagined it, where you can decide to put the "rest" of the second tree under a leaf node of the first. So I would suggest to just iterate the nodes of the second tree and insert them one by one in the first.
Here is the suggested code:
"use strict"; // To help avoid all kinds of problems
class Node { // Use a class for creating node instances
constructor(i, j) {
this.x = i;
this.y = j;
this.left = null;
this.right = null;
}
* inorder() { // Generator to visit all nodes
if (this.left) yield * this.left.inorder();
yield [this.x, this.y];
if (this.right) yield * this.right.inorder();
}
}
class BinaryTree {
constructor() {
this.root = null;
}
locate(i, j) { // A common function to avoid code repetition
if (this.root == null) return [null, "root"];
let current = this.root;
let axis = "x";
let otherAxis = "y";
while (true) {
// alternate the axis:
[axis, otherAxis, i, j] = [otherAxis, axis, j, i];
if (i < current[axis]) {
if (current.left == null) return [current, "left"];
current = current.left;
} else if (i > current[axis] || j != current[otherAxis]) {
if (current.right == null) return [current, "right"];
current = current.right;
} else { // point is already in the tree
return [current, "equal"];
}
}
}
add(i, j) { // this method should have parameters
if (this.root == null) {
this.root = new Node(i, j); // Use constructor for creating node
} else {
const [current, side] = this.locate(i, j);
if (side !== "equal") {
current[side] = new Node(i, j);
}
}
}
search(i, j) {
const [_, side] = this.locate(i, j);
return side === "equal";
}
* inorder() {
if (this.root) yield * this.root.inorder();
}
mergeWith(otherTree) {
// Insert all the other nodes one by one:
for (let point of otherTree.inorder()) {
this.add(...point);
}
}
toString() { // Don't print, but produce string
return JSON.stringify(Array.from(this.inorder()));
}
}
const tree = new BinaryTree();
for (const point of [[0, 2], [9, 8], [7, 0], [6, 0]]) tree.add(...point);
const tree2 = new BinaryTree();
for (const point of [[3, 2], [8, 5], [4, 1], [5, 6]]) tree2.add(...point);
console.log("First tree:");
console.log(tree.toString());
console.log("Second tree:");
console.log(tree2.toString());
tree.mergeWith(tree2);
console.log("Merged trees:");
console.log(tree.toString());
// Check that all points are found:
for (const point of tree.inorder()) {
console.log(...point, tree.search(...point));
}

Struggling with an increasing paths algorithm question

I’m struggling to find a good solution to a problem which asks for ALL paths which increase as you traverse a 2D array/matrix (rather than the classic ‘Longest Increasing Path’.
Here’s the question:
Definitions
• Path: a sequence of two or mere spaces for which ea. space is horizontally or vertically adjacent to the previous
• Increasing path: a path for which each space has a greater value than the previous space.
Example 1:
[
[5, 1],
[2, 7]
]
There are 4 Increasing paths.
1 -> 5
1 -> 7
2 -> 5
2 -> 7
Example 2:
[
[0, 4, 3],
[5, 8, 9],
[5, 9, 9]
]
There are 4 Increasing paths.
0 -> 4
0 -> 4 -> 8
0 -> 4 -> 8
0 -> 4 -> 8 -> 9
0 -> 5
0 -> 5 -> 8
... and so on.
I’ve tried a few things, but none of which what I need. Because I don’t want this to seem like an “answer my homework for me”, here’s the code of what I’ve tried (I knew it wouldn’t work 100%, but it was a good start for me, and I wasn’t sure where to go from there)
/*
This attempt was from what I
gathered from longest increasing,
so it clearly isn’t valid.
*/
function(v){
let n=v.length;
let m=v[0].length;
let mem=(new Array(n));
for(let i=0;i<n;i++)mem[i]=(new Array(m)).fill(0);
mem[0][0]=1;
for(let i=1;i<n;i++){
if (v[i][0] > v[i-1][0] && mem[i-1][0] == 1) {
mem[i][0] = 1;
}
}
for(let i=1;i<m;i++){
if (v[0][i] > v[0][i-1] && mem[0][i-1] == 1) {
mem[0][i] = 1;
}
}
for(let i=1;i<n;i++){
for(let j=1;j<m;j++){
if (v[i][j] > v[i-1][j] && mem[i-1][j] == 1) {
mem[i][j] = 1;
}
if (mem[i][j] == 0 && v[i][j] > v[i][j-1] && mem[i][j-1] == 1){
mem[i][j] = 1;
}
}
}
return mem[n-1][m-1] ? n+m-1 : -1;
}
(Note: I come from a strictly UX and front-end background, but I’m trying to improve my skills on this type of programming and move to a more full stack position, so I appreciate the help with a novice question! :))
Some tips:
View the grid as a graph, nodes are each gridpoint and edges are formed where it is possible to move from a to b
An increasing path means going from a smaller value a to a bigger value b.
This ensures that the graph is directed. (you can never go back the same edge)
such a path a->b->c...->f you can never connect to any earlier point in your path, as it would imply that a < b < .. < f < a. this means that the graph has no cycles
A graph with directed edges and no cycles are known as DAGs (directed acyclic graphs). Many graph algorithms are a lot easier on these graphs, including listing all paths.
Your task is simply to write a DFS (depth first search) and start it on every gridpoint (filter out path of length 0 in the end).
The following is the way I have solved using Javascript
const savedPathCount = [];
function getAvailablePath(grid, x, y) {
if (!savedPathCount[x]) {
savedPathCount[x] = [];
}
if (savedPathCount[x][y]) {
return savedPathCount[x][y]
}
savedPathCount[x][y] = 0
const currentValue = grid[x][y];
if (y > 0) {
const topValue = grid[x][y - 1];
if (topValue && topValue > currentValue) {
savedPathCount[x][y]++;
savedPathCount[x][y] += getAvailablePath(grid, x, y - 1)
}
}
if (x > 0) {
const leftValue = grid[x - 1][y];
if (leftValue && leftValue > currentValue) {
savedPathCount[x][y]++;
savedPathCount[x][y] += getAvailablePath(grid, x - 1, y)
}
}
if (grid[x]) {
const rightValue = grid[x][y + 1];
if (rightValue && rightValue > currentValue) {
savedPathCount[x][y]++;
savedPathCount[x][y] += getAvailablePath(grid, x, y + 1)
}
}
if (grid[x + 1]) {
const bottomValue = grid[x + 1][y];
if (bottomValue && bottomValue > currentValue) {
savedPathCount[x][y]++;
savedPathCount[x][y] += getAvailablePath(grid, x + 1, y)
}
}
return savedPathCount[x][y];
}
function paths(grid) {
// Write your code here
let pathCount = 0
for (let x = 0; x < grid.length; x++) {
for (let y = 0; y < grid[x].length; y++) {
pathCount += getAvailablePath(grid, x, y);
}
}
return pathCount;
}
const grid = [[15, 34],[1, 6]]
console.log(grid(path))

JavaScript method to determine correct path is confusing

I'm learning algorithms and doing JavaScript exercise questions, and I don't understand how one reaches the correct answer for a particular algorithm.
The question provided in the exercise is:
Have the function CorrectPath(str) read the str parameter being
passed, which will represent the movements made in a 5x5 grid of cells
starting from the top left position. The characters in the input
string will be entirely composed of: r, l, u, d, ?. Each of the
characters stand for the direction to take within the grid, for
example: r = right, l = left, u = up, d = down. Your goal is to
determine what characters the question marks should be in order for a
path to be created to go from the top left of the grid all the way to
the bottom right without touching previously travelled on cells in the
grid.
For example, the input drdr??rrddd? should ouptut drdruurrdddd
I've not found a solution on my own. I'm taking a look at a solution provided, and I'm bothered because:
A. pure functions are not used to manipulate values within the CorrectPath function (note the addX() and addY() methods contained within). I'm not convinced the solution provided is using best practices, especially coming from a functional programming background.
B. I don't understand how the steps taken, specifically in the while block and the succeeding for block, are taken to reach the correct answer and why sometimes the missingLetters array has letters remaining and other times not
The working solution provided is below
function CorrectPath(str) {
let x = 0, //start x coord
y = 0, //start y coord
missingLetters = []
const unknowns = str.match(/\W/g)
function addX() {
while(x !== 4) {
if (x > 4) {
x--;
missingLetters.push('l');
} else {
x++;
missingLetters.push('r');
}
}
}
function addY() {
while (y !== 4) {
if (y > 4) {
y--;
missingLetters.push('u');
} else {
y++;
missingLetters.push('d');
}
}
}
//tallies current number of x and y movements
for (let i=0; i<str.length; i++) {
switch (str[i]) {
case 'd':
y += 1;
break;
case 'u':
y -= 1;
break;
case 'l':
x -= 1;
break;
case 'r':
x += 1;
break;
}
}
if (x > y) { addX(); addY(); }
if (y >= x) { addY(); addX(); }
while (missingLetters.length < unknowns.length) {
var pos = missingLetters.length - 1;
if (missingLetters[pos] === 'r') {x += 1; missingLetters.push('r'); addX()}
if (missingLetters[pos] === 'l') {x -= 1; missingLetters.push('l'); addX()}
if (missingLetters[pos] === 'd') {y += 1; missingLetters.push('d'); addY()}
if (missingLetters[pos] === 'u') {y -= 1; missingLetters.push('u'); addY()}
}
var newStr = str.split('');
for (var j=0; j<str.length; j++) {
if (newStr[j] === '?') {
newStr[j] = missingLetters.shift()
}
}
return newStr.join('');
}
CorrectPath(readline());
Here's a solution I found
const dirMap = {
u: { x: 0, y: -1 },
r: { x: 1, y: 0 },
d: { x: 0, y: 1 },
l: { x: -1, y: 0 }
}
function CorrectPath(pathString) {
const map = Array(5*5)
return trace(pathString, map)
}
function trace(path, [...map], x = 0, y = 0, newPath = "") {
const steps = path.split(""),
nextMove = steps.shift()
if (nextMove === undefined) {
if (5 * y + x === (5*5-1)) return newPath
return "Bad move"
}
if (nextMove === "?") {
const moves = availableMoves(x,y,map)
if (!moves.length) return "Bad move"
for(let i = 0; i<moves.length; i++) {
let move = moves[i],
trySteps = [move,...steps].join("")
res = trace(trySteps,map,x,y,newPath)
if (!res || res === "Bad move") continue
else return res
}
return "Bad move"
} else {
if (!canMove(nextMove, x, y, map)) return "Bad move"
const pos = dirMap[nextMove],
newX = pos.x + x,
newY = pos.y + y
newPath += nextMove
map[5*newY+newX] = nextMove
return trace(steps.join(""),map,newX,newY,newPath)
}
}
function availableMoves(x,y,map) {
const steps = []
Object.keys(dirMap).forEach(z => {
if (canMove(z,x,y,map)) steps.push(z)
})
return steps
}
function canMove(dir, xPath, yPath, map) {
const pos = dirMap[dir],
x = pos.x + xPath,
y = pos.y + yPath
if (x > 4 || x < 0 || y > 4 || y < 0) return false
if (map[5*y+x] !== undefined) return false
return true
}
CorrectPath(readline());

algorithm connect four javascript

Hy,
I am trying to implement an Connect Four Game in javascript / jQuery. First off this is no homework or any other duty. I'm just trying to push my abilities.
My "playground" is a simple html table which has 7 rows and 6 columns.
But now I have reached my ken. I'm stuck with the main functionality of checking whether there are 4 same td's around. I am adding a class to determine which color it should represent in the game.
First I thought I could handle this with .nextAll() and .prevAll() but this does not work for me because there is no detection between.
Because I was searching for siblings, when adding a new Item and just looked up the length of siblings which were found and if they matched 4 in the end I supposed this was right, but no its not :D Is there maybe any kind of directNext() which provides all next with a css selector until something different comes up ?
I will put all of my code into this jsfiddle: http://jsfiddle.net/LcUVf/5/
Maybe somebody has ever tried the same or someone comes up with a good idea I'm not asking anybody to do or finish my code. I just want to get hints for implementing such an algorithm or examples how it could be solved !
Thanks in anyway !
DOM traversal is not particularly efficient so, when you can avoid it, I'd recommend doing so. It'd make sense for you to build this as a 2D array to store and update the state of the game. The table would only be a visual representation of the array.
I know that, normally, you would build the array with rows as the first dimension and columns as the second dimension but, for the purposes of being able to add pieces to each column's "stack," I would make the first dimension the columns and the second dimension the rows.
To do the check, take a look at this fiddle I made:
http://jsfiddle.net/Koviko/4dTyw/
There are 4 directions to check: North-South, East-West, Northeast-Southwest, and Southeast-Northwest. This can be represented as objects with the delta defined for X and Y:
directions = [
{ x: 0, y: 1 }, // North-South
{ x: 1, y: 0 }, // East-West
{ x: 1, y: 1 }, // Northeast-Southwest
{ x: 1, y: -1 } // Southeast-Northwest
];
Then, loop through that object and loop through your "table" starting at the farthest bounds that this piece can possibly contribute to a win. So, since you need 4 pieces in a row, the currently placed piece can contribute in a win for up to 3 pieces in any direction.
minX = Math.min(Math.max(placedX - (3 * directions[i].x), 0), pieces.length - 1);
minY = Math.min(Math.max(placedY - (3 * directions[i].y), 0), pieces[0].length - 1);
maxX = Math.max(Math.min(placedX + (3 * directions[i].x), pieces.length - 1), 0);
maxY = Math.max(Math.min(placedY + (3 * directions[i].y), pieces[0].length - 1), 0);
To avoid any issues with less-than and greater-than (which I ran into), calculate the number of steps before looping through your pieces instead of using the calculated bounds as your conditions.
steps = Math.max(Math.abs(maxX - minX), Math.abs(maxY - minY));
Finally, loop through the items keeping a count of consecutive pieces that match the piece that was placed last.
function isVictory(pieces, placedX, placedY) {
var i, j, x, y, maxX, maxY, steps, count = 0,
directions = [
{ x: 0, y: 1 }, // North-South
{ x: 1, y: 0 }, // East-West
{ x: 1, y: 1 }, // Northeast-Southwest
{ x: 1, y: -1 } // Southeast-Northwest
];
// Check all directions
outerloop:
for (i = 0; i < directions.length; i++, count = 0) {
// Set up bounds to go 3 pieces forward and backward
x = Math.min(Math.max(placedX - (3 * directions[i].x), 0), pieces.length - 1);
y = Math.min(Math.max(placedY - (3 * directions[i].y), 0), pieces[0].length - 1);
maxX = Math.max(Math.min(placedX + (3 * directions[i].x), pieces.length - 1), 0);
maxY = Math.max(Math.min(placedY + (3 * directions[i].y), pieces[0].length - 1), 0);
steps = Math.max(Math.abs(maxX - x), Math.abs(maxY - y));
for (j = 0; j < steps; j++, x += directions[i].x, y += directions[i].y) {
if (pieces[x][y] == pieces[placedX][placedY]) {
// Increase count
if (++count >= 4) {
break outerloop;
}
} else {
// Reset count
count = 0;
}
}
}
return count >= 4;
}
I released a fully working version of the game on Github.
It implements an optimised variation on the algorythm Sirko mentioned.
To avoid any unnecessary redunancy, the algorythm directly checks the DOM rather than a JS table. As that algorythm requires a minimum amount of checks, the performance overhead for accessing the DOM is neglectable.
The current player and a flag for keeping track of whether the game has ended are basicly the only statuses stored in the JS itself.
I even used the DOM to store strings. It has no external dependencies and is supported by all versions of IE from IE6 upwards as well as modern browsers.
Code is optimised for filesize and performance. The latest version also includes animation, even though the total JS code of the game is still only 1.216 bytes after minification.
The Code :
Here's the full, un-minified JS code :
(function (doc, win, onclick, gid, classname, content, showMessage) {
var
a, b, c, colorLabel, cid, players, current, finished, newgameLabel, wonLabel, laststart = 1,
cellAt = function (i, j) {
return doc[gid](cid + i + j);
},
isCurrentColor = function (i, j) {
return cellAt(i, j)[classname] === players[current];
},
start = function () {
current = laststart = (laststart + 1) % 2;
finished = 0;
colorLabel[content] = colorLabel[classname] = players[current = (current + 1) % 2];
for (a = 1; a < 7; a++)
for (b = 1; b < 8; b++)
cellAt(a, b)[classname] = '';
},
makeMove = function (i, j, s) {
s > 0 && (cellAt(s, j)[classname] = '');
cellAt(s + 1, j)[classname] = players[current];
s === i - 1 ? function (i, j) {
return function (i, j) {
for (a = j - 1; 0 < a && isCurrentColor(i, a); a--) {
}
for (b = j + 1; 8 > b && isCurrentColor(i, b); b++) {
}
return 4 < b - a;
}(i, j) || function (i, j) {
for (c = i + 1; 7 > c && isCurrentColor(c, j); c++) {
}
return 3 < c - i;
}(i, j) || function (i, j) {
for (a = i - 1, b = j - 1; 0 < a && !(1 > b) && isCurrentColor(a, b); a--)
b--;
for (c = i + 1, b = j + 1; 7 > c && !(7 < b) && isCurrentColor(c, b); c++)
b++;
return 4 < c - a
}(i, j) || function (i, j) {
for (a = i - 1, b = j + 1; 0 < a && !(7 < b) && isCurrentColor(a, b); a--)
b++;
for (c = i + 1, b = j - 1; 7 > c && !(1 > b) && isCurrentColor(c, b); c++)
b--;
return 4 < c - a;
}(i, j);
}(i, j)
? finished = 1 && win[showMessage](doc[gid](wonLabel)[content].replace("%s", players[current].toLowerCase())) && start()
: colorLabel[content] = colorLabel[classname] = players[current = (current + 1) % 2]
: setTimeout(function () {
makeMove(i, j, s + 1)
}, 20);
};
return function (n, w, c, h, p1, p2) {
cid = c;
newgameLabel = n;
wonLabel = w;
colorLabel = doc[gid](c);
players = [doc[gid](p1)[content], doc[gid](p2)[content]];
for (a = 1; a < 7; a++)
for (b = 1; b < 8; b++)
cellAt(a, b)[onclick] = function (b, a) {
return function () {
if (!finished)
for (a = 6; a > 0; a--)
if (!cellAt(a, b)[classname]) {
makeMove(a, b, 0);
break;
}
};
}(b);
;
doc[gid](h)[onclick] = function () {
win[showMessage](doc[gid](newgameLabel)[content]) && start()
};
start();
};
})(document, window, "onclick", "getElementById", "className", "innerHTML", "confirm")("newgame", "won", "color", "restart", "p1", "p2");
A screenshot :
In general a 2dimensional array would be better suited for checking for a line of 4. You could then do something like the following:
function check( lastPiece, playground, player ) {
// check length in each direction
var l = 1,
i = 1;
// top to bottom
while( (playground[ lastPiece.x ][ lastPiece.y - i ] === player) && ((lastPiece.y - i) >= 0) ) { l += 1; i += 1; };
i = 1;
while( (playground[ lastPiece.x ][ lastPiece.y + i ] === player) && ((lastPiece.y + i) <= MAX_Y) ) { l += 1; i += 1; };
if ( l >= 4 ) { return true; }
// left to right
l = 1;
while( (playground[ lastPiece.x - i][ lastPiece.y ] === player) && ((lastPiece.x - i) >= 0) ) { l += 1; i += 1; };
i = 1;
while( (playground[ lastPiece.x + i][ lastPiece.y ] === player) && ((lastPiece.x + i) <= MAX_X) ) { l += 1; i += 1; };
if ( l >= 4 ) { return true; }
// same for top left to bottom right and bottom left to top right
// . . .
// if we got no hit until here, there is no row of 4
return false;
}
EDIT: added checks for borders of the playground

Generating Fibonacci Sequence

var x = 0;
var y = 1;
var z;
fib[0] = 0;
fib[1] = 1;
for (i = 2; i <= 10; i++) {
alert(x + y);
fib[i] = x + y;
x = y;
z = y;
}
I'm trying to get to generate a simple Fibonacci Sequence but there no output.
Can anybody let me know what's wrong?
You have never declared fib to be an array. Use var fib = []; to solve this.
Also, you're never modifying the y variable, neither using it.
The code below makes more sense, plus, it doesn't create unused variables:
var i;
var fib = [0, 1]; // Initialize array!
for (i = 2; i <= 10; i++) {
// Next fibonacci number = previous + one before previous
// Translated to JavaScript:
fib[i] = fib[i - 2] + fib[i - 1];
console.log(fib[i]);
}
According to the Interview Cake question, the sequence goes 0,1,1,2,3,5,8,13,21. If this is the case, this solution works and is recursive without the use of arrays.
function fibonacci(n) {
return n < 1 ? 0
: n <= 2 ? 1
: fibonacci(n - 1) + fibonacci(n - 2)
}
console.log(fibonacci(4))
Think of it like this.
fibonacci(4) .--------> 2 + 1 = 3
| / |
'--> fibonacci(3) + fibonacci(2)
| ^
| '----------- 2 = 1 + 1 <----------.
1st step -> | ^ |
| | |
'----> fibonacci(2) -' + fibonacci(1)-'
Take note, this solution is not very efficient though.
Yet another answer would be to use es6 generator functions.
function* fib() {
var current = a = b = 1;
yield 1;
while (true) {
current = b;
yield current;
b = a + b;
a = current;
}
}
sequence = fib();
sequence.next(); // 1
sequence.next(); // 1
sequence.next(); // 2
// ...
Here's a simple function to iterate the Fibonacci sequence into an array using arguments in the for function more than the body of the loop:
fib = function(numMax){
for(var fibArray = [0,1], i=0,j=1,k=0; k<numMax;i=j,j=x,k++ ){
x=i+j;
fibArray.push(x);
}
console.log(fibArray);
}
fib(10)
[ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 ]
You should've declared the fib variable to be an array in the first place (such as var fib = [] or var fib = new Array()) and I think you're a bit confused about the algorithm.
If you use an array to store the fibonacci sequence, you do not need the other auxiliar variables (x,y,z) :
var fib = [0, 1];
for(var i=fib.length; i<10; i++) {
fib[i] = fib[i-2] + fib[i-1];
}
console.log(fib);
Click for the demo
You should consider the recursive method too (note that this is an optimised version) :
function fib(n, undefined){
if(fib.cache[n] === undefined){
fib.cache[n] = fib(n-1) + fib(n-2);
}
return fib.cache[n];
}
fib.cache = [0, 1, 1];
and then, after you call the fibonacci function, you have all the sequence in the fib.cache field :
fib(1000);
console.log(fib.cache);
The golden ration "phi" ^ n / sqrt(5) is asymptotic to the fibonacci of n, if we round that value up, we indeed get the fibonacci value.
function fib(n) {
let phi = (1 + Math.sqrt(5))/2;
let asymp = Math.pow(phi, n) / Math.sqrt(5);
return Math.round(asymp);
}
fib(1000); // 4.346655768693734e+208 in just a few milliseconds
This runs faster on large numbers compared to the recursion based solutions.
You're not assigning a value to z, so what do you expect y=z; to do? Likewise you're never actually reading from the array. It looks like you're trying a combination of two different approaches here... try getting rid of the array entirely, and just use:
// Initialization of x and y as before
for (i = 2; i <= 10; i++)
{
alert(x + y);
z = x + y;
x = y;
y = z;
}
EDIT: The OP changed the code after I'd added this answer. Originally the last line of the loop was y = z; - and that makes sense if you've initialized z as per my code.
If the array is required later, then obviously that needs to be populated still - but otherwise, the code I've given should be fine.
Another easy way to achieve this:
function fibonacciGenerator(n) {
// declare the array starting with the first 2 values of the fibonacci sequence
// starting at array index 1, and push current index + previous index to the array
for (var fibonacci = [0, 1], i = 2; i < n; i++)
fibonacci.push(fibonacci[i-1] + fibonacci[i - 2])
return fibonacci
}
console.log( fibonacciGenerator(10) )
function fib(n) {
if (n <= 1) {
return n;
} else {
return fib(n - 1) + fib(n - 2);
}
}
fib(10); // returns 55
fibonacci 1,000 ... 10,000 ... 100,000
Some answers run into issues when trying to calculate large fibonacci numbers. Others are approximating numbers using phi. This answer will show you how to calculate a precise series of large fibonacci numbers without running into limitations set by JavaScript's floating point implementation.
Below, we generate the first 1,000 fibonacci numbers in a few milliseconds. Later, we'll do 100,000!
const { fromInt, toString, add } =
Bignum
const bigfib = function* (n = 0)
{
let a = fromInt (0)
let b = fromInt (1)
let _
while (n >= 0) {
yield toString (a)
_ = a
a = b
b = add (b, _)
n = n - 1
}
}
console.time ('bigfib')
const seq = Array.from (bigfib (1000))
console.timeEnd ('bigfib')
// 25 ms
console.log (seq.length)
// 1001
console.log (seq)
// [ 0, 1, 1, 2, 3, ... 995 more elements ]
Let's see the 1,000th fibonacci number
console.log (seq [1000])
// 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875
10,000
This solution scales quite nicely. We can calculate the first 10,000 fibonacci numbers in under 2 seconds. At this point in the sequence, the numbers are over 2,000 digits long – way beyond the capacity of JavaScript's floating point numbers. Still, our result includes precise values without making approximations.
console.time ('bigfib')
const seq = Array.from (bigfib (10000))
console.timeEnd ('bigfib')
// 1877 ms
console.log (seq.length)
// 10001
console.log (seq [10000] .length)
// 2090
console.log (seq [10000])
// 3364476487 ... 2070 more digits ... 9947366875
Of course all of that magic takes place in Bignum, which we will share now. To get an intuition for how we will design Bignum, recall how you added big numbers using pen and paper as a child...
1259601512351095520986368
+ 50695640938240596831104
---------------------------
?
You add each column, right to left, and when a column overflows into the double digits, remembering to carry the 1 over to the next column...
... <-001
1259601512351095520986368
+ 50695640938240596831104
---------------------------
... <-472
Above, we can see that if we had two 10-digit numbers, it would take approximately 30 simple additions (3 per column) to compute the answer. This is how we will design Bignum to work
const Bignum =
{ fromInt: (n = 0) =>
n < 10
? [ n ]
: [ n % 10, ...Bignum.fromInt (n / 10 >> 0) ]
, fromString: (s = "0") =>
Array.from (s, Number) .reverse ()
, toString: (b) =>
Array.from (b) .reverse () .join ('')
, add: (b1, b2) =>
{
const len = Math.max (b1.length, b2.length)
let answer = []
let carry = 0
for (let i = 0; i < len; i = i + 1) {
const x = b1[i] || 0
const y = b2[i] || 0
const sum = x + y + carry
answer.push (sum % 10)
carry = sum / 10 >> 0
}
if (carry > 0) answer.push (carry)
return answer
}
}
We'll run a quick test to verify our example above
const x =
fromString ('1259601512351095520986368')
const y =
fromString ('50695640938240596831104')
console.log (toString (add (x,y)))
// 1310297153289336117817472
And now a complete program demonstration. Expand it to calculate the precise 10,000th fibonacci number in your own browser! Note, the result is the same as the answer provided by wolfram alpha
const Bignum =
{ fromInt: (n = 0) =>
n < 10
? [ n ]
: [ n % 10, ...Bignum.fromInt (n / 10 >> 0) ]
, fromString: (s = "0") =>
Array.from (s, Number) .reverse ()
, toString: (b) =>
Array.from (b) .reverse () .join ('')
, add: (b1, b2) =>
{
const len = Math.max (b1.length, b2.length)
let answer = []
let carry = 0
for (let i = 0; i < len; i = i + 1) {
const x = b1[i] || 0
const y = b2[i] || 0
const sum = x + y + carry
answer.push (sum % 10)
carry = sum / 10 >> 0
}
if (carry > 0) answer.push (carry)
return answer
}
}
const { fromInt, toString, add } =
Bignum
const bigfib = function* (n = 0)
{
let a = fromInt (0)
let b = fromInt (1)
let _
while (n >= 0) {
yield toString (a)
_ = a
a = b
b = add (b, _)
n = n - 1
}
}
console.time ('bigfib')
const seq = Array.from (bigfib (10000))
console.timeEnd ('bigfib')
// 1877 ms
console.log (seq.length)
// 10001
console.log (seq [10000] .length)
// 2090
console.log (seq [10000])
// 3364476487 ... 2070 more digits ... 9947366875
100,000
I was just curious how far this little script could go. It seems like the only limitation is just time and memory. Below, we calculate the first 100,000 fibonacci numbers without approximation. Numbers at this point in the sequence are over 20,000 digits long, wow! It takes 3.18 minutes to complete but the result still matches the answer from wolfram alpha
console.time ('bigfib')
const seq = Array.from (bigfib (100000))
console.timeEnd ('bigfib')
// 191078 ms
console.log (seq .length)
// 100001
console.log (seq [100000] .length)
// 20899
console.log (seq [100000])
// 2597406934 ... 20879 more digits ... 3428746875
BigInt
JavaScript now has native support for BigInt. This allows for calculating huge integers very quickly -
function* fib (n)
{ let a = 0n
let b = 1n
let _
while (n >= 0) {
yield a.toString()
_ = a
a = b
b = b + _
n = n - 1
}
}
console.time("fib(1000)")
const result = Array.from(fib(1000))
console.timeEnd("fib(1000)")
document.body.textContent = JSON.stringify(result, null, 2)
body {
font-family: monospace;
white-space: pre;
}
I like the fact that there are so many ways to create a fibonacci sequence in JS. I will try to reproduce a few of them. The goal is to output a sequence to console (like {n: 6, fiboNum: 8})
Good ol' closure
// The IIFE form is purposefully omitted. See below.
const fiboGenClosure = () => {
let [a, b] = [0, 1];
let n = 0;
return (fiboNum = a) => {
[a, b] = [b, a + b];
return {
n: n++,
fiboNum: fiboNum
};
};
}
// Gets the sequence until given nth number. Always returns a new copy of the main function, so it is possible to generate multiple independent sequences.
const generateFiboClosure = n => {
const newSequence = fiboGenClosure();
for (let i = 0; i <= n; i++) {
console.log(newSequence());
}
}
generateFiboClosure(21);
Fancy ES6 generator
Similar to the closure pattern above, using the advantages of generator function and for..of loop.
// The 'n' argument is a substitute for index.
function* fiboGen(n = 0) {
let [a, b] = [0, 1];
while (true) {
yield [a, n++];
[a, b] = [b, a + b];
}
}
// Also gives a new sequence every time is invoked.
const generateFibonacci = n => {
const iterator = fiboGen();
for (let [value, index] of iterator) {
console.log({
n: index,
fiboNum: value
});
if (index >= n) break;
}
}
generateFibonacci(21);
Tail call recursion
This one is a little tricky, because, now in late 2018, TC optimization is still an issue. But honestly – if you don't use any smart tricks to allow the default JS engine to use a really big numbers, it will get dizzy and claims that the next fibonacci number is "Infinity" by iteration 1477. The stack would probably overflow somewhere around iteration 10 000 (vastly depends on browser, memory etc…). Could be probably padded by try… catch block or check if "Infinity" was reached.
const fibonacciRTC = (n, i = 0, a = 0, b = 1) => {
console.log({
n: i,
fibonacci: a
});
if (n === 0) return;
return fibonacciRTC(--n, ++i, b, a + b);
}
fibonacciRTC(21)
It can be written as a one-liner, if we throe away the console.log thing and simply return a number:
const fibonacciRTC2 = (n, a = 0, b = 1) => n === 0 ? a : fibonacciRTC2(n - 1, b, a + b);
console.log(fibonacciRTC2(21))
Important note!
As I found out reading this mathIsFun article, the fibonacci sequence is valid for negative numbers as well! I tried to implement that in the recursive tail call form above like that:
const fibonacciRTC3 = (n, a = 0, b = 1, sign = n >= 0 ? 1 : -1) => {
if (n === 0) return a * sign;
return fibonacciRTC3(n - sign, b, a + b, sign);
}
console.log(fibonacciRTC3(8)); // 21
console.log(fibonacciRTC3(-8)); // -21
There is also a generalization of Binet's formula for negative integers:
static float phi = (1.0f + sqrt(5.0f)) / 2.0f;
int generalized_binet_fib(int n) {
return round( (pow(phi, n) - cos(n * M_PI) * pow(phi, -n)) / sqrt(5.0f) );
}
...
for(int i = -10; i < 10; ++i)
printf("%i ", generalized_binet_fib(i));
A quick way to get ~75
ty #geeves for the catch, I replaced Math.floor for Math.round which seems to get it up to 76 where floating point issues come into play :/ ...
either way, I wouldn't want to be using recursion up and until that point.
/**
* Binet Fibonacci number formula for determining
* sequence values
* #param {int} pos - the position in sequence to lookup
* #returns {int} the Fibonacci value of sequence #pos
*/
var test = [0,1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,10946,17711,28657,46368,75025,121393,196418,317811,514229,832040,1346269,2178309,3524578,5702887,9227465,14930352,24157817,39088169,63245986,102334155,165580141,267914296,433494437,701408733,1134903170,1836311903,2971215073,4807526976,7778742049,12586269025,20365011074,32951280099,53316291173,86267571272,139583862445,225851433717,365435296162,591286729879,956722026041,1548008755920,2504730781961,4052739537881,6557470319842,10610209857723,17167680177565,27777890035288,44945570212853,72723460248141,117669030460994,190392490709135,308061521170129,498454011879264,806515533049393,1304969544928657,2111485077978050,3416454622906707,5527939700884757,8944394323791464,14472334024676221,23416728348467685,37889062373143906,61305790721611591,99194853094755497,160500643816367088,259695496911122585,420196140727489673,679891637638612258,1100087778366101931,1779979416004714189,2880067194370816120,4660046610375530309,7540113804746346429,12200160415121876738,19740274219868223167,31940434634990099905,51680708854858323072,83621143489848422977,135301852344706746049,218922995834555169026];
var fib = function (pos) {
return Math.round((Math.pow( 1 + Math.sqrt(5), pos)
- Math.pow( 1 - Math.sqrt(5), pos))
/ (Math.pow(2, pos) * Math.sqrt(5)));
};
/* This is only for the test */
var max = test.length,
i = 0,
frag = document.createDocumentFragment(),
_div = document.createElement('div'),
_text = document.createTextNode(''),
div,
text,
err,
num;
for ( ; i < max; i++) {
div = _div.cloneNode();
text = _text.cloneNode();
num = fib(i);
if (num !== test[i]) {
err = i + ' == ' + test[i] + '; got ' + num;
div.style.color = 'red';
}
text.nodeValue = i + ': ' + num;
div.appendChild(text);
frag.appendChild(div);
}
document.body.appendChild(frag);
You can get some cache to speedup the algorithm...
var tools = {
fibonacci : function(n) {
var cache = {};
// optional seed cache
cache[2] = 1;
cache[3] = 2;
cache[4] = 3;
cache[5] = 5;
cache[6] = 8;
return execute(n);
function execute(n) {
// special cases 0 or 1
if (n < 2) return n;
var a = n - 1;
var b = n - 2;
if(!cache[a]) cache[a] = execute(a);
if(!cache[b]) cache[b] = execute(b);
return cache[a] + cache[b];
}
}
};
If using ES2015
const fib = (n, prev = 0, current = 1) => n
? fib(--n, current, prev + current)
: prev + current
console.log( fib(10) )
If you need to build a list of fibonacci numbers easily you can use array destructuring assignment to ease your pain:
function fibonacci(n) {
let fibList = [];
let [a, b] = [0, 1]; // array destructuring to ease your pain
while (a < n) {
fibList.push(a);
[a, b] = [b, a + b]; // less pain, more gain
}
return fibList;
}
console.log(fibonacci(10)); // prints [0, 1, 1, 2, 3, 5, 8]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>fibonacci series</title>
<script type="text/javascript">
function generateseries(){
var fno = document.getElementById("firstno").value;
var sno = document.getElementById("secondno").value;
var a = parseInt(fno);
var result = new Array();
result[0] = a;
var b = ++fno;
var c = b;
while (b <= sno) {
result.push(c);
document.getElementById("maindiv").innerHTML = "Fibonacci Series between "+fno+ " and " +sno+ " is " +result;
c = a + b;
a = b;
b = c;
}
}
function numeric(evt){
var theEvent = evt || window.event;
var key = theEvent.keyCode || theEvent.which;
key = String.fromCharCode(key);
var regex = /[0-9]|\./;
if (!regex.test(key)) {
theEvent.returnValue = false;
if (theEvent.preventDefault)
theEvent.preventDefault();
}
}
</script>
<h1 align="center">Fibonacci Series</h1>
</head>
<body>
<div id="resultdiv" align="center">
<input type="text" name="firstno" id="firstno" onkeypress="numeric(event)"><br>
<input type="text" name="secondno" id="secondno" onkeypress="numeric(event)"><br>
<input type="button" id="result" value="Result" onclick="generateseries();">
<div id="maindiv"></div>
</div>
</body>
</html>
I know this is a bit of an old question, but I realized that many of the answers here are utilizing for loops rather than while loops.
Sometimes, while loops are faster than for loops, so I figured I'd contribute some code that runs the Fibonacci sequence in a while loop as well! Use whatever you find suitable to your needs.
function fib(length) {
var fibArr = [],
i = 0,
j = 1;
fibArr.push(i);
fibArr.push(j);
while (fibArr.length <= length) {
fibArr.push(fibArr[j] + fibArr[i]);
j++;
i++;
}
return fibArr;
};
fib(15);
sparkida, found an issue with your method. If you check position 10, it returns 54 and causes all subsequent values to be incorrect. You can see this appearing here: http://jsfiddle.net/createanaccount/cdrgyzdz/5/
(function() {
function fib(n) {
var root5 = Math.sqrt(5);
var val1 = (1 + root5) / 2;
var val2 = 1 - val1;
var value = (Math.pow(val1, n) - Math.pow(val2, n)) / root5;
return Math.floor(value + 0.5);
}
for (var i = 0; i < 100; i++) {
document.getElementById("sequence").innerHTML += (0 < i ? ", " : "") + fib(i);
}
}());
<div id="sequence">
</div>
Here are examples how to write fibonacci using recursion, generator and reduce.
'use strict'
//------------- using recursion ------------
function fibonacciRecursion(n) {
return (n < 2) ? n : fibonacciRecursion(n - 2) + fibonacciRecursion(n - 1)
}
// usage
for (let i = 0; i < 10; i++) {
console.log(fibonacciRecursion(i))
}
//-------------- using generator -----------------
function* fibonacciGenerator() {
let a = 1,
b = 0
while (true) {
yield b;
[a, b] = [b, a + b]
}
}
// usage
const gen = fibonacciGenerator()
for (let i = 0; i < 10; i++) {
console.log(gen.next().value)
}
//------------- using reduce ---------------------
function fibonacciReduce(n) {
return new Array(n).fill(0)
.reduce((prev, curr) => ([prev[0], prev[1]] = [prev[1], prev[0] + prev[1]], prev), [0, 1])[0]
}
// usage
for (let i = 0; i < 10; i++) {
console.log(fibonacciReduce(i))
}
I just would like to contribute with a tail call optimized version by ES6. It's quite simple;
var fibonacci = (n, f = 0, s = 1) => n === 0 ? f : fibonacci(--n, s, f + s);
console.log(fibonacci(12));
There is no need for slow loops, generators or recursive functions (with or without caching). Here is a fast one-liner using Array and reduce.
ECMAScript 6:
var fibonacci=(n)=>Array(n).fill().reduce((a,b,c)=>a.concat(c<2?c:a[c-1]+a[c-2]),[])
ECMAScript 5:
function fibonacci(n){
return Array.apply(null,{length:n}).reduce(function(a,b,c){return a.concat((c<2)?c:a[c-1]+a[c-2]);},[]);
}
Tested in Chrome 59 (Windows 10):
fibonacci(10); // 0 ms -> (10) [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
JavaScript can handle numbers up to 1476 before reaching Infinity.
fibonacci(1476); // 11ms -> (1476) [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, ...]
Another implementation, while recursive is very fast and uses single inline function. It hits the javascript 64-bit number precision limit, starting 80th sequence (as do all other algorithms):
For example if you want the 78th term (78 goes in the last parenthesis):
(function (n,i,p,r){p=(p||0)+r||1;i=i?i+1:1;return i<=n?arguments.callee(n,i,r,p):r}(78));
will return: 8944394323791464
This is backwards compatible all the way to ECMASCRIPT4 - I tested it with IE7 and it works!
This script will take a number as parameter, that you want your Fibonacci sequence to go.
function calculateFib(num) {
var fibArray = [];
var counter = 0;
if (fibArray.length == 0) {
fibArray.push(
counter
);
counter++
};
fibArray.push(fibArray[fibArray.length - 1] + counter);
do {
var lastIndex = fibArray[fibArray.length - 1];
var snLastIndex = fibArray[fibArray.length - 2];
if (lastIndex + snLastIndex < num) {
fibArray.push(lastIndex + snLastIndex);
}
} while (lastIndex + snLastIndex < num);
return fibArray;
};
This is what I came up with
//fibonacci numbers
//0,1,1,2,3,5,8,13,21,34,55,89
//print out the first ten fibonacci numbers
'use strict';
function printFobonacciNumbers(n) {
var firstNumber = 0,
secondNumber = 1,
fibNumbers = [];
if (n <= 0) {
return fibNumbers;
}
if (n === 1) {
return fibNumbers.push(firstNumber);
}
//if we are here,we should have at least two numbers in the array
fibNumbers[0] = firstNumber;
fibNumbers[1] = secondNumber;
for (var i = 2; i <= n; i++) {
fibNumbers[i] = fibNumbers[(i - 1)] + fibNumbers[(i - 2)];
}
return fibNumbers;
}
var result = printFobonacciNumbers(10);
if (result) {
for (var i = 0; i < result.length; i++) {
console.log(result[i]);
}
}
Beginner, not too elegant, but shows the basic steps and deductions in JavaScript
/* Array Four Million Numbers */
var j = [];
var x = [1,2];
var even = [];
for (var i = 1;i<4000001;i++){
j.push(i);
}
// Array Even Million
i = 1;
while (i<4000001){
var k = j[i] + j[i-1];
j[i + 1] = k;
if (k < 4000001){
x.push(k);
}
i++;
}
var total = 0;
for (w in x){
if (x[w] %2 === 0){
even.push(x[w]);
}
}
for (num in even){
total += even[num];
}
console.log(x);
console.log(even);
console.log(total);
My 2 cents:
function fibonacci(num) {
return Array.apply(null, Array(num)).reduce(function(acc, curr, idx) {
return idx > 2 ? acc.concat(acc[idx-1] + acc[idx-2]) : acc;
}, [0, 1, 1]);
}
console.log(fibonacci(10));
I would like to add some more code as an answer :), Its never too late to code :P
function fibonacciRecursive(a, b, counter, len) {
if (counter <= len) {
console.log(a);
fibonacciRecursive(b, a + b, counter + 1, len);
}
}
fibonacciRecursive(0, 1, 1, 20);
Result
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181
function fibo(count) {
//when count is 0, just return
if (!count) return;
//Push 0 as the first element into an array
var fibArr = [0];
//when count is 1, just print and return
if (count === 1) {
console.log(fibArr);
return;
}
//Now push 1 as the next element to the same array
fibArr.push(1);
//Start the iteration from 2 to the count
for(var i = 2, len = count; i < len; i++) {
//Addition of previous and one before previous
fibArr.push(fibArr[i-1] + fibArr[i-2]);
}
//outputs the final fibonacci series
console.log(fibArr);
}
Whatever count we need, we can give it to above fibo method and get the fibonacci series upto the count.
fibo(20); //output: [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181]
Fibonacci (one-liner)
function fibonacci(n) {
return (n <= 1) ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
Fibonacci (recursive)
function fibonacci(number) {
// n <= 1
if (number <= 0) {
return n;
} else {
// f(n) = f(n-1) + f(n-2)
return fibonacci(number - 1) + fibonacci(number - 2);
}
};
console.log('f(14) = ' + fibonacci(14)); // 377
Fibonacci (iterative)
function fibonacci(number) {
// n < 2
if (number <= 0) {
return number ;
} else {
var n = 2; // n = 2
var fn_1 = 0; // f(n-2), if n=2
var fn_2 = 1; // f(n-1), if n=2
// n >= 2
while (n <= number) {
var aa = fn_2; // f(n-1)
var fn = fn_1 + fn_2; // f(n)
// Preparation for next loop
fn_1 = aa;
fn_2 = fn;
n++;
}
return fn_2;
}
};
console.log('f(14) = ' + fibonacci(14)); // 377
Fibonacci (with Tail Call Optimization)
function fibonacci(number) {
if (number <= 1) {
return number;
}
function recursion(length, originalLength, previous, next) {
if (length === originalLength)
return previous + next;
return recursion(length + 1, originalLength, next, previous + next);
}
return recursion(1, number - 1, 0, 1);
}
console.log(`f(14) = ${fibonacci(14)}`); // 377

Categories

Resources