I am currently working on my investigation for my Extended Essay. I am testing the comparison between the merge and quick sorting algorithms. I am having this weird anomaly with my results. Every first sort in my second for loop return a much higher time taken than the rest. I have no clue why, could someone maybe explain?
For some reason, JSFiddle will not output anything, though when I run it locally it works fine. So, I'll just post the code here:
function generateRandomArray(l, min, max) {
var a = [];
for (var i = 0; i < l; i++) {
a.push(Math.ceil(Math.random() * max + min - 1));
}
return a;
}
function quickSort(a) {
var less = [],
pivotList = [],
greater = [];
if (a.length <= 1) return a;
var pivot = a[0];
for (var i = 0; i < a.length; i++) {
if (a[i] < pivot) less.push(a[i]);
else if (a[i] > pivot) greater.push(a[i]);
else pivotList.push(a[i]);
}
less = quickSort(less);
greater = quickSort(greater);
return less.concat(pivotList, greater);
}
function mergeSort(left, right) {
if (!left) return right;
if (!right) return left;
var result = [],
leftIndex = 0,
rightIndex = 0;
while (leftIndex < left.length & rightIndex < right.length) {
if (left[leftIndex] <= right[rightIndex]) {
result.push(left[leftIndex]);
leftIndex++;
} else {
result.push(right[rightIndex]);
rightIndex++;
}
}
if (leftIndex != left.length) {
var temp = left.slice(leftIndex, left.length);
result = result.concat(temp);
} else if (rightIndex != right.length) {
var temp = right.slice(rightIndex, right.length);
result = result.concat(temp);
}
return result;
}
function mergeSortSplit(a) {
if (a.length <= 1) return a;
var middle = Math.floor(a.length / 2);
var left = a.slice(0, middle),
right = a.slice(middle, a.length);
left = mergeSortSplit(left);
right = mergeSortSplit(right);
return mergeSort(left, right);
}
window.onload = function() {
var timeResults = [
[[], [], [], [], []],
[[], [], [], [], []]
];
for (var i = 0; i < 10; i++) {
for (var j = 3; j < 6; j++) {
var array = generateRandomArray(Math.pow(10, j), 1, 100);
var mergeSortTime = window.performance.now();
mergeSortSplit(array);
timeResults[0][j - 3].push(window.performance.now() - mergeSortTime);
var quickSortTime = window.performance.now();
quickSort(array);
timeResults[1][j - 3].push(window.performance.now() - quickSortTime);
}
}
for (var i = 0; i < timeResults.length; i++) {
document.getElementById("demo").innerHTML += "<b>" + (i + 1) + ". </b><br>";
for (var j = 0; j < timeResults[i].length; j++) {
document.getElementById("demo").innerHTML += "<b>" + Math.pow(10, j + 3) + ": </b>";
for (k = 0; k < timeResults[i][j].length; k++) {
document.getElementById("demo").innerHTML += timeResults[i][j][k] + "<b> | </b>";
}
document.getElementById("demo").innerHTML += "<br><br>";
}
document.getElementById("demo").innerHTML += "<br><br><br>";
}
console.log(timeResults);
}
<html>
<head>
<meta charset="utf-8">
<title>EE Investigation</title>
<script type="text/javascript" src="index.js"></script>
</head>
<body>
<p id="demo"></p>
</body>
</html>
Related
My code currently has a bug where my 2-d array with the bool value false suddenly contains true values before it is assigned any. My current guesses is either console.log somehow is delayed and picks up the values after it is called, with the updated values or that there is some issue that I don't understand about how scope works in javascript.
As seen below console.log(visited[i][j]) results in false for all values but the
new visited line contains true values even before the following is called.
const field_size = 800;
const cells_in_row = 5;
const frames_per_second = 1;
const cell_size = field_size / cells_in_row;
class Cell {
constructor(x,y) {
this.value = 0;
this.x = x;
this.y = y;
this.coordinates = [x*cell_size,y*cell_size];
}
fill() {
this.value = 1;
}
clear() {
this.value = 0;
}
}
const get_new_grid = (random = 0) => {
const grid = new Array(cells_in_row);
for (let i = 0; i < grid.length; i++) {
grid[i] = new Array(cells_in_row);
for (let j = 0; j < grid.length; j++) {
grid[i][j] = new Cell(i,j);
v = 0;
if (random) {
v = Math.floor(Math.random() * 2);
}
grid[i][j].value = v;
}
}
return grid;
}
const get_islands = (grid) => {
// bool array to mark visited cells
let visited = new Array(cells_in_row);
for (let i = 0; i < grid.length; i++) {
visited[i] = new Array(cells_in_row);
for (let j = 0; j < grid[0].length; j++) {
visited[i][j] = false;
}
}
console.log("New Visited", visited);
let count = 0;
let islands = [];
let island_coords = [];
for (let i = 0; i < grid.length; i++) {
for (let j = 0; j < grid.length; j++) {
if (visited[i][j] == false && grid[i][j].value == 1) {
// visit all cells in this island and increment island count
// dfs will return array of coordinates of island
[visited, island_coords] = dfs(i, j, grid, visited, island_coords);
console.log(visited);
islands.push(island_coords);
count += 1;
}
}
}
return [count, islands];
}
const dfs = (i, j, grid, visited, island_coords) => {
let row_nbr = [-1, -1, -1, 0, 0, 1, 1, 1];
let col_nbr = [-1, 0, 1, -1, 1, -1, 0, 1];
visited[i][j] = true;
island_coords.push([i,j]);
for (let k = 0; k < 8; k++) {
if (is_safe(i + row_nbr[k], j + col_nbr[k], grid, visited)) {
console.log("DFSing " + i + "," + j);
[visited, island_coords] = dfs(i + row_nbr[k], j + col_nbr[k],
grid, visited, island_coords);
}
}
return [visited, island_coords];
}
const is_safe = (i, j, grid, visited) => {
return (i >= 0 && i < grid.length &&
j >= 0 && j < grid.length &&
!(visited[i][j]) && grid[i][j].value === 1);
}
(function () {
var old = console.log;
var logger = document.getElementById('log');
console.log = function () {
for (var i = 0; i < arguments.length; i++) {
if (typeof arguments[i] == 'object') {
logger.innerHTML += (JSON && JSON.stringify ? JSON.stringify(arguments[i], undefined, 2) : arguments[i]) + '<br />';
} else {
logger.innerHTML += arguments[i] + '<br />';
}
}
}
})();
window.onload = () => {
const canvas = document.getElementById('canvas');
const grid = get_new_grid(random = 0);
grid[0][0].value = true;
grid[0][1].value = true;
grid[1][0].value = true;
grid[1][1].value = true;
const islands = get_islands(grid);
console.log(grid);
console.log(islands);
}
<!DOCTYPE html>
<html>
<body>
<script src="gameoflife.js"></script>
<pre id="log"></pre>
</body>
</html>
EDIT:
So I updated the snippet but it looks like it works on this end, however it shows the behavior I mentioned before on my own browser even with the exact same javascript code and html in the snippet.
Mentioned in the comments by Niet, objects logged to the console are live.
My HW assignment requires me to have a user enter integers and for it to come out on the HTML in sorted array without the sort method. I have this code and it asks the users input but the integers do not come up on page.
<script type="text/javascript">
var arr = [];
function addNum() {
var n = prompt("How many integrs?", "0");
var num = parseInt(n);
for (var i = 0; i < num; i++) {
arr[i] = parseInt(prompt("Enter next integer: ","0"));
}
var outputSorted = document.getElementById('outputSorted');
outputSorted = "";
outputSorted.append("Input array : ");
for (var i = 0; i < num; i++) {
outputSorted.append(arr[i]+" ");
}
bubbleSort(arr);
outputSorted.append("Sorted array : ");
for (var i = 0; i < num; i++) {
outputSorted.append(arr[i]+" ");
}
}
function bubbleSort(a) {
var swapped;
do {
swapped = false;
for (var i=0; i < a.length - 1; i++) {
if (a[i] > a[i+1]) {
var temp = a[i];
a[i] = a[i+1];
a[i+1] = temp;
swapped = true;
}
}
} while (swapped);
}
function searchNum() {
var m = parseInt(prompt("Enter num to be searched: ","0"));
var found = binarySearch(arr, m);
var outputSearch = document.getElementById('outputSearch');
if (found == -1) {
outputSearch.append("Number not found");
} else {
outputSearch.append("Number found at index : " + (found + 1));
}
}
function binarySearch(array, targetValue) {
var min = 0;
var max = array.length - 1;
var guess;
while (min <= max) {
guess = Math.floor((max + min) / 2);
if (array[guess] === targetValue) {
return guess;
}
else if (array[guess] < targetValue) {
min = guess + 1;
}
else {
max = guess - 1;
}
}
return -1;
}
</script>
outputSorted is a DOM element, and append() is not a function of that element. Rather than that, use innerHTML += for each bit you want to add. See below. And note, those are the ONLY changes I made. So your ugly rendered HTML is what it is.
var arr = [];
addNum = function addNum() {
var n = prompt("How many integrs?", "0");
var num = parseInt(n);
for (var i = 0; i < num; i++) {
arr[i] = parseInt(prompt("Enter next integer: ", "0"));
}
var outputSorted = document.getElementById('outputSorted');
outputSorted.innerHTML += "Input array : "
for (var i = 0; i < num; i++) {
outputSorted.innerHTML += arr[i] + " ";
}
bubbleSort(arr);
outputSorted.innerHTML += "Sorted array : ";
for (var i = 0; i < num; i++) {
outputSorted.innerHTML += arr[i] + " ";
}
}
function bubbleSort(a) {
var swapped;
do {
swapped = false;
for (var i = 0; i < a.length - 1; i++) {
if (a[i] > a[i + 1]) {
var temp = a[i];
a[i] = a[i + 1];
a[i + 1] = temp;
swapped = true;
}
}
} while (swapped);
}
function searchNum() {
var m = parseInt(prompt("Enter num to be searched: ", "0"));
var found = binarySearch(arr, m);
var outputSearch = document.getElementById('outputSearch');
if (found == -1) {
outputSearch.innerHTML += ("Number not found");
} else {
outputSearch.innerHTML += ("Number found at index : " + (found + 1));
}
}
function binarySearch(array, targetValue) {
var min = 0;
var max = array.length - 1;
var guess;
while (min <= max) {
guess = Math.floor((max + min) / 2);
if (array[guess] === targetValue) {
return guess;
} else if (array[guess] < targetValue) {
min = guess + 1;
} else {
max = guess - 1;
}
}
return -1;
}
<button onclick="addNum()">
Add some!
</button>
<div id="outputSorted">
</div>
<div id="outputSearch">
</div>
The function is returning undefined why it's not returning the array length.even at the start of the code it's printing in the console but return is not working.
var resArr = [];
var p;
function persistence(num) {
resArr.push(num);
console.log(resArr);
console.log(resArr.length);
if (num > 10) {
var v = 1;
var x = num.toString();
var arr = [];
for (i = 0; i < x.length; i++) {
arr.push(x.charAt(i));
}
console.log(arr);
for (j = 0; j < arr.length; j++) {
var v = v * arr[j];
}
persistence(v);
} else {
return resArr.length - 1;
}
}
You're not returning in all cases.
Change
persistence(v);
to
return persistence(v);
I'm having a little trouble with my attempt at this problem. Code Below:
function pasc(n){
var result = [[1]];
for (var row = 1; row < n; row++){
for (var col = 1; col <= row; col++){
result[row][col] = result[row - 1][col] + result[row - 1][col - 1];
}
}
return result;
}
pasc(10)
for (var i = 0; i < result.length; i++){
document.write(result[i]+"<br>");
}
It seems the problem hinges on assigning values to an array using an expression like myArray[1][1] = "foo"
I'm confused about this because I can do this: var myArray = []; myArray[4] = "foo" which seems to suggest that an element can be created at an arbitrary position in a 1 dimensional array, but not with 2 dimensions.
Any help with clearing up my misconceptions appreciated.
The Pascal's Triangle can be printed using recursion
Below is the code snippet that works recursively.
We have a recursive function pascalRecursive(n, a) that works up till the number of rows are printed. Each row is a element of the 2-D array ('a' in this case)
var numRows = 10,
triangle,
start,
stop;
// N is the no. of rows/tiers
// a is the 2-D array consisting of the row content
function pascalRecursive(n, a) {
if (n < 2) return a;
var prevRow = a[a.length-1];
var curRow = [1];
for (var i = 1; i < prevRow.length; i++) {
curRow[i] = prevRow[i] + prevRow[i-1];
}
curRow.push(1);
a.push(curRow);
return pascalRecursive(n-1, a); // Call the function recursively
}
var triangle = pascalRecursive(numRows, [[1]]);
for(var i = 0; i < triangle.length; i++)
console.log(triangle[i]+"\n");
JavaScript doesn't have two-dimensional arrays. What it does have is arrays that happen to contain other arrays. So, yes, you can assign a value to any arbitrary position in an array, and the array will magically make itself big enough, filling in any gaps with 'undefined'... but you can't assign a value to any position in a sub-array that you haven't explicitly created yet. You have to assign sub-arrays to the positions of the first array before you can assign values to the positions of the sub-arrays.
Replacing
for (var row = 1; row < n; row++){
for (var col = 1; col <= row; col++){
with
for (var row = 1; row < n; row++){
result[row] = [];
for (var col = 1; col <= row; col++){
should do it. Assuming all of your indexing logic is correct, anyway. You've got some problems there, too, since your initial array only contains a single value, so result[row][col] = result[row - 1][col] + result[row - 1][col - 1]; is accessing at least one cell that has never been defined.
Thanks Logan R. Kearsley. I have now solved it:
function pasc(n){
var result = [];
result[0] = [1];
result[1] = [1,1];
for (var row = 2; row < n; row++){
result[row] = [1];
for (var col = 1; col <= row -1; col++){
result[row][col] = result[row-1][col] + result[row-1][col-1];
result[row].push(1);
}
}
return result;
}
for (var i = 0; i < pasc(10).length; i++){
document.write(pasc(10)[i]+"<br>");
console.log(pasc(10)[i]+"<br>");
}
you can create Pascal's triangle using below code:
function pascal(n) {
var arr = [];
if (n == 1) {
arr[0] = [];
arr[0][0] = 1;
} else if (n == 2) {
arr[0] = [];
arr[0][0] = 1;
arr[1] = [];
arr[1][0] = 1;
arr[1][1] = 1;
} else if (n > 2) {
arr[0] = [];
arr[1] = [];
arr[0][0] = 1;
arr[1][0] = 1;
arr[1][1] = 1;
for (i = 2; i < n; i++) {
arr[i] = [];
arr[i][0] = 1;
for (j = 1; j < i; j++) {
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
}
arr[i][j] = 1;
}
}
console.log(arr);
for (i = 0; i < arr.length; i++) {
console.log(arr[i].join(' '))
}
}
function pascal(n) {
var arr = [];
if (n == 1) {
arr[0] = [];
arr[0][0] = 1;
} else if (n == 2) {
arr[0] = [];
arr[0][0] = 1;
arr[1] = [];
arr[1][0] = 1;
arr[1][1] = 1;
} else if (n > 2) {
arr[0] = [];
arr[1] = [];
arr[0][0] = 1;
arr[1][0] = 1;
arr[1][1] = 1;
for (i = 2; i < n; i++) {
arr[i] = [];
arr[i][0] = 1;
for (j = 1; j < i; j++) {
arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j];
}
arr[i][j] = 1;
}
}
console.log(arr);
for (i = 0; i < arr.length; i++) {
console.log(arr[i].join(' '))
}
}
pascal(5)
This function will calculate Pascal's Triangle for "n" number of rows. It will create an object that holds "n" number of arrays, which are created as needed in the second/inner for loop.
function getPascalsTriangle(n) {
var arr = {};
for(var row = 0; row < n; row++) {
arr[row] = [];
for(var col = 0; col < row+1; col++) {
if(col === 0 || col === row) {
arr[row][col] = 1;
} else {
arr[row][col] = arr[row-1][col-1] + arr[row-1][col];
}
}
}
return arr;
}
console.log(getPascalsTriangle(5));
Floyd triangle
You can try the following code for a Floyd triangle
var prevNumber=1,i,depth=10;
for(i=0;i<depth;i++){
tempStr = "";j=0;
while(j<= i){
tempStr = tempStr + " " + prevNumber;
j++;
prevNumber++;
}
console.log(tempStr);
}
You can create arbitrary 2d arrays and store it in there and return the correct Pascal.
JavaScript does not have a special syntax for creating multidimensional arrays. A common workaround is to create an array of arrays in nested loops.
source
Here is my version of the solution
function pascal(input) {
var result = [[1], [1,1]];
if (input < 0) {
return [];
}
if (input === 0) {
return result[0];
}
for(var j = result.length-1; j < input; j++) {
var newArray = [];
var firstItem = result[j][0];
var lastItem = result[j][result[j].length -1];
newArray.push(firstItem);
for (var i =1; i <= j; i++) {
console.log(result[j][i-1], result[j][i]);
newArray.push(sum(result[j][i-1], result[j][i]));
}
newArray.push(lastItem);
result.push(newArray);
}
return result[input];
}
function sum(one, two) {
return one + two;
}
Here is the code i created for pascal triangle in javascript
'use strict'
let noOfCoinFlipped = 5
let probabiltyOfnoOfHead = 2
var dataStorer = [];
for(let i=0;i<=noOfCoinFlipped;i++){
dataStorer[i]=[];
for(let j=0;j<=i;j++){
if(i==0){
dataStorer[i][j] = 1;
}
else{
let param1 = (j==0)?0:dataStorer[i-1][j-1];
let param2 = dataStorer[i-1][j]?dataStorer[i-1][j]:0;
dataStorer[i][j] = param1+param2;
}
}
}
let totalPoints = dataStorer[noOfCoinFlipped].reduce((s,n)=>{return s+n;})
let successPoints = dataStorer[noOfCoinFlipped][probabiltyOfnoOfHead];
console.log(successPoints*100/totalPoints)
Here is the link as well
http://rextester.com/TZX59990
This is my solve:
function pascalTri(n){
let arr=[];
let c=0;
for(let i=1;i<=n;i++){
arr.push(1);
let len=arr.length;
if(i>1){
if(i>2){
for(let j=1;j<=(i-2);j++){
let idx=(len-(2*i)+j+2+c);
let val=arr[idx]+arr[idx+1];
arr.push(val);
}
c++;
}
arr.push(1);
}
}
return arr;
}
let pascalArr=pascalTri(7);
console.log(pascalArr);
here is the pattern for n = 3
#
##
###
here is js code to print this.
function staircase(n) {
for(var i=0 ; i<n ; i++) {
for(var j=n-1 ; j>i ; j--)
process.stdout.write(" ");
for(var k=0 ; k<=i; k++) {
process.stdout.write("#");
}
process.stdout.write("\n");
}
}
class PascalTriangle {
constructor(n) {
this.n = n;
}
factoriel(m) {
let result = 1;
if (m === 0) {
return 1;
}
while (m > 0) {
result *= m;
m--;
}
return result;
}
fill() {
let arr = [];
for (let i = 0; i < this.n; i++) {
arr.push([]);
}
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j <= i; j++) {
arr[i].push(this.factoriel(i) / (this.factoriel(j) * this.factoriel(i - j)));
}
}
return arr;
}
}
var m = prompt("enter number:");
var arrMain = new Array();
for (var i = 0; i < m; i++) {
arrMain[i] = [];
}
for (var i = 0; i < m; i++) {
if (i == 0) {
arrMain[i] = [1];
} else if (i == 1) {
(arrMain[i]) = [1, 1];
} else {
for (var j = 0; j <= i; j++) {
if (j == 0 || j == arrMain[i - 1].length) {
arrMain[i][j] = 1;
} else {
arrMain[i][j] = arrMain[i - 1][j] + arrMain[i - 1][j - 1];
}
}
}
document.write(arrMain[i] + "<br>");
}
This is my take on this problem by gaining access to the previous row.
const generate = numRows => {
const triangle = [[1]]
for (let i = 1; i < numRows; i++) {
// Previous row
const previous = triangle[i - 1]
// Current row
const current = new Array(i + 1).fill(1)
// Populate the current row with the previous
// row's values
for (let j = 1; j < i; j++) {
current[j] = previous[j - 1] + previous[j]
}
// Add to triangle result
triangle.push(current)
}
return triangle
}
I have a strange problem with my alghoritm, which work if array size less than 114468 and doesn't work if more than 114468. Browse with google chrome. Can't understand why =\ Here is the code:
Generate array:
var arr = [];
var res = [];
for (var i = 114467; i > 0; i--) {
arr.push([i - 1, i]);
}
Find first elem in array to sort:
for (var i = 0, j = arr.length; i < j && res.length == 0; i++) {
var found = false;
for (var m = 0; m < j; m++) {
if (i == m || arr[i][0] == arr[m][1] || arr[i][1] == arr[m][0]) {
found = true;
break;
}
if (!found) {
res.push(arr[m]);
arr.splice(m, 1);
}
}
}
Sorting:
do {
for (var i = 0, j = arr.length; i < j; i++) {
var resLength = res.length - 1;
if (arr[i][1] == res[resLength][0] || arr[i][0] == res[resLength][1]) {
res.push(arr[i]);
arr.splice(i, 1);
break;
}
}
} while (arr.length > 0);
On the step sorting it stops to work.
All code:
var t = function () {
var arr = [];
var res = [];
for (var i = 114467; i > 0; i--) {
arr.push([i - 1, i]);
}
var startsec = new Date().getSeconds();
var startmilsec = new Date().getMilliseconds();
document.write(startsec + '.' + startmilsec + '<br>');
for (var i = 0, j = arr.length; i < j && res.length == 0; i++) {
var found = false;
for (var m = 0; m < j; m++) {
if (i == m || arr[i][0] == arr[m][1] || arr[i][1] == arr[m][0]) {
found = true;
break;
}
if (!found) {
res.push(arr[m]);
arr.splice(m, 1);
}
}
}
do {
for (var i = 0, j = arr.length; i < j; i++) {
var resLength = res.length - 1;
if (arr[i][1] == res[resLength][0] || arr[i][0] == res[resLength][1]) {
res.push(arr[i]);
arr.splice(i, 1);
break;
}
}
} while (arr.length > 0);
var stopsec = new Date().getSeconds();
var stopmilsec = new Date().getMilliseconds();
document.write(stopsec + '.' + stopmilsec + '<br>');
var executionTime = (stopsec - startsec).toString() + "s" + (stopmilsec - startmilsec).toString() + "'ms";
document.write(executionTime + '<br>');
} ();
Do i get my memory limit?
Alright, I isolated the problem. It seems that splice(0,1) slows down astronomically when the array size increases from 114467 to 114468.
Using this custom benchmark:
var t;
function startBench(){t=new Date().getTime();}
function stopBench(){console.log(new Date().getTime()-t);}
var arr=[];
for (var i = 114467; i > 0; i--) {
arr.push([i - 1, i]);
}
var arr2=[];
for (var i = 114468; i > 0; i--) {
arr2.push([i - 1, i]);
}
startBench();
for(i=0;i<1000;i++){
arr.splice(0,1);
}
stopBench();
startBench();
for(i=0;i<1000;i++){
arr2.splice(0,1);
}
stopBench();
I get 3 ms for 114467 and 2740ms for 114468 on Chrome (1000 iterations), but 170 each on Firefox. Maybe you ought to be using a different way to remove elements? Using a variant of bubble sort may work better.
I've submitted a bug report on this. Looking at the reply, it seems to be a valid bug. Hopefully it'll be fixed.