While trying to solve this project euler problem (using Google chrome - snippets feature in developer tools to code and execute) , I encountered a strange behavior.
var palFound = false;
isPal = function (word) {
var wordCount = word.length;
for (i = 0; i < wordCount; i++) {
if (word[i] != word[wordCount - i - 1]) {
return false;
}
}
return true;
}
for (var k = 999; k >= 100; k--) {
for (var j = 999; j >= 100; j--) {
var prod = k * j,
prodString = prod + '';
if (isPal(prodString)) {
console.log(prod, k, j);
palFound = true;
break;
}
}
if (palFound) {
break;
}
}
Above code should ideally display the first encountered palindrome product and should break.But when executed the above code displays a wrong answer 580085 which is a product of 995 and 583.
But when the for loops limit are changed to 999 to 900 (as shown below), correct answer is displayed - 906609 which is a product of 993 and 913.
for(var k=999;k >=900;k--){
for(var j=999;j>=900;j--)
ideally, 993 and 913 should be encountered first, instead of 995 and 583. I am curious to know why is this happening?.
For each k value in your outer loop your inner loop counts down from 999 to 100, so when k is 995 then j counts down to 583 finds a palindrome and the code breaks out of your loop.
When you amend j to only count down to 900 it does not reach 583 and so the first palidrome you now reach is 993 * 913.
Related
I have the given code:
function fill_random() {
let field = document.getElementsByClassName("field")
let random
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
random = Math.floor(1 + Math.random() * 9)
if (check(random))
field[j + (i * 9)].innerHTML = `${random}`
else
j--
}
}
}
function check(random) {
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (parseInt(document.getElementsByClassName("field")[j + (i * 9)].innerHTML) === random) {
console.log("Match!")
return false
}
}
}
return true
}
random is a let filled with
Math.floor(1 + Math.random() * 9)
When I try to execute it, the page won't load. When I try without parseInt() the page and everything else works but the if-condition never matches.
Obviously because I cant compare the innterHTML to an int.
So how to correctly cast the innerHTML to an int?
EDIT
Added more code as requested in the comments.
By "page won't load" I mean the page is loading forever. After few seconds the browser (Chrome latest version, no addons) asks me to leave the page or wait.
In the state of waiting it wont let me open developer tools.
The output of
console.log(document.getElementsByClassName("field")[j + (i * 9)].innerHTML)
gives a Number from 1 to 9 as string. Which is what I expect. Maybe my problem is not the parseInt() function but something else I can't figure out.
If you are having problems with the parseInt function, you could remove it and use a loose equality comparison (== instead of ===).
function check(random) {
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (document.getElementsByClassName("field")[j + (i * 9)].innerHTML == random) {
console.log("Match!")
return false
}
}
}
return true
}
I'm trying to get N ways of solves a N rook problem. The issue I am having is currently, I seem to get n*n solutions while it needs to be N! . Below is my code, I have written it in simple loops and functions, so it's quite long. Any help would be greatly appreciated
Note: Please ignore case for n = 2. I get some duplicates which I thought I would handle via JSON.stringify
var createMatrix = function (n) {
var newMatrix = new Array(n);
// build matrix
for (var i = 0; i < n; i++) {
newMatrix[i] = new Array(n);
}
for (var i = 0; i < n; i++) {
for (var j = 0; j < n; j++) {
newMatrix[i][j] = 0;
}
}
return newMatrix;
};
var newMatrix = createMatrix(n);
// based on rook position, greying out function
var collision = function (i, j) {
var col = i;
var row = j;
while (col < n) {
// set the row (i) to all 'a'
col++;
if (col < n) {
if (newMatrix[col][j] !== 1) {
newMatrix[col][j] = 'x';
}
}
}
while (row < n) {
// set columns (j) to all 'a'
row++;
if (row < n) {
if (newMatrix[i][row] !== 1) {
newMatrix[i][row] = 'x';
}
}
}
if (i > 0) {
col = i;
while (col !== 0) {
col--;
if (newMatrix[col][j] !== 1) {
newMatrix[col][j] = 'x';
}
}
}
if (j > 0) {
row = j;
while (row !== 0) {
row--;
if (newMatrix[i][row] !== 1) {
newMatrix[i][row] = 'x';
}
}
}
};
// checks position with 0 and sets it with Rook
var emptyPositionChecker = function (matrix) {
for (var i = 0; i < matrix.length; i++) {
for (var j = 0; j < matrix.length; j++) {
if (matrix[i][j] === 0) {
matrix[i][j] = 1;
collision(i, j);
return true;
}
}
}
return false;
};
// loop for every position on the board
loop1:
for (var i = 0; i < newMatrix.length; i++) {
var row = newMatrix[i];
for (var j = 0; j < newMatrix.length; j++) {
// pick a position for rook
newMatrix[i][j] = 1;
// grey out collison zones due to the above position
collision(i, j);
var hasEmpty = true;
while (hasEmpty) {
//call empty position checker
if (emptyPositionChecker(newMatrix)) {
continue;
} else {
//else we found a complete matrix, break
hasEmpty = false;
solutionCount++;
// reinitiaze new array to start all over
newMatrix = createMatrix(n);
break;
}
}
}
}
There seem to be two underlying problems.
The first is that several copies of the same position are being found.
If we consider the case of N=3 and we visualise the positions by making the first rook placed red, the second placed green and the third to be placed blue, we get these three boards:
They are identical positions but will count as 3 separate ones in the given Javascript.
For a 3x3 board there are also 2 other positions which have duplicates. The gets the count of unique positions to 9 - 2 - 1 -1 = 5. But we are expecting N! = 6 positions.
This brings us to the second problem which is that some positions are missed. In the case of N=3 this occurs once when i===j==1 - ie the mid point of the board.
This position is reached:
This position is not reached:
So now we have the number of positions that should be found as 9 - 2 - 1 - 1 +1;
There appears to be nothing wrong with the actual Javascript in as much as it is implementing the given algorithm. What is wrong is the algorithm which is both finding and counting duplicates and is missing some positions.
A common way of solving the N Rooks problem is to use a recursive method rather than an iterative one, and indeed iteration might very soon get totally out of hand if it's trying to evaluate every single position on a board of any size.
This question is probably best taken up on one of the other stackexchange sites where algorithms are discussed.
I've got 5 sheets - 1 main sheet and 4 sheets for data. The 4 sheets hold a column of W's and L's, and the main sheet has 8 cells to keep track of these - one cell for each # of W's and # of L's. I'm trying to do so with the following script and then calling the methods in the respective cells of the main sheet.
function totalWins(data) {
var win = 0;
for(var i = 0; i < data.length; i = + 1) {
if(data[i][0] = "W") {
win = win + 1;
}
}
return win;
}
function totalLosses(data) {
var loss = 0;
for(var i = 0; i < data.length; i = + 1) {
if(data[i][0] = "L") {
loss = loss + 1;
}
}
return loss;
}
I get the Internal error executing the custom function. error, which means the code takes longer than 30 seconds to run through the column (n = 100) in one of the four sheets. I really can't figure out why it does this. Any help is appreciated!
You need to increment i. Without you assign +1 to i and the loop takes only the first two values and loops forever with i === 1.
for (var i = 0; i < data.length; i = i + 1) {
// ^
or a bit shorter
for (var i = 0; i < data.length; ++i) {
As mentioned in the comments by TheWizEd, you assign a value if the if statement, where you should compare the value
if (data[i][0] === "W") {
// ^^ strict comparison
You placed + at wrong place in your code
for (var i = 0; i < data.length; i = + 1) {
// ^
|____ This makes acts as `+` sign
So in this case you're not actually incrementing your index so you loop keep on running
change to this
for (var i = 0; i < data.length; i += 1) {
// ^
|_____ This acts as `addition`
Or simply use i++
Fixed it by changing the counters win = win + 1 and loss = loss + 1 to win +=1 and loss +=1. Also with the above increments.
The task is the following: "Write a JavaScript program to find the shortest possible string which can create a string to make it a palindrome by adding characters to the end of it."
This is the code I am looking at:
function build_Palindrome(new_str) {
var flag;
for (var i = new_str.length;; i++) {
flag = true;
for (var j = 0; j < i - j - 1; j++) {
if (i - j - 1 < new_str.length && new_str[j] != new_str[i - j - 1]) {
flag = false;
break;
}
}
if (flag) {
for (var j = new_str.length; j < i; j++) {
new_str += new_str[i - j - 1];
}
return new_str;
}
}
}
Test:
console.log(build_Palindrome("abcddc"))
Output:
abcddcba
My question: At first it starts with j=0. If in the for loop, flag=false, then how does it proceed? Is i=7 (i++?) and is j=0 or j=1?
Yes, you can use console.log or any debugger to debug.
For your situation, you if the flag is false, it will break the loop of j and go to its outer loop (i here)
I made the demo here:
https://repl.it/repls/LoyalProfuseRouter
You can see the demo (it come with my solution), and instead of break you can use simple loop to return your string, it more readable.
I am half asleep so I may be overlooking something over here but what is happening is very odd. I implemented the Selection Sort algorithm from Wikipedia in JavaScript. You can view the code here under or at jsbin
The Problem
I am populating an array with a for loop with 10000 randomly generated numbers because it takes that many to show the issue. The algorithm works as expected with anything under 9800. However, with 10000 numbers and an empty unsorted array var unsorted = []; the last numbers are alternating like this 9, 10, 9, 10, 9, 10, 9, 10 .... If I initialize the unsorted array with at least one element i.e var unsorted = [1];, the alternating problem is fixed.
So, why is this happening and why is it happening when the unsorted array contains at least 9800 numbers and why is it fixed when i initialize the unsorted array with at least one number before populating it through the for loop?
Edit
The problem doesn't seem to always happen so if everything looks sorted the first time you try, then try a few more times. Also, i've tested it on Edge, Firefox and Opera with the problem occurring across browsers. (latest versions as of now)
var unsorted = [];
for (let i = 0; i < 10000; i++) {
unsorted[i] = Math.floor(Math.random() * 11);
}
for (let j = 0; j < unsorted.length; j++) {
let min = j;
for (let i = j + 1; i < unsorted.length; i++) {
if (unsorted[i] < unsorted[min]) {
min = i;
}
}
if (min != j) {
[unsorted[j], unsorted[min]] = [unsorted[min], unsorted[j]]
}
}
console.log(unsorted);
Edit: A Test With C
I've been learning C this month and i translated the code to see how it behaves in a different language. The answer - there is no problem. Everything is sorted just fine. Here is the code for those who like to compare. This does not mean that i am not interested in understanding why the problem happens in JavaScript
and not in C.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
int arrLen = 10000;
int unsorted[arrLen];
time_t t;
srand((unsigned) time(&t));
for (int i = 0; i < arrLen; i++)
{
unsorted[i] = rand() % 11;
}
for (int j = 0; j < arrLen; j++)
{
int min = j;
for (int i = j + 1; i < arrLen; i++)
{
if (unsorted[i] < unsorted[min]) {
min = i;
}
}
if (min != j)
{
int tmp = unsorted[j];
unsorted[j] = unsorted[min];
unsorted[min] = tmp;
}
}
for (int a = 0; a < arrLen; a++)
{
printf("%d-", unsorted[a]);
}
printf("\n");
}