I'm trying to figure out why the bottom function I've written isn't working properly. Whenever I try to test it out, I get the following error: Uncaught ReferenceError: Invalid left-hand side expression in postfix operation. I'm assuming it's because the code is failing to recognize the "x" string as being the same as the variable x once it's been stripped of it quotation marks when adding to the value of x. Can someone help me finesse this in a way to make it work? If not, can you suggest some alternate approach? Thanks in advance!
var grid = [[null, null, null],
[null, null, null],
[null, null, null]];
function checkWin() {
vals = ["x", "o"];
var x = 0;
var o = 0;
for (var k = 0; k < vals.length; k++) {
var value = vals[k];
for (var i = 0; i < 3; i++) {
if (grid[i][i] === value) {
(value.replace(/['"]+/g, '')) ++;
}
if (grid[2 - i][i] === value) {
(value.replace(/['"]+/g, '')) ++;
}
for (var j = 0; j < 3; j++) {
if (grid[i][j] === value) {
(value.replace(/['"]+/g, '')) ++;
}
if (grid[j][i] === value) {
(value.replace(/['"]+/g, '')) ++;
}
}
}
}
if (x === 3) {
alert("X wins!");
} else if (o === 3) {
alert("O wins!");
}
}
The following uses objects. The different grid definitions were tested
var grid = [
["o", "x", "x"],
["o", "x", "x"],
["o", "", "o"]];
var grid = [
["o", "x", ""],
["x", "x", "x"],
["o", "o", ""]];
var grid = [
["x", "x", ""],
["o", "x", "o"],
["o", "o", "x"]];
var grid = [
["x", "x", "o"],
["x", "o", "x"],
["o", "x", "x"]];
checkWin(grid)
function checkWin(grid) {
var vals = [{player: "x", value: 0}, {player: "o", value: 0}];
for (var k = 0; k < vals.length; k++) {
for (var i = 0; i < 3; i++) {
// check win by row
vals[k].value = 0;
// check win by col
for (var j = 0; j < 3; j++) {
if (grid[i][j] === vals[k].player) {
vals[k].value++;
}
}
if (vals[k].value === 3) {
alert(vals[k].player + " wins by row " + (i+1));
return vals[k].player;
}
// check win by col
vals[k].value = 0;
for (var j = 0; j < 3; j++) {
// check col
if (grid[j][i] === vals[k].player) {
vals[k].value++;
if (vals[k].value === 3) {
// break if you want to know what column won by
break;
}
}
}
if (vals[k].value === 3) {
alert(vals[k].player + " wins by col " + (i+1));
return vals[k].player;
}
}
}
// check win by diag l to r
for (var k = 0; k < vals.length; k++) {
vals[k].value = 0;
for (var i = 0; i < 3; i++) {
if (grid[i][i] === vals[k].player) {
vals[k].value++;
}
}
if (vals[k].value === 3) {
alert(vals[k].player + " wins by diag left to right!");
return vals[k].player;
}
}
// check win by diag r to l
for (var k = 0; k < vals.length; k++) {
vals[k].value = 0;
for (var i = 0; i < 3; i++) {
if (grid[i][2-i] === vals[k].player) {
vals[k].value++;
}
}
if (vals[k].value === 3) {
alert(vals[k].player + " wins by diag right to left!");
return vals[k].player;
}
}
}
What about put your data in a object like this:
var _ = {
x : 0,
o : 0
};
and change the value like this:
_[value]++;
I hope this helps.
Related
const N = 4;
const fourbyfour = [
[1, 0, 0, 4],
[3, 4, 1, 2],
[2, 1, 4, 3],
[4, 3, 2, 1],
];
function solve(board) {
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
if (board[i][j] === 0) {
for (let k = 1; k < N + 1; k++) {
board[i][j] = k;
if (isValidBoard(board)) {
if (isSolved(board)) return board;
else solve(board);
}
}
}
}
}
return;
}
function isSolved(board) {
let cells = [];
for (let row of board) {
cells.push(...row);
}
return !cells.includes(0);
}
function isValidBoard(board) {
// Check rows are valid
for (let i = 0; i < N; i++) {
const row = board[i].filter((cell) => cell !== 0);
if (new Set(row).size !== row.length) {
return false;
}
}
// Check columns are valid
for (let i = 0; i < N; i++) {
let column = [];
for (let j = 0; j < N; j++) {
if (board[j][i] !== 0) column.push(board[j][i]);
}
if (new Set(column).size !== column.length) {
return false;
}
}
const root = Math.sqrt(N);
// Check each grid
for (let i = 0; i < N; i += root) {
for (let j = 0; j < N; j += root) {
const square = [];
for (let k = i; k < i + root; k++) {
for (let l = j; l < j + root; l++) {
if (board[k][l] !== 0) {
square.push(board[k][l]);
}
}
}
if (new Set(square).size !== square.length) {
return false;
}
}
}
return true;
}
console.table(solve(fourbyfour));
solve() keeps on returning undefined.
I'm fairly certain the issue is in the solve function, and not related to isSolved() and isValidBoard(). The solve function is getting the correct board, if I console.log the board instead of returning it, the correct board gets printed, but for some reason it isn't getting returned.
You are never returning the value of your recursion. You need to return from the second time you enter solve.
Also, console.table does not seams to be working in the snippet
const N = 4;
const fourbyfour = [
[1, 0, 0, 4],
[3, 4, 1, 2],
[2, 1, 4, 3],
[4, 3, 2, 1],
];
function solve(board) {
for (let i = 0; i < N; i++) {
for (let j = 0; j < N; j++) {
if (board[i][j] === 0) {
for (let k = 1; k < N + 1; k++) {
board[i][j] = k;
if (isValidBoard(board)) {
if (isSolved(board)) {
return board;
} else {
return solve(board);
}
}
}
}
}
}
return 'test';
}
function isSolved(board) {
let cells = [];
for (let row of board) {
cells.push(...row);
}
return !cells.includes(0);
}
function isValidBoard(board) {
// Check rows are valid
for (let i = 0; i < N; i++) {
const row = board[i].filter((cell) => cell !== 0);
if (new Set(row).size !== row.length) {
return false;
}
}
// Check columns are valid
for (let i = 0; i < N; i++) {
let column = [];
for (let j = 0; j < N; j++) {
if (board[j][i] !== 0) column.push(board[j][i]);
}
if (new Set(column).size !== column.length) {
return false;
}
}
const root = Math.sqrt(N);
// Check each grid
for (let i = 0; i < N; i += root) {
for (let j = 0; j < N; j += root) {
const square = [];
for (let k = i; k < i + root; k++) {
for (let l = j; l < j + root; l++) {
if (board[k][l] !== 0) {
square.push(board[k][l]);
}
}
}
if (new Set(square).size !== square.length) {
return false;
}
}
}
return true;
}
console.log(solve(fourbyfour));
I'm super confused with getting this to run, as nested loops are still a bit funny to me.
With the following two arrays:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
How do I get it to print one value from a, and then two values from z after that so and so on?
'y',
'x',
'x',
'y',
'x',
'x',
'y',
'x',
'x'
If the values were instead:
let a = ['y','y'];
let z = ['x','x','x','x','x'];
It'd print:
'y',
'x',
'x',
'y',
'x',
'x',
'x'
This is what I've tried so far:
for (let i = 0; i < a.length; i++) {
console.log(a[i]);
for (let j = 0; j < z.length; j++) {
console.log(z[j], z[j+1]);
// break?
}
}
I repair your loop:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
for (let i = 0; i < a.length; i++) {
console.log(a[i]);
console.log(z[i*2], z[i*2+1]);
}
`
let a = ['y','y'];
let z = ['x','x','x','x','x'];
let j = 0;
for (let i = 0; i < a.length; i++) {
console.log(a[i]);
for (j; j < z.length; j++) {
console.log(z[j], z[j+1]);
if(j % 2 == 1){
break;
}
}
}`
try this one.
One option you have is to use do/while loop. Use shift() to remove the first item.of an array
let a = ['y1', 'y2', 'y3'];
let z = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6'];
//Copy the array a and z
let aTemp = [...a];
let zTemp = [...z];
do {
if (aTemp.length) console.log(aTemp.shift());
if (zTemp.length) console.log(zTemp.shift());
if (zTemp.length) console.log(zTemp.shift());
} while (aTemp.length || zTemp.length); //Loop while both the temp variables have elements
let aIndex = 0, zIndex = 0;
while(aIndex < a.length || zIndex < z.length) {
console.log(
a[aIndex++],
z[zIndex++],
z[zIndex++]
);
}
Here is non destructive way of doing this
var pointer = 0;
for (let i = 0; i < a.length; i++) {
var count = 0;
console.log(a[i]);
for (let j = pointer; j < z.length; j++) {
console.log(z[j]);
count++;
if(count == 2){
count = 0;
if(i == a.length-1) { continue; }else { pointer = j+1; break; }
}
}
}
let c = j = 0;
z.map(function(item){
if(c === 0 && a[j]){ console.log(a[j++]); }
console.log(item);
c = c > 0 ? 0 : c + 1;
});
Please have a look at the below code. I pushed your expected output result in to an array.
let a = ['y','y'];
let z = ['x', 'x', 'x', 'x', 'x'];
let arr = [];
for (let i = 0; i < a.length; i++) {
var count = 0
arr.push(a[i]);
for (let j = i * 2; j < z.length; j++) {
arr.push(z[j]);
count++
if (count > 1) {
if (z[j+1] !== undefined && a[i+1] === undefined) {
for (let k = j+1; k < z.length; k++) {
arr.push(z[k])
}
}
break;
}
}
}
console.log(arr);
// ["y", "x", "x", "y", "x", "x", "x"]
You don't need a nested loop at all. This can be done with a single loop with two counters.
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
let result = [];
for(let i = 0, j = 0; i < a.length, j < z.length; i++, j+=2) {
result.push(a[i], z[j], z[j+1]);
}
result = result.filter(item => item !== undefined);
console.log(result);
And here's the same code condensed to a one-liner core:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
let result = [];
for(let i = 0, j = 0; i < a.length, j < z.length; i++, j+=2) {
result.push.apply(result, [a[i], z[j], z[j+1]].filter(m => m !== undefined));
}
console.log(result);
You could take the length and calculate the interval/part lenght of the array for splicing and pushing to the result set.
function getX(a, b) {
var iA = Math.ceil(a.length / b.length),
iB = Math.ceil(b.length / a.length),
pA = 0,
pB = 0,
result = [];
while (pA < a.length || pB < b.length) {
result.push(
...a.slice(pA, pA += iA),
...b.slice(pB, pB += iB)
);
}
return result;
}
console.log(getX(['y','y','y'], ['x','x','x','x','x']).join(' '));
console.log(getX(['y','y'], ['x','x','x','x','x']).join(' '));
Here is an example using Array.prototype.reduce() and a destructuring assignment:
let a = ["y", "y", "y"];
let z = ["x", "x", "x", "x", "x"];
let y = a.reduce((acc, current, index) => {
return [...acc, current, ...z.splice(0, a[index + 1] ? 2 : z.length)];
}, []);
console.log(y);
console.log(z);
On every a array element you take previously accumulated array (initially []), add current element and two elements from z if a has next element or the rest of z elements if current is the last element of a.
This unfortunately deletes elements from z in the process, so you might want to copy it before running it, i.e. you can wrap reduce in a function and pass a copy of z:
let a = ["y", "y", "y"];
let z = ["a", "b", "c", "d", "e", "f", "g"];
const interweave = (arr1, arr2) => {
return arr1.reduce((acc, current, index) => {
return [
...acc,
current,
...arr2.splice(0, arr1[index + 1] ? 2 : arr2.length)
];
}, []);
};
console.log(interweave(a, [...z]));
console.log(z);
You can do it without any for or while too! try this:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
console.log(
[].concat.apply([], a.map(function(m, i){return [m].concat(z.slice(i*2, i*2+2));}))
);
Now you can join the result if you want like this:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
console.log(
[].concat.apply([], a.map(function(m, i){return [m].concat(z.slice(i*2, i*2+2));})).join(",")
);
Or if you like reduce function, you can try this:
let a = ['y','y','y'];
let z = ['x','x','x','x','x'];
console.log(
a.reduce(function(ac, m, i){return ac.push.apply(ac, [m].concat(z.slice(i*2, i*2+2))), ac;}, [])
);
First I am creating an array with an specific size.
$("#bntSize").one('click', function(e){
var memoria = $("#memoria").val();
console.log(memoria)
html = "";
for(var i = 0; i < memoria ; i++){
html += "<div class='square' name='mem"+i+"' data-id='"+i+"' data-pos='"+i+"' >"+i+"</div>";
arrayMemoria.push('');
}
console.log(arrayMemoria)
$("#contenedor").html(html);
});
If memoria is equal to 7 I am getting this:
["", "", "", "", "", "", ""]
Now I am giving some values to the array:
var nada = 0;
function firstFit(){
var cantidad = $("#ffinput").val();
var value = $("#ffinput2").val();
/*console.log(cantidad)*/
if(nada == 0){
for (nada ; nada < cantidad ; nada++) {
arrayMemoria.splice(nada , 1 , value);
nada = nada;
}
}
else{
for (nada; nada < arrayMemoria.length ; nada++) {
arrayMemoria.splice(nada , 1 , value);
nada = nada;
}
}
Here cantidad: how many spaces I am suppose to use in array & value: just a value.
So if I put => cantidad = 3 and value = A
["A", "A", "A", "", "", "", ""]
Then if I want to put => cantidad = 2 and value = B
["A", "A", "A", "B", "B", "B", "B"]
But I am trying to get this:
["A", "A", "A", "B", "B", "", ""]
and if I put => cantidad = 1 and value = C
["A", "A", "A", "B", "B", "C", ""]
And my second problem
If I do remove the values equals to A and I am inserting => cantidad = 2 AND VALUE = D
I am suppose to get this:
["D", "D", "", "B", "B", "C", ""]
How to count the available space in my array? cause if I want to insert
cantidad = 1 and value = E , I need to get the first available space
["D", "D", "E", "B", "B", "C", ""]
If someone can help me please!!
You can try the following code
var arr = ["", "", "", "", "", "", ""];
arr = insertValue(3, "A", arr);
console.log(arr);
arr = insertValue(2, "B", arr);
console.log(arr);
arr = insertValue(1, "C", arr);
console.log(arr)
arr = removeValue("A", arr);
console.log(arr)
arr = insertValue(2, "D", arr);
console.log(arr)
function insertValue(cantidad, value, arr){
var arrLength = arr.length;
var count = 0;
for (var i = 0; i < arrLength; i++) {
if(arr[i] == "" && count < cantidad){
arr[i] = value;
count ++;
}
};
return arr;
}
function removeValue(value, arr){
var arrLength = arr.length;
for (var i = 0; i < arrLength; i++) {
if(arr[i] == value){
arr[i] = "";
}
};
return arr;
}
EDIT: To get the number of spaces in the array
var arr = ["A", "A", " " , " ", " " , "B" ,"C " , " "];
var spaceCount = 0;
arr.forEach(function(i) { if(i == " ") spaceCount++; });
console.log(spaceCount)
EDIT 2: To count consecutive spaces in an array
var arr = ["A", "A", " " , " ", " " , "B"," ", " " ,"C " , " "];
var count = 1;
var countArr = [];
for (var i = 0; i < arr.length; i++) {
if(arr[i] == " "){
if(arr[i+1] == arr[i]){
count ++;
}else {
countArr.push(count);
count = 1;
}
}
};
console.log(countArr)
EDIT 3: To get consecutive space count + starting position
var arr = [" ", "A", "A", " " , " ", " " , "B"," ", " " ,"C " , " "];
var count = 1;
var countArr = [];
var pos = 0;
for (var i = 0; i < arr.length; i++) {
if(arr[i] == " "){
if(arr[i] === arr[i+1]){
count ++;
}else {
countArr.push({'pos': pos, 'count': count});
count = 1;
}
}else{
pos = i+1;
}
};
console.log(countArr)
var array = ["A", "", "", "", "B", "B", "B"];
var cantidad = 2;
for (var x = 0; x < array.length; x++) {
if (array[x] === "") {
if (cantidad >0){
array.splice(x, 1, "C");
cantidad--;
}
}
}
function codeAddress() {
alert(array);
}
window.onload = codeAddress;
Here's a solution, I realized you can solve this problem in a lot of different ways, mine is not necessarily the best approach.
Good luck.
EDIT: This is a working solution for both questions.
var array = ["","","","","","",""];
function addValues(num, value) {
for(var i=0; i<num; i++) {
for(var j=0; j<array.length; j++){
if(array[j] ==="") {
array[j] = value;
break;
}
}
}
}
function removeValues(value) {
for(var i=0; i<array.length; i++) {
if(array.indexOf(value) !== -1) {
array[i] = "";
}
}
}
addValues(3, 'A');
addValues(2, 'B');
addValues(1, 'C');
removeValues('A');
addValues(2, 'D');
addValues(2, 'E');
console.log(array);
I'm trying to write an algorithm to get all the possible combinations of N elements inside a multi dimensional array of M elements.
Something like:
function getCombinations(arr, n){
...
}
var arr = [ ["A"],["B","C"],["D","E"]];
var n = 2;
getCombinations(arr,n);
This should produce:
[
["A","B"],["A","C"],["A","D"],["A","E"],
["B","D"],["B","E"],
["C","D"],["C","E"]
]
The number of elements inside the array may vary, the only thing set is the number of elements of the combinations.
The order doesn't matter but you cannot repeat, I mean ["A","B"] == ["B","A"], so the second one is not take in consideration.
Any help?
ChrisB solution had a mistake, he wasn't caching the length of the loop before the arr.shift, and it was not returning the last combination, I think this will do the job:
function getCombinations (arr, n) {
var i, j, k, elem, l = arr.length, childperm, ret = [];
if (n == 1){
for (i = 0; i < arr.length; i++) {
for (j = 0; j < arr[i].length; j++) {
ret.push([arr[i][j]]);
}
}
return ret;
}
else {
for (i = 0; i < l; i++) {
elem = arr.shift();
for (j = 0; j < elem.length; j++) {
childperm = getCombinations(arr.slice(), n-1);
for (k = 0; k < childperm.length; k++) {
ret.push([elem[j]].concat(childperm[k]));
}
}
}
return ret;
}
}
getCombinations([["A"],["B"],["C","D"]], 2);
// [["A", "B"], ["A", "C"], ["A", "D"], ["B", "C"], ["B", "D"]]
getCombinations([["A"],["B"],["C"],["D"]], 2);
// [["A", "B"], ["A", "C"], ["A", "D"], ["B", "C"], ["B", "D"], ["C", "D"]]
Updated
Per your restriction that elements that are contained in the same array in the beginning cannot be combined I've modified the algorithm to the following:
Here is the updated jsfiddle that now even outputs the data in the correct format :) http://jsfiddle.net/QKg2H/7/
function getCombinations(arr, n)
{
if(n == 1)
{
var ret = [];
for(var i = 0; i < arr.length; i++)
{
for(var j = 0; j < arr[i].length; j++)
{
ret.push([arr[i][j]]);
}
}
return ret;
}
else
{
var ret = [];
for(var i = 0; i < arr.length; i++)
{
var elem = arr.shift();
for(var j = 0; j < elem.length; j++)
{
var childperm = getCombinations(arr.slice(), n-1);
for(var k = 0; k < childperm.length; k++)
{
ret.push([elem[j]].concat(childperm[k]));
}
}
}
return ret;
}
}
The algorithm is still recursive, but now it will consider each of the second degree elements in turn, but not with each other. Other than that, it still pops off one element and then appends the permutations of all of the remaining elements. I hope it's straightforward.
Following code i wanted to share which compares two array of array:-
var x = [["x", "r", "t"], ["a", "b", "n"], ["j", "l", "x"]];
var y = [["y", "w", "z"], ["a", "b", "n"], ["j", "l", "x"]];
var objX = [];
var objY = [];
for (var i = 0; i < x.length; i++)
{
objX[i] = {};
for (var j = 0; j < x[i].length; j++)
{
objX[i][x[i][j]] = i;
}
}
for (var i = 0; i < y.length; i++)
{
objY[i] = {};
for (var j = 0; j < y[i].length; j++)
{
objY[i][y[i][j]] = i;
}
}
Object.size = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key))
size++;
}
return size;
};
function compareObjs(oA, oB)
{
if (Object.size(oA) > Object.size(oB))
{
aa = oA;
ba = oB;
}
else
{
aa = oB;
ba = oA;
}
for (var property in aa) {
if (!ba.hasOwnProperty(property)) {
return false;
}
}
return true;
}
function compareArrayOfObj(aA, aB)
{
var aIb = [];
var aMb = [];
var bMa = [];
var aIIndex = [];
var bIIndex = [];
var aIF = [];
var bIF = [];
if (aA.length > aB.length)
{
a = aA;
b = aB;
}
else
{
a = aB;
b = aA;
}
for (var i in a)
{
for (var j in b)
{
if (compareObjs(a[i], b[j]))
{
for (var blah in a[i])
{
aIb.push(x[a[i][blah]]);
break;
}
aIIndex.push(i);
bIIndex.push(j);
}
}
}
for (var i in a)
{
if (aIIndex.indexOf(i) == -1)
{
for (var blah in a[i])
{
aIF.push(x[a[i][blah]]);
break;
}
}
}
for (var j in b)
{
if (bIIndex.indexOf(j) == -1)
{
for (var blah in b[j])
{
bIF.push(y[b[j][blah]]);
break;
}
}
}
return {"aIb": aIb, "aMb": aIF, "bMa": bIF}
}
resultSet=compareArrayOfObj(objX, objY);
/*
resultSet object holds three properties as:-
1. aIb = objX Intersection objY
2. aMb = objX - objY
3. bMa = objY - objX
*/
Improvisation in the code is always welcome.
Basically i have written this code to have set operation on arrays.
It will return A minus B,B minus A and A intersection B.