J'essaie de résoudre ce problème de leetcode (jeu de la vie) : https://leetcode.com/problems/game-of-life
Voici mon code :
function isLive(board: number[][], row: number, column: number) {
let liveNeighbours = 0;
[row - 1, row, row + 1].forEach(r => {
if (r < 0 || r >= board.length) return;
[column - 1, column, column + 1].forEach(c => {
if (c === column && r === row) return;
if (c < 0 || c >= board[0].length) return;
if (board[r][c] === 1) liveNeighbours++
})
})
if (board[row][column] === 1 && (liveNeighbours === 3 || liveNeighbours === 2)) return true;
if (board[row][column] === 0 && liveNeighbours === 3) return true;
return false;
}
/**
Do not return anything, modify board in-place instead.
*/
function gameOfLife(board: number[][]): void {
let nextGen = Array(board.length).fill(Array(board[0].length).fill(0));
for (let i = 0; i < board.length; i++) {
for (let j = 0; j < board[0].length; j++) {
console.log("isLive row ", i, " col ", j, isLive(board, i, j))
if (isLive(board, i, j)) nextGen[i][j] = 1
}
}
console.log("next gen", nextGen);
board = nextGen;
};
J'exécute le code avec cette entrée :
[
[0,1,0],
[0,0,1],
[1,1,1],
[0,0,0]
]
Et il produit ceci (la même chose en gros) :
[
[0,1,0],
[0,0,1],
[1,1,1],
[0,0,0]
]
Alors qu'il s'attend à ça :
[
[0,0,0],
[1,0,1],
[0,1,1],
[0,1,0]
]
Ce qui me rend vraiment fou, ce sont les journaux d'impression. Lorsque j'imprime chaque cellule, qu'elle soit active ou non, le résultat est parfaitement conforme à ce qu'il devrait être. Voici le journal :
isLive row 0 col 0 false
isLive row 0 col 1 false
isLive row 0 col 2 false
isLive row 1 col 0 true
isLive row 1 col 1 false
isLive row 1 col 2 true
isLive row 2 col 0 false
isLive row 2 col 1 true
isLive row 2 col 2 true
isLive row 3 col 0 false
isLive row 3 col 1 true
isLive row 3 col 2 false
De plus, dans le dernier journal d'impression de nextGen, il y a ceci : next gen [ [ 1, 1, 1 ], [ 1, 1, 1 ], [ 1, 1, 1 ], [ 1, 1, 1 ] ]
Ainsi, toutes les cellules sont réassignées à 1, même si je peux voir que toutes les déclarations ne sont pas vraies.
Ce qui ne ressemble à rien. Il ne correspond pas au retour individuel que j'obtiens pour chaque cellule, et ne correspond même pas à ce qu'il prétend que je renvoie, même si c'est essentiellement à la fin. Est-ce que j'ai raté quelque chose sur la façon d'assigner des valeurs aux tableaux ?
EDIT : Au lieu de simplement assigner board=nextGen
J'ai également essayé ce qui suit :
for (let i = 0; i < board.length; i++) {
for (let j = 0; j < board[0].length; j++) {
board[i][j] = nextGen[i][j];
}
}
J'obtiens maintenant ceci comme résultat [[1,1,1],[1,1,1],[1,1,1],[1,1,1]]
(le prit de nextGen).
EDIT 2 : J'ai essayé de changer la fonction pour qu'elle renvoie simplement le nombre de voisins et faire le conditionnement après. Bien que je n'aie pas encore déplacé le conditionnement, je peux déjà voir qu'il y a toujours un problème avec l'assignation des éléments au nouveau tableau.
Voici mon code modifié (encore une fois, il n'est pas complet, mais le reste n'est pas pertinent pour le problème à ce stade) :
function countNeighbors(board: number[][], row:number, column:number){
let liveNeighbors = 0;
[row-1, row, row+1].forEach(r=>{
if(r<0 || r>= board.length) return;
[column-1, column, column+1].forEach(c=>{
if(c === column && r=== row) return;
if(c<0 || c>= board[0].length) return;
if(board[r][c]===1) liveNeighbors++
})
})
return liveNeighbors;
}
/**
Do not return anything, modify board in-place instead.
*/
function gameOfLife(board: number[][]): void {
let neighbors = Array(board.length).fill(Array(board[0].length).fill(0));
for (let i = 0; i<board.length; i++){
for (let j = 0; j<board[0].length; j++){
let numberOfNeighbors = countNeighbors(board,i,j);
console.log(i, j, numberOfNeighbors)
neighbors[i][j] = numberOfNeighbors
}
console.log("neighbors", neighbors)
}
};
J'ai ajouté un journal de console après chaque itération de i
et voici ce qu'il imprime :
0 0 1
0 1 1
0 2 2
neighbors [ [ 1, 1, 2 ], [ 1, 1, 2 ], [ 1, 1, 2 ], [ 1, 1, 2 ] ]
1 0 3
1 1 5
1 2 3
neighbors [ [ 3, 5, 3 ], [ 3, 5, 3 ], [ 3, 5, 3 ], [ 3, 5, 3 ] ]
2 0 1
2 1 3
2 2 2
neighbors [ [ 1, 3, 2 ], [ 1, 3, 2 ], [ 1, 3, 2 ], [ 1, 3, 2 ] ]
3 0 2
3 1 3
3 2 2
neighbors [ [ 2, 3, 2 ], [ 2, 3, 2 ], [ 2, 3, 2 ], [ 2, 3, 2 ] ]
En fait, chaque ligne est dupliquée sur toutes les lignes. Cela semble être ce qui perturbe ma fonction, quelle que soit la façon dont je l'ai fait, mais pourquoi cela se produit-il ?
Est-ce que ça a quelque chose à voir avec le comportement de fill
?
Edit 3 : Ok, donc je suis sur la façon dont le nouveau tableau est créé. Si je le crée comme ceci pour mon cas de test : let neighbors = [[],[],[],[]];
Ensuite, tout fonctionne parfaitement.
J'aimerais cependant savoir quelle est la cause de ce comportement ? Existe-t-il un moyen efficace de créer ce tableau sans que cela ne se produise ? Je peux simplement pousser de nouveaux tableaux vides pour chaque itération de i
tout en fonctionnant et en n'étant pas très gourmand, mais j'ai pensé que la façon dont je l'ai fait en premier était plus élégante.