javascript : create for loops into for loops - javascript

I had to solve the following problem:-
9 values, from 1 to 9 (0 and 10 not accepted) and all numbers need to be different.
To solve the problem, I made those horrible for loops inside for loops.
(I added 2 more conditions to check if I had one of the solutions)
It is working, but I was wondering how to create those for loops inside for loops in a better way?
Also, each number can't be equal to another. How can you accomplish this another way than I did? (Again, 2 first conditions can be deleted)
Here is code:
var a = 1,
b = 1,
c = 1,
d = 1,
e = 1,
f = 1,
g = 1,
h = 1,
i = 1
var x = 0
var result = []
function calc() {
x = a + (13 * b) / c + d + 12 * e - f - 11 + (g * h) / i - 10
if (x == 66) {
result.push([a, b, c, d, e, f, g, h, i])
}
}
for (a = 1; a < 10; a++) {
calc()
for (b = 1; b < 10; b++) {
calc()
for (c = 1; c < 10; c++) {
calc()
for (d = 1; d < 10; d++) {
calc()
for (e = 1; e < 10; e++) {
calc()
for (f = 1; f < 10; f++) {
calc()
for (g = 1; g < 10; g++) {
calc()
for (h = 1; h < 10; h++) {
calc()
for (i = 1; i < 10; i++) {
calc()
}
}
}
}
}
}
}
}
}
console.log(result)
var result2 = result.filter(function (el) {
return (
el[0] == 5 &&
el[1] == 9 &&
el[0] != el[1] &&
el[0] != el[2] &&
el[0] != el[3] &&
el[0] != el[4] &&
el[0] != el[5] &&
el[0] != el[6] &&
el[0] != el[7] &&
el[0] != el[8] &&
el[1] != el[0] &&
el[1] != el[2] &&
el[1] != el[3] &&
el[1] != el[4] &&
el[1] != el[5] &&
el[1] != el[6] &&
el[1] != el[7] &&
el[1] != el[8] &&
el[2] != el[0] &&
el[2] != el[1] &&
el[2] != el[3] &&
el[2] != el[4] &&
el[2] != el[5] &&
el[2] != el[6] &&
el[2] != el[7] &&
el[2] != el[8] &&
el[3] != el[0] &&
el[3] != el[1] &&
el[3] != el[2] &&
el[3] != el[4] &&
el[3] != el[5] &&
el[3] != el[6] &&
el[3] != el[7] &&
el[3] != el[8] &&
el[4] != el[0] &&
el[4] != el[1] &&
el[4] != el[2] &&
el[4] != el[3] &&
el[4] != el[5] &&
el[4] != el[6] &&
el[4] != el[7] &&
el[4] != el[8] &&
el[5] != el[0] &&
el[5] != el[1] &&
el[5] != el[2] &&
el[5] != el[3] &&
el[5] != el[4] &&
el[5] != el[6] &&
el[5] != el[7] &&
el[5] != el[8] &&
el[6] != el[1] &&
el[6] != el[2] &&
el[6] != el[3] &&
el[6] != el[4] &&
el[6] != el[5] &&
el[6] != el[7] &&
el[6] != el[8] &&
el[7] != el[0] &&
el[7] != el[1] &&
[7] != el[2] &&
el[7] != el[3] &&
el[7] != el[4] &&
el[7] != el[5] &&
el[7] != el[6] &&
el[7] != el[8] &&
el[8] != el[0] &&
el[8] != el[1] &&
el[8] != el[2] &&
el[8] != el[3] &&
el[8] != el[4] &&
el[8] != el[5] &&
el[8] != el[6] &&
el[8] != el[7]
)
})
console.log(result2)

for starters you can make N x nested for loops like this
nested_for in C++
You can handle your problem as a 9 digit number generation
As your digits are not repeating you can discard many iterations. If encoded in the above manner (like nested for) you will came up with something like this:
Generalized Permutation (without repetitions) in C++:
//---------------------------------------------------------------------------
//--- permutation class ver 0.00 --------------------------------------------
//---------------------------------------------------------------------------
#ifndef _permutation_h
#define _permutation_h
/*---------------------------------------------------------------------------
// usage:
permutation per;
per.alloc(N);
per.first();
for (;;)
{
... here per.i[0..N-1] contains actual permutation
... N! permutations
if (!per.next()) break;
}
//-------------------------------------------------------------------------*/
class permutation
{
public:
int *i; // i[N] permutation
BYTE *a; // a[N] item not used yet ?
int N; // items
int ix; // actual permutation layer
permutation() { N=0; i=NULL; a=NULL; ix=0; }
permutation(permutation& b) { *this=b; }
~permutation() { free(); }
permutation* operator = (const permutation *b) { *this=*b; return this; }
permutation* operator = (const permutation &b) { alloc(b.N); for (int j=0;j<N;j++) { i[j]=b.i[j]; a[j]=b.a[j]; } ix=b.ix; return this; }
void alloc(int _N)
{
free();
i=new int[_N];
if (i==NULL) return;
a=new BYTE[_N];
if (a==NULL) { free(); return; }
N=_N;
}
void free ()
{
N=0; ix=0;
if (i!=NULL) delete i; i=NULL;
if (a!=NULL) delete a; a=NULL;
}
void first() // init permutation
{
for (ix=0;ix<N;ix++)
{
i[ix]=ix;
a[ix]=0;
} ix--;
}
bool next() // next permutation return if it is not last
{
int *ii=&i[ix];
for (;;)
{
if (*ii>=0) a[*ii]=1;
for ((*ii)++;*ii<N;(*ii)++) if (a[*ii]) { a[*ii]=0; break; }
if (*ii>=N)
{
if (ix== 0) return false;
*ii=-1; ix--; ii=&i[ix];
}
else{
if (ix==N-1) return true;
ix++; ii=&i[ix];
}
}
}
};
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
The important stuff is in first() and next() members, each permutation is stored in the i[] array as index so set N=9 and your output numbers will be (per.i[0]+1),(per.i[1]+1),...,(per.i[9]+1)
it works in following manner:
first() initialize permutation to state i[9]=(0,1,2,...8) and a[9]=(0,0,0,...0)
I will write this for simplicity like this: i=012345678,a=000000000 where
ix points to last digit
i is the actual permutation
a flags if digit is unused(1) or used(0) (to avoid O(N^N) operation)
next() increment to next valid permutation
Increase the last digit to next unused value. If no unused value set it as unused and increment previous digit. The same goes for overflow. The first iteration will be like this:
i=012345678,a=000000000 // starting iteration
i=01234567? a=000000001 // unset (no unused values)
i=01234568? a=000000010 // increment 8th digit
i=012345687 a=000000000 // set the last digit result
next iteration:
i=012345687 a=000000000 // starting iteration
i=01234568? a=000000010 // unset (no unused values)
i=0123456?? a=000000011 // unset (8->9 overflow)
i=0123457?? a=000000101 // increment 7th digit
i=01234576? a=000000001 // after overflow digit set to lowest free value
i=012345768 a=000000000 // after overflow digit set to lowest free value
I hope it is clear enough.
Of coarse if you use recursion instead of iteration the code will look much nicer but in most languages will run also slower due to stack/heap trashing
As #NikolaDimitroff pointed out this is in C++ instead of javascript so:
ignore new,delete and class members other then first(),next()
set N=9; and arrays i,a can be static like: int i[9]; BYTE a[9];
Here the solution O(N!) for the task in C++:
int a,b,c,d,e,f,g,h,i;
permutation per;
per.alloc(9);
per.first();
for (;;)
{
if ((per.i[0]+1)
+(13*(per.i[1]+1)/(per.i[2]+1))+(per.i[3]+1)
+(12*(per.i[4]+1))
-(per.i[5]+1)-11
+((per.i[6]+1)*(per.i[7]+1)/(per.i[8]+1))-10
==66)
{
a=per.i[0]+'1';
b=per.i[1]+'1';
c=per.i[2]+'1';
d=per.i[3]+'1';
e=per.i[4]+'1';
f=per.i[5]+'1';
g=per.i[6]+'1';
h=per.i[7]+'1';
i=per.i[8]+'1';
// here a,b,c,d,e,f,g,h,i holds the solution
break;
}
if (!per.next()) break;
}

Related

What is the difference between putting the variable "top" inside for loop and before?

var isValid = function (s) {
let stack = [];
for (let i = 0; i < s.length; i++) {
let top = stack[stack.length - 1];
if (s[i] === "(" || s[i] === "{" || s[i] === "[") {
stack.push(s[i]);
} else if (s[i] === ")" && top === "(" && stack.length !== 0) {
stack.pop();
} else if (s[i] === "]" && top === "[" && stack.length !== 0) {
stack.pop();
} else if (s[i] === "}" && top === "{" && stack.length !== 0) {
stack.pop();
} else {
return false;
}
}
return stack.length === 0;
};
Function like this works (this is the problem https://leetcode.com/problems/valid-parentheses/)
However when i put variable "top" before the for loop ,the function doest do its job.
Can you please explain me what is the difference in this 2 cases?
Thank you!
I tried to put variable "top" before and in the for loop ,got different acting function.

2D Array in While loop bounds

I'm having some issues with figuring out how to work with a 2D array and a while loop.
Here's the relevant code snippet:
while (
table[i - count][j] === 0 ||
table[i + count][j] === 0 ||
table[i][j - count] === 0 ||
table[i][j + count] === 0
) { ... count++; }
I get the following error when running my snippet:
TypeError: Cannot read property '0' of undefined
Now I understand that this is happening because if I have i = 0 then table[i - count][j] would been it is checking table[-1][j]. Obviously this shouldn't work but that is the purpose of the while loop that I've implemented.
I want the code to stop running when either the edge of this 2D array is out of bounds (like explained above) or if the element's value is 0.
Currently it gives me the error when I just need it to stop and carry on with the code after the while loop. How do I solve this?
EDIT:
Yeah I'm sure I want these conditions to be &&. The main issue is that i -count could result in a negative number. Or i + count could result in a number out of bounds for the array.
How do I deal with those out of bounds occasions in this while loop?
You need to make shure the array exists before accessing its keys, and checking for 0 or undefined is irrelevant as both are falsy :
while(
(table[i - count] || [])[j] &&
(table[i + count] || [])[j] &&
(table[i] || [])[j + count] &&
(table[i] || [])[j - count]
) count++;
Right I've found a solution. It's probably not optimal in general but for what I'm doing it's perfect:
while (
i - count >= 0 &&
j - count >= 0 &&
i + count < table.length &&
j + count < table[i].length
) {
if (
table[i - count][j] === 0 ||
table[i + count][j] === 0 ||
table[i][j - count] === 0 ||
table[i][j + count] === 0
) return prod;
prod *= (
table[i - count][j] *
table[i + count][j] *
table[i][j - count] *
table[i][j + count]
);
count++;
}
As commented before, using I would suggest using a function that returns a boolean value. This will keep your loop clean and you can choose to have a more descriptive code for conditions.
function validate(array, i, j, count){
// To cover case when either variable is 0
if(i && j){
let prev = array[i - count];
let next = array[i + count];
let curr = array[i];
return (
(j < prev.length && prev[j] === 0) ||
(j < next.length && next[j] === 0) ||
// Since we have already added a check for value !== 0,
// we just have to check for out of bound here.
(j < curr.length -1) && (
curr[j - count] === 0 ||
curr[j + count] === 0
)
)
}
return false;
}
while (validate(table, i, j, count)) { ... count++; }
Assuming your conditions are connected by "and"
Just add extra conditions to check for valid values/bounds for your array index
while (
table[i - count][j] !== 0 && table[i - count][j] !== undefined &&
table[i + count][j] !== 0 && table[i + count][j] !== undefined &&
table[i][j - count] !== 0 && table[i][j - count] !== undefined &&
table[i][j + count] !== 0 && table[i][j + count] !== undefined &&
i - count > 0 &&
j - count > 0
) { ... count++; }

Why am I unable to enter % sign after my custom validation

I have a requirement wherein I can enter number not more than 100 (100 allowed). Additionally these number can have +, - sign at start and % at the end.
I have come up with the following function to validate. However, even after struggling a lot, I am unable to fix why I am not able to enter a % sign when I have already enter 2 digits.
Ex: after typing 10, I cant type % (Shift + 5)
My Function:
$scope.checkInputValidation = function(event, value) {
var key = event.keyCode;
var currentcharacter = String.fromCharCode(key);
if (key === 91 || key === 187 || key === 189 || (15 < key && key < 19) || (35 <= key && key <= 40)) {
return;
}
if (isNaN(currentcharacter) && ((currentcharacter !== "%") || (currentcharacter !== "+") || (currentcharacter !== "-") || (currentcharacter !== ""))) {
if ((key !== 46) && (key !== 8)) {
event.preventDefault();
return false;
}
}
var formattedValue;
if (value.indexOf('%') !== -1) {
formattedValue = value.replace('%', "");
} else {
formattedValue = value;
}
if (!isNaN(currentcharacter)) {
if (parseInt(formattedValue + currentcharacter) > 100 || parseInt(formattedValue + currentcharacter) < -100) {
event.preventDefault();
return false;
}
}
}
I would like to know the cause and how should I be able to enter %.
currentcharacter is never going to contain the % character. You have to check the keyCode for 5 (53) in combination with the event.shiftKey property.
if(key === 53 && event.shiftKey) {
.. % pressed ..
}

Reduce JavaScript if statement

I need help, I have this function in javascript:
function getPosition(elementToFind, array) {
var i;
for (i = 0; i < array.length; i += 1) {
if (array == elementToFind) {
return i;
}
}
}
And then I have a cycle if that I would like to reduce:
if (
getPosition(1, arraySomething) == 0 &&
getPosition(2, arraySomething) == 1 &&
getPosition(3, arraySomething) == 2 &&
getPosition(4, arraySomething) == 3 &&
getPosition(5, arraySomething) == 4 &&
getPosition(6, arraySomething) == 5 &&
getPosition(7, arraySomething) == 6 &&
getPosition(8, arraySomething) == 7 &&
getPosition(9, arraySomething) == 8 &&
getPosition(10, arraySomething) == 9 &&
getPosition(11, arraySomething) == 10
) {
...code
}
How can I do it?
How about something like this
var isTrue = true;
for(var n = 1; n <= length; n ++){
if (getPosition(n, arraySomething) !== (n - 1)){
isTrue = false;
break;
}
}
if (isTrue){
...
}else{
...
}
?

How can I loop through two arrays comparing values in Javascript?

I have the following Javascript function where the parameters newValue and oldValue are arrays of integers and the same length. Any values in these arrays can be an integer, undefined or null:
function (newValue, oldValue) {
});
Is there some way that I could check the values in the arrays one element at a time and then do an action only if:
newValue[index] is >= 0 and < 999
oldValue[index] is >= 0 and < 999
newValue[index] is not equal to oldValue[index]
What I am not sure of is how can I handle in my checks and ignore the cases where newValue or oldValue are not null and not undefined? I know I can do a check as in if (newValue) but then this will show false when it's a 0.
Update:
I had a few quick answers so far but none are checking the right things which I listed above.
compare against null and undefined:
if (newValue[index] !== null && typeof newValue[index] !== 'undefined') {}
for OPs update:
n = newValue[index];
o = oldValue[index];
if (
n !== null && typeof n !== 'undefined' && n >= 0 && n < 999 &&
o !== null && typeof o !== 'undefined' && o >= 0 && o < 999
) {
// your code
}
for array-elements its not necessary to use typeof so n !== undefined is ok because the variable will exist.
n = newValue[index];
o = oldValue[index];
if (
n !== null && n !== undefined && n >= 0 && n < 999 &&
o !== null && o !== undefined && o >= 0 && o < 999 &&
n !== o
) {
// your code
}
This will do it:
function isEqual (newValue, oldValue) {
for (var i=0, l=newValue.length; i<l; i++) {
if (newValue[i] == null || newValue[i] < 0 || newValue[i] >= 999
|| oldValue[i] == null || oldValue[i] < 0 || oldValue[i] >= 999)
continue;
if (newVale[i] !== oldValue[i])
return false;
}
return true;
}
if (newValue != null || newValue != undefined) && (oldValue != null || oldValue != undefined)

Categories