Java Script Loop for comparing different dictionaries from an Array - javascript

I want to compare a dicitonary, which has certain preferences of a coachee, with other dictionaries, which contain the profil of coaches.
So every Coach got a score on how well he matches the coachee preference, or gets excluded with a score of -1 because he doesnt match an important preference.
One coachee will be compared to 24 coaches, and get a score, so i can see which is the best match.
QUESTION: How can I loop this?
Here is a code example:
//coachee\\
var coachee = {
"geschlecht": 1,
"alter_option_1": 1,
"alter_option_2": 1,
"alter_option_3": 0,
"themen_option_1": 1,
"themen_option_2": 0,
"themen_option_3": 0,
"branche_option_1": 1,
"branche_option_2": 0,
"branche_option_3": 0,
"erfahrung_option_1": 1,
"erfahrung_option_2": 0,
"erfahrung_option_3": 1,
"sprache_option_1": 1,
"sprache_option_2": 0,
"sprache_option_3": 0,
}
//coach1\\
var coach1 = {
coach1_answers_geschlecht : 2,
coach1_answers_alter_option_1 : 0,
coach1_answers_alter_option_2 : 1,
coach1_answers_alter_option_3 : 0,
coach1_answers_themen_option_1 : 1,
coach1_answers_themen_option_2 : 0,
coach1_answers_themen_option_3 : 1,
coach1_answers_branche_option1 : 1,
coach1_answers_branche_option2 : 1,
coach1_answers_branche_option3 : 0,
coach1_answers_erfahrung_option1 : 1,
coach1_answers_erfahrung_option2 : 1,
coach1_answers_erfahrung_option3 : 0,
coach1_answers_sprache_option_1 : 1,
coach1_answers_sprache_option_2 : 1,
coach1_answers_sprache_option_3 : 1,
};
///COMPARISON\\\
//Themen\\
if (answers["themen_option_1"] == 1 && coach1_answers_themen_option_1 == 1) {
coach1_themen1_score = 1;
} else {
coach1_themen1_score = 0
}
if (answers["themen_option_2"] == 1 && coach1_answers_themen_option_2 == 1) {
coach1_themen2_score = 1;
} else {
coach1_themen2_score = 0
}
if (answers["themen_option_3"] == 1 && coach1_answers_themen_option_3 == 1) {
coach1_themen3_score = 1;
} else {
coach1_themen3_score = 0
}
var coach1_themen_score = coach1_themen1_score + coach1_themen2_score + coach1_themen3_score
//Branche\\
if (answers["branche_option_1"] == 1 && coach1_answers_branche_option1 == 1) {
coach1_branche1_score = 1;
} else {
coach1_branche1_score = 0
}
if (answers["branche_option_2"] == 1 && coach1_answers_branche_option2 == 1) {
coach1_branche2_score = 1;
} else {
coach1_branche2_score = 0
}
if (answers["branche_option_3"] == 1 && coach1_answers_branche_option3 == 1) {
coach1_branche3_score = 1;
} else {
coach1_branche3_score = 0
}
var coach1_branche_score = coach1_branche1_score + coach1_branche2_score + coach1_branche3_score
//Erfahrung\\
if (answers["erfahrung_option_1"] == 1 && coach1_answers_erfahrung_option1 == 1) {
coach1_erfahrung1_score = 1;
} else {
coach1_erfahrung1_score = 0
}
if (answers["erfahrung_option_2"] == 1 && coach1_answers_erfahrung_option2 == 1) {
coach1_erfahrung2_score = 1;
} else {
coach1_erfahrung2_score = 0
}if (answers["erfahrung_option_3"] == 1 && coach1_answers_erfahrung_option3 == 1) {
coach1_erfahrung3_score = 1;
} else {
coach1_erfahrung3_score = 0
}
var coach1_erfahrung_score = coach1_erfahrung1_score + coach1_erfahrung2_score + coach1_erfahrung3_score
//Score\\
var coach1_score = (coach1_alter_score + coach1_themen_score + coach1_branche_score + coach1_erfahrung_score)*10
///EXCLUSION\\\
//Alter\\
if (answers["alter_option_1"] == 1 && coach1_answers_alter_option_1 == 1) {
coach1_alter_score = 1;
} else if (answers["alter_option_2"] == 1 && coach1_answers_alter_option_2 == 1) {
coach1_alter_score = 1;
} else if (answers["alter_option_3"] == 1 && coach1_answers_alter_option_3 == 1) {
coach1_alter_score = 1;
} else {
coach1_score = -1
}
//Sprache\\
if (answers["sprache_option_1"] == 1 && coach1_answers_sprache_option_1 == 1 ) {
coach1_sprache_score = 1;
} else if (answers["sprache_option_2"] == 1 && coach1_answers_sprache_option_2 == 1 ) {
coach1_sprache_score = 1;
} else if (answers["sprache_option_3"] == 1 ) {
coach1_sprache_score = 1;
} else {
coach1_score = -1;
}
//Geschlecht\\
if (answers["geschlecht"] == 3) {
coach1_geschlecht_score = 1;
} else if (answers["geschlecht"] == coach1_answers_geschlecht) {
coach1_geschlecht_score = 1;
} else {
coach1_score = -1;
}
//Coach2\\
var coach2 = {
coach2_answers_geschlecht : 2,
coach2_answers_alter_option_1 : 0,
coach2_answers_alter_option_2 : 1,
coach2_answers_alter_option_3 : 0,
coach2_answers_themen_option_1 : 1,
coach2_answers_themen_option_2 : 1,
coach2_answers_themen_option_3 : 1,
coach2_answers_branche_option1 : 1,
coach2_answers_branche_option2 : 1,
coach2_answers_branche_option3 : 0,
coach2_answers_erfahrung_option1 : 1,
coach2_answers_erfahrung_option2 : 1,
coach2_answers_erfahrung_option3 : 0,
coach2_answers_sprache_option_1 : 1,
coach2_answers_sprache_option_2 : 1,
coach2_answers_sprache_option_3 : 1,
};
As a result I want an Array with all the scores like:
coaches_score = [coach1_score, coach2_score, ...]
Manually i would repeat the //COMPARISON\ and //EXCLUSION\ Block for every Coach, but i would have to do this 24 times. Is there any way to Loop this?
Thanks a lot guys.

I suggest to change the data structure to a more iterable style with arrays and take same keys for calculating score with a group of keys.
const
getScore = coach => {
const
score = {},
keys1 = ['themen', 'branche', 'erfahrung'],
keys2 = ['alter', 'sprache'];
keys1.forEach(k => score[k] = coachee[k].reduce((s, v, i) => s + v * coach[k][i], 0));
score.score = keys1.reduce((s, k) => s + score[k], 0) * 10;
keys2.forEach(k => {
score[k] = +coachee[k].slice(0, -1).some((v, i) => v * coach[k][i]) || +coach1[k][coach[k].length - 1] || 0;
if (!score[k]) score.score = -1;
});
score.geschlecht = +(coach.geschlecht === 3 || coachee.geschlecht === coach.geschlecht)
if (!score.geschlecht) score.score = -1;
return score;
},
coachee = {
geschlecht: 1,
alter: [1, 1, 0, 0],
themen: [1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],
branche: [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0],
erfahrung: [1, 0, 1, 0, 0],
sprache: [1, 0, 0]
},
coach1 = {
geschlecht: 2,
alter: [0, 1, 0, 1],
themen: [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1],
branche: [1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1],
erfahrung: [1, 1, 0, 0, 1],
sprache: [1, 1, 1]
};
console.log(getScore(coach1));

Ok, i still dont get the code, because it is way to complexe for my understanding of Java Script, but i still got it working for me. I edited this to the Code:
var coach1_values = getScore(coach1)
var coach2_values = getScore(coach2)
var coach3_values = getScore(coach3);
//Summieren der Werte zum Score\\
const sumValues = obj => Object.values(obj).reduce((a, b) => a + b);
if (coach1_values.score != -1) {
var coach1_score = sumValues(coach1_values);
} else coach1_score = -1;
if (coach2_values.score != -1) {
var coach2_score = sumValues(coach2_values);
} else coach2_score = -1;
if (coach3_values.score != -1) {
var coach3_score = sumValues(coach3_values);
} else coach3_score = -1;
I dont get why the score gets the value 110 if it matches the "geschlecht", but its no problem, because everyone gets the 110 to their score. Thanks a lot again

Related

trying to create sudoko matrix help (JS)

I'm trying to create a random board for my project but it finishes without filling the whole board(leaves 0)
I converted the original code from this site:
www.101computing.net/sudoku-generator-algorithm/
from python to javascript manually and checked all the functions that I created but some things were wrong.
would love to get some help here thnks!
the code:
let grid = Array(9).fill().map(()=>Array(9).fill(0))
let numberList = [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(grid);
fillGrid(grid)
console.log(grid)
function fillGrid(grid){
//var counter;
// Find next empty cell
for (i in range(0,81)){
row = ~~(i / 9);
col = i % 9;
if (grid[row][col]== 0){
shuffle(numberList);
for (g in numberList){
value = numberList[g]
// Check that this value has not already be used on this row and col
if (!checkForNumebrInRaw(grid,row,value) && !checkForNumebrInColomn(grid,col,value)){
// Identify which of the 9 squares we are working on
square = []
if (row<3){
if (col<3){
square = getSquare(grid,0,3,0,3);
}else if (col<6){
square = getSquare(grid,3,6,0,3);
}else{
square = getSquare(grid,6,9,0,3);
}
}
else if (row<6){
if (col<3){
square = getSquare(grid,0,3,3,6);
}else if (col<6){
square = getSquare(grid,3,6,3,6);
}else{
square = getSquare(grid,6,9,3,6);
}
}
else{
if (col<3){
square = getSquare(grid,0,3,6,9);
}else if (col<6){
square = getSquare(grid,3,6,6,9);
}else{
square = getSquare(grid,6,9,6,9);
}
}
// Check that this value has not already be used on this 3x3 square
if (!checkForNumInSquare(square,value)){
grid[row][col] = value;
if (checkGrid(grid)){
return true;
}else
{
if (fillGrid(grid)){
return true;
}
}
}
}
break
}
grid[row][col] = 0;
}
}
}
function range(start, end) {
let res=[];
for (i=start;i<end;i++){
res.push(i)
}
return res
};
function getSquare(mat,a,b,c,d) {
var _pj_a = []
_pj_b = range(c, d);
for (var _pj_c = 0, _pj_d = _pj_b.length; _pj_c < _pj_d; _pj_c += 1) {
var i = _pj_b[_pj_c];
_pj_a.push(mat[i].slice(a, b));
}
return _pj_a;
};
function checkForNumebrInRaw(grid,raw,num){
for (let i = 0; i<grid.length;i++){
if (grid[raw][i] == num){return true;}
}
return false;
}
function checkForNumebrInColomn(grid,colomn,num){
for (let i = 0; i<grid.length;i++){
if (grid[i][colomn] == num){return true;}
}
return false;
}
function shuffle(array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
}
function checkForNumInSquare(grid,num){
for (let i=0;i<grid.length;i++){
for(let j=0;j<grid[i].length;j++){
if (grid[i][j]== num){return true;}
}
}
return false
}
// A function to check if the grid is full
function checkGrid(grid){
for (let i=0;i<grid.length;i++){
for(let j=0;j<grid[i].length;j++){
if (grid[i][j]== 0){return false;}
}
}
return true
}
output:
[
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
],
[
0, 0, 0, 0, 0,
0, 0, 0, 0
]
]
[
[
3, 8, 7, 4, 1,
2, 5, 6, 9
],
[
5, 9, 6, 3, 7,
8, 1, 4, 0
],
[
1, 2, 4, 5, 6,
9, 7, 3, 8
],
[
9, 4, 3, 1, 5,
7, 0, 8, 2
],
[
2, 1, 8, 0, 9,
4, 3, 7, 6
],
[
7, 0, 5, 6, 8,
3, 9, 1, 4
],
[
4, 7, 2, 8, 0,
1, 6, 9, 5
],
[
0, 6, 9, 2, 3,
5, 8, 0, 7
],
[
8, 3, 1, 7, 0,
6, 4, 2, 0
]
]
Ok so after a million tries i made it!
// true - row and colomn without the number
function rowAndColomnCheck(grid,row,col,num){
function checkForNumebrInRaw(grid,row,num){
for (let i = 0; i<grid.length;i++){
if (grid[row][i] == num){return true;}
}
return false;
}
function checkForNumebrInColomn(grid,colomn,num){
for (let i = 0; i<grid.length;i++){
if (grid[i][colomn] == num){return true;}
}
return false;
}
if (!checkForNumebrInColomn(grid,col,num) && !checkForNumebrInRaw(grid,row,num)){
return true;
}else{
return false;
}
};
function range(start, end) {
let res=[];
for (i=start;i<end;i++){
res.push(i)
}
return res
};
function getSquare(mat,a,b,c,d) {
var _pj_a = []
_pj_b = range(c, d);
for (var _pj_c = 0, _pj_d = _pj_b.length; _pj_c < _pj_d; _pj_c += 1) {
var i = _pj_b[_pj_c];
_pj_a.push(mat[i].slice(a, b));
}
return _pj_a;
};
function shuffle(array) {
let currentIndex = array.length, randomIndex;
// While there remain elements to shuffle...
while (currentIndex != 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
// And swap it with the current element.
[array[currentIndex], array[randomIndex]] = [
array[randomIndex], array[currentIndex]];
}
return array;
};
// check if number is in sqare given
function checkForNumInSquare(grid,num){
for (let i=0;i<grid.length;i++){
for(let j=0;j<grid[i].length;j++){
if (grid[i][j]== num){return true;}
}
}
return false
};
// A function to check if the grid is full
function checkGrid(grid){
for (let i=0;i<grid.length;i++){
for(let j=0;j<grid[i].length;j++){
if (grid[i][j]== 0){return false;}
}
}
// complete
return true
};
function fillSudoku(mat){
for(let i in range(0,81)){
var mainRow = ~~(i / 9);
var mainCol = i % 9;
if (mat[mainRow][mainCol] == 0){
shuffle(numberList);
for (let value of numberList){
if(rowAndColomnCheck(mat,mainRow,mainCol,value)){
var mySquare = [[]];
if(mainRow<3){
if (mainCol<3){
mySquare = getSquare(mat,0,3,0,3);
}
else if (mainCol<6){
mySquare = getSquare(mat,3,6,0,3);
}
else{
mySquare = getSquare(mat,6,9,0,3);
}
}
else if(mainRow<6){
if (mainCol<3){
mySquare = getSquare(mat,0,3,3,6);
}
else if (mainCol<6){
mySquare = getSquare(mat,3,6,3,6);
}
else{
mySquare = getSquare(mat,6,9,3,6);
}
}
else{
if (mainCol<3){
mySquare = getSquare(mat,0,3,6,9);
}
else if (mainCol<6){
mySquare = getSquare(mat,3,6,6,9);
}
else{
mySquare = getSquare(mat,6,9,6,9);
}
}
bol_t = checkForNumInSquare(mySquare,value);
if (bol_t == false){
mat[mainRow][mainCol] = value;
if (checkGrid(mat)){
return true;
}
else{
if (fillSudoku(mat)){
return true;
}
}
}
}
}
break
}
}
mat[mainRow][mainCol] = 0;
};
var numberList = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var grid = Array(9).fill().map(()=>Array(9).fill(0));
fillSudoku(grid);
console.log(grid);

What does element.count & element.value means in array?

I found a great solution to get maximum Bi-valued slice of an array. And I want to apply it in Swift. However, I'm not familiar with JavaScript, I search it via Google, but no result yet.
Well, I simply want to know what does last.count & last.value means in below code. What they do with element last?
function getLongestSlice(array) {
var count = 0,
max = 0,
temp = [];
array.forEach(function (a) {
var last = temp[temp.length - 1];
if (temp.length < 2 || temp[0].value === a || temp[1].value === a) {
++count;
} else {
count = last.count + 1;
}
if (last && last.value === a) {
last.count++;
} else {
temp.push({ value: a, count: 1 });
temp = temp.slice(-2);
}
if (count > max) {
max = count;
}
});
return max;
}
console.log(getLongestSlice([58, 800, 0, 0, 0, 356, 8988, 1, 1])); // 4
console.log(getLongestSlice([58, 800, 0, 0, 0, 356, 356, 8988, 1, 1])); // 5
console.log(getLongestSlice([1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8])); // 10
Update:
Thanks. Now it is working in Swift.
import Foundation
struct Tmp {
var value: Int
var count: Int
}
func getLongestSlice(A: [Int]) -> Int {
var count = 0,
max = 0,
temp: [Tmp] = []
var last: Tmp = Tmp(value: 0, count: 0)
for a in A {
if temp.count != 0 {
last = temp[temp.count - 1]
}
print("last: \(last)")
if temp.count < 2 || temp[0].value == a || temp[1].value == a {
count += 1
} else {
count = last.count + 1
}
if last.value == a {
last.count += 1
// assign last.count to last element's count of temp array
temp[temp.count - 1].count = last.count
} else {
temp.append(Tmp(value: a, count: 1))
temp = Array(temp.suffix(2))
}
if count > max {
max = count
}
}
return max
}
getLongestSlice(A: [58, 800, 0, 0, 0, 356, 8988, 1, 1]) // return 4
getLongestSlice(A: [58, 800, 0, 0, 0, 356, 356, 8988, 1, 1]) // return 5
getLongestSlice(A: [1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8]) // return 10
getLongestSlice(A: [777]) // return 1
getLongestSlice(A: []) // return 0
From thread: Find Max Slice Of Array | Javascript
The temp array holds objects of the following shape:
{ count: ..., value: ... }
So the last refers to the last element of that array, while count and value are the properties of that element.
This is not related to JavaScript.

(Game bug) Tetris pieces being disappearing when colliding

I'm making a Tetris game with javascript, but there's a bug I haven't been able to fix yet. It only happens when pieces Z, S, and T collide with an object while going down. I thought the problem was with the 3rd row of 0s, but the other pieces draw fine when I add it to other pieces. I also can't remove the rows because I need them to rotate the pieces.
If anyone can find the error I'd really appreciate it! Thank you.
Here's the code on repl.it:
https://repl.it/#julkothegu1/Oke-Oke
Raw:
const canvas = document.getElementById('tetris');
const context = canvas.getContext('2d');
context.scale(20, 20);
function arena_sweep(){
let row_count = 1
outer: for (let y = arena.length -1; y > 0; y--){
for (let x = 0; x < arena[y].length; x++){
if (arena[y][x] == 0){
continue outer
}
}
const row = arena.splice(y, 1)[0].fill(0);
arena.unshift(row);
++y;
player.score += row_count * 10
row_count *= 2
}
}
function draw(){
context.fillStyle = '#000';
context.fillRect(0, 0, canvas.width, canvas.height);
draw_matrix(arena, {x:0, y:0})
draw_matrix(player.matrix, player.pos)
}
function create_matrix(w, h){
const matrix = []
while (h--){
matrix.push(new Array(w).fill(0))
}
return matrix
}
function player_reset(){
const pieces = 'ILJOZST'
player.matrix = create_piece(pieces[pieces.length * Math.random() | 0])
player.pos.y = 0
player.pos,x = (arena[0].length / 2 | 0) - (player.matrix[0].length / 2 | 0)
if (collide(arena, player)){
arena.forEach(row => row.fill(0))
player.score = 0
update_score()
}
}
function create_piece(type)
{
if (type === 'I') {
return [
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 0, 0],
];
} else if (type === 'L') {
return [
[0, 2, 0],
[0, 2, 0],
[0, 2, 2],
];
} else if (type === 'J') {
return [
[0, 3, 0],
[0, 3, 0],
[3, 3, 0],
];
} else if (type === 'O') {
return [
[4, 4],
[4, 4],
];
} else if (type === 'Z') {
return [
[5, 5, 0],
[0, 5, 5],
[0, 0, 0],
];
} else if (type === 'S') {
return [
[0, 6, 6],
[6, 6, 0],
[0, 0, 0],
];
} else if (type === 'T') {
return [
[0, 7, 0],
[7, 7, 7],
[0, 0, 0],
];
}
}
function draw_matrix(matrix, offset){
matrix.forEach((row, y) => {
row.forEach((value, x) => {
if (value !== 0){
context.fillStyle = colors[value]
context.fillRect(x + offset.x, y + offset.y, 1, 1)
}
});
});
}
function merge(arena, player){
player.matrix.forEach((row, y) => {
row.forEach((value, x) => {
if (value !== 0){
arena[y + player.pos.y][x + player.pos.x] = value;
}
});
});
}
function collide(arena, player){
const m = player.matrix;
const o = player.pos;
for (let y = 0; y < m.length; y++){
for (let x = 0; x < m[y].length; x++){
if (m[y][x] != 0 && (arena[y + o.y] && arena[y + o.y][x + o.x]) != 0){
return true
}
}
}
return false
}
let drop_counter = 0
let last_time = 0
let drop_interval = 400
function update(time = 0){
const delta_time = time - last_time
drop_counter += delta_time
if (drop_counter > drop_interval){
player_drop()
}
last_time = time
draw()
requestAnimationFrame(update)
}
function player_drop(){
player.pos.y++
if (collide(arena, player)){
player.pos.y--
merge(arena, player)
player_reset()
arena_sweep()
update_score()
}
drop_counter = 0
}
function player_move(dir){
player.pos.x += dir
if (collide(arena, player)){
player.pos.x -= dir
}
}
function player_rotate(dir){
const pos = player.pos.x
let offset = 1
rotate(player.matrix, dir)
while (collide(arena, player)){
player.pos.x += offset
offset = -(offset + (offset > 0 ? 1 : -1))
if (offset > player.matrix[0].length){
rotate(player.matrix, -dir)
player.pos.x = pos
return
}
}
}
function update_score(){
document.getElementById('score').innerText = player.score
}
function rotate(matrix, dir){
for (let y = 0; y < matrix.length; y++){
for (let x = 0; x < y; x++){
[
matrix[x][y],
matrix[y][x],
] = [
matrix[y][x],
matrix[x][y],
];
}
}
if (dir > 0){
matrix.forEach(row => row.reverse());
} else {
matrix.reverse();
}
}
const colors = [
null,
'green',
'blue',
'violet',
'red',
'purple',
];
const player = {
pos: {x: 0, y: 0},
matrix: null,
score: 0,
}
const arena = create_matrix(12, 20)
document.addEventListener('keydown', event => {
if (event.keyCode === 37){
player_move(-1);
}else if (event.keyCode == 39){
player_move(1);
}else if (event.keyCode == 40){
player_drop();
}else if (event.keyCode == 81){
player_rotate(-1)
}else if (event.keyCode == 87){
player_rotate(1)
}
});
update_score()
player_reset()
update()
Never mind, I found the error. I forgot to give 7 colors to the pieces, so it was looping on colors it shouldn't have been.

Flood-fill algorithm in Javascript not filling the entire grid when using for loops

I've been working at this all day, and I can't work out why this algorithm doesn't cover the entire grid when starting at position grid[1][1].
I start by setting up the grid and calculating the number of rows and columns in the grid to give me a limit on the edges of the array.
I then call the function, setting position grid[1][1] = 1, calculating the offset and making sure it is not outside the array and making sure the new position has not already been called before calling the function recursively.
I just can't figure out why this isn't working!
var grid = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]];
var cols = grid.length;
var rows = grid[0].length;
floodFill(1, 1)
function floodFill(col, row) {
grid[col][row] = 1;
for (c_off = -1; c_off < 2; c_off++) {
for (r_off = -1; r_off < 2; r_off++) {
var i = col + c_off;
var j = row + r_off;
if (i > -1 && i < cols && j > -1 && j < rows) {
if (grid[i][j] != 1) {
floodFill(i, j);
}
}
}
}
}
grid;
/*
output:
[ [ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 0 ],
[ 1, 1, 0, 0, 0 ] ]
expected output:
[ [ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1 ],
[ 1, 1, 1, 1, 1 ] ]
*/
That's because c_off and r_off are not defined as local variables (via the var or let keywords) so they are treated like a global variables which means that a recursive invocation of floodFill() overwrites the values for its calling invocation thereby interfering with the caller's iteration order.
The fix is simple: just add a var keyword in both for loops:
function floodFill(col, row) {
grid[col][row] = 1;
for (var c_off = -1; c_off < 2; c_off++) {
for (var r_off = -1; r_off < 2; r_off++) {
var i = col + c_off;
var j = row + r_off;
if (i > -1 && i < cols && j > -1 && j < rows) {
if (grid[i][j] != 1) {
floodFill(i, j);
}
}
}
}
}
Appendix
You can move the detection of out-of-grid condition, and the check whether the given point is already filled, to the beginning of the function (instead of doing it just before the recursive call). Some may argue that the resulting code is simpler to understand:
function floodFill(col, row) {
if (col < 0 || col >= cols || row < 0 || row >= rows) {
return;
}
if (grid[col][row] == 1) {
return;
}
grid[col][row] = 1;
for (var c_off = -1; c_off < 2; c_off++) {
for (var r_off = -1; r_off < 2; r_off++) {
floodFill(col + c_off, row + r_off);
}
}
}
I think Itay Maman answer is probably better. I solved it this way. by changing c_off < 5 and r_off < 5
var grid = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]];
var cols = grid.length;
var rows = grid[0].length;
floodFill(1, 1)
function floodFill(col, row) {
grid[col][row] = 1;
for (c_off = -1; c_off < 5; c_off++) {
for (r_off = -1; r_off < 5; r_off++) {
var i = col + c_off;
var j = row + r_off;
if (i > -1 && i < cols && j > -1 && j < rows) {
if (grid[i][j] != 1) {
floodFill(i, j);
}
}
}
}
}
console.log(grid);

Find Max Slice Of Array | Javascript

I need to find the maximum slice of the array which contains no more than two different numbers.
Here is my array [1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8]
My thought process on this is to find the numbers that are not repeated and return their index within a new array.
Here is what I have so far:
function goThroughInteger(number) {
var array = [];
//iterate the array and check if number is not repeated
number.filter(function (element, index, number) {
if(element != number[index-1] && element != number[index+1]) {
array.push(index);
return element;
}
})
console.log(array);
}
goThroughInteger([1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8]);
I'm unsure where to go next, I'm struggling to understand the question that being - find the maximum slice which contains no more than two different numbers - that confuses me.
A solution with a single loop, which checks the last values and increments a counter.
function getLongestSlice(array) {
var count = 0,
max = 0,
temp = [];
array.forEach(function (a) {
var last = temp[temp.length - 1];
if (temp.length < 2 || temp[0].value === a || temp[1].value === a) {
++count;
} else {
count = last.count + 1;
}
if (last && last.value === a) {
last.count++;
} else {
temp.push({ value: a, count: 1 });
temp = temp.slice(-2);
}
if (count > max) {
max = count;
}
});
return max;
}
console.log(getLongestSlice([58, 800, 0, 0, 0, 356, 8988, 1, 1])); // 4
console.log(getLongestSlice([58, 800, 0, 0, 0, 356, 356, 8988, 1, 1])); // 5
console.log(getLongestSlice([1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8])); // 10
function goThroughInteger(array) {
var solutionArray = [];
var max = 0;
for (var i = 0; i <= array.length; i++) {
for (var j = i + 1; j <= array.length; j++) {
var currentSlice= array.slice(i,j);
var uniqSet = [...new Set(currentSlice)];
if(uniqSet.length <3) {
if(currentSlice.length>max) {
max= currentSlice.length;
}
}
}
}
console.log(max);
}
goThroughInteger([1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8]);
This solution checks every possible slice of the array, checks if it has not more than 2 different numbers and finally prints out the length of the longest slice.
This is a possible solution, with complexity O(n²) (as pointed out by #le_m in the comments)
goThroughInteger = (list) => {
let scores = list.reduce((slices, num, pos) => {
let valid = [num];
let count = 0;
for (let i = pos; i < list.length; i++) {
if (valid.indexOf(list[i]) == -1) {
if (valid.length < 2) {
valid.push(list[i]);
count++;
} else {
break;
}
} else {
count++;
}
}
slices[pos] = { pos, count };
return slices;
}, []);
scores.sort((a, b) => b.count - a.count);
let max = scores[0];
return list.slice(max.pos, max.pos + max.count);
};
console.log(goThroughInteger([1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8]));
console.log(goThroughInteger([58, 800, 0, 0, 0, 356, 8988, 1, 1]));
```
The solution calculates the 'score' at every position of the input list, counting the length of a sequence of no more than 2 different values, then takes the result with the highest score and extracts a slice from the original list based on that information.
It can definitely be cleaned and optimized but I think it's a good starting point.
Using the sliding window algorithm in O(n) time:
const arr = [1, 1, 1, 2, 2, 2, 1, 1, 2, 2, 6, 2, 1, 8, 1, 1 ,1 ,1, 8, 1, 1, 8, 8];
const map = {
length: 0
};
let required = [];
for(start = 0, end = 0; end <= arr.length; ){
if(map.length > 2){
if(map[arr[start]] === 1){
delete map[arr[start]];
map.length --;
}else{
map[arr[start]]--;
};
start++;
}else{
if(end - start > required.length){
required = arr.slice(start, end);
};
if(map[arr[end]]){
map[arr[end]]++;
}else{
map[arr[end]] = 1;
map.length++;
}
end++;
}
}
console.log(required);

Categories

Resources