You have a value n, it will determine the dimension of a 2D array or table. Then you should fill the array or the table from the outer layer to the center once with ones and once with zeros up to the point where there is no other element to write.
n=5
n=6
Have been trying this for a long time now, would appreciate any help. Am able to fill the boundaries nothing more.
My latest code :
function fillArray(n) {
var exArray = [];
var html = '';
for (var i = 0; i < n; i++) {
html+= '<tr>';
exArray[i] = [];
for (var j = 0; j < n; j++) {
exArray[i][j] = 0;
if(i%(n-1)==0 || j%(n-1)==0) {
exArray[i][j] = 1;
}
html+='<td class="text-center">'+exArray[i][j]+' ['+i+','+j+']</td>';
};
html+= '</tr>';
};
return html;
}
I think the simplest way is considering only the top-left quadrant, and fill the others by symmetry:
var arr = Array(n);
for(var i=0; i<n/2; ++i) {
arr[ i ] = new Array(n);
arr[n-1-i] = new Array(n);
for(var j=0; j<n/2; ++j)
arr[ i ][j] = arr[ i ][n-1-j] =
arr[n-1-i][j] = arr[n-1-i][n-1-j] =
+ !(Math.min(i,j) % 2);
}
function fillArray(n) {
var arr = Array(n);
for(var i=0; i<n/2; ++i) {
arr[ i ] = new Array(n);
arr[n-1-i] = new Array(n);
for(var j=0; j<n/2; ++j)
arr[ i ][j] = arr[ i ][n-1-j] =
arr[n-1-i][j] = arr[n-1-i][n-1-j] =
+ !(Math.min(i,j) % 2);
}
var table = document.createElement('table');
for(var i=0; i<n; ++i) {
var row = table.insertRow();
for(var j=0; j<n; ++j)
row.insertCell().textContent = arr[i][j];
}
return table;
}
document.body.appendChild(fillArray(9));
td {
width: .8em;
height: .8em;
line-height: .8em;
}
Not as succinct but works:
var n = 10;
function isMiddleIndex(middleIdx, rowIndex, cellIndex) {
return middleIdx.indexOf(rowIndex) != -1 && middleIdx.indexOf(cellIndex) != -1;
}
function isBoundaryIndex(n, boundsIdx, i, j) {
return boundsIdx.indexOf(i) > -1 || boundsIdx.indexOf(j) > -1;
}
function fillArray(n) {
var num,
html = '',
nMid = n / 2,
middleIdx = n % 2 == 1 ? [(n - 1) / 2] : [Math.floor(nMid) - 1, Math.ceil(nMid)],
boundsIdx = [0, n - 1];
for (var i = 0; i < n; i++) {
html += '<tr>';
for (var j = 0; j < n; j++) {
num = isMiddleIndex(middleIdx, i, j) || isBoundaryIndex(n, boundsIdx, i, j) ? 1 : 0;
html += '<td class="text-center">' + num + '</td>';
};
html += '</tr>';
};
return html;
}
$('table').html(fillArray(n));
DEMO
A more readable way
function fillArray(n) {
var exArray = [];
for (var i = 0; i < n; i++) {
exArray[i] = [];
for (var j = 0; j < n; j++) {
exArray[i][j] = 0;
if(i < j) {
if(n - j - 1 > i) {
if(i % 2 == 0) {
exArray[i][j] = 1;
}
}
else {
if((n - j - 1) % 2 == 0) {
exArray[i][j] = 1;
}
}
}
else {
if(j > n - i - 1) {
if((n - i - 1) % 2 == 0) {
exArray[i][j] = 1;
}
}
else {
if(j % 2 == 0) {
exArray[i][j] = 1;
}
}
}
};
};
}
And Fiddle.
Related
I have an array list I loop over and modify it each time. I want to store all instances of my list array in an other array I named allLists, and to do so, I'm using the slice method.
It seems to work in the simple example below:
let list=[1,2,3,4];
let allList = [];
allList.push(list.slice());
list[2]=6;
allList.push(list.slice());
console.log(allList);// returns [1,2,3,4] [1,2,6,4]
But it doesn't work in the following code. Instead, allLists is filled with the last instance of the list array.
let list = Array.from({
length: 9
}, () => Array.from({
length: 9
}, () => [1, 2, 3, 4, 5, 6, 7, 8, 9]));
let allLists = [list.slice()];
let indexList = [];
let lengthList = [];
let key = true;
function handleNewIndex(list) {
let newIndex = [0, 0];
let maxLength = 9;
for (let i = 0; i < list.length; i++) {
for (let j = 0; j < list.length; j++) {
if (list[i][j].length < maxLength && list[i][j].length > 0) {
maxLength = list[i][j].length;
newIndex = [i, j];
}
}
}
return newIndex;
}
function isSudokuValid(list) {
for (let i = 0; i < list.length; i++) {
for (let j = 0; j < list.length; j++) {
if (list[i][j].length === 0) {
return false;
}
}
}
return true;
}
function handleWrongSudoku(allLists, indexList, lengthList) {
let counter = 1;
while (lengthList[lengthList.length - counter] <= 1) {
counter = counter + 1;
allLists.pop();
indexList.pop();
}
let wrongList = allLists.pop();
list = allLists.pop();
indexLine = indexList[indexList.length - 1][0];
indexColumn = indexList[indexList.length - 1][1];
let wrongNumber = wrongList[indexLine][indexColumn];
for (let i = 0; i < list[indexLine][indexColumn].length; i++) {
if (list[indexLine][indexColumn][i] != wrongNumber) {
list[indexLine][indexColumn] = list[indexLine][indexColumn][i];
}
}
allLists.push(list.slice());
indexLine = handleNewIndex(list)[0];
indexColumn = handleNewIndex(list)[1];
}
function generateSudoku() {
let indexLine = Math.floor(Math.random() * 9);
let indexColumn = Math.floor(Math.random() * 9);
let counter = 0;
while (counter < 81) {
indexList.push([indexLine, indexColumn]);
let bigSquareIndex = 3 * Math.floor(indexLine / 3) + Math.floor(indexColumn / 3);
lengthList.push(list[indexLine][indexColumn].length);
list[indexLine][indexColumn] = list[indexLine][indexColumn][Math.floor(Math.random() * list[indexLine][indexColumn].length)];
counter = counter + 1;
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
if (3 * Math.floor(i / 3) + Math.floor(j / 3) === bigSquareIndex) {
let k = 0;
let n = list[i][j].length;
while (list[i][j][k] != list[indexLine][indexColumn] && k < n) {
k = k + 1;
}
if (k < n) {
list[i][j].splice(k, 1);
}
} else if (i === indexLine || j === indexColumn) {
let k = 0;
let n = list[i][j].length;
while (list[i][j][k] != list[indexLine][indexColumn] && k < n) {
k = k + 1;
}
if (k < n) {
list[i][j].splice(k, 1);
}
}
}
}
allLists.push(list.slice());
key = isSudokuValid(list);
if (key === false) { //ignore this scenario, not done yet, assume key = true at all time
console.log(key, lengthList, indexList, allLists);
handleWrongSudoku(allLists, indexList, lengthList);
key = true;
//return;
} else {
indexLine = handleNewIndex(list)[0];
indexColumn = handleNewIndex(list)[1];
}
}
}
generateSudoku();
console.log(allLists); // returns 81 times the same 9x9 array instead of the 81 different instances of the list array
I don't know what I'm doing wrong here.
Thanks for the hint Code Maniac.
I used the JSON method instead to create a deep copy and it's working fine now.
allLists.push(JSON.parse(JSON.stringify(list)));
This post explains the difference between shallow and deep copy:
https://www.freecodecamp.org/news/how-to-clone-an-array-in-javascript-1d3183468f6a/
I'm trying to add a score counter to my Tetris game for my retro games website made completely out of JavaScript and html. how would I go about adding a score counter to my script?
I have tried multiple different ways even trying to use local storage but I just couldn't do it, could some one help me out?
let arena = [];
let rand;
const player = {
pos: {x: 0, y: 1},
matrix: null,
color: null
}
rand = Math.floor(Math.random() * pieces.length);
player.matrix = pieces[rand];
player.color = colors[rand+1];
function drawMatrix(matrix, x, y) {
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
if (matrix[i][j])
ctx.fillRect(x + j, y + i, 1, 1);
}
}
}
function rotateMatrix(matrix, dir) {
let newMatrix = [];
for (let i in matrix)
newMatrix.push([]);
if (dir === 1) {
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
newMatrix[j][matrix.length - i - 1] = matrix[i][j];
}
}
} else {
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
newMatrix[matrix.length - j - 1][i] = matrix[i][j];
}
}
}
return newMatrix;
}
function collides(player, arena) {
for (let i = 0; i < player.matrix.length; i++) {
for (let j = 0; j < player.matrix[i].length; j++) {
if (player.matrix[i][j] && arena[player.pos.y + i + 1][player.pos.x + j + 1])
return 1;
}
}
return 0;
}
function mergeArena(matrix, x, y) {
for (let i = 0; i < matrix.length; i++) {
for (let j = 0; j < matrix[i].length; j++) {
arena[y+i+1][x+j+1] = arena[y+i+1][x+j+1] || matrix[i][j];
}
}
}
function clearBlocks() {
for (let i = 1; i < arena.length-2; i++) {
let clear = 1;
for (let j = 1; j < arena[i].length-1; j++) {
if (!arena[i][j])
clear = 0;
}
if (clear) {
let r = new Array(tWidth).fill(0);
r.push(1);
r.unshift(1);
arena.splice(i, 1);
arena.splice(1, 0, r);
}
}
}
When I have finished adding to score to the game. I am going to add a leader board outside of local storage using a database, any suggestions on how?
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 want to sort a string in javascript without using a built in method, just by using for's and comparisons like 'a' > 'b';
Something that doesn't work:
function replaceAt(str, i, char) {
return str.substr(0,i) + char + str.substr(i + 1)
}
function swap(str, i1, i2) {
return replaceAt(replaceAt(str, i1, str[i2]),i2,str[i1]);
}
function sort(str) {
var sorted = str;
for (var i = 0; i < str.length; i++) {
if (str[i] > str[i + 1]) {
str = swap(str, i, i+1)
}
}
return str;
}
Pseudo-code or books, courses recommendations on programming are welcome!
Your code is not applying any sort algorithm logic, I recommend you to read atleast 1 to solve your problem.
Below is the program, which produces the expected output from your program using selection sort.
swap and replace functions works fine.
function sort(str) {
var sorted = str;
//Selection sort
for (var i = 0; i < str.length; i++) {
for(var j = i + 1; j < str.length - 1; j++) {
if (str[i] < str[j]) {
str = swap(str, i, j)
}
}
}
return str;
}
console.log(sort("zaasfweqrouoicxzvjlmmknkniqwerpopzxcvdfaa"));
//output: aaaaccdeeffiijkklmmnnoooppqqrrsuvvwwxxzzz
function sort(arr) {
arr = arr.split("");
for (i = 0; i < arr.length; i++) {
for (j = 0; j < arr.length; j++) {
if (arr[j] > arr[i]) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
return arr.join("");
}
console.log(sort("dcna"));
function sort(arr) {
arr = arr.split("");
for (i = 0; i < arr.length; i++) {
for (j = 0; j < arr.length; j++) {
if (arr[j] > arr[i]) {
[arr[j], arr[j+1]] = [arr[j+1], arr[j]]
}
}
}
return arr.join("");
}
console.log(sort("dcna"));
Note: no need of using temp variable
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
array=[4, 10, 2, 9, 6, 3, 13, 5];
function arrayOperations()
{
var count = array.length - 1,
temp,
j,
i;
for (j = 0; j < count; j++)
{
for (i = 0; i < count; i++)
{
if (array[i] > array[i + 1])
{
temp = array[i + 1];
array[i + 1] = array[i];
array[i] = temp;
}
}
}
document.write("ascending order is <br>")
for(k=0;k<=array.length-1;k++){
document.write(array[k]+ "<br>");
}
document.write("descending order is <br>")
for(k=array.length-1;k>=0;k--){
document.write(array[k]+ "<br>");
}
document.write("biggest number is <br>")
for(k=array.length-1;k>=0;k--){
if((array[k])>array[k-1]){
document.write(array[k]+"<br>")
break;
}
}
document.write("smallest number is <br>")
for(k=0;k<=array.length;k++){
if((array[k])<array[k+1]){
document.write(array[k]+"<br>")
break;
}
}
}
</script>
<title></title>
</head>
<body>
array=[4, 10, 2, 9, 6, 3, 13, 5]
<br>
<input type="button" onclick="arrayOperations()" value="find">
</body>
</html>
//generic sort function to sort a word
function sortArray(str){
let strr = str.split('');
for(var index = 0 ;index <strr.length ;index ++ ){
for(var index1 = 0;index1<(strr.length-index) ;index1++){
let temp;
if( strr[index1] > strr[index1+1] ){
temp = strr[index1] ;
strr[index1] = strr[index1 +1];
strr[index1+1] =temp;
}
}
}
return(strr.join(''));
}
//data set to sort
let data = "Hey Goodmorning How are you";
let result;
let data1 =data.split(' ');
data1.forEach(value => {
value = sortArray(value.toLowerCase());
if(result){
result += " ";
result += value;
}
else {result = value;}
});
console.log(result);
This code works when I have my array of arrays of numbers, but not when I typed in an array of arrays of strings; I did change the code to use .length afterward for the strings, but that helps. The error is with the line of "arr[i].reduce(function (onea, twoa) {" being an undefined function in the second version.
Oh, #user1600124, that prompt might be the error, even though I did still type in "[ ["one", "two", "three"], ["one1", "two2", "three3"] ]", it changed that all into a string. You have solved it, I think, but is there a way for user input without prompt. Thanks, #user1600124 for your solution!
var ArrayWidth = function(arr){
var ret = [], i;
for (i = 0; i < arr.length; i++) {
arr[i].reduce(function (onea, twoa) {
return ret[i] = Math.max(onea.length, twoa.length); //added ".length" to stings version
}, 0); //added ",0" to strings version
ret[i] = ret[i].toString().length;
}
return ret;
}
Working full code of array of arrays of numbers:
//Draws Non=Jagged Table with columns be the arrays in the array of arrays and the first being the heading.
var arrays = [
[111111, 22222, 333],
[444444444, 534334, 63],
[73, 83748395, 9343],
[279571, 327894598571490581, 34815, 2]
];
function ArrayHeight (arr) {
var ret = [], i, j;
for(i = 0; i < arr.length; i++){
window["a"+i] = arr[i];
ret[i] = window["a"+i];
for(j = 0; j < ret[i].length; j++)
ret[i][j] = ret[i][j].toString();
}
return ret;
}
var ArrayWidth = function(arr){
var ret = [], i;
for (i = 0; i < arr.length; i++) {
arr[i].reduce(function (onea, twoa) {
return ret[i] = Math.max(onea, twoa);
});
ret[i] = ret[i].toString().length;
}
return ret;
}
function addSpace (){
var ret = ArrayHeight(arrays);
console.log(ret);
var widthOfRet = ArrayWidth(arrays);
console.log(widthOfRet);
var i, j, k;
for(j = 0; j < ret.length; j++){
for(k = 0; k < (ret[j].length); k++){
for(i = ret[j][k].length; i < (widthOfRet[j] + 1); i++){
ret[j][k] = ret[j][k] + " ";
}
}
}
return ret;
}
var drawTable = function(){
var ret = addSpace();
var ArrayWid = ArrayWidth(arrays);
var table = "", retFirst = "", retSecond = "", totaled = 0, i, j;
for (i = 0; i < ArrayWid.length; i++)
totaled = totaled + ArrayWid[i];
for(i = 0; i < ret.length; i++)
retFirst = retFirst + ret[i][0];
for(i = 0; i < (totaled + ret.length); i++)
retSecond = retSecond + "-";
for(j = 0; j < ret.length; j++)
for(i = 0; i < ret[j].length; i++)
window["reti"+i] = "";
for(j = 0; j < ret.length; j++)
for(i = 0; i < ret[j].length; i++)
window["reti"+i] = window["reti"+i] + ret[j][i];
table = retFirst + "\n" + retSecond;
for(i = 1; window["reti"+i] != undefined; i++)
table = table + "\n" + window["reti"+i];
return table;
}
console.log(drawTable());
nonworking with array of arrays of strings:
//Draws Non-Jagged Table with columns be the arrays in the array of arrays and the first being the heading.
var arrays = prompt("To draw a table, type in an array of arrays. Each array is a column and the first is the heading. Cannot be jagged.", "[ [ , ... ], [, ... ], ... ]");
function ArrayHeight (arr) {
var ret = [], i, j;
for(i = 0; i < arr.length; i++){
window["a"+i] = arr[i];
ret[i] = window["a"+i];
for(j = 0; j < ret[i].length; j++)
ret[i][j] = ret[i][j].toString();
}
return ret;
}
var ArrayWidth = function(arr){
var ret = [], i;
for (i = 0; i < arr.length; i++) {
arr[i].reduce(function (onea, twoa) {
return ret[i] = Math.max(onea.length, twoa.length);
}, 0);
ret[i] = ret[i].toString().length;
}
return ret;
}
function addSpace (){
var ret = ArrayHeight(arrays);
console.log(ret);
var widthOfRet = ArrayWidth(arrays);
console.log(widthOfRet);
var i, j, k;
for(j = 0; j < ret.length; j++){
for(k = 0; k < (ret[j].length); k++){
for(i = ret[j][k].length; i < (widthOfRet[j] + 1); i++){
ret[j][k] = ret[j][k] + " ";
}
}
}
return ret;
}
var drawTable = function(){
var ret = addSpace();
var ArrayWid = ArrayWidth(arrays);
var table = "", retFirst = "", retSecond = "", totaled = 0, i, j;
for (i = 0; i < ArrayWid.length; i++)
totaled = totaled + ArrayWid[i];
for(i = 0; i < ret.length; i++)
retFirst = retFirst + ret[i][0];
for(i = 0; i < (totaled + ret.length); i++)
retSecond = retSecond + "-";
for(j = 0; j < ret.length; j++)
for(i = 0; i < ret[j].length; i++)
window["reti"+i] = "";
for(j = 0; j < ret.length; j++)
for(i = 0; i < ret[j].length; i++)
window["reti"+i] = window["reti"+i] + ret[j][i];
table = retFirst + "\n" + retSecond;
for(i = 1; window["reti"+i] != undefined; i++)
table = table + "\n" + window["reti"+i];
return table;
}
console.log(drawTable());
alert("Your table is in the console.log");
my html:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script language="javascript">
//script was here
</script>
</body>
</html>
Thanks! :)
You are calling the reduce function on the content of the input array.
When you have array of arrays of numbers, arr[i] is an array, and hence has the reduce method
When you have array of strings, arr[i] is a string, and do not have the reduce method you tried to use. So you end up with errors
Try this:
function ArrayWidth(ary){
var r = [];
for(var i=0,l=ary.length; i<l; i++) {
r[i] = ary[i].reduce(function(a, b){
return Math.max(a, b);
}, 0);
}
return r;
}