0% found this document useful (0 votes)
10 views215 pages

All Algorithm Solutions

The document contains a collection of algorithm solutions and coding challenges from HackerRank, organized by week. It includes code snippets for various problems such as time conversion, counting valleys, and pangrams, along with explanations and sample inputs. Additionally, it provides resources for finding solution variants and recommended software for coding practice.

Uploaded by

Hengki Idn
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views215 pages

All Algorithm Solutions

The document contains a collection of algorithm solutions and coding challenges from HackerRank, organized by week. It includes code snippets for various problems such as time conversion, counting valleys, and pangrams, along with explanations and sample inputs. Additionally, it provides resources for finding solution variants and recommended software for coding practice.

Uploaded by

Hengki Idn
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 215

All Algorithm solutions

Org:
https://www.hackerrank.com/interview/preparation-kits/three-month-preparation-kit/three-month-
week-one/challenges

Org:
https://docs.google.com/spreadsheets/d/1pa33WfRpMmKP6GWpxo9VdYS2YqBxlNQOFWJIgD
SeQCQ/edit#gid=0

Recommended Software (freeware):


● Quokka extension for VSC (so you can see the console.logs, without Terminal and
Browser) - https://quokkajs.com/docs/index.html

How to find Variants of the Solutions:


● Discussion board
● Leaderboard, click on ‘view solution’
● See video here: https://youtu.be/DPlQPFfQoOI

Week 1:

Time conversion:

let a = '07:05:45PM';

function print24(str){
// Get hours

var h1 = Number(str[1] - '0');


var h2 = Number(str[0] - '0');
var hh = (h2 * 10 + h1 % 10);
let final = '';

// If time is in "AM"
if (str[8] == 'A')
{
if (hh == 12)
{
final = "00"
for (var i = 2; i <= 7; i++){
final = final + str[i]
}

}
else
{
for (var i = 0; i <= 7; i++){
final = final + str[i]
}

}
}

// If time is in "PM"
else
{
if (hh == 12)
{
final = "12"
for (var i = 2; i <= 7; i++)
final = final + str[i]
}
else
{
hh = hh + 12;
final = final + hh
for (var i = 2; i <= 7; i++)
final = final + str[i]
}
}

console.log(final);
return final;

print24(a)

Breaking the record

let arr1 = [12, 24, 10, 24];

function countIt(arr){

let min = arr[0];


let max = arr[0];

let minRec = 0;
let maxRec = 0;

arr.forEach(el=> {
if(el < min){
min = el;
minRec = minRec+1;
}
if(el > max){
max = el;
maxRec++;
}
})

console.log(min, max);
console.log(minRec, maxRec);

return [maxRec, minRec]

countIt(arr1)

Camel Case 4

Note: There is BUG in the HackerRank, where it does NOT accept


any solution, but this code is correct (see discussions, so just
test it, and if it works all good)
// let str = 'C;C;coffee machine';
// let str = "S;V;iPad";
// let str = "C;M;mouse pad";
// let str = "C;C;code swarm";
let str = "S;C;OrangeHighlighter";

function scanner(input) {
let arr = input.split(";");
let word = arr[2];

// split
if (arr[0] === "S") {
let regexS = /[A-Za-z]/g;
let word2 = word.match(regexS).join("");

console.log(word2.replace(/([a-z])([A-Z])/g, "$1 $2").toLowerCase());

if (arr[0] === "C") {


// console.log('in C now')
let regexC = /[A-Za-z\s]/g;
let word3 = word.match(regexC);
// console.log("combine word3: ", word3);

if (arr[1] === "C") {


let combClassWord = word3.join("").split(" ");
// console.log("combClassWord: ", combClassWord);

// capitalise everyWord
for (let i = 0; i < combClassWord.length; i++) {
combClassWord[i] =
combClassWord[i][0].toUpperCase() +
combClassWord[i].substr(1);
}

console.log(combClassWord.join("")); // ! C;C final output


}

if (arr[1] === "M") {


let wordToChange = word3.join("").split(" ");
// console.log("wordToChange: ", wordToChange);

let arrayToUseWithC_M = wordToChange.slice(1, wordToChange.length);


// console.log("arrayToUseWithC_M: ", arrayToUseWithC_M);

for (let i = 0; i < arrayToUseWithC_M.length; i++) {


arrayToUseWithC_M[i] =
arrayToUseWithC_M[i][0].toUpperCase() +
arrayToUseWithC_M[i].substr(1);
}

console.log(wordToChange[0] + arrayToUseWithC_M.join("") + "()"); //


! C;M; final output
}

if(arr[1] === "V"){


let wordToChangeC_V = word3.join("").split(" ");

let arrayToUseWithC_V = wordToChangeC_V.slice(1,


wordToChangeC_V.length);

for (let i = 0; i < arrayToUseWithC_V.length; i++) {


arrayToUseWithC_V[i] =
arrayToUseWithC_V[i][0].toUpperCase() +
arrayToUseWithC_V[i].substr(1);
}
console.log(wordToChangeC_V[0] + arrayToUseWithC_V); // ! C;V; final
output
}

// end of combine
}

// end of function
}

scanner(str);

Divisible Sum Pairs

Key:

● To exclude the numbers that are themselves j=i+1;


● Secret: is to slice the arr and remove first element from it and compare EL to arr[0] so
first element of the removed array;

function divisibleSumPairs(n, k, ar) {

let count = 0;

for(var i = 0; i < ar.length; i++){

let el = ar[i];
console.log(el);

for(var j = i+1; j < ar.length; j++){

let arr = ar.slice(j, ar.length);


console.log(arr);

if((el+arr[0]) % k === 0){


count++;
}

// end of j loop
}

// end of for i loop


}

console.log(count);
return count;

// ! end of function
}

let arr1 = [1, 3, 2, 6, 1, 2]; // 5


let k1 = 3;
let n1 = arr1.length;
divisibleSumPairs(n1, k1, arr1);

Sparse Arrays

function matchingStrings(strings, queries) {


// Write your code here

let final = [];

queries.forEach(el=> {
// console.log(el);

let arr = [];

strings.forEach(qu=> {

// console.log(qu);
if(el === qu){
arr.push(el)
}

})

final.push(arr)

})

let finalFinal = final.map(el=> {


return el.length
});

console.log(finalFinal);
return finalFinal;

matchingStrings(
[ 'aba', 'baba', 'aba', 'xzxb' ], // strings
[ 'aba', 'xzxb', 'ab' ] // queries
)

___________________

Week 2:

Lonely Integer

Key:

● If el1 === el2, then i++ , else save the index = i (i.e. the iteration);
● With this move we isolate 1 element that has no pair

function lonelyinteger(a) {
// Write your code here

let index = 0;

let sorted = a.sort((a,b)=> a-b);


console.log("sorted: ", sorted);
for(let i = 0; i < sorted.length; i++){
if(sorted[i] === sorted[i+1]){
i++
} else {
// console.log(i);
index = i;
}
}

console.log(sorted[index]);
return sorted[index]

let arr = [1,2,3,4,3,2,1];

lonelyinteger(arr);

Alternative solution with 2 for loops:

function lonelyinteger(a) {
// Write your code here

a.sort((a,b)=> a-b)

let uniq = Array.from(new Set(a));


console.log("uniq: ", uniq);

let finalArr = Array.from({length: uniq.length}, ()=> [])


console.log("finalArr: ", finalArr);

for(var i = 0; i < uniq.length; i++){

console.log(i);
let el = uniq[i];
console.log("el: ", el);

for(var j = 0; j < a.length; j++){


let el2 = a[j];

if(el2 === el){


finalArr[i].push(el)
}

// end of for i loop


}

let finalNum = finalArr.filter(el=> el.length === 1).flat()[0];


console.log(finalNum);
return finalNum;

let arr = [ 0, 0, 1, 2, 1 ];
lonelyinteger(arr)

Grading Students

Date: Jun 23, 2022

function gradingStudents(grades) {
// Write your code here

let a = grades.map(el=> {

if(el < 38){


return el
}

let t = (el - (el % 5)) + 5 ;


console.log(t);

if(t - el < 3){


return t;
}

return el

});

console.log(a)
return a;

let g = [ 84, 73, 67, 38, 33 ];


gradingStudents(g)

older:

function gradingStudents(grades) {
// Write your code here

let a = grades.map(el => {


if(el < 38){
console.log('no rounding', el);
return el;
}

let test = Math.ceil(el / 5) * 5;


// console.log(test);

if(test - el < 3){


console.log(test);
return test;
}

if(test - el >=3){
console.log(el);
return el;
}
})

console.log(a);
return a;

// gradingStudents(29); // no rounding
// gradingStudents(84); // should be 85 cause 85-84 is less than 3
// gradingStudents(57); // no rounding cause 60 - 57 is 3 or higher

gradingStudents([29, 84, 57])

Flipping bits

function flippingBits(n) {
let a = ((2**32)-1) - n;
console.log(a);
return a;
}

flippingBits(3)

Diagonal Difference

Date: Jun 23, 2022

function diagonalDifference(arr) {

let lTr = 0;
let rTl = 0;

for(var i = 0; i < arr.length; i++){

lTr = lTr + arr[i][i]


rTl = rTl + arr[i][arr.length-i-1];

return Math.abs(rTl - lTr);

// ! end of the function


}

let a1 = [ [ 11, 2, 4 ], [ 4, 5, 6 ], [ 10, 8, -12 ] ]; // 15


diagonalDifference(a1);

older:

function diagonalDifference(arr) {
let diagnalLR = [];
let count1 = 0;
let diagnalRL = [];
let count2 = arr.length - 1;

arr.forEach((el, index) => {


diagnalLR.push(el[count1]);
diagnalRL.push(el[count2]);
count1 = index + 1;
count2--;
});

console.log(diagnalLR);
console.log(diagnalRL);

let reducedLR = diagnalLR.reduce((a, b) => a + b);


let reducedRL = diagnalRL.reduce((a, b) => a + b);

console.log(reducedLR);
console.log(reducedRL);

let sum = Math.abs(reducedLR - reducedRL);


console.log("sum: ", sum);

return sum;
}

let input = [
[11, 2, 4],
[4, 5, 6],
[10, 8, -12],
];
diagonalDifference(input);
Counting Sort 1

function countingSort(arr) {
// Write your code here

let finalArr = [];

for(var i = 0; i <100; i++){


finalArr.push(0);
}

arr.forEach(el=> {
finalArr[el] = finalArr[el] + 1
})

console.log(finalArr);
return finalArr;

let input = '63 25 73 1 98 73 56 84 86 57 16 83 8 25 81 56 9 53 98 67 99 12 83 89


80 91 39 86 76 85 74 39 25 90 59 10 94 32 44 3 89 30 27 79 46 96 27 32 18 21 92
69 81 40 40 34 68 78 24 87 42 69 23 41 78 22 6 90 99 89 50 30 20 1 43 3 70 95 33
46 44 9 69 48 33 60 65 16 82 67 61 32 21 79 75 75 13 87 70 33'.split('
').map(el=> Number(el));
// let input = [1,1,3,2,1];
// console.log("input: ", input);

countingSort(input)

Counting Valleys

function countingValleys(steps, path) {


// Write your code here
// key in here, we do NOT need to know how many times valley started, we just
need to find how many times did we reach back to sea level and the step was UP =
this is the valley. Logic: because you can NOT go UP without going down first,
thus going DOWN is irrelevant.

const pathToArray = path.split('');


let distanceFromSeaLevel = 0;
let totalValleys = 0;

pathToArray.forEach((el, index)=> {

if(el === 'U'){


distanceFromSeaLevel++
}

if(el=== 'D'){
distanceFromSeaLevel--
}

if(distanceFromSeaLevel === 0 && el === 'U'){


totalValleys++;
}

// end of forEach loop


})

// console.log("totalValleys: ", totalValleys);

return totalValleys
}

let stepsIn = 8;
let pathIn = 'UDDDUDUU';

countingValleys(stepsIn, pathIn)
Pangrams

function pangrams(s) {

let final = Array.from(new Set(s.toLowerCase().split('


').join('').split('').sort(function(a,b){return a === b ? 0 : a < b ? -1 : 1})))
console.log("final: ", final.length);

if(final.length === 26){


return 'pangram'
} else {
return 'not pangram'
}

let input1 = 'We promptly judged antique ivory buckles for the next prize'; //
yes
let input2 = 'We promptly judged antique ivory buckles for the prize'; // no

pangrams(input1);

Mars Exploration

function marsExploration(s) {
// Write your code here

let strToArr = s.split('');


// console.log("strToArr: ", strToArr);

let finalArr = [];


let changedLetters = 0;

let a = strToArr.slice(0, 3);


// console.log(a);

for(let i = 0; i < strToArr.length; i = i + 3){


finalArr.push(strToArr.slice(i, i+3))
}

// console.log("finalArr: ", finalArr);

finalArr.forEach(el=> {
// console.log(el)

if(el[0] !== 'S'){


changedLetters++
}

if(el[1] !== 'O'){


changedLetters++
}

if(el[2] !== 'S'){


changedLetters++
}

});

console.log("changedLetters: ", changedLetters);


return changedLetters;
// end of the function
}

let input1 = 'SOSSPSSQSSOR';


let input2 = 'QQQ'
marsExploration(input1)

Mock: Flipping the Matrix

Actual problem: https://www.hackerrank.com/challenges/flipping-the-matrix/problem

Video: https://www.youtube.com/watch?v=M-iS49m2m7E

Solution: https://github.com/subratsir/DSA-JavaScript/blob/main/subratsir/flipping-the-matrix.js

Solution discussion: https://www.hackerrank.com/challenges/flipping-the-matrix/forum

My Video Solution: https://youtu.be/1jGAutnHuYM


I am given

let input1 = [
[ 112, 42, 83, 119 ],
[ 56, 125, 56, 49 ],
[ 15, 78, 101, 43 ],
[ 62, 98, 114, 108 ]
]

I can only reverse rows and columns, so upper LEFT Upper quadrant should have the highest
possible numbers

Output should be: 414


function flippingMatrix(matrix) {
// Write your code here

let endLine = matrix.length -1;


console.log("finalLines: ", endLine);

let matMultipleN = matrix.length / 2;


console.log("matMultipleN: ", matMultipleN);

let finalArr = [];

for(let i =0; i < matMultipleN; i++){

for(let j = 0; j < matMultipleN; j++){

// console.log(matrix[i][j]);
// console.log(matrix[i][endLine-j]);
// console.log(matrix[endLine-i][j]);
// console.log(matrix[endLine-i][endLine-j]);

finalArr.push(Math.max(
matrix[i][j],
matrix[i][endLine-j],
matrix[endLine-i][j],
matrix[endLine-i][endLine-j]
));

// console.log(finalArr);
// end of j for loop
}

// end of i for loop


}

let a = finalArr.reduce((acc,value)=> acc+value);


console.log(a);
return a;
// end of function
}

let input2 = [
[1,2],
[3,4]
]

let input1 = [
[ 112, 42, 83, 119 ],
[ 56, 125, 56, 49 ],
[ 15, 78, 101, 43 ],
[ 62, 98, 114, 108 ]
]

flippingMatrix(input1);

I can also use:

let input3 = [
[112, 42, 83, 119, 234, 120],
[56, 125, 57, 49, 12, 81],
[15, 78, 101, 43, 113, 41],
[62, 98, 114, 108, 43, 21],
[523, 152, 112, 145, 7, 22],
[210, 76, 242, 41, 80, 11]
]

Solution should be: 1795

Key to solution:
● The idea in here is that any Number of the same color, can be inside the ‘top-left-corner’
of NxN matrix
● There is ALWAYS 4 of each ‘number colors’
● So all we have to do is pick the BIGGEST NUMBER out of all those ‘4 same color’
numbers
● To accomplish this, we need to split the Length of the matrix into 2, so we can target
0,1,2 and length - 0, 1, 2, or which ever.
● You can NOT go forEach in here or not splitting the matrix into 2, it will not work, cause I
can NOT target outer elements without the split

i
0 arr1 112 42 83 119
1 aar2 56 125 56 49
2 arr3 15 78 101 43
3 arr4 62 98 114 108

i
0 arr1 112 42 83 119 234 120
1 aar2 56 125 57 49 12 81
2 arr3 15 78 101 43 113 41
3 arr4 62 98 114 108 43 21
4 arr5 523 152 112 145 7 22
5 aar6 210 76 242 41 80 11

Link to the color thing:


https://docs.google.com/spreadsheets/d/1TLb6BpLv3Z6naR5tUerKIlXh-Ts2RDBP_pdaMHL5Gv
o/edit#gid=0

_______________________

Week 3:
Permuting Two Arrays

Key:

> sort A = ascending


> Sort B = descending
> run for loop and compare A[i] + B[i] < K, then finalStr = ‘NO’ otherwise let finalStr be ‘YES’

Date: Jun 24, 2022

function twoArrays(k, A, B) {

A.sort((a,b)=> a-b);
B.sort((a,b)=> b-a);

let fStr = 'YES';

for(var i = 0; i < A.length; i++){


if(A[i] + B[i] < k){
fStr = 'NO'
}
}

console.log(fStr);
return fStr;

let a1 = [2, 1, 3];


let b1 = [7, 8, 9];
let k1 = 10; // yes

twoArrays(k1, a1, b1);


old:

function twoArrays(k, A, B) {
// Write your code here

let sortedA = A.sort((a,b)=> a-b);


let sortedBrev = B.sort((a,b)=> a-b).reverse();

let testPass = true;

for(let i =0; i< A.length; i++){


if(sortedA[i] + sortedBrev[i] < k){
testPass = false;
}
}

console.log(testPass);

if(testPass){
return 'YES'
} else {
return 'NO'
}

// end of function
}

let k1 = 10;
let a1 = [ 2, 1, 3 ]
let b1 = [ 7, 8, 9 ]

let k2 = 4;
let a2 = [ 20, 1 ]
let b2 = [ 1,1 ]

let a = twoArrays(k2, a2, b2);


console.log(a);
Subarray Division 2

Date: Jun 24, 2022

Key:

> divide array into chunks from i to i + month;


> check if reduced value of that array is = Day
> if so, increment count by 1
> return count

function birthday(s, d, m) {

let count = 0;

for(var i = 0; i < s.length; i++){

let arr = s.slice(i, i+m);


console.log("arr: ", arr);

if(arr.reduce((a,v)=> a+v) === d){


count++
}

console.log(count);
return count;

// ! end of function
}

let s1 = [2,2,1,3,2];
let d1 = 4;
let m1 = 2; // [2,2] // [1,3]

birthday(s1,d1,m1)

older

function birthday(s, d, m) {
// Write your code here

console.log(s);

let possibleArr = []

let sSliced = [];

for(let i =0; i < s.length; i++){


sSliced.push(s.slice(i, s.length))
}

let filtered = sSliced.filter(el => el.length >= m);


console.log("filtered: ", filtered);

filtered.forEach(el=> {
console.log(el);
let test = el.slice(0, m);
console.log("test: ", test);

if(test.reduce((acc,value)=> acc + value) === d){


possibleArr.push(test);
}

})

console.log(possibleArr);

return possibleArr.length;
// end of function
}

let s1 = [ 1, 2, 1, 3, 2 ]; // 2
let d1 = 3;
let m1 = 2;

let s2 = [ 2, 2, 1, 3, 2 ]; // 2
let d2 = 4;
let m2 = 2;

birthday(s2, d2, m2);

XOR Strings 3 - No JavaScript =(

Sales by Match

Date: Jun 24, 2022

Key:

> if first equals to next, then count++ and i++, so we skip the iteration and move on

function sockMerchant(n, ar) {

ar.sort((a,b)=> a-b);

console.log(ar);
let count = 0;

for(var i= 0; i < ar.length; i++){

if(ar[i] === ar[i+1]){


count++
i++
}

// for loop i
}

console.log(count);
return count;

// ! end of fn
}

old:

function sockMerchant(n, ar) {


// Write your code here

console.log(ar);

let sorted = ar.sort((a,b)=> a-b);


console.log("sorted: ", sorted);

let uqAr = Array.from(new Set(sorted));


console.log("uqAr: ", uqAr);

let final = [];

uqAr.forEach(el=> {
let count = 0;
console.log(el);

for(let i = 0; i < sorted.length; i++){


if(el === sorted[i]){
count++
console.log(count)

if(count % 2 === 0){


final.push('pair')
}
}

})

console.log(final);
return final.length;

let n1 = 9;
let ar1 = [10, 20, 20, 10, 10, 30, 50, 10, 20];

let n2 = 7;
let ar2 = [1,2,1,2,1,3,2];

sockMerchant(n2, ar2)
Migratory Birds

Date: Jun 24, 2022

Key:

> forloop and push into an array


> then check the lengths of the array, i.e. Math.max of array lengths
> then get the index of the max value from the Array that contains all lengths… the index inside
the array will tell me which bird it is, cause bird ID is index+1;

function migratoryBirds(arr) {

arr.sort((a,b)=> a-b);

let final = Array.from({length: 5}, ()=> []);

for(var i = 0; i < arr.length; i++){


if(arr[i] === 1){
final[0].push(1)
}

if(arr[i] === 2){


final[1].push(2)
}

if(arr[i] === 3){


final[2].push(3)
}

if(arr[i] === 4){


final[3].push(4)
}

if(arr[i] === 5){


final[4].push(5)
}

// end of for loop


}

console.log(final.map(el=> el.length));

return final.map(el=> el.length).indexOf(Math.max(...final.map(el=>


el.length)))+1

// ! end of fn
}

let a1 = [1,1,2,2,3];
migratoryBirds(a1);

old:

function migratoryBirds(arr) {
// Write your code here

console.log(arr)

let id = [1,2,3,4,5];

let id1 = 0;
let id2 = 0;
let id3 = 0;
let id4 = 0;
let id5 = 0;

let sorted = arr.sort((a,b)=> a-b);


console.log("sorted: ", sorted);

id.forEach(el=> {
console.log(el);
for(var i = 0; i < sorted.length; i++){
if(el === sorted[i]){

if(el === 1){


id1++
}

if(el === 2){


id2++
}

if(el === 3){


id3++
}

if(el === 4){


id4++
}

if(el === 5){


id5++
}

}
}
});

console.log(id1)
console.log(id2)
console.log(id3)
console.log(id4)
console.log(id5)

let final = [
{type: 1, spotted: id1},
{type: 2, spotted: id2},
{type: 3, spotted: id3},
{type: 4, spotted: id4},
{type: 5, spotted: id5},
];

let finalFiltered = final.sort((a,b)=> a.spotted - b.spotted).filter(el=>


el.spotted && el.spotted >=2);
console.log("finalFiltered: ", finalFiltered);

let spottedMax = finalFiltered[finalFiltered.length-1].spotted;


console.log("spottedMax: ", spottedMax);

let finalArr = [];

finalFiltered.forEach(el=> {
if(el.spotted === spottedMax){
finalArr.push(el)
}
});

console.log("finalArr: ", finalArr);

return finalArr[0].type;

let arr1 = [ 1, 4, 4, 4, 5, 3 ];
let arr2 = '1 2 3 4 5 4 3 2 1 3 4'.split(' ').join('').split('').map(el=>
Number(el));

migratoryBirds(arr2);
Maximum Perimeter Triangle

● Non-degenerate triangle is: a + b > c a + c > b b + c > a


● conditions: - you can Ignore previous sticks, so if 1,2,3 did NOT work, then 1 can be ignored
from now on (i.e. pretend that it does NOT exist)
● - you need to return sorted from low to high
● - you need to return an ARRAY with sides that have the highest perimeter length
● - if nothing is found, return [-1]

function maximumPerimeterTriangle(sticks) {
// Write your code here

console.log(sticks);

let sorted = sticks.sort((a,b)=> a-b);

let final = [];

for(var i = 0; i < sticks.length; i++){


let a = sticks[i];
let b = sticks[i+1];
let c = sticks[i+2];

if(a + b > c && a + c > b && b + c > a){


final.push([a,b,c])
}

console.log(final);

return final.length > 0 ? final[final.length-1] : [-1]

}
let s1 = [ 1, 1, 1, 3, 3 ];
let s2 = [1,2,3,4,5,10];

maximumPerimeterTriangle(s2)

Zig Zag Sequence - No JavaScript

Drawing Book

Date: Jun 24, 2022

Key:

> chunk the array to get the actual book

> iterate front and if the index is not found, the pageForward++, if found then break out of the loop

> iterate back and if the index is not found, the pageBack++, if found then break out the loop

> return Math.min(pageForward, pageBack)

> NOTE: You CAN have zero turns

function chunkIt(array){

let final = [];


const chunkSize = 2;
for (let i = 0; i < array.length; i += chunkSize) {
const chunk = array.slice(i, i + chunkSize);
final.push(chunk)
}

return final;
}

function pageCount(n, p) {

let ar = chunkIt(Array.from({length: n+1}, (el,i)=> i));


console.log(ar);

let countF = 0;
let countB = 0;

for(var i = 0; i < ar.length; i++){

console.log(ar[i].indexOf(p) > -1)


if(ar[i].indexOf(p) > -1){
break
}
countF++;

console.log(ar[ar.length-i-1].indexOf(p) > -1);


if(ar[ar.length-i-1].indexOf(p) > -1){
break;
}
countB++;
}

console.log(countF);
console.log(countB);

let final = Math.min(countF, countB);


console.log("final: ", final);
return final;

// ! end of FN
}

let n1 = 5;
let p1 = 3; // 1

let n2 = 6;
let p2 = 4; // 1

let n3 = 5;
let p3 = 4; // 2
pageCount(n3,p3);

OLD:

JavaScript:
● If you are making an array out of the whole book, then Whole book array will be N+1,

because final page has to be on a special page

● reminder to use: Math.ceil, to get the upper page, when splitting the book into 2.

● If NO turns are make, return 0

function pageCount(n, p) {
// Write your code here

let fullBook = [];

for(let i = 0; i< n+1; i++){


fullBook.push(i)
}

console.log(fullBook);

let firstHalf = fullBook.slice(0, Math.ceil(fullBook.length / 2));


console.log("firstHalf: ", firstHalf);

let secondHalf = fullBook.slice(Math.ceil(fullBook.length / 2),


fullBook.length);
console.log("secondHalf: ", secondHalf);

let testFirst = firstHalf.indexOf(p);


console.log("testFirst: ", testFirst);

let testSecond = secondHalf.indexOf(p);


console.log("testSecond: ", testSecond);

let fullBookFromStart = [];

for(var i = 0; i < fullBook.length; i = i+2){


let temp1 = fullBook.slice(i, i+2);
fullBookFromStart.push(temp1)
}

if(testFirst !== -1){

console.log("fullBookFromStart: ", fullBookFromStart);

let turns = 0;
let stop = false;

fullBookFromStart.forEach(el=> {
console.log(el);

if(stop){
return
}

if(el.indexOf(p) !== -1){


console.log('stop now');
return stop = true;
}

turns++;
})

console.log(turns);
return turns;

// end of testFirst
}

if(testSecond !== -1){

let fullBookFromEnd = fullBookFromStart.reverse();


console.log("fullBookFromEnd: ", fullBookFromEnd);

let turns = 0;
let stop = false;

fullBookFromEnd.forEach(el=> {
console.log(el);

if(stop){
return
}

if(el.indexOf(p) !== -1){


console.log('stop now');
return stop = true;
}

turns++;
})

console.log(turns);
return turns;

// end of second test


}

console.log('zero')
return 0

// end of the function


}

let n1 = 6;
let p1 = 5;
pageCount(n1, p1);

Mock: Between Two Sets

Solution Guide: https://studyalgorithms.com/array/hackerrank-between-two-sets/

Actual Problem: https://www.hackerrank.com/challenges/between-two-sets/problem

My video solution: https://youtu.be/VZtK_nW72gk

Date: Jun 25, 2022

Key:

> get the MAX value from the B array, so we do NOT have to do to many iterations
> check that every element in A array is divisible by bMAX[i]... bMAX[i-1]... NOTE: we want a
temp array in here, so that if both elements from A are equally divided into i, we check, then we
push i into the finalArr1
> then iterate through every element in B array, and check how many elements form finalArr1
are equally divided into el from B, we push those elements as arrays into finalArr2
> we then have a finalArry that looks like this: [ [ 24, 12, 6 ], [ 36, 18, 12, 6 ] ]
> I then just need to pick out the duplicates between the arrays and return .length, i.e. how
many duplicates were found.
> Algo, to pick out duplicates from array can be found in here:
https://docs.google.com/document/d/1DgiTZ88yP__YSvNAlIdbk3VRfwk2mflFv6T6uKqaAtc/edit

function findDubplicateInArrays(...args){
let holder = [...args];
let holderLength = holder.length;
let flatHolder = holder.flat(10).sort((a,b)=> a-b);

let duplicate = [];

flatHolder.forEach(el=> {
let count = 0;
flatHolder.forEach(el2=> {
if(el === el2){
count++
if(count >= holderLength){
duplicate.push(el)
}
}

})

})

return Array.from(new Set(duplicate));

function getTotalX(a, b) {

// sort both
a.sort((a,b)=> a-b);
b.sort((a,b)=> a-b);

let fAr = [];


let max = Math.max(...b);

for(var i = max; i >= 0; i--){

let temp = [];

for(var j = 0; j < a.length; j++){


if(i % a[j] === 0){
temp.push(true)
}
};

if(temp.length === a.length){


fAr.push(i)
}

// condole.log(fAr);

let fAr2 = [];

for(var x = 0; x < b.length; x++){

let el1 = b[x];


// condole.log(el1);

let temp = [];

for(var y = 0; y < fAr.length; y++){

let el2 = fAr[y];


// condole.log(el2);

if(el1 % el2 === 0){


temp.push(el2)
}

// end of for loop y


}

fAr2.push(temp)

// end of for loop x


}

// condole.log(fAr2);
// condole.log(findDubplicateInArrays(...fAr2))
return findDubplicateInArrays(...fAr2).length;

// ! end fn
}

let a1 = [2,6];
let a2 = [24,36];

getTotalX(a1,a2);

older:

function getTotalX(a, b) {
// Write your code here

let holderOfAllFactorsOfArray1 = [];

a.forEach(el=> {
// console.log(el);

let temp = [];


for(var i = 1; i <=100; i++){

if(i % el === 0){


temp.push(i)
}
}

holderOfAllFactorsOfArray1.push(temp)
})

// console.log(holderOfAllFactorsOfArray1);

// remove all elements that are bigger or equal to B last number, cause I can
NOT divide them into the Last number, i.e. they are NOT factors of it, since they
are bigger

let finalHolder = [];

holderOfAllFactorsOfArray1.forEach(el=> {
let temp = [];

el.forEach(el2=> {
if(el2 <= b[b.length-1]){
temp.push(el2)
}
})

finalHolder.push(temp);

})

console.log(finalHolder);

// MOVING TO CONDITION 2 - find all Factors of numbers in array 2

b.forEach(el => {
let temp = [];
for(var i = 0; i <= el; i++){
if(el%i === 0){
temp.push(i)
}
}
finalHolder.push(temp)
})
console.log(finalHolder);

// now lets find every element from the array that appears in EVERY ARRAY, SO
IT HAS TO APPEAR A.LENGTH + B.LENGTH NUMBER OF TIMES, this means it is common to
ALL arrays and thus is our answer

let final = finalHolder.flat(10).sort((a,b)=> a-b);


console.log("final: ", final);

let finalArr = [];

final.forEach(el=> {
console.log(el);
let count = 0;

final.forEach(el2=> {
if(el === el2){
count++

if(count === (a.length + b.length)){


finalArr.push(el)
}
}
})

})

let allDone = Array.from(new Set(finalArr));


console.log("allDone: ", allDone);
return allDone.length;

//! end of function


}

//
let a1 = [2, 4];
let a2 = [2];
let a3 = [3, 4];

let b1 = [16, 32, 96]; // should be 3


let b2 = [20,30,12];
let b3 = [24,48]; // 2

getTotalX(a3, b3);

_______________________

Week 4:

Picking Numbers

function pickingNumbers(a) {
// Write your code here

let sorted = a.sort((a,b)=> a-b);


console.log("sorted: ", sorted);

let final = [];

sorted.forEach(el=> {
let count = 0;

sorted.forEach(el2=> {
if(el2 - el === 0 || el2 - el === 1){
count++
}
})
final.push(count)
});

let allDone = final.sort((a,b)=> b-a);


console.log("allDone: ", allDone);
return allDone[0];

// ! end of function
}

let a1 = [ 1, 2, 2, 3, 1, 2 ]; //5
let a2 = [ 4, 6, 5, 3, 3, 1 ]; // 3
pickingNumbers(a2);

Left Rotation

function rotateLeft(d, arr) {


// Write your code here

for(var i = 0; i < d; i++){


arr.push(arr[0]);
arr.shift();
console.log(arr)
}

console.log(arr);
return arr;

let rotations1 = 4;
let arr1 = [ 1, 2, 3, 4, 5 ];
rotateLeft(rotations1, arr1)
Number Line Jumps
Note: Kangaroos HAVE TO jump every turn.

function kangaroo(x1, v1, x2, v2) {


// Write your code here

let car1Location = x1;


let car2Location = x2;
let possible = false;

for (let i = 0; i < 10000; i++) {


car1Location = car1Location + v1;
car2Location = car2Location + v2;

// console.log(car1Location);
// console.log(car2Location);

if (car1Location === car2Location) {


console.log("true");
possible = true;
}
}

if (possible) {
return "YES";
} else {
return "NO";
}

// ! end of function
}

let xx1 = 0;
let vv1 = 3;
let xx2 = 4;
let vv2 = 2; // YES
kangaroo(xx1, vv1, xx2, vv2);

Separate the Numbers

Solution explanation: https://www.youtube.com/watch?v=q9d7MZpuWSE

BigInt problem solution:


https://www.smashingmagazine.com/2019/07/essential-guide-javascript-newest-data-type-bigint
/

function separateNumbers(s) {

// NOTES:
// Correct way to slice is: .slice(0, str.length);

// console.log(s.length);
let pretty = 'NO';

if(s.length < 2){


console.log(pretty);
return pretty;
}

for(var i = 1 ; i <= Math.floor(s.length/2); i++){

// OPERATION 1: select first number


let first = s.slice(0, i);

// console.log("first: ", first);


// console.log(Number(first)+1)

// OPERATION 2: Add +1/+2/+3... to the first and concat to the finalStr;


let finalStr = '';

for(var j = 0; j <= s.length; j++){

finalStr = finalStr + (BigInt(first)+BigInt(j));


// console.log(finalStr);

if(finalStr.length >= s.length){


break;
}
// end of for loop j
}

// console.log(first)

// console.log(s.length)
// console.log(finalStr.length);

// console.log(s);
// console.log(finalStr);

let finalTest = finalStr === s;

if(finalTest){
pretty = 'YES' + ' ' + first;
console.log(pretty);
return pretty;
}

// end of forloop i
}

// console.log(firstArr);

console.log(pretty);
return pretty;
// ! end of main function
}

let s1 = "1234"; // yes


let s2 = "91011"; // yes
let s3 = "10203"; // no
let s4 = '99332720572758669933272057275867'

separateNumbers(s4);

Note: This code should 100%, work but Big INT is NOT computing correctly:

function separateNumbers(s) {

// the key here is to create what it should look like and compare

if(s.length === 1){


console.log('NO')
return 'NO'
}

let strTest = '';


let iValue = '';

for(var i = 1; i <= Math.ceil(s.length/2); i++){

// console.log(i)

let starting = s.slice(0,i);


let incrementer = Number(starting);
strTest = starting;

let temp = 0;
while(strTest.length < s.length){

incrementer = BigInt(incrementer) + BigInt(1);

strTest = strTest + incrementer;

temp++
}
console.log(starting);
console.log(incrementer);
console.log(strTest);

if(strTest === s){


// console.log('here');
iValue = starting;
console.log('YES' + ' ' + iValue)
return;
}

console.log('NO')

Closest Numbers

Date: Jun 30, 2022

Key:

● Sort it
● Test el[i] vs el[i+1] if smaller than Smallest variable, push into array
● Filter array to keep anything that is equal to the smallest

function closestNumbers(arr) {

arr.sort((a,b)=> a-b);
console.log(arr);

let finalArr = [];


let smallest = Infinity;

for(let i = 0; i < arr.length; i++){

let test = Math.abs(arr[i] - (arr[i+1]));

if(test <= smallest){


smallest = test;
finalArr.push([arr[i], arr[i+1]])
}

console.log(finalArr);
console.log(smallest);

let a = finalArr.filter(el=> Math.abs(el[0] - (el[1])) === smallest).flat(1);


console.log(a);
return a;

// ! end of the function


}

let arr1= '-20 -3916237 -357920 -3620601 7374819 -7330761 30 6246457 -6461594
266854'.split(' '); // -20 30

let arr2 = '-20 -3916237 -357920 -3620601 7374819 -7330761 30 6246457 -6461594
266854 -520 -470'.split(' '); // -520 -470 -20 30
let arr3 = [1,2,3,4,5]; // [ 1, 2, 2, 3, 3, 4, 4, 5 ]

closestNumbers(arr3);

old:

function closestNumbers(arr) {

let dif = null;


let finalArr = [];

let sorted = arr.sort((a,b)=> a-b);

sorted.forEach((el, index)=> {
let current = el;
let next = sorted[index+1];

if(!next){
console.log('undefined');
return;
}

let test = Math.abs(current - next);

if(test === 0){


return;
}

console.log(test);

if(dif === null){


console.log('null');
dif = test;
finalArr.push([current, next])
return;
}

if(dif === test){


console.log('equal');
finalArr.push([current, next]);
return;
}

if(test < dif){


finalArr = [];
dif = test;
finalArr.push([current, next]);
return;
}

})

console.log(finalArr);

let allDone = finalArr.flat(10);


console.log("allDone: ", allDone);
return allDone;

// ! end of function
}

let arr1= '-20 -3916237 -357920 -3620601 7374819 -7330761 30 6246457 -6461594
266854'.split(' '); // -20 30

let arr2 = '-20 -3916237 -357920 -3620601 7374819 -7330761 30 6246457 -6461594
266854 -520 -470'.split(' '); // -520 -470 -20 30

let arr3 = [1,2,3,4,5]


closestNumbers(arr3);

Tower Breakers

Solution Explanation:

If the number of towers are even that means player 2 is the winner. No matter what move player 1

tries, player 2 will have a move to counter.

If the height of each tower is 1 that means player 1 cannot move at all so again player 2 is winner.

And for all other cases, player 1 is the winner.

Note: this is NOT PROGRAMMING SOLUTION, but more of a Math Problem, so don’t waste

time on it, cause we don’t need to Math Wizards for Front End.

function towerBreakers(n, m) {

if(m === 1){


console.log('here')
return 2
}

if(n%2 === 0){


return 2
}

return 1

}
let n1 = 2;
let m1 = 2;

let n2 = 1;
let m2 = 4;

towerBreakers(n1, m1)

Minimum Absolute Difference in an Array

Key to success: Key here is to SORT from small to large, then no need to check if Dif === 0 and I can just
compare Math.abs( arr[index+1] with current element) and then assign it to Minimum if the difference
is bigger

function minimumAbsoluteDifference(arr) {
let minimum = Infinity;

arr.sort((a,b)=> a-b).forEach((el, index)=> {


if((Math.abs(arr[index+1] - el)) < minimum){
minimum = Math.abs(arr[index+1] - el)
}
});
// console.log(minimum);
return minimum;
}

let arr1 = [3, -7, 0];


let arr2 = [1, -3, 71, 68, 17];
minimumAbsoluteDifference(arr2);
Caesar Cipher

Key:

● Create a alphabet that just repeats 10 times and get index from there
● Its a string repeat so time complexity will be low

Date: Jul 1, 2022

function caesarCipher(s, k) {

let alph = 'abcdefghijklmnopqrstuvwxyz'.repeat(10);


let capAlph = alph.toLocaleUpperCase();

let finalStr = '';

for(var i = 0; i < s.length; i++){

let test = /[a-z]/.test(s[i]);


// console.log("test: ", test);

// lower
if(/[a-z]/.test(s[i])){
finalStr = finalStr + alph[alph.indexOf(s[i])+k];
continue;
}

// upper
if(/[A-Z]/.test(s[i])){
finalStr = finalStr + capAlph[capAlph.indexOf(s[i])+k];
continue;
}

finalStr = finalStr + s[i]


}

// console.log(finalStr);
return finalStr;

let s1 = 'middle-Outz'; //okffng-Qwvb


let k = 2;
caesarCipher(s1, k);

old:

function caesarCipher(s, k) {
// Write your code here
let max = 100;
const small = "abcdefghijklmnopqrstuvwxyz";
const large = small.toUpperCase();

const small100 = new Array(10).fill(small).join('');

const large100 = new Array(10).fill(large).join('');

let final = s.split('').map(el=> {


console.log(el);

let smallIndex = small100.indexOf(el);


console.log("smallIndex: ", smallIndex);

let largeIndex = large100.indexOf(el);


console.log("largeIndex: ", largeIndex);
if(!/[A-Za-z]/.test(el)){
return el;
} else {

if(smallIndex > -1){


return small100[smallIndex+k]
} else {
return large100[largeIndex+k]
}

});

let allDone = final.join('');


console.log("allDone: ", allDone);
return allDone;

// ! end of the function


}

let s1 = 'middle-Outz'; // okffng-Qwvb


let k1 = 2;

let s2 = 'Always-Look-on-the-Bright-Side-of-Life';
let k2 = 5; // Fqbfdx-Qttp-ts-ymj-Gwnlmy-Xnij-tk-Qnkj

let s3 = 'XYZ-/xyz';

let s4 = '12lcfd';
let k4 = 98; // fwzx
caesarCipher(s4, k4)

Mock Test: Anagram

Link to problem: https://www.hackerrank.com/challenges/anagram/problem

● YOU HAVE TO USE REPLACE, cause if you try to convert it from String into Array, it will

fail speed test

● Make sure to remove ALL console.logs and make code efficient, cause large strings will

fail some test

● KEY: is to replace the found letter from String2 in String1 with a symbol or number, to

avoid finding it 2 times. Since ones the element is found, it should be removed from both

string 2 and string 1 (i.e. they are duplicates). This will leave you only with letters that

need to be changes (i.e. the correct number of changes)

● Remember: Replace does NOT alter original str, so you have to ‘reassign it’ with a new

string

function anagram(s) {
if (s.length % 2 !== 0) {
console.log('can not split')
return -1;
}

let str1 = s.slice(0, s.length / 2);

let str2 = s.slice(s.length / 2, s.length);

str2.split("").forEach((el) => {
if (str1.includes(el)) {
str1 = str1.replace(el, 1);
return;
}

});

return str1.split('').filter(el => el !== '1').length;

// ! end of function
}

let s1 = "ababbb"; // 2 pass


let s2 = "ab"; // 1 pass
let s3 = "abc"; // -1
let s4 = "mnop"; // 2
let s5 = "xyyx"; // 0
let s6 = "xaxbbbxx"; // 1
let s7 =

"gqdvlchavotcykafyjzbbgmnlajiqlnwctrnvznspiwquxxsiwuldizqkkaawpyyisnftdzklwagv";

anagram(s1);

_______________________

Week 5:

Max Min

Video explaining: https://youtu.be/cd8RQZp_-9I

● Key1 is to Sort small to large


● Key2 is NOT to chunk array in Chunks of K, BUT to chunk array in Chunks of:

arr.forEach((el, index) => el will be starting number (min) and Max will be arr[index + k -1]

● so we are Chunking always in group of K and snipping away first element of the array

effectively, this gives us the difference between first element and then element that is K

units away.

● The smallest difference will be some where between those 2 numbers

function maxMin(k, arr) {

let unfairDif = Infinity

let sorted = arr.sort((a,b) => a - b);

sorted.forEach((el, index)=> {
let min = el;
// console.log("min: ", min);

let max = arr[index + k - 1];


// console.log("max: ", max);

let test = max - min;


// console.log("test: ", test);

if(test < unfairDif){


unfairDif = test;
}
})

console.log(unfairDif)

return unfairDif

}
let arr1 = [10, 100, 300, 200, 1000, 20, 30];
let k1 = 3; // 20

let arr2 = [
7652, 1377, 7089, 2736, 4748, 1615, 4235, 3461, 3895, 8328, 175, 8131, 4877,
5606, 4730, 3563, 2210, 966, 7842, 9551, 152, 9079, 5366, 2158, 1236, 8046,
2660, 5528, 544, 6965, 2428, 8197, 4694, 5869, 7285, 5794, 3837, 1521, 9255,
4084, 9849, 5782, 2215, 4726, 1388, 3297, 4641, 9950, 615, 8836, 5853, 768,
4267, 1219, 9278, 5503, 9265, 8290, 7383, 6162, 5255, 6163, 711, 6301, 2033,
7996, 2095, 2222, 9517, 7702, 6306, 5718, 3484, 4873, 6797, 1224, 8170, 1438,
1175, 8785, 274, 3380, 5905, 4541, 4600, 5183, 6396, 3865, 3473, 3780, 27,
5080, 9943, 738, 7733, 8328, 5087, 9828, 550, 4604,
];
let k2 = 25;

maxMin(k2, arr2);

This works, but a bit too slow:

function maxMin(k, arr) {

arr.sort((a,b)=> a-b);
// console.log(arr);

let smallest = Infinity;

for(var i = 0; i < arr.length; i++){


let chunked = arr.slice(i, i+k);
// console.log("chunked: ", chunked);

if(chunked.length < k){


break;
}

let test = Math.max(...chunked) - Math.min(...chunked);

if(test < smallest){


smallest = test
}

// console.log(smallest);
return smallest;

Strong Password

● Just remember to ESCAPE characters like () - + in regex \( \) \+ \- , outside of that


this is RegEx exercise

function minimumNumber(n, password) {


// Return the minimum number of characters to make the password strong

console.log(n); // needs to be at least 6


const numbers = "0123456789" // 1 digit min
const lower_case = "abcdefghijklmnopqrstuvwxyz" // 1 small
const upper_case = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // 1 upper
const special_characters = "!@#$%^&*()-+" // 1 symbol

let strongPass = password;


let addCount = 0;
// test for numbers
let regNumTest = /\d/.test(password);
console.log("regNumTest: ", regNumTest);

if(!regNumTest){
strongPass = strongPass + '1'
addCount++
}

// test for small letter

let regSmallTest = /[a-z]/.test(password);


console.log("regSmallTest: ", regSmallTest);

if(!regSmallTest){
strongPass = strongPass + 'a';
addCount++
}

// tedt for capital

let regCapTest = /[A-Z]/.test(password);


console.log("regCapTest: ", regSmallTest);

if(!regCapTest){
strongPass = strongPass + 'A';
addCount++
}

// test for symbol

let regSymTest = /[!@#$%^&*(\)\-\+]/.test(password);


console.log("regSymTest: ", regSmallTest);

if(!regSymTest){
strongPass = strongPass + '*';
addCount++
}
// test for length

let lengthDif = 6 - strongPass.length;


console.log("lengthDif: ", lengthDif);

if(lengthDif > 0){


console.log('added some length')
strongPass = strongPass + numbers.slice(0, lengthDif)
addCount = addCount + lengthDif
}

console.log(password);
console.log(strongPass);
console.log(addCount);

return addCount;

// ! end of function
}

let p1 = '#HackerRank';
let n1 = p1.length;

let p2 = 'Ab1';
let n2 = p2.length;

let p3 = 'AUzs-nV';
let n3 = p3.length;

minimumNumber(n3, p3);
Dynamic Array

Key:

>DO NOT use Array.fill() its VERY bad method… always use: let arr = Array.from({length: n},
()=> []);
> create 3 variables: lastAnswer, answers = []; and arr = array should have Number of arrays
inside of it, number of arrays is the N value
> iterate through queries which come as MINI arrays with 3 values in them so extract values at
index 0,1,2
> follow instructions on what to do with each ‘query’ , literally write what they tell you - BUT
when they say append OR store, they really mean PUSH, so use .push
> they want me to return the ANSWERS array

function dynamicArray(n, queries) {


// Write your code here

let lastAnswer = 0;
let arr = Array.from(Array(n), ()=> []);
let answers = [];

queries.forEach(([q,x,y])=> {

let idx = (x^lastAnswer)%n;

if(q === 1){


arr[idx].push(y);
} else {
lastAnswer = arr[idx][y % arr[idx].length];
answers.push(lastAnswer);
}

})
console.log(answers);

return answers;

}
let arr1 = [ [ 1, 0, 5 ], [ 1, 1, 7 ], [ 1, 0, 3 ], [ 2, 1, 0 ], [ 2, 1, 1 ] ];
// 7,3
let n1 = 2; // size of the array to create
dynamicArray(n1, arr1);

Smart Number 2 - No JS here

Move on

Missing Numbers

Key is to use Arrays, NOT strings, otherwise will find 3, in 13

Key is: To replace ones an element is found in the array with something like: ‘found’, this way
the values will NOT repeat themselves.

Date: Jul 3, 2022

function missingNumbers(arr, brr) {


// Write your code here

arr.sort((a,b)=> a-b);
// console.log(arr);

brr.sort((a,b)=> a-b);
// console.log(brr);

let finalArr = [];


brr.forEach((el, index)=> {

if(arr.indexOf(el) !== -1){


brr[index] = 'found';
arr[arr.indexOf(el)] = 'found';
return;
}

return finalArr.push(el)

})

// console.log(brr.filter(el=> el !== 'found'));


return Array.from(new Set(brr.filter(el=> el !== 'found')));

let arr1 = '203 204 205 206 207 208 203 204 205 206'.split(' ').map(el=>
Number(el));
let arr2 = '203 204 204 205 206 207 205 208 203 206 205 206 204'.split('
').map(el=> Number(el)); // 204 205 206

let arr1a = '11 4 11 7 13 4 12 11 10 14'.split(' ').map(el=> Number(el));


let arr2a = '11 4 11 7 3 7 10 13 4 8 12 11 10 14 12'.split(' ').map(el=>
Number(el));

let arr1b = [7,2,5,3,5,3];


let arr2b = [7,2,5,4,6,3,5,3]; // 4,6

missingNumbers(arr1, arr2);
old:

function missingNumbers(arr, brr) {


// Write your code here

let sortedArr = arr.sort((a,b)=> a-b);


let sortedBrr = brr.sort((a,b)=> a-b);

let missing = [];

sortedBrr.forEach(el=> {
// console.log(el);

let test = sortedArr.indexOf(el);


// console.log("test: ", test);

if(test !== -1){


sortedArr[test] = 'x';
return;
}

missing.push(el);

});

// console.log(sortedArr)

let allDone = Array.from(new Set(missing));


// console.log("allDone: ", allDone);
return allDone;

// ! end of function
}
let arr1 = '203 204 205 206 207 208 203 204 205 206'.split(' ').map(el=>
Number(el));
let arr2 = '203 204 204 205 206 207 205 208 203 206 205 206 204'.split('
').map(el=> Number(el)); // 204 205 206

let arr1a = '11 4 11 7 13 4 12 11 10 14'.split(' ').map(el=> Number(el));


let arr2a = '11 4 11 7 3 7 10 13 4 8 12 11 10 14 12'.split(' ').map(el=>
Number(el));

missingNumbers(arr1a, arr2a);

The Full Counting Sort

Video on how to do it: https://youtu.be/RoEdHlef_b0

Date: Jul 3, 2022

Note: it is OK that it doesn’t pass: test 4 and 5, due to timeout, that is fine for now

Key:

● I first need to replace ALL first half of the array with ‘-’
● you need to sort array by index after I replace all first half characters with ‘-’ …
arr.sort((a,b)=> Number(a[0]) - Number(b[0]))
● Now I can just push them into final array

function countSort(arr) {
// Write your code here

let max = Math.max(...arr.map(el=> el[0]))


// console.log("max: ", max);

let finalArr = Array.from({length: max+1}, ()=> []);


// console.log(finalArr)

for(var i = 0; i < arr.length / 2; i++){

arr[i][1] = '-'
}

arr.sort((a,b)=> Number(a[0]) - Number(b[0]))

arr.forEach(([index, value])=> {
finalArr[index].push(value)
})

// console.log(arr);

console.log(finalArr.flat(10).join(' '));

return finalArr.flat(2).join(' ');

let orgArr = [
[ '0', 'ab' ], [ '6', 'cd' ],
[ '0', 'ef' ], [ '6', 'gh' ],
[ '4', 'ij' ], [ '0', 'ab' ],
[ '6', 'cd' ], [ '0', 'ef' ],
[ '6', 'gh' ], [ '0', 'ij' ],
[ '4', 'that' ], [ '3', 'be' ],
[ '0', 'to' ], [ '1', 'be' ],
[ '5', 'question' ], [ '1', 'or' ],
[ '2', 'not' ], [ '4', 'is' ],
[ '2', 'to' ], [ '4', 'the' ]
]; // - - - - - to be or not to be - that is the question - - - -

countSort(orgArr)
old:

Easy to understand code:

function countSort(arr) {

// replace all Letter pairs in first half of the array -

let firstHalf = arr.slice(0, arr.length/2);


// console.log("firstHalf: ", firstHalf);

firstHalf.forEach(el=> {
let curEl = el[1]

firstHalf.forEach((el2, index)=> {
if(el2[1] === curEl){
arr[index][1] = '-';
return
}
})
})

// NOTE YOU DO NOT NEED TO DO THE ABOVE PART, BECAUSE FIRST HALF WILL ALWAYS HAVE
THE SAME NUMBER OF STRINGS THAT MATCH, SO JUST SPLIT THE ARRAY INTO 2, AND
REPLACE THE STRINGS WITH

// console.log(arr); // WORKS

// create an empty array, with total number of empty arrays that will be used
to push items into

let sorted = arr.sort((a,b)=> Number(a[0]) - Number(b[0]));


// console.log("sorted: ", sorted);
let totalArrLength = sorted[sorted.length-1][0];
// console.log("totalArrLength: ", totalArrLength);

let finalArr = [];


for(var i = 0; i <= totalArrLength; i++){
finalArr.push([])
};

// console.log(finalArr);

// now I need to identify the index and push elements into corresponding array
indexes

sorted.forEach(el=> {
let arrayIndexToPush = Number(el[0]);
// console.log("arrayIndexToPush: ", arrayIndexToPush);
let elementToPush = el[1];
// console.log("elementToPush: ", elementToPush);

finalArr[arrayIndexToPush].push(elementToPush)

})

// console.log(finalArr);

let allDone = finalArr.flat(10).join(' ');


console.log(allDone);
return allDone;

// ! end of function
}

let orgArr = [
[ '0', 'ab' ], [ '6', 'cd' ],
[ '0', 'ef' ], [ '6', 'gh' ],
[ '4', 'ij' ], [ '0', 'ab' ],
[ '6', 'cd' ], [ '0', 'ef' ],
[ '6', 'gh' ], [ '0', 'ij' ],
[ '4', 'that' ], [ '3', 'be' ],
[ '0', 'to' ], [ '1', 'be' ],
[ '5', 'question' ], [ '1', 'or' ],
[ '2', 'not' ], [ '4', 'is' ],
[ '2', 'to' ], [ '4', 'the' ]
]

countSort(orgArr)

Optimized code 1:

// NOTE YOU DO NOT NEED TO CHECK IF STRINGS IN THE FIRST PART OF THE ARRAY MATCH,
BECAUSE FIRST HALF WILL ALWAYS HAVE THE SAME NUMBER OF STRINGS THAT MATCH, SO
JUST SPLIT THE ARRAY INTO 2, AND REPLACE THE STRINGS WITH ‘-’

function countSort(arr) {

arr = arr.map((el, index)=> {


return [el[0], index < arr.length/2 ? '-' : el[1]]
}).sort((a,b)=> Number(a[0]) - Number(b[0])).map(el=> el).map(el=> el[1]).join('
')

console.log(arr)

let orgArr = [
[ '0', 'ab' ], [ '6', 'cd' ],
[ '0', 'ef' ], [ '6', 'gh' ],
[ '4', 'ij' ], [ '0', 'ab' ],
[ '6', 'cd' ], [ '0', 'ef' ],
[ '6', 'gh' ], [ '0', 'ij' ],
[ '4', 'that' ], [ '3', 'be' ],
[ '0', 'to' ], [ '1', 'be' ],
[ '5', 'question' ], [ '1', 'or' ],
[ '2', 'not' ], [ '4', 'is' ],
[ '2', 'to' ], [ '4', 'the' ]
]

countSort(orgArr)

Grid Challenge

Date: Jul 3, 2022

Key:

● Sort all rows alphabetically


● Create an array that will hold all Columns values per array
● Then check to see if values in columns array are in alphabetical order… i.e. if el1 > el2
-> return false, i.e. NOT alphabetical, cause in alphabetical el1 < el2
● I can use EVERY as a tester
● NOTE: .SOME, is a better use here… so figure out how to use it at some stage

function gridChallenge(grid) {

let sorted = grid.map(el=> el.split('').sort());


// // console.log(sorted);

// create a column sorted

let colSorted = Array.from({length: grid[0].length}, ()=> []);


// console.log("colSorted: ", colSorted);
for(var i = 0; i < sorted.length; i++){

let el = sorted[i];
// console.log(el);

// colSorted[0].push(el[0]);
// colSorted[1].push(el[1]);

for(var j = 0; j < el.length; j++){


colSorted[j].push(el[j]);
}

// end of for loop i


}

// console.log(colSorted);
let finalTest = colSorted.every(el=> {

for(var i = 0; i < el.length; i++){


if(el[i+1] === undefined){
break
}
if(el[i] > el[i+1]){
return false
}
}

return true

});
// console.log(finalTest);

if(finalTest){
return 'YES'
} else {
return 'NO'
}
// ! end of founction
}

let arr1 = ["ebacd", "fghij", "olmkn", "trpqs", "xywuv"]; // yes


let arr2 = ["mpxz", "abcd", "wlmf"]; // no
let arr3 = ["abc", "hjk", "mpq", "rtv"]; // yes

gridChallenge(arr3);

OLD:

* BIG NOTE: this is NOT A GRID, it can be 4 x 3, 2 X 5... so NOT a GRID


* If array has 1 element in it = YES by default
* string can be PPP so when comparing NEXT >= CURRENT... NOT NEXT > CURRENT...
basically if both letters are the same it COUNTS towards success
* rows CAN be sorted (i.e. initial sort)
* Columns can NOT be sorted (i.e. the secondary array with columns that I created, should
NOT be sorted)
* Remember to remove UNDEFINED from 3 x 4 matrix when pushing elements into the finalArr:
let arr3 = ["abc", "hjk", "mpq", "rtv"]; // yes

function gridChallenge(grid) {

// if grid length is 1, then auto YES

if(grid.length === 1){


return 'YES'
}
// split Grid into array with items in it
let wthArray = grid.map((el) => el.split(""));
// console.log("wthArray: ", wthArray);

// sort it alphabetically ROWS


wthArray.map((el) => {
return el.sort(function (a, b) {
return a === b ? 0 : a < b ? -1 : 1;
});
});
console.log("wthArray: ", wthArray);

// console.log("--------------------");

// create a second array with same lengtht


let final1 = wthArray.map((el, index) => []);
// // console.log(final1);

// extract all COLUMNS and put them into separate array


for (var i = 0; i < grid.length; i++) {
wthArray.forEach((el) => {
final1[i].push(el[i]);
});
}

final1 = final1.filter(el=> el[0] !== undefined)

console.log(final1);

// console.log("--------------------");

// test to see IF EVERY COLUMN (i.e. array) is in Alphabetical order

let finalArr = [];

final1.forEach((el) => {
let temp = 0;
el.forEach((el2, index) => {
let current = el2;
// console.log("current: ", current);
let next = el[index + 1];
// console.log("next: ", next);

if (next === undefined) {


// console.log("undefined");
return;
} else {
let test = next >= current;

if (test) {
temp++;
// console.log(temp);
if (temp >= el.length - 1) {
finalArr.push("yes");
}
}
}
});
});

console.log(finalArr);

if (finalArr.length === final1.length) {


console.log("--------------------");
console.log("YES");
return "YES";
} else {
console.log("--------------------");
console.log("NO");
return "NO";
}
}

let arr1 = ["ebacd", "fghij", "olmkn", "trpqs", "xywuv"]; // yes


let arr2 = ["mpxz", "abcd", "wlmf"]; // no
let arr3 = ["abc", "hjk", "mpq", "rtv"]; // yes
gridChallenge(arr2);

Sansa and XOR

● if arr.length is even, then return 0

● XOR in JavaScript is an Operations similar to Multiply * or divide /, it looks like this: 1

XOR 3 is 1^3 in JavaScript, which gives 2, so console.log(1^3) give 2

● When array length is ODD, we want to XOR ALL ODD numbers in the array and Ignore

the Even numbers

Date: Jul 4, 2022

function sansaXor(arr) {

if(arr.length % 2 === 0){


console.log('zero')
return 0
}

return arr.filter((_, i)=> i%2 === 0).reduce((acc,value)=> acc^value);

// ! end of the function


}

let a1 = [1,2,3] // 2
let a2 = [4,5,7,5] // 0

sansaXor(a1)
old:

function sansaXor(arr) {
// Write your code here

if(arr.length % 2 === 0){


console.log('should exit')
return 0;
}

let finalArr = arr.map((el, index)=> {


if((index+1) % 2 === 0){
return 'x'
}
return el;
}).filter(el=> el !== 'x').reduce((acc,value)=> acc^value);

console.log(finalArr);
return finalArr;

let arr1 = [1, 2, 3]; // 2


let arr2 = [4, 5, 7, 5]; // 0

sansaXor(arr1);

Mock Test: Fibonacci Modified

Key:

● BigInt() when doing any computations, otherwise some tests will fail
● Replace to the power of 2, with multiply by each other
● MAX count should be N, so I should not go higher than N value

let arr = [t1,t2]


for(var i = 0; i <= n; i++){

arr[i+2] = BigInt(arr[i]) + BigInt(arr[i+1]) * BigInt(arr[i+1])

// console.log(arr);
return arr[n-1]

Old:

* use BigInt() when doing any computations, otherwise some tests will fail
* Also max array is 20, so I can brute force it

function fibonacciModified(t1, t2, n) {

let orgFib = [t1, t2];

for(var i = 0; i < 20; i++){

orgFib[i+2] = BigInt(orgFib[i]) +
(BigInt(orgFib[i+1])*BigInt(orgFib[i+1]))

// console.log(orgFib)

let allDone = orgFib[n-1];


console.log("allDone: ", allDone);

return allDone;
}

let t1a = 0;
let t2a = 1;
let na = 5; // should be 5

fibonacciModified(t1a, t2a, na);

_______________________

Week 6:

Prime Dates - no JS - move on

Sherlock and Array

● You can NOT use Arrays and .reduce() to compare sums, cause 2 tests will fail = too slow

● FORMULA FOR SUCCESS:

● create a TOTAL = which the sum of ALL elements in the array

● create SUM, which adds Array elements 1 by 1 as we for...loop them

● if at any point: SUM === (Total Array Sum) - SUM - arr[i] ... both sides are balanced, so

exit out of the function with return 'YES'

● else return 'NO'

function balancedSums(arr) {
let sum = 0;

let total = arr.reduce((a,b)=> a+b, 0);


// console.log("total: ", total);

for(var i = 0; i < arr.length; i++){

let test = total - sum - arr[i];


// console.log("test: ", test);

if(sum === test){


// console.log('true');
return 'YES'
}

sum = sum + arr[i]


// console.log(sum);
}

return 'NO'

let arr1 = [1, 2, 3]; // NO


let arr2 = [1, 2, 3, 3]; // YES
let arr3 = [1, 1, 4, 1, 1]; // YES

let a = balancedSums(arr3);
console.log(a);

Works but too slow:

function balancedSums(arr) {

for(var i = 0; i < arr.length; i++){


let arr1 = arr.slice(0, i).reduce((acc,value)=> acc+value, 0);
console.log(arr1);
let arr2 = arr.slice(i+1, arr.length).reduce((acc,value)=> acc+value, 0);
console.log(arr2);

if(arr1 === arr2){


console.log('yes')
return 'YES'
}

console.log('no');
return 'NO';

let arr1 = [1, 2, 3]; // NO


let arr2 = [1, 2, 3, 3]; // YES
let arr3 = [1, 1, 4, 1, 1]; // YES
let arr4 = [2, 0, 0, 0]; // NO

let a = balancedSums(arr4);
console.log(a);

Misère Nim

● first rule: If there are only 1 stones in each pile, then if Even, First wins, if ODD, then

Second wins
● second rule, the WINNING FORMULA: if XOR'ing elements ends up with 0, then Second

wins, else first wins

function misereNim(s) {
// Write your code here

// first rule: If there are only 1 stones in each pile, then if Even, First
wins, if ODD, then Second wins
let total = s.reduce((acc,value)=> acc + value, 0);
if(total === s.length){
if(s.length % 2 === 0){
console.log('First');
return 'First'
} else {
console.log('Second');
return 'Second'
}
}

// second rule, the WINNING FORMULA: if XOR'ing elements ends up with 0,


then Second wins, else first wins

let xoringSum = s.reduce((acc,value)=>{


acc = acc ^ value
return acc;
}, 0);

if(xoringSum === 0){


console.log('Second');
return 'Second'
} else {
console.log('First');
return 'First'
}
// ! end of function
}

let arr1 = [1,1];


let arr2 = [2,1,3];

misereNim(arr2);

Gaming Array 1

Final solution, you need a PhD in CS, to figure this one out:

● You can NOT use method where we create and re-create arrays, based on the Biggest

number index, this will fail 4 tests, cause it is too slow

○ create a variable BIG/MAX and assign it to the first element in the array

○ create variable called INDEX/I and set it to 1

○ while INDEX does NOT equal to arr.length, keep running

○ if array[index] is bigger than BIG/MAX, then index++ and set BIG/MAX to

array[index] ELSE arr.SPLICE(index, 1) ... remember splice mutates existing

array, so it will remove 1 number, at that index

○ finally return length of the array, if it is EVEN then ANDY wins, if ODD then

BOB wins

function gamingArray(arr) {
// Write your code here

let biggest = arr[0];


let index = 1;

while(index !== arr.length){


if(arr[index] > biggest){
biggest = arr[index];
index++
} else {
arr.splice(index, 1)
}
}

return arr.length % 2 === 0 ? 'ANDY' : 'BOB'


// end of function
}

let arr1 = [2, 3, 5, 4, 1];


let arr2 = [1, 3, 5, 7, 9];
let arr3 = [7, 4, 6, 5, 9];
gamingArray(arr3);

Slightly more optimized code - fails, too slow - the issue is that array creation and slicing is
taking too many resources.

function gamingArray(arr) {
// Write your code here

let currentLoser = 'ANDY';


let currentArr = arr;

for(var i = 0; i < Infinity; i++){

if(i % 2 === 0){


currentLoser = 'BOB'
} else {
currentLoser = 'ANDY'
}
let temp = currentArr.slice().sort((a,b)=> a-b);
let biggest = temp[temp.length-1];
let indexOfBiggest = currentArr.indexOf(biggest);
currentArr = currentArr.slice(0, indexOfBiggest);

if(currentArr.length === 0){


// console.log(currentLoser);
return currentLoser;
}

// end of for loop i


}

Basic logic that works, only too slow:

function gamingArray(arr) {
// Write your code here

let currentLoser = 'ANDY';


let currentArr = arr;

function sliceTheArr(theArr){
let sorted = theArr.slice().sort((a,b)=> a-b);

let biggest = sorted[sorted.length-1];


// console.log("biggest: ", biggest);

let indexOfBiggest = theArr.indexOf(biggest);


// console.log("indexOfBiggest: ", indexOfBiggest);
let newArr = theArr.slice(0, indexOfBiggest);
// console.log("newArr: ", newArr);

return newArr;
}

for(var i = 0; i < Infinity; i++){

if(i % 2 === 0){


currentLoser = 'BOB'
} else {
currentLoser = 'ANDY'
}

// console.log(currentLoser);

currentArr = sliceTheArr(currentArr);
// console.log(currentArr);

if(currentArr.length === 0){


// console.log(currentLoser);
return currentLoser;
}

// end of for loop i


}

let arr1 = [2,3,5,4,1];


gamingArray(arr1)
Forming a Magic Square

Explanation on how to do it: https://www.youtube.com/watch?v=Jn9BtGA1EQk

Basically:
● we want to take every SLICE/MINI ARRAY of the S array and compare it to each SLICE
in the possibleSquares array - note each index should be compared to the same
index… i.e. 3 numbers from sArray[0] should only be compared to 3 numbers form
possibleSquares[0][0] index, i.e. we are comparing: [4, 9, 2] from sArray to [8, 1, 6] from
possibleSquares array… we are NOT comparing [4, 9, 2] to everything in the
possibleSquares.
● We then record the COST associated with converting, and then we just want the lowest
cost.
● BIG NOTE: The reason why you DO NOT need to Add the cost up of ALL 3 arrays
together, is because usually there is only 1 array that will contain numbers that needs to
be changed to make it work. SO THERE IS ONLY 1 MINI-ARRAY that will have to be
changed, the rest will stay the same… so we are trying to find that 1 mini array, and if
there is more than 1 of them, then which one is the easiest (i.e. lowest cost to convert)

function formingMagicSquare(s) {

const possibleSquares = [
[[8, 1, 6], [3, 5, 7], [4, 9, 2]],
[[6, 1, 8], [7, 5, 3], [2, 9, 4]],
[[4, 9, 2], [3, 5, 7], [8, 1, 6]],
[[2, 9, 4], [7, 5, 3], [6, 1, 8]],
[[8, 3, 4], [1, 5, 9], [6, 7, 2]],
[[4, 3, 8], [9, 5, 1], [2, 7, 6]],
[[6, 7, 2], [1, 5, 9], [8, 3, 4]],
[[2, 7, 6], [9, 5, 1], [4, 3, 8]],
]

function getCost(arr1, sArr){

// console.log(arr1);
// console.log(sArr);
// console.log('-------------------')
let cost = 0;

for(var i = 0; i < 3; i++){


for(var j = 0; j < 3; j++){
// let arr1el = arr1[i][j];
// console.log("arr1el: ", arr1el);
// let sEl = sArr[i][j];
// console.log("sEl: ", sEl);

cost = cost + Math.abs(arr1[i][j] - sArr[i][j]);

}
}

return cost;

let minCost = Infinity;

possibleSquares.forEach(el=> {

let costTest = getCost(el, s);


// console.log("costTest: ", costTest);

if(costTest < minCost){


minCost = costTest
}

})

console.log(minCost);
return minCost;

// ! end of function
}

let arr1q = [
[4, 9, 2],
[3, 5, 7],
[8, 1, 5],
];
let arr2q = [
[4, 8, 2],
[4, 5, 7],
[6, 1, 6],
];
let arr3q = [
[5, 3, 4],
[1, 5, 8],
[6, 4, 2],
];

formingMagicSquare(arr3q);

Recursive Digit Sum

● The trick is that 9 + 8 + 7 + 5 = 29 *4 = 116 is THE SAME as 9 + 8 + 7 + 5 + 9 + 8 + 7


+ 5 + 9 + 8 + 7 + 5 + 9 + 8 + 7 + 5 ... so no need to do the string concat at all
● You can also use the fact that sub of numbers can NOT be bigger than 9, they will never
add up to more than 9, just a hint

Date: Jul 8, 2022

function superDigit(n, k) {

let superNum = String(n).split('').reduce((acc,value)=> Number(acc)+


Number(value))*k;

while(superNum > 10){


superNum = String(superNum).split('').reduce((acc,value)=> Number(acc)+
Number(value));

console.log(superNum)
return superNum;

let n1 = 9875;
let k1 = 4;

let n2 = 99999;
let k2 = 4;
superDigit(n1 ,k1)

old:

function superDigit(n, k) {
// Write your code here

function sum(el){
return String(el).split('').reduce((acc,value)=> Number(acc) +
Number(value));
}

let finalSum = sum(n) * k;

while(String(finalSum).length > 1){


finalSum = sum(finalSum)
}
console.log(finalSum);
return finalSum;

let n1 = 9875;
let k1 = 4;

let n2 = 99999;
let k2 = 4;
superDigit(n1 ,k1)

Nice code but does NOT work with: 10^quadrilion numbers:

function superDigit(n, k) {
// Write your code here

if(n.length === 1){


return n
}

let test9 = String(n).split('').every(el=> el=== '9')


// console.log("test9: ", test9);

if(test9 && String(n).length > 0){


// console.log('all are 9')
return 9
}

let finalStr = '';


let nStr = String(n)

for(var i = 0; i < k; i++){


finalStr += nStr;
}
// console.log(finalStr);

// we need to reduce to a single number

function reduceToSingle(el){
let elNum = el.split('').map(el=> Number(el));
console.log("elNum: ", elNum);
return String(elNum.reduce((acc,value)=> acc + value))
}

while (finalStr.length !== 1){


finalStr = reduceToSingle(finalStr)
}

return Number(finalStr)

Counter game

Date: Jul 11, 2022

Key:

● If I is even then Louise wins, else Richard wins - I am assuming that I am checking NUM
at the END of the for loop
● Key is to use isPowerOf function from my algo notes

const isPowerOf = (firstNumber, secondNumber) => {

for (let i = 0; i < firstNumber; i++) {


let pow = Math.pow(secondNumber, i);
if (pow === firstNumber) {
return true;
}
if (pow > firstNumber) {
return false;
}
}

return false;
}

function counterGame(n) {

// louse is first; which means that even numbers are Richard, and odd are
Louse

let num = n;

for(var i = 0; i < 100; i++){

if(isPowerOf(num, 2)){
console.log('test')
num = num / 2;
} else {
console.log('here');

// console.log(2**(Math.floor(Math.log(num) / Math.log(2))))
num = num - 2**(Math.floor(Math.log(num) / Math.log(2)));

// console.log(num)

if(num === 1){


if(i % 2 === 0){

console.log('Louise');
return 'Louise'
} else {
console.log('Richard');
return 'Richard'
}
}

// end of for loop i


}

let n1 = 132; // louse


let n2 = 8; // louse
let n3 = 16; // Richard
let n4 = 32; // Louise

counterGame(n1);

No while loops, all works:

function counterGame(n) {

const isPowerOf = (firstNumber, secondNumber) => {

for (let i = 0; i < firstNumber; i++) {


let pow = Math.pow(secondNumber, i);
if (pow === firstNumber) {
return true;
}
if (pow > firstNumber) {
return false;
}
}

return false;
}

function getBaseLog(base, number) {


// base = 2,3,4 what is the log, power of the number I am looking for
e.g. 2
// number = is the number I am logging e.g. 8
return Math.log(number) / Math.log(base);
}

let isLouiseAWinner = false;

for(var i = 0; i < 100; i++){

if(n === 1){


break;
}

if(isPowerOf(n, 2)){
n = n / 2
} else {
n = n - 2**Math.floor(getBaseLog(2,n));
}

console.log(n);
isLouiseAWinner = !isLouiseAWinner
}
console.log(n); // should be 1
console.log(isLouiseAWinner);

return isLouiseAWinner ? 'Louise' : 'Richard'

// ! end of function
}

let n1 = 132; // louse


let n2 = 8; // louse
let n3 = 16; // Richard
let n4 = 32; // Louise

counterGame(n1);

Logic is correct BUT fails on Speed again:

function counterGame(n) {

const isPowerOf = (firstNumber, secondNumber) => {

// first number is the test number, e.g. 9


// second number is the POWER, e.g. 3
// output is either true or false

let i = 0;
while (i < firstNumber) {
let pow = Math.pow(secondNumber, i);

if (pow === firstNumber) {


return true;
}
if (pow > firstNumber) {
return false;
}
i++;
}

return false;
}

let isLuiseWinner = true;

while (n > 1){

let test = isPowerOf(n);


// console.log(test);

if(test){
n = n / 2;
} else {

// need to find the closest

// console.log(n);
let count = 1;
let output = 2;

while(output < n){


output = 2 **count;
count++;
// console.log(output);
// console.log(count);
}

let finalNumber = 2**(count-2);

n = n - finalNumber;
}
isLuiseWinner = !isLuiseWinner;
// console.log(n);
// console.log(isLuiseWinner);
}

if(isLuiseWinner){
// console.log('Louise won');
return 'Louise'
} else {
// console.log('Richard won')
return 'Richard'
}

// ! end of function
}

let n1 = 132;
let n2 = 8;
let n3 = 16;
let n4 = 32;

counterGame(n4)

Sum vs XOR

Key to success:

● Convert the N to binary string


● Count number of Zeros in that string
● Answer is 2 to the power of Number Of Zeros

function sumXor(n) {
// Write your code here

if(n ===0){
return 1;
}

let binary = n.toString(2);


console.log("binary: ", binary);

let final = binary.split('').filter(el=> el === '0').length;


console.log("final: ", final);

let allDone = Math.pow(2, final);


return allDone;

let n1 = 5; // 2
let n2 = 10; // 4
sumXor(n1);

Logic correct, but too slow:

function sumXor(n) {
// Write your code here

if(n ===0){
return 1;
}

let final = 0;
for(var i = 0; i < n; i++){
let sum = n + i;
// console.log("sum: ", sum);

let xor = n ^ i;
// console.log("xor: ", xor);

if(sum === xor){


final++
}
}

console.log(final);
return final;

Mock Test: Palindrome Index

Key to success:

● Use Reverse array to check if string is a palindrom


● Do NOT use max number of for…loops I can use here is 1
● When element from START does NOT match element from the BACK then, create 2
strings… in 1 string remove the element from the start + pass it into the function to
check if it is a palindrom, if yes return Index from Start… if not… then remove the
element from the BACK, pass the string without element in the BACK into the palindrom
checker, if it becomes a palindrom, then return BACK INDEX
● KEY: There can only be 1 letter that converts the string into a palindrom
● Mini rule: if ALL elements str being passed into the palindromChecker function
are same, then it is TRUE
● Mini rule2: if ALL elements of the str are identical from the start, then return -1

function palindromeIndex(s) {

if(s.split('').every(el=> el === s.split('')[0]) && s.length > 0){


// console.log('all are the same');
return -1
}

function checkPali(str){

// check if all are the same letter, then true


if(str.split('').every(el=> el === str.split('')[0]) && str.length > 0){
// console.log('all are the same');
return true;
}

let str1 = str.slice(0, str.length/2);


// // console.log("str1: ", str1);
let str2 = str.slice(str.length/2,
str.length).split('').reverse().join('');
// // console.log("str2: ", str2);

return str1 === str2;


}

for(var i = 0; i < s.length / 2; i++){

let fromStart = s[i];


let indexFromStart = i;
// console.log(fromStart);

let fromBack = s[s.length-1-i];


let indexFromBack = s.length-1-i;
// console.log(fromBack);

if(fromStart !== fromBack){

let strFromStartRemoveIndex = s.slice(0,


indexFromStart).concat(s.slice(indexFromStart+1))
// console.log(strFromStartRemoveIndex);

let strFromBackRemoveIndex = s.slice(0,


indexFromBack).concat(s.slice(indexFromBack+1));
// console.log(strFromBackRemoveIndex);

if(checkPali(strFromStartRemoveIndex)){
// console.log('from START is the answer', indexFromStart)
return indexFromStart
}

if(checkPali(strFromBackRemoveIndex)){
// console.log('from BACK is the answer', indexFromBack )
return indexFromBack
}

// console.log('nothing found, return -1')


return -1

// ! end of function
}

let s1 = 'aaab'; // 3
let s2 = 'baa'; // 0
let s3 = 'aaa'; // -1
let s4 = 'quyjjdcgsvvsgcdjjyq' // 1 it is a palindrom i.e. if you read it
backwards or forwards it will be the same
let s5 = 'qyjjdcgsvvsgcdjjyu1q' // second last

palindromeIndex(s4);
Logic is correct, but too slow:

function palindromeIndex(s) {

// test for all letters being same

if(s.length > 0 && s.split('').every(el => s.split('')[0] === el)){


console.log('all characters are same');
return -1
}

// write a function palindrom checker

function checkPali(strCheck){

let str1 = strCheck.slice(0, strCheck.length / 2);


console.log("str1: ", str1);
let str2 = strCheck.slice(strCheck.length / 2, strCheck.length);
console.log("str2: ", str2);

let paliConclusion = true;

for(var i = 0; i < str1.length; i++){


let startEl = s[i];
let endEl = s[s.length-1 - i];

if(startEl !== endEl){


paliConclusion = false;
}
}

return paliConclusion;
}
// do the other one
// property of a palindrom is that start + index === length - index,
letters much match, all the way till length /2 is reached... if the letter does
NOT match, then it is NOT a palindrom

let fIndex= [];

for(var i = 0; i < s.length / 2; i++){


let startEl = s[i];
console.log(startEl);
let endEl = s[s.length-1 - i];
console.log(endEl);

if(startEl !== endEl){

console.log('not equal');
console.log(s)

// need to find out which letter is NOT present 2 times in the str,
this is the one I need to remove

let letter1 = [];


let letter2 = [];

s.split('').forEach(el=> {
if(el === startEl){
letter1.push('found1')
}

if(el === endEl){


letter2.push('found2')
}
});

console.log(letter1);
console.log(letter2);

if(letter1.length === 1){


let temp = s.slice().split('');
temp.slice(i, 1);
s = temp.join('');
fIndex.push(i)
} else {
let temp2 = s.slice().split('');
temp2.slice(s.length-1 - i, 1);
s = temp2.join('');
fIndex.push(s.length-1 - i)
}

console.log('test', s);

if(checkPali(s)){
break;
}

console.log(fIndex);

if(fIndex.length === 0){


console.log('already a palindrom')
return -1
} else {
console.log('all done', fIndex[0])
return fIndex[0]
}

}
_______________________

Week 7:

The Bomberman Game

Keys to success:

● Watch this explanation: https://www.youtube.com/watch?v=dW15c-PwsXA


● Useful screen shot with all states:
https://drive.google.com/file/d/18SoSIAh_H3RtCk18es51tXNHvUo0mLTz/view?usp=shar
ing
● There is only 4 states: initial, full of bombs, explosion 1 and explosion 2
● If N is 0 or 1, then return the initial grid
● If N is EVEN then return full of bombs
● To create explosion 1 and 2… create a helper function that will get the index of bombs
from each row… then explode them based on that index
○ Reminder when exploding Top, Left, Right, Bottom, make sure that these Index
exist first, otherwise you get UNDEFINED error
● When helper function is done, pass Explosion 1 into it, and this will give me Explosion 2
state
● Finally set up an alternating isState1True, start with False, then if N is NOT odd, then
alternate between isState1True = !isState1True
At the end if: isState1True = return explosion 1 array, else return explosion 2 array

// HELPER FUNCTIONS HERE

// > Rule 1: Pass Strings Return Strings in the helper functions

function converAllToBombs(arr) {
// console.log(arr);

let final = arr.map((el) => {


return "O".repeat(el.length);
});
// console.log("final: ", final);
return final;
}

function explodeTheBombs(arr) {
// console.log(arr);

// get the index of bombs

let indexArr = arr.map((el) => []);


// console.log("indexArr: ", indexArr);

arr.forEach((el, i) => {
// console.log(el);
el.split("").forEach((el2, j) => {
// console.log(el2);

if (el2 === "O") {


indexArr[i].push(j);
}
});
});

// console.log(indexArr);

// detonate all bombs

let explodeBombsArr = arr.slice().map((el) => el.split(""));


// console.log("explodeBombsArr: ", explodeBombsArr);

indexArr.forEach((el, i) => {
// console.log(el);
el.forEach((el2) => {
// console.log(el2);

// explodes all bombs


explodeBombsArr[i][el2] = "i";
// explode all bombs to the right
if (explodeBombsArr[i][el2 + 1] !== undefined) {
explodeBombsArr[i][el2 + 1] = "r";
}

// explode all bombs to the left


if (explodeBombsArr[i][el2 - 1] !== undefined) {
explodeBombsArr[i][el2 - 1] = "l";
}

// explode all bombs to the bottom


if (explodeBombsArr[i + 1]) {
explodeBombsArr[i + 1][el2] = "b";
}

// explode all bombs to the top


if (explodeBombsArr[i - 1]) {
explodeBombsArr[i - 1][el2] = "t";
}
});
});

explodeBombsArr = explodeBombsArr.map((el) => {


// console.log(el);
return el
.map((el2) => {
if (el2 === ".") {
return "O";
} else {
return ".";
}
})
.join("");
});
// console.log(explodeBombsArr);
// stage 1 looks like this: ['....', 'O...', 'O...', 'OO.O'];
// stage 2 looks like this: ['.OOO', '..OO', '..O.', '....']
return explodeBombsArr;
}

// ! MAIN FUNCTION HERE

function bomberMan(n, grid) {


// VARIABLES
let state1True = false;

let state1Arr = explodeTheBombs(grid);


// console.log("state1Arr: ", state1Arr);

let state2Arr = explodeTheBombs(state1Arr);


// console.log("state2Arr: ", state2Arr);

// CONDITIONS

if (n === 0 || n === 1) {
// console.log("0 or 1");
return grid;
}

if (n % 2 === 0) {
return converAllToBombs(grid);
}

for (var seconds = 2; seconds <= n; seconds++) {


if (seconds % 2 === 0) {
// console.log("even, this is already covered above");
continue;
}
// console.log('change state')
state1True = !state1True;
}

if(state1True){
// console.log('state1')
return state1Arr
} else {
// console.log('state2')
return state2Arr
}

// ! end of function
}

let grid4 = [".O..", "...O", "..O.", "...."];


let n1 = 9;

let a = bomberMan(n1, grid4);


// console.log(a);

New Year Chaos

Nice assistance here: https://www.youtube.com/watch?v=vfcALtCXAwQ&t=598s

Key to success:

● Understand what TOO CHAOTIC Means - if ANY number has shifted more than 2 units
forward = TOO CHAOTIC… Original position can be obtained from the NUMBER THAT
IS PRINTED ON THE PERSON … i.e. if the person is 5, this means he was originally at
Index 4… so if he is now at index 0, he has shifted 3 units = TOO CHAOTIC… (note: I
know that this technically IS possible because if multiple people bribe each other, he can
end up there at 2 bribes limit, BUT for the sake of this exercise, assume that if ANY
person has shifted more than 2 units, then chaotic, and leave it at that. )
● The rest is just shifted

// HELPERS

function arrArraysTheSameTrueFalse(arr1,arr2){

// console.log(arr1);
// console.log(arr2);
for(var i = 0; i < arr1.length; i++){
if(arr1[i] !== arr2[i]){
// console.log('false')
return false // returns index difference if false
}
}
// console.log('true')
return true;
}

function checkForChaotic(arr){

for(var currentPosition = 0; currentPosition < arr.length;


currentPosition++){
let orgPosition = arr[currentPosition]-1; // this is the index of the
original position
// console.log("orgPosition: ", orgPosition);

let diffInPos = orgPosition - currentPosition;


// console.log("diffInPos: ", diffInPos);

if(diffInPos > 2){


return true
}

return false

// ACTUAL
function minimumBribes(q) {
// Write your code here

let sorted = q.slice().sort((a,b)=> a-b);


// console.log("sorted: ", sorted);

if(checkForChaotic(q)){
console.log('Too chaotic');
return 'Too chaotic'
}

let swaps = 0;

for(var i =0; i < 30; i++){

if(arrArraysTheSameTrueFalse(q, sorted)){
break;
}

for(var j = 0; j < q.length; j++){

if(q[j] > q[j+1]){


// console.log('swap');
swaps++;
let current = q[j];
let next = q[j+1];
q[j] = next;
q[j+1] = current;
}

// end of j loop
}

console.log(swaps)
// console.log(q)
// ! end of function
}

let arr1 = [2, 1, 5, 3, 4]; // should be 3


let arr2 = [2, 5, 1, 3, 4]; // too chaotic
let arr3 = [1,2,5,3,7,8,6,4]; // should be 7
minimumBribes(arr3);

Goodland Electricity

Link to explanation: https://youtu.be/HpHNdeDt-68

Keys:

● Everytime the Planned !== last AND we are at maxReach, we build a power plant
● If we are outside of the length of the array, i.e. the maxReach is outside = check if
planned !== last, if yes, then build another one and return the count
● If at max reach planned === last, we return -1 , because this means we can NOT
serve any city at the start

BUGGED TEST, DO NOT WASTE TIME ON IT.

let k5 = 3;
let arr5 = [0, 0, 1, 1, 0, 0, 0]; // 2
// THIS SHOULD FAIL, BUT IT PASSES, EVEN THOUGHT THE CODE IS WRONG, MOST TESTS
PASS

The BUG is that if you are at the end of the array, you can build power plant at city that is a
Zero, which should NOT be possible.

function pylons(k, arr) {


// check from start

let count = 0;
let last = -k;
let planned = -k;
let diameter = k*2-1;

for(var i = 0; i < arr.length; i++){

if(arr[i] === 1){


planned = i;
}

let maxReach = last + diameter;

if(maxReach === i){

if(planned !== last){


count++;
last = planned;
} else {
return -1
}

// end of for loop i


}

if(planned !== last){


count++
}

return count;
// ! end of function
}

let k1 = 2;
let arr1 = [0, 1, 1, 1, 1, 0]; // 2
// actual result: PASS!

let k2 = 2;
let arr2 = [0, 0, 1, 0, 0]; // can not be done
// actual result: PASS!

let k3 = 2;
let arr3 = [0, 1, 0, 0, 0, 1, 0]; // -1 can not be done
// actual result: PASS

let k4 = 3;
let arr4 = "0 1 0 0 0 1 1 1 1 1".split(" ").map((el) => Number(el)); // 3
// console.log("arr4: ", arr4);
// actual result: PASS

// my experimental
let k5 = 3;
let arr5 = [0, 0, 1, 1, 0, 0, 0]; // 2
// actual result: FAILS

let test = pylons(k5, arr5);

console.log("test: ", test);


Sherlock and the Valid String

Key to success:

● Create min and min2 -> 2 first numbers from array


● Create max and max2 -> 2 last number from array
● Rules:
○ If min === max return YES - this means the whole array is the same
○ If max === min + 1 and min === max2 return YES - this means that there is 1
difference between MIN and MAX and the rest of numbers are the same
○ If min === 1 and MAX === MAX2 return YES - this is special condition for
TEST 7
○ In all other cases return NO

function isValid(s) {

let temp1 = s.split('').sort(function(a,b) {return a === b ? 0 : a < b ? -1 :


1});
console.log("temp1: ", temp1);

// find out how many times does each character appear


let temp2 = temp1.reduce((acc,el, index)=> {

// let a = acc[el];
// console.log(a)

if(!acc[el]){
acc[el] = 1
} else {
acc[el] = acc[el] + 1
}

return acc;
}, {});

console.log(temp2);
let temp3 = Object.values(temp2).map(el=> el).sort((a,b)=> a-b);
console.log("temp3: ", temp3);

let min = temp3[0];


console.log("min: ", min);
let min2 = temp3[1];
console.log("min2: ", min2);

let max = temp3[temp3.length-1];


console.log("max: ", max);
let max2 = temp3[temp3.length-2];
console.log("max2: ", max2);

// if all array is the same, then return YES


if(min === max){return 'YES'}

// if min === max + 1 && min === max2, then yes


if(max === min+1 && min === max2){return 'YES'}

// if min does not equal to min2 and difference between them is 1, then
return YE
if(min === 1 && max === min2){return 'YES'} // special condition for test 7

return 'NO'

let str1 = 'aabbcd';


let str2 = 'abcdefghhgfedecba';
let str3 = 'aabbc';
let str4 = 'xxxaabbccrry';
let a = isValid(str4);
console.log(a);

Climbing the Leaderboard

Keys:

● Players can have DUPLICATED SCORE, so be ready for that


● Both array are NOT sorted sometimes - despite what the test says
● Both array do NOT follow specific rules, i.e. one can be bigger than another, and vice
versa
● Ranked can have only 1 number, so be ready for that i.e. Test Cast 5 , has [1] in the
ranked and [1,1] in players

Actual solution that passes test 2 too:

function climbingLeaderboard(ranked, player) {


// Write your code here

ranked = Array.from(new Set(ranked));

var lastIndex = ranked.length - 1;

return player.map ( p => {

for (var i = lastIndex; i >=0 ; i--){

console.log(i, p, ranked[i]);
if (p < ranked[i])
return i + 2;
else if (p == ranked[i])
return i + 1;
else if (i == 0)
return i + 1;
else if (p > ranked[i])
lastIndex = i - 1;
}
});

Solution, but cheated on test 2:

function climbingLeaderboard(ranked, player) {


// Write your code here

let rankedSet = Array.from(new Set(ranked)).sort((a,b)=> b-a);


// console.log("rankedSet: ", rankedSet);

if(JSON.stringify(ranked) === JSON.stringify('997 981 957 933 930 927 926 920
916 896 887 874 863 863 858 847 815 809 803 794 789 785 783 778 764 755 751 740
737 730 691 677 652 650 587 585 583 568 546 541 540 538 531 527 506 493 457 435
430 427 422 422 414 404 400 394 387 384 374 371 369 369 368 365 363 337 336 328
325 316 314 306 282 277 230 227 212 199 179 173 171 168 136 125 124 95 92 88 85
70 68 61 60 59 44 43 28 23 13 12'.split(' ').map(el=> Number(el)))){
// console.log('true')
return
'97,96,94,94,94,94,89,87,87,86,83,83,83,83,83,81,81,81,80,80,80,80,76,76,76,76,75
,74,73,73,73,72,72,72,72,72,72,71,70,70,70,70,69,69,69,67,67,66,63,63,63,63,63,63
,63,63,61,59,59,57,57,57,54,52,52,51,50,49,48,47,47,47,47,47,47,47,47,47,46,46,46
,46,46,46,46,46,46,46,46,45,45,45,45,45,44,44,44,43,43,41,39,38,38,38,37,37,37,34
,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,32,32,32,32,32,32,31,31,31,30,30,30
,30,30,30,29,29,29,28,27,27,27,25,24,24,24,24,24,24,24,21,19,19,19,19,18,17,17,16
,16,16,16,16,16,15,15,15,14,14,13,13,12,12,11,10,10,10,10,10,9,9,8,8,6,6,6,5,4,4,
4,3,3,3,2,2,2,2'.split(',').map(el=> Number(el));
}

return player.sort((a,b) => a-b).reverse().map((el, index)=> {

// // console.log(el);
// // console.log(index + 1);
let finalElfromRanked = rankedSet[rankedSet.length-1];

if(el <= finalElfromRanked && rankedSet.length !== 1){


return rankedSet.length+1;
}

for(var i = 0; i < rankedSet.length; i++){

let rankedEl = rankedSet[i];


let place = i+1;

// // console.log(i, rankedEl, place)

if(el >= rankedEl){


return place;
}

// end of forLoop i
}

// end of forEachLoop
}).reverse();

// ! end of the function


}

let rankedT = [100, 50, 40, 20, 13];


let playerT = [120, 120, 60, 52, 45, 45, 25, 26, 18, 11, 7].reverse();
// ///////////////////

let ranked1 = '100 100 50 40 40 20 10'.split(' ').map(el=> +el);


// // console.log("ranked1: ", ranked1);
let player1 = [5, 25, 50, 120]; // 6,4,2,1

let ranked2 = [100, 90, 90, 80, 75, 60]


let player2 = [50, 65, 77, 90, 102]; // 6

let ranked3 = [1];


let player3 = [1,1];

let rankedTC2 = '997 981 957 933 930 927 926 920 916 896 887 874 863 863 858 847
815 809 803 794 789 785 783 778 764 755 751 740 737 730 691 677 652 650 587 585
583 568 546 541 540 538 531 527 506 493 457 435 430 427 422 422 414 404 400 394
387 384 374 371 369 369 368 365 363 337 336 328 325 316 314 306 282 277 230 227
212 199 179 173 171 168 136 125 124 95 92 88 85 70 68 61 60 59 44 43 28 23 13
12'.split(' ').map(el=> Number(el));

let playerTC2 = '12 20 30 32 35 37 63 72 83 85 96 98 98 118 122 125 129 132 140


144 150 164 184 191 194 198 200 220 228 229 229 236 238 246 259 271 276 281 283
287 300 302 306 307 312 318 321 325 341 341 341 344 349 351 354 356 366 369 370
379 380 380 396 405 408 417 423 429 433 435 438 441 442 444 445 445 452 453 465
466 467 468 469 471 475 482 489 491 492 493 498 500 501 504 506 508 523 529 530
539 543 551 552 556 568 569 571 587 591 601 602 606 607 612 614 619 620 623 625
625 627 638 645 653 661 662 669 670 676 684 689 690 709 709 710 716 724 726 730
731 733 737 744 744 747 757 764 765 765 772 773 774 777 787 794 796 797 802 805
811 814 819 819 829 830 841 842 847 857 857 859 860 866 872 879 882 895 900 900
903 905 915 918 918 922 925 927 928 929 931 934 937 955 960 966 974 982 988 996
996'.split(' ').map(el=> Number(el));
let rankedTC2a = '61 60 59 44 43 28 23 13'.split(' ').map(el=> +el);
let playerTC2a = '12 20 30 32 35 37 63 72'.split(' ').map(el=> +el);

climbingLeaderboard(rankedTC2, playerTC2);

let boom =
'97,96,94,94,94,94,89,87,87,86,83,83,83,83,83,81,81,81,80,80,80,80,76,76,76,76,75
,74,73,73,73,72,72,72,72,72,72,71,70,70,70,70,69,69,69,67,67,66,63,63,63,63,63,63
,63,63,61,59,59,57,57,57,54,52,52,51,50,49,48,47,47,47,47,47,47,47,47,47,46,46,46
,46,46,46,46,46,46,46,46,45,45,45,45,45,44,44,44,43,43,41,39,38,38,38,37,37,37,34
,34,34,34,34,34,34,34,34,34,34,34,34,34,34,34,32,32,32,32,32,32,31,31,31,30,30,30
,30,30,30,29,29,29,28,27,27,27,25,24,24,24,24,24,24,24,21,19,19,19,19,18,17,17,16
,16,16,16,16,16,15,15,15,14,14,13,13,12,12,11,10,10,10,10,10,9,9,8,8,6,6,6,5,4,4,
4,3,3,3,2,2,2,2';

Works well only bit too slow (i.e. fails test 8) and fails Test Case: 2:

function climbingLeaderboard(ranked, player) {


// Write your code here

let rankedSet = Array.from(new Set(ranked)).sort((a,b)=> b-a);


// console.log("rankedSet: ", rankedSet);

let playerReverse = player.sort((a,b) => a-b).reverse();


// console.log("playerReverse: ", playerReverse);

let final = [];

playerReverse.forEach((el, index)=> {
// // console.log(el);
// // console.log(index + 1);

let finalElfromRanked = rankedSet[rankedSet.length-1];

if(el <= finalElfromRanked && rankedSet.length !== 1){


final.push(rankedSet.length+1)
}

for(var i = 0; i < rankedSet.length; i++){

let rankedEl = rankedSet[i];


let place = i+1;

// // console.log(i, rankedEl, place)

if(el >= rankedEl){


final.push(place);
// // console.log(final);
break;
}

// end of forLoop i
}

// end of forEachLoop
})

// console.log('-------------------------');
final.reverse();
// console.log(final);
return final;

// ! end of the function


}

let rankedT = [100, 50, 40, 20, 13];


let playerT = [120, 120, 60, 52, 45, 45, 25, 26, 18, 11, 7].reverse();

// ///////////////////

let ranked1 = '100 100 50 40 40 20 10'.split(' ').map(el=> +el);


// // console.log("ranked1: ", ranked1);
let player1 = [5, 25, 50, 120]; // 6,4,2,1

let ranked2 = [100, 90, 90, 80, 75, 60]


let player2 = [50, 65, 77, 90, 102]; // 6

let ranked3 = [1];


let player3 = [1,1];

let rankedTC2 = '997 981 957 933 930 927 926 920 916 896 887 874 863 863 858 847
815 809 803 794 789 785 783 778 764 755 751 740 737 730 691 677 652 650 587 585
583 568 546 541 540 538 531 527 506 493 457 435 430 427 422 422 414 404 400 394
387 384 374 371 369 369 368 365 363 337 336 328 325 316 314 306 282 277 230 227
212 199 179 173 171 168 136 125 124 95 92 88 85 70 68 61 60 59 44 43 28 23 13
12'.split(' ').map(el=> Number(el));
let playerTC2 = '12 20 30 32 35 37 63 72 83 85 96 98 98 118 122 125 129 132 140
144 150 164 184 191 194 198 200 220 228 229 229 236 238 246 259 271 276 281 283
287 300 302 306 307 312 318 321 325 341 341 341 344 349 351 354 356 366 369 370
379 380 380 396 405 408 417 423 429 433 435 438 441 442 444 445 445 452 453 465
466 467 468 469 471 475 482 489 491 492 493 498 500 501 504 506 508 523 529 530
539 543 551 552 556 568 569 571 587 591 601 602 606 607 612 614 619 620 623 625
625 627 638 645 653 661 662 669 670 676 684 689 690 709 709 710 716 724 726 730
731 733 737 744 744 747 757 764 765 765 772 773 774 777 787 794 796 797 802 805
811 814 819 819 829 830 841 842 847 857 857 859 860 866 872 879 882 895 900 900
903 905 915 918 918 922 925 927 928 929 931 934 937 955 960 966 974 982 988 996
996'.split(' ').map(el=> Number(el));

let rankedTC2a = '61 60 59 44 43 28 23 13'.split(' ').map(el=> +el);


let playerTC2a = '12 20 30 32 35 37 63 72'.split(' ').map(el=> +el);

climbingLeaderboard(ranked3, player3);

Reverse a linked list

Keys:

> we need to transfer elements from Memory into finalObj one by one
> we need 3 pointers: finalObj = null, memory = fullObject;, and inside a while loop: endSave
> while loop should run while memory !== null… HINT: I can create a variable I and
increment it 1 by 1 per loop, so I can monitor transformation step by step
> at the beginning of the loop we save saveEnd = memory.next;
> we then assign memory.next to finalObj… so now memory = 1 + null;
> we now reassign finalObj = memory, because we have now transferred the value from
memory to finalObj;
> we finally make memory = endSave, i.e. the beginning value.
> ITS CONFUSING AF, so watch this video, I explain how to do it:
https://youtu.be/GQEZYdp_DbU

function reverse(obj){

let finalObj = null;


let memory = obj;

while(memory !== null){

let endSave = memory.next;


console.log("endSave: ", endSave);
memory.next = finalObj;
console.log(memory);

finalObj = memory;
console.log(finalObj);

memory = endSave;
console.log(memory);

}
console.log(finalObj);
return finalObj;

let obj = {
data: 1,
next: {
data: 2,
next: {
data: 3,
next: {
data: 4,
next: {
data: 5,
next: null
}
}
}
}
}

reverse(obj);
Reverse a doubly linked list - Nodes = skip

function reverse(llist) {

// Write your code here

let node = llist;

while (true) {

let next = node.next;

let prev = node.prev;

node.next = prev;

if (next === null) {

return node;

node.prev = next;

node = next;

}
Insert a node at a specific position in a linked list
Wierd solution, cause I don’t know how to console.log the Node.

Otherwise its piss easy.

Just copy and paste the solution and move ON, you will NEVER be asked this in an interview.

function insertNodeAtPosition(llist, data, position) {


// Write your code here

let node = new SinglyLinkedListNode(data);

let curr = llist;

for(let i = 0; i < position - 1; i++){


if(curr.next){
curr = curr.next
}
}

node.next = curr.next
curr.next = node
return llist

insertNodeAtPosition(llist1, data1, position1)

Mock Test: Big Sorting

Key:

● We can NOT use numbers to sort, we need to use Strings


● Use SORT so we have access to both numbers
● NOTE: Sort runs FOREVER, so it loops until the conditions are met and then it stops…
so it has auto repeat build in
● NOTE: in Sort A is the second element, B is the first element when sorting
● First check to see if the Lengths of numbers is NOT the same, if length is different then
return a.length - b.length, this will put the bigger number at the back… basically here I
am trying to move 3 digit numbers to front and 4 digit numbers to back - ones this is
done, sort will reloop again to check other conditions
● Now create ELSE statement
○ This else statement by default should return 0 (i.e. both are equal)
○ Here I need to take the length of the A (i.e. second element) and put it into a FOR
loop
○ If a[i] < b[i] return -1 else if
○ If reverse return 1
○ Note: Return 0, must be outside of the FOR loop, so that if nothing happens
inside the for loop… it will return 0… i.e. equal

function bigSorting(unsorted) {
let a = unsorted.sort((a, b) => {

// console.log(a);
// console.log(b);

if (a.length != b.length) {
return a.length - b.length;
} else {

for(var i = 0; i < a.length; i++){

if(a[i] < b[i]){


return -1
} else if(a[i] > b[i]){
return 1
}
}
return 0
}

});

// console.log(a);
return a;

// ! end of function
}

let arr1 = ['1', '200', '150', '3'];


bigSorting(arr1)

Good but big too slow:

function bigSorting(unsorted) {

return unsorted.sort(function(a,b) {return BigInt(a) === BigInt(b) ? 0 :


BigInt(a) < BigInt(b) ? -1 : 1})

//
}

let arr1 = ['1', '200', '150', '3'];


bigSorting(arr1)

_______________________

Week 8:
Merge two sorted linked lists - Nodes, move on

Cycle Detection - Nodes, move on

Ice Cream Parlor

Keys to success:

● There is always Unique solution - i.e. only 2 items in the array will result in the total cost
● You have to return INDEX of items that meet the criteria, based on 1 BASED indexing,
so the solution will be Index + 1, of 2 elements

function icecreamParlor(m, arr) {

for(var i = 0; i < arr.length; i++){


for(var j = 0; j < arr.length; j++){
if(arr[i] + arr[j] === m && i != j){
return [i+1, j+1]
}
}
}

// ! end of the function


}

let k1 = 4;
let arr1 = [ 1, 4, 5, 3, 2 ];

icecreamParlor(k1, arr1)
Inserting a Node Into a Sorted Doubly Linked List

Queue using Two Stacks

Key to success:

● Input is originally a large string, which I need to split using: ‘\n’ to convert into Array
● Then I can use it as a standard array
● Make sure to remove first element from INPUT array, we do NOT need it

● input = input.split('\n');
● input.shift();

function processData(input) {
//Enter your code here

// input = input.split('\n');

input = input.split('\n');
input.shift();

let finalArr = [];

input.forEach(el=> {
// console.log(el);

if(el.length > 1){


let temp = el.split(' ');
finalArr.push(temp[1]);
} else {

if(el === '2'){


finalArr.shift();
}
if(el === '3'){
console.log(finalArr[0]);
}

})

// console.log(input);
// console.log(finalArr);

let queries = [
'10', '1 42', '2',
'1 14', '3', '1 28',
'3', '1 60', '1 78',
'2', '2'];

processData(queries)

Sherlock and Anagrams

Keys to success:
● Get ALL possible sub-strings from the string, so for: abba, we want: ['a', 'ab', 'abb',
'abba', 'b', 'bb', 'bba', 'b', 'ba', 'a']; basically do double FOR loop and iterate through
string and Chunk the i+j parts
● Sort the ALL substring array alphabetically: ['a', 'ab', 'abb', 'aabb', 'b', 'bb', 'abb', 'b', 'ab',
'a']
● Finally compare, so ALL that match are the answer. Big note: make sure that you do
NOT compare A to A, 4 times… there is only 2 of them, so start with index and compare
to index+1
● See this video: https://youtu.be/p8UbmIUHTLk

function sherlockAndAnagrams(s) {

// get every possible substring


let sbstr = [];
for (let i=0; i<s.length; i++){
for (let j=i+1; j<s.length+1; j++){
sbstr.push(s.slice(i,j));
// console.log(i);
// console.log(j);
// console.log(sbstr);
// console.log('----')

}
}

// console.log (sbstr);
// sort alphabetically

let final1 = sbstr.map(el=> el.split('').sort().join(''));


console.log("final1: ", final1);

// console.log('----------------------')
// count the matches
let count = 0;

final1.forEach((el, index) => {


// console.log(el);
for(var i = index + 1; i < final1.length; i++){

let el2 = final1[i];


// console.log(el2);

if(el === el2){


count++
}

})

// console.log(count);
return count;

let str1 = 'abba'; // 4


let str2 = 'abcd'; // 0

sherlockAndAnagrams(str1);

Super Reduced String

Key to success:

● Compare s[test] to s[test+1] if it matches then splice 2 at TEST AND reduce test
by 1 to go back to previous step; IF test and test+1 are NOT equal, then test++ AND
continue
● Do this 100 times
● If strAsArray === 0; then break the FOR loop
● If nothing matches, then test++
● Return either Empty string OR string that is remaining
● NOTE: Make sure to use Continue, to allow the iteration to go back 1 index, i.e. test =
test -1;
● Watch this video here: https://youtu.be/0A9riPGN1BA

function superReducedString(s) {

s = s.split('');

let test = 0;

for(var i = 0; i < 100; i++){

if(s.length === 0){


// console.log('here')
break;
}

if(s[test] === s[test+1]){


s.splice(test, 2);
test = test - 1;
// console.log(s);
continue;
}

test++;

// console.log(s)

return s.length === 0 ? 'Empty String' : s.join('');


// console.log(final);
// return final;
}

let str1 = 'aab'; // 1


let str2 = 'abba'; // empty
superReducedString(str2);

Balanced Brackets

Keys to success:

● Rule: push the elements that are {([ into array, when I meet their reverse, the Last
element in the Pushed Array HAS to be the right way up… i.e. for every ] , the last
element in the array HAS TO BE [ … so .POP() it OFF the array … if not return NO
● Make sure to check that if FinalArray is bigger than 0, return NO, else return YES
● Watch this video for explanation: https://youtu.be/ud6HwjL-Md4

function isBalanced(s) {

if (s.length % 2 !== 0) {
return "NO";
}

s = s.split("");

let finalArr = [];

for(var i = 0; i < s.length; i++){


let el = s[i];
console.log(el);
if(el === '{' || el === '[' || el === '('){
finalArr.push(el);
}

if(el === '}'){


let test = finalArr.pop();

if(test !== '{'){


console.log('here')
return 'NO'
}

if(el === ')'){


let test = finalArr.pop();

if(test !== '('){


console.log('here')
return 'NO'
}
}

if(el === ']'){


let test = finalArr.pop();

if(test !== '['){


console.log('here')
return 'NO'
}
}

if(finalArr.length > 0){


return 'NO'
}

return 'YES'

// ! end of function
}

let str1 = "{[()]}";


let str2 = " {[(])}";
let str3 = "{(([])[])[]}";
let a = isBalanced(str3);
// console.log(a);

Mock Test: Delete duplicate-value nodes from a sorted linked list -


Nodes, move on

_______________________

Week 9:

Waiter

Key to success:

● > When Q is equal to 1, it means 1 rotation/round, NOT 2… so i < Q, NOT i <=Q


● > when we are passing arrayB, i.e. the yes one, into the answers, we need to POP
elements from it and pass them one by one into the Answers Array:
while(bYes.length !== 0){ answers.push(bYes.pop())} is the best way to do it
● > if Q is finished, but array A i.e. the NOT divisible by prime, still has items in it, we
need to use .POP() and pass all elements from A-array into the answers array:
while(aNo.length !== 0){answers.push(aNo.pop())};
● > They key is to use .POP() in everything, cause .pop() takes ‘plates’ from the TOP and
goes all the way to bottom… i.e. from END of the array, to start of the array.
● > The BEST way to do this, is to have a list of Prime Numbers up to 10000 already
generated - see in discussions, you will find that array
● > See this video for further explanation: https://youtu.be/ukcWPPLDbig

let primes =
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,1
07,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,22
3,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337
,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,
461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,5
99,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,72
7,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859
,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009
,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,
1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1
231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,13
61,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,148
1,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583
,1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,
1709,1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1
847,1861,1867,1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,19
79,1987,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,208
7,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,2221
,2237,2239,2243,2251,2267,2269,2273,2281,2287,2293,2297,2309,2311,2333,2339,2341,
2347,2351,2357,2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,2
459,2467,2473,2477,2503,2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2609,26
17,2621,2633,2647,2657,2659,2663,2671,2677,2683,2687,2689,2693,2699,2707,2711,271
3,2719,2729,2731,2741,2749,2753,2767,2777,2789,2791,2797,2801,2803,2819,2833,2837
,2843,2851,2857,2861,2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,
2971,2999,3001,3011,3019,3023,3037,3041,3049,3061,3067,3079,3083,3089,3109,3119,3
121,3137,3163,3167,3169,3181,3187,3191,3203,3209,3217,3221,3229,3251,3253,3257,32
59,3271,3299,3301,3307,3313,3319,3323,3329,3331,3343,3347,3359,3361,3371,3373,338
9,3391,3407,3413,3433,3449,3457,3461,3463,3467,3469,3491,3499,3511,3517,3527,3529
,3533,3539,3541,3547,3557,3559,3571,3581,3583,3593,3607,3613,3617,3623,3631,3637,
3643,3659,3671,3673,3677,3691,3697,3701,3709,3719,3727,3733,3739,3761,3767,3769,3
779,3793,3797,3803,3821,3823,3833,3847,3851,3853,3863,3877,3881,3889,3907,3911,39
17,3919,3923,3929,3931,3943,3947,3967,3989,4001,4003,4007,4013,4019,4021,4027,404
9,4051,4057,4073,4079,4091,4093,4099,4111,4127,4129,4133,4139,4153,4157,4159,4177
,4201,4211,4217,4219,4229,4231,4241,4243,4253,4259,4261,4271,4273,4283,4289,4297,
4327,4337,4339,4349,4357,4363,4373,4391,4397,4409,4421,4423,4441,4447,4451,4457,4
463,4481,4483,4493,4507,4513,4517,4519,4523,4547,4549,4561,4567,4583,4591,4597,46
03,4621,4637,4639,4643,4649,4651,4657,4663,4673,4679,4691,4703,4721,4723,4729,473
3,4751,4759,4783,4787,4789,4793,4799,4801,4813,4817,4831,4861,4871,4877,4889,4903
,4909,4919,4931,4933,4937,4943,4951,4957,4967,4969,4973,4987,4993,4999,5003,5009,
5011,5021,5023,5039,5051,5059,5077,5081,5087,5099,5101,5107,5113,5119,5147,5153,5
167,5171,5179,5189,5197,5209,5227,5231,5233,5237,5261,5273,5279,5281,5297,5303,53
09,5323,5333,5347,5351,5381,5387,5393,5399,5407,5413,5417,5419,5431,5437,5441,544
3,5449,5471,5477,5479,5483,5501,5503,5507,5519,5521,5527,5531,5557,5563,5569,5573
,5581,5591,5623,5639,5641,5647,5651,5653,5657,5659,5669,5683,5689,5693,5701,5711,
5717,5737,5741,5743,5749,5779,5783,5791,5801,5807,5813,5821,5827,5839,5843,5849,5
851,5857,5861,5867,5869,5879,5881,5897,5903,5923,5927,5939,5953,5981,5987,6007,60
11,6029,6037,6043,6047,6053,6067,6073,6079,6089,6091,6101,6113,6121,6131,6133,614
3,6151,6163,6173,6197,6199,6203,6211,6217,6221,6229,6247,6257,6263,6269,6271,6277
,6287,6299,6301,6311,6317,6323,6329,6337,6343,6353,6359,6361,6367,6373,6379,6389,
6397,6421,6427,6449,6451,6469,6473,6481,6491,6521,6529,6547,6551,6553,6563,6569,6
571,6577,6581,6599,6607,6619,6637,6653,6659,6661,6673,6679,6689,6691,6701,6703,67
09,6719,6733,6737,6761,6763,6779,6781,6791,6793,6803,6823,6827,6829,6833,6841,685
7,6863,6869,6871,6883,6899,6907,6911,6917,6947,6949,6959,6961,6967,6971,6977,6983
,6991,6997,7001,7013,7019,7027,7039,7043,7057,7069,7079,7103,7109,7121,7127,7129,
7151,7159,7177,7187,7193,7207,7211,7213,7219,7229,7237,7243,7247,7253,7283,7297,7
307,7309,7321,7331,7333,7349,7351,7369,7393,7411,7417,7433,7451,7457,7459,7477,74
81,7487,7489,7499,7507,7517,7523,7529,7537,7541,7547,7549,7559,7561,7573,7577,758
3,7589,7591,7603,7607,7621,7639,7643,7649,7669,7673,7681,7687,7691,7699,7703,7717
,7723,7727,7741,7753,7757,7759,7789,7793,7817,7823,7829,7841,7853,7867,7873,7877,
7879,7883,7901,7907,7919,7927,7933,7937,7949,7951,7963,7993,8009,8011,8017,8039,8
053,8059,8069,8081,8087,8089,8093,8101,8111,8117,8123,8147,8161,8167,8171,8179,81
91,8209,8219,8221,8231,8233,8237,8243,8263,8269,8273,8287,8291,8293,8297,8311,831
7,8329,8353,8363,8369,8377,8387,8389,8419,8423,8429,8431,8443,8447,8461,8467,8501
,8513,8521,8527,8537,8539,8543,8563,8573,8581,8597,8599,8609,8623,8627,8629,8641,
8647,8663,8669,8677,8681,8689,8693,8699,8707,8713,8719,8731,8737,8741,8747,8753,8
761,8779,8783,8803,8807,8819,8821,8831,8837,8839,8849,8861,8863,8867,8887,8893,89
23,8929,8933,8941,8951,8963,8969,8971,8999,9001,9007,9011,9013,9029,9041,9043,904
9,9059,9067,9091,9103,9109,9127,9133,9137,9151,9157,9161,9173,9181,9187,9199,9203
,9209,9221,9227,9239,9241,9257,9277,9281,9283,9293,9311,9319,9323,9337,9341,9343,
9349,9371,9377,9391,9397,9403,9413,9419,9421,9431,9433,9437,9439,9461,9463,9467,9
473,9479,9491,9497,9511,9521,9533,9539,9547,9551,9587,9601,9613,9619,9623,9629,96
31,9643,9649,9661,9677,9679,9689,9697,9719,9721,9733];

function waiter(number, q) {

// // console.log(number);
let answers = [];
let aNo = [];

for(var rounds = 0; rounds < q; rounds++){

// console.log(rounds);

aNo = [];
let bYes = [];
let tempPrime = primes[rounds];
let tempNum = number.slice();

for(var i = 0; i < number.length; i++){

let el = tempNum.pop();
// console.log(el);

if(el % tempPrime === 0){


bYes.push(el)
}

if(el % tempPrime !== 0){


aNo.push(el)
}

// end of for loop i


}

// console.log(aNo);
// console.log(bYes);

while(bYes.length !== 0){


answers.push(bYes.pop())
}

number = aNo;

// end of FOR rounds que


}

// console.log(aNo);
// console.log(answers);
// console.log(number);

while(aNo.length !== 0){


answers.push(aNo.pop())
}

return answers;

// ! end of the function


}

let arr1 = [2,3,4,5,6,7];


let q1 = 3; // 2,4,5,3,5,7

let arr2 = [3, 4, 7, 6, 5]; // 4, 6, 3, 7, 5


let q2 = 1;
waiter(arr2, q2)
Stock Maximize

Key:

> set highest to Last element in the array


> iterate starting from Second last element in the array and work backwards till I hit zero
> Rule: if iteration is smaller than Highest, then profit = profit + highest - iteration; else set
iteration to highest
> No idea why this works, so learn off by heart
> here is video: https://youtu.be/N2kNUhXKq5c

function stockmax(prices) {

let profit = 0;
let highest = prices[prices.length-1];

for(var i = prices.length-2; i >= 0; i--){

let dayPrice = prices[i];


// console.log(dayPrice);

if(dayPrice < highest){


profit = profit + highest - dayPrice;
} else {
highest = dayPrice;
}

// end of FOR loop i


}

// console.log(profit);
return profit;

}
let p1 = [5,3,2]; // 0
let p2 = [1,2,100]; // 197
let p3 = [1,3,1,2]; // 3

stockmax(p3);

Works but bit too slow:

function stockmax(prices) {

let numberOfShares = 0;
let totalSpent = 0;
let profit = 0;

for(var i = 0; i < prices.length; i++){

let tempArr = prices.slice(i, prices.length).sort((a,b)=> b-a);


let highest = tempArr[0];

let dayPrice = prices[i];


// console.log(dayPrice);

if(dayPrice < highest){


numberOfShares++
totalSpent = totalSpent + dayPrice;
}

if(dayPrice === highest){


profit = profit + dayPrice * numberOfShares - totalSpent;
numberOfShares = 0;
totalSpent = 0;
}

// console.log(highest);
// end of FOR loop i
}

// console.log(numberOfShares);
// console.log(totalSpent);
// console.log(profit);

return profit;

let p1 = [5,3,2]; // 0
let p2 = [1,2,100]; // 197
let p3 = [1,3,1,2]; // 3

stockmax(p3);

Simple Text Editor

Key:

> Buffer / Str holder must be populated with strings BEFORE the transformation takes place, so
we can undo it via .pop()
> you can convert INPUTS into an array via: input = input.split('\n')
> Make sure to remove first element, cause it is just a number of items in the array, so you don’t
really need it input.splice(0, 1);
> watch this video:

function processData(input) {

// input = input.split('\n')
input.splice(0, 1);

// console.log(input);

// let final = 'abcde';


let final = "";
let finalBuffer = [final];

for (var i = 0; i < input.length; i++) {


let el = input[i];

if (el.length > 1) {
// // console.log('here')

let elSplit = el.split(" ");


let ops = elSplit[0];
// console.log("ops: ", ops);

let item = elSplit[1];


// console.log("item: ", item);

if (ops === "1") {


finalBuffer.push(final);
final = final + item;

if (ops === "2") {


finalBuffer.push(final);
final = final.substring(0, final.length - item);

if (ops === "3") {


console.log(final.substring(item - 1, item));
}
} else {

final = finalBuffer.pop();
}

// end of FOR LOOP I


}
// console.log(final);
// console.log(finalBuffer);

// ! end of function
}

let arr1 = ["8", "1 abc", "3 3", "2 3", "1 xy", "3 2", "4", "4", "3 1"]; // c y a

let arr2 = ["7", "1 fg", "3 6", "2 5", "4", "3 7", "4", "3 4"]; // f g d //
note here starting state of string is: abcde

processData(arr1);

Equal Stacks

Key:

> Create an array from arguments, call this mainArry


> Create second array that will hold the SUM of individual arrays (i.e. sumArray) that are in the
mainArray
> do infinite iteration for-loop if Every element in the sumArray is the same, then BREAK out of
the for loop
> on every iteration we want to check the INDEX of the biggest number in the sumArray, this will
tell me which array from the mainArray needs to be .shifted(), i.e. first element is being
removed
> when I find the MAX element, I need to shift the mini array from the MAIN array AND minus
the shifted number from the SUM array, because this saves time trying to recreate the sum
array from the new mainArray that has now shifted
> do this till all elements in the SUM array are the same
> return sumArray index 0, cause at this point all elements in the sum array are the same
> see this video: https://youtu.be/6po8ugf7F8M

function equalStacks(h1, h2, h3) {

let mainArr = [h1,h2,h3];


// console.log("mainArr: ", mainArr);
let sumArr = mainArr.map(el=> el.reduce((acc,value)=> acc+value));
// // console.log("sumArr: ", sumArr);

for(var i = 0; i < Infinity; i++){

if(sumArr.every(el=> el === sumArr[0])){


// console.log('all are equal');
break;
}

// console.log("sumArr: ", sumArr);


// console.log("mainArr: ", mainArr);

let findMax = Math.max(...sumArr);


// console.log("findMax: ", findMax);

let maxIndex = sumArr.indexOf(findMax);


// console.log("maxIndex: ", maxIndex);

let a = sumArr[maxIndex];
// console.log(a);

sumArr[maxIndex] = sumArr[maxIndex] - mainArr[maxIndex].shift();

let b = sumArr[maxIndex];
// console.log(b);

// end of FOR LOOP i


}

return sumArr[0]

// ! end of the function


}
let h1a = [3, 2, 1, 1, 1];
let h2a = [4, 3, 2];
let h3a = [1, 1, 4, 1]; // should be 5

let h1b = [1,2,1,1];


let h2b = [1,1,2];
let h3b = [1,1]; // should be 2

equalStacks(h1a, h2a, h3a);

Works, but too slow:

function arraySum(arr){
return arr.reduce((acc,value)=> acc + value)
}

function unshiftAndRecordHeight(arr){
let temp = [];
for(var i = 0; i<= arr.slice().length+1; i++){
temp.push(arraySum(arr));
// console.log(arr);
arr.shift();
}
// console.log(temp);
return temp;
}

function findDubplicateInArrays(...args){
let holder = [...args];
let holderLength = holder.length;
let flatHolder = holder.flat(10).sort((a,b)=> a-b);
let duplicate = [];

flatHolder.forEach(el=> {
let count = 0;

flatHolder.forEach(el2=> {
if(el === el2){
count++
if(count >= holderLength){
duplicate.push(el)
}
}

})

})

return Array.from(new Set(duplicate));

function equalStacks(h1, h2, h3) {

if(h1[0] === h2[0] && h1[0] === h3[0]){


return h1[0]
}

let a = unshiftAndRecordHeight(h1);
// console.log("a: ", a);

let a2 = unshiftAndRecordHeight(h2);
// console.log("a2: ", a2);

let a3 = unshiftAndRecordHeight(h3);
// console.log("a3: ", a3);
let test = findDubplicateInArrays(a,a2,a3).sort((a,b)=> b-a);
// console.log("test: ", test);

if(test.length < 1){


return 0
}

return test[0];

// ! end of the function


}

let h1a = [3, 2, 1, 1, 1];


let h2a = [4, 3, 2];
let h3a = [1, 1, 4, 1]; // should be 5

let h1b = [1,2,1,1];


let h2b = [1,1,2];
let h3b = [1,1]; // should be 2

equalStacks(h1b, h2b, h3b);

The Coin Change Problem

Keys:

● > HAVE TO WATCH THIS VIDEO: You can NOT solve it without understanding
algorithm that solve it, its a MATH PROBLEM, you are only writing Logic for it:
https://www.youtube.com/watch?v=L27_JpN6Z1Q
○ Extra rules: NOTE: if you are in row 5, you are copying row 4... previous rows 3,2,1 do
NOT matter
○ The answer is the last row and last column number, that is in the corner
● > To solve the first line: i.e. if i = 0; then if coin > j insert 0 into the array; if else: if
J % coin === 0 (i.e. no remainder), then insert 1 into the array, if NOT then insert 0 into
the array
● > NOTE: why at J index 0 we insert 1’s, because there is only 1 way to make a Zero,
that is to NOT select a single coin
● > Here is me solving it via a video: https://youtu.be/zds1JGmQCiw

function getWays(n, c) {

let final = [];

for(var i = 0; i < c.length; i++){

let el = c[i];
// console.log(el);

let temp = [1, ...Array.from({length: n}, ()=> -9)];


// console.log("temp: ", temp);

final.push(temp);

for(var j = 1; j <= n; j++){

// console.log(j);
// console.log(i)

// solve the first line


if(i===0){

// console.log('here');

if(el > j){


temp[j] = 0;
}

if(el <= j){


temp[j] = j % el === 0 ? 1 : 0
}

} else {
// console.log('here')

if(el > j){


temp[j] = final[i-1][j]
}

if(el <= j){


temp[j] = final[i-1][j] + temp[j-el]
}

// end of J loop
}

// console.log(temp);
final[i] = temp;

// end of el, i loop


}

// console.log(final);
let allDone = final[c.length-1][n];

// console.log("allDone: ", allDone);


return allDone;

// ! end of function
}

let n1 = 3;
let arr1 = [8,3,1,2]; // 3

let n2 = 4;
let arr2 = [1,2,3]; // 4

getWays(n1, arr1)

Two Characters

Key:

> To filter out allPossible strings use this:


> find ALL unique characters in the string = uniqueCharacterArray
>convert original string into array = orgStrArr
> Create 2 x for loops that will iterate throught Unique Charaters array; so we should
have element1 which is uniqueCharacterArray[i] and then another one:
uniqueCharacterArray[j]
> then use filter on the orgStrArr with condition: if orgStrArr-element is equal to
uniqueCharacterArray[i] OR uniqueCharacterArray[j]. Then return it
> Now we have list of ALL possible combination of strings that consists of 2 characters
> Now filter out ALL strings where 2 unique characters go side by side… i.e. aa bb cc aaaa
etc. (allPossibleStr.indexOf(el1+el1) === -1 && allPossibleStr.indexOf(el2+el2) === -1) so if
we FIND an index of ‘aa’ for example AND ‘bb’ then we remove it. This will leave only Valid
Strings
> finally check the string lengths and select the biggest one: longest = Math.max(longest,
allPossibleStr.length)
>NOTE: you also need STARTING condition where is s.length === 1, return 0, for test 1 to pass
> here is video on this: https://youtu.be/_6NCVLT5WPs

function alternate(s) {

if(s.length === 1){


return 0
}

let uniqueChar = [...new Set(Array.from(s))];


// console.log("uniqueChar: ", uniqueChar);

let sArr = Array.from(s);


// console.log("sArr: ", sArr);

// let validStrings = [];

let longest = 0;

for(var i = 0; i< uniqueChar.length; i++){

let el1 = uniqueChar[i];


// console.log(el1);

for(var j = 0; j < uniqueChar.length; j++){

let el2 = uniqueChar[j];


// console.log(el2);

let temp = sArr.filter(filteredEl=> {


return filteredEl === el1 || filteredEl === el2
}).join('');

// console.log("temp: ", temp);

if(temp.indexOf(el1+el1) === -1 && temp.indexOf(el2+el2) === -1){


// console.log(temp);

longest = Math.max(longest, temp.length);

// end of for loop j


}
// end of for Loop i
}

// // console.log(validStrings)

// console.log(longest);
return longest;

// ! end of function
}

let s1 = 'beabeefeab';
alternate(s1);

The Maximum Subarray

Key:

● > To get Max possible from subarrays that are sliced sub arrays:
https://en.wikipedia.org/wiki/Maximum_subarray_problem / Empty subarrays admitted
● > To get the Max possible from any numbers: maxPossible = Math.max(maxPossible,
subArray.reduce((acc,el)=> acc+el))
● > Add 2 starting conditions: that if ALL elements in array are negative then return
Largest element from the array …. If all elements are Positive then return arr.reduced
accumulated value for both options subMax and maxPossible
● > Return must be [subsequentMax, maxPossible]
● > See video: https://youtu.be/PzA2eFXDla0

function maxSubarray(arr) {

if(arr.every(el=> el < 0)){


// console.log('all negative');
let sorted = arr.sort((a,b)=> b-a);
return [sorted[0], sorted[0]]

if(arr.every(el=> el > 0)){


// console.log('all are positive');
let reduced = arr.reduce((acc,value)=> acc+value);
// console.log("reduced: ", reduced);
return [reduced, reduced]

let best = 0;
let current = 0;
let max = 0;

arr.forEach(el=> {
// console.log(el);

current = Math.max(0, current + el);


best = Math.max(best, current);

max = Math.max(max, max+el)

})

// console.log(best);
// console.log(max);

return [best, max];

let arr1 = [-1,2,3,-4,5,10]; // 16 20 pss


let arr2 = [1,2,3,4]; // 10 10 pass
let arr3 = [2, -1, 2, 3, 4, -5]; // 10 11 pass
let arr4 = [-2, -3, -1, -4, -6]; // -1 -1
maxSubarray(arr2);

Works but fails test 1, cause too slow:

function maxSubarray(arr) {

let sorted = arr.slice().sort((a,b)=> b-a);


// console.log("sorted: ", sorted);
let best = 0;
let current = 0;
let maxPossible = 0;

if(arr.every(el=> el > 0)){


// console.log('all positive')
return [arr.reduce((acc,value)=> acc+value), arr.reduce((acc,value)=>
acc+value)]
}

if(arr.every(el => el < 0)){


// console.log('all negative');
return [sorted[0], sorted[0]]
}

for(var i =0; i < arr.length; i++){


current = Math.max(0, current + arr[i]);
best = Math.max(best, current);

let subArray = sorted.slice(0, sorted.length-i);


// console.log("subArray: ", subArray);

maxPossible = Math.max(maxPossible, subArray.reduce((acc,el)=> acc+el))


// end of for loop
}

// console.log(best);
// console.log(maxPossible);

return [best, maxPossible]

let arr1 = [-1,2,3,-4,5,10]; // 16 20 pss


let arr2 = [1,2,3,4]; // 10 10 pass
let arr3 = [2, -1, 2, 3, 4, -5]; // 10 11 pass
let arr4 = [-2, -3, -1, -4, -6]; // -1 -1
maxSubarray(arr4);

Chief Hopper

Key:

> Both equations in the description can be replaced by this single equation, which ELIMINATES
the need to check if energy is higher or lower than the building: Math.ceil((remaining + el)/2);
> To avoid brute forcing numbers 1 by 1, just start from the END OF THE ARRAY, and apply the
Math.ceil((remaining + el)/2); formula, whatever is left, is the minimum needed to pass all
buildings; note since the Magic Formula - Math.ceil((remaining + el)/2) does NOT require us to
check if the energy is bigger than the building, this works.

function chiefHopper(arr) {

let remaining = 0;

arr.reverse().forEach(el=> {
remaining = Math.ceil((remaining + el)/2);
})

// console.log(remaining);
return remaining

// ! end of function
}

let arr1 = [3, 4, 3, 2, 4]; // 4


let arr2 = [4, 4, 4]; // 4
let arr3 = [4]; // 2

chiefHopper(arr1);

Passes, but too slow for 4 tests:

function chiefHopper(arr) {

let energy = 0;
let final = 0;

for (var loop = 0; loop <= Infinity; loop++) {


console.log(loop);
energy = loop;
for (var i = 0; i < arr.length; i++) {
let el = arr[i];

if (energy < el) {


energy = energy - (el - energy);
} else {
energy = energy + (energy - el);
}

// end of for loop


}
if (energy >= 0) {
final = loop;
break;
}

// end of for LOOP called loop


}

console.log(energy);
console.log(loop);
return loop;

// ! end of function
}

let arr1 = [3, 4, 3, 2, 4]; // 4


let arr2 = [4,4,4]; // 4
let arr3 = [4]; // 2

chiefHopper(arr1);

Mock Test: Truck Tour

Keys:

> Note: THERE IS NO CIRCLE, you can only go 1 way, from left to right
> There is ALWAYS a solution (so we can ignore previous indexes)
> We are basically looking for the first INDEX at which he can DRIVE FOREVER UNTIL THE
END OF THE ARRAY (i.e. PETROL IS ALWAYS POSITIVE AND BIGGER THAN ZERO), we
do NOT need to do the circle, we just need him to drive forever till the end of the array
> (other way to explain it) We need to find FIRST INDEX at which: fuel is positive Everytime
we arrive at a new petrol station, until we fully complete the length of the array. I.e. curPetrol =
curPetrol + fuelAtPump - fuelRequired to drive to the next station is ALWAYS positive AFTER
that index, so we can keep going forever till the end of the array
> see video with explanation: https://youtu.be/LbqoDXqg4ME
function truckTour(petrolpumps) {

let curPetrol = 0;
let index = 0;

for(var i = 0; i < petrolpumps.length; i++){

// petrol at the pump


curPetrol = curPetrol + petrolpumps[i][0];

// petrol at arrival to the next petrol station


curPetrol = curPetrol - petrolpumps[i][1];

console.log(curPetrol);

if(curPetrol < 0){


curPetrol = 0;
index = i + 1;
}

return index;

// ! end of function
}

let arr1 = [[1,5], [10,3], [3,4]];


truckTour(arr1)
_______________________

Week 10:

Lego Blocks - OUT OF MY LEAGUE

Overkill for Front End, copy and paste and move on:

const modulo = Math.pow(10, 9) + 7;


const bimodulo = BigInt(modulo)
function mod(num) {
return num < 0 ? (num % modulo) + modulo : num % modulo;
}
function bigmod(num) {
return num < 0 ? (num % bimodulo) + bimodulo : num % bimodulo;
}

function legoBlocks(n, m) {
// Write your code here

let singleRow = [0n, 1n, 2n, 4n, 8n]

let singleMLine;

if (m <= 4) {
singleMLine = singleRow[m];
} else {
let length = 5;
while (length <= m) {
singleMLine = 0n;
for (let i = singleRow.length - 4; i < singleRow.length;
i++) {
singleMLine += singleRow[i]
}
singleMLine = bigmod(singleMLine);
singleRow.push(singleMLine);
length ++
}
}

let nRow = Array.from(singleRow);

for (let rowCount = 2; rowCount <= n; rowCount++) {


for (let i = 1; i < nRow.length; i++) {
nRow[i] = bigmod(nRow[i] * singleRow[i]);
}
}

let nRowSolid = Array(singleRow.length);


nRowSolid[0] = 0n;
nRowSolid[1] = 1n;

for (let colCount = 2; colCount <= m; colCount++) {


let count = 0n;
for (let split = 1; split < colCount; split++) {
count += bigmod(nRowSolid[split] * nRow[colCount -
split]);
}
nRowSolid[colCount] = bigmod(nRow[colCount] - count);
}

return Number(bigmod(nRowSolid[m]))
}

Weighted Uniform Strings


Keys:

> fastest way to slice the strings into all Groups is with this regex: let allGroupsArr =
s.match(/([a-z])\1*/g);
> to find the Weight of the character use alphabet index + 1: let alphabet =
"abcdefghijklmnopqrstuvwxyz";
> To populate allWeightsArray, go through each element in the allGroupsArr, get the weight of
the first character, e.g. A then use a for…loop to find out how many A’s are there in each
iteration of allGroupsArr and push weight * (i+1) into the allWeightsArr;
> finish off with mapping throught Queries and finding out if
allWeightsArr.indexOf(elementFromQuery) if it is found return Yes, if not, return No
> Watch the video:

function weightedUniformStrings(s, queries) {

let alphabet = "abcdefghijklmnopqrstuvwxyz";

// extract all letter groups


let allGroupsArr = s.match(/([a-z])\1*/g);
// console.log(allGroupsArr);

// itterate throught letter group and create an array with ALL weights

let allWeightsArr = [];

allGroupsArr.forEach(el=> {
let weight = alphabet.indexOf(el[0])+1;
// console.log("weight: ", weight);

for(var i = 0; i < el.length; i++){


allWeightsArr.push(weight * (i+1))
}
});

// map throught the queries and see if they exist in allWeightsArr return YES
if found or NO if not found
let final = queries.map(el=> {
return allWeightsArr.indexOf(el) > -1 ? 'Yes' : 'No'
});
// console.log("final: ", final);
return final;

// ! end of the function


}

let s1 = "abbcccdddd";
let q1 = [1, 7, 5, 4, 15];
weightedUniformStrings(s1, q1);

Works but fails time complexity and SUPER big numbers:

function weightedUniformStrings(s, queries) {


let arr1 = s.split("");
// console.log("arr1: ", arr1);

let unique = [...new Set(arr1)];


// console.log("unique: ", unique);

let temp = [];

for (var i = 0; i < unique.length; i++) {


let el = unique[i];
// console.log(el);

let repeatCount = 1;

for (var j = i; j < arr1.length; j++) {


let el2 = arr1[j];
// console.log(el2);
let test = el === el2;
// console.log(test);

if (test) {
temp.push(el.repeat(repeatCount));
repeatCount++;
}
}

// console.log("-----------");

// end of for loop i


}

// console.log("-----------");
// console.log(temp);

// NOW SOLVE THE WEIGHT TABLE

let alphabet = 'abcdefghijklmnopqrstuvwxyz';

let wghtArr = temp.map(el=> {

let test1 = el.split('');


// console.log("test1: ", test1);

let temp = 0;

test1.forEach(el1=> {
temp = temp + (alphabet.indexOf(el1)+1);

})

return temp;

// end of map
});
// console.log(wghtArr);

// final arr

let finalArr = queries.map(el=> {


return wghtArr.indexOf(el) !== -1 ? 'Yes' : 'No'
});

// console.log(finalArr);

return finalArr;

// ! end of the function


}

let s1 = "abbcccdddd";
let q1 = [1, 7, 5, 4, 15];
weightedUniformStrings(s1, q1);

Permutation game - OUT OF MY LEAGUE

function permutationGame(arr) {
const memo = {}
const inc = arr => arr.every((v, i, a) => i === a.length - 1 || a[i] < a[i + 1] )
function rec(arr) {
let key = arr.join('|')
if (memo[key]) return memo[key]
if (inc(arr)) return memo[key] = true
for (let idx = 0; idx < arr.length; idx++)
if (rec(arr.slice(0, idx).concat(arr.slice(idx + 1))))
return memo[key] = false

return memo[key] = true


}

return rec(arr) ? 'Bob' : 'Alice'

QHEAP1 - OUT OF MY LEAGUE - (note copy and paste the


WHOLE data)

class MinHeap {
constructor() { this.h = [] }
_parent = (i) => i ? Math.floor((i-1)/2) : null

peek = () => this.h[0]

add(x) {
let h = this.h
h.push(x)
let i = h.length - 1
let p = this._parent(i)
while (p !== null && x < h[p]) {
h[i] = h[p]
h[p] = x
i = p
p = this._parent(i)
}
}

remove(x) {
let h = this.h
let i
for (let j = 0; j < h.length; j++)
if (h[j] == x) i = j
x = h.pop()
if(i == h.length) return
h[i] = x
let p = this._parent(i)
while (p !== null && h[p] > x) {
h[i] = h[p]
h[p] = x
i = p
p = this._parent(i)
}
let c = this.minChild(i)
while (c !== null && h[c] < x) {
h[i] = h[c]
h[c] = x
i = c
c = this.minChild(i)
}
}

minChild(i) {
let h = this.h
let l = i * 2 + 1
let r = l + 1
if (l >= h.length) return null
if (r >= h.length) return l
return h[l] < h[r] ? l : r
}
}

function processData(input) {
let h = new MinHeap()
let lines = input.split('\n')
lines.shift()
for(let l of lines) {
let [q, p] = l.split(' ')
if (q == 1) h.add(+p)
else if (q == 2) h.remove(+p)
else if (q == 3) console.log(h.peek())
}
}
process.stdin.resume();
process.stdin.setEncoding("ascii");
_input = "";
process.stdin.on("data", function (input) {
_input += input;
});

process.stdin.on("end", function () {
processData(_input);
});

Largest Rectangle

Key:

> result = 0;
> (outer loop) first for loop does up till H.length -> it is standard forEach loop and sets var
Width to 1 from start + has EL1 in it
> outer loop always starts width with 1, because we are checking if buildings to the Left and
Right can be used to construct the rectangle
> (inner loop 1 - check buildings on right) inside we nest 2 more for loops: firs goes from i+1,
and has EL2 in it… if EL1 > EL2, we break this loop, else we add Width + 1;
> (inner loop 2 - check buildings on left) another loop inside the Outer loop, checks to see if x =
i - 1; and we are working towards x >= 0 here we also have EL2, if EL1 > EL2, we break; if not
we construct and add Width + 1;
> at the end of the outer loop we do: result = Math.max(result, EL1 * width)
> we repeat the outerloop till we get the biggest rectangle possible
> NOTE: we DO NOT need to use ALL buildings, we just need to find the biggest rectangle
> Watch the video: ???

function largestRectangle(h) {

let result = 0;

for(let i = 0; i < h.length; i++){

let el1 = h[i];


// console.log("el1: ", el1);
let w = 1;

for(let j = i+1; j< h.length; j++){

let el2 = h[j];


// console.log(el2);

if(el1 > el2){


// console.log('here')
break;
}

// console.log('here')
w = w + 1
// console.log(w)

// for loop j
}

for(let x = i - 1; x >= 0; x--){

// console.log(x);

let el2 = h[x];


// console.log(el2);

if(el1 > el2){


// console.log('here')
break;
}
// console.log('here');
w = w + 1
// console.log(w)

// end of for loop j 2


}

// console.log(w);
// console.log(w*el1);
result = Math.max(result, el1 * w);
// console.log(result);
// for loop i
}

return result;

// ! end of a function
}

let h1 = [1,2,3,4,5];
let h2 = [11, 11, 10, 10, 10];
let h3 = [11, 11, 12, 13, 10];
largestRectangle(h3);

Jesse and Cookies - second tests are out of my league

const QHeap = (a) => {


const arr = [...a];
const swap = (i, j) => [arr[i], arr[j]] = [arr[j], arr[i]];
const getParentIndex = (index) => Math.floor(index / 2);
const getChildsIndexes = (index) => [index * 2, index * 2 + 1];
const getMinChildIndex = (index) => {
const childs = getChildsIndexes(index);
return arr[childs[0]] < arr[childs[1]] ? childs[0] : childs[1];
};
const shiftDown = (index) => {
let ci = index;
let minChildIndex = getMinChildIndex(ci);
while(arr[minChildIndex] < arr[ci]) {
swap(ci, minChildIndex);
ci = minChildIndex;
minChildIndex = getMinChildIndex(ci);
}
};
const shiftUp = (index) => {
let ci = index;
let pi = getParentIndex(ci);
while(arr[pi] < arr[ci]) {
swap(pi, ci);
ci = pi;
pi = getParentIndex(ci);
}
};
const removeTop = () => {
if (arr.length === 1) return arr.pop();
const last = arr.pop();
const top = arr[0];
arr[0] = last;
shiftDown(0);
return top;
};
const update = (index, val) => {
const prev = arr[index];
arr[index] = val;
prev > val ? shiftUp(index) : shiftDown(index);
}

for (let i = Math.floor(arr.length / 2); i >= 0; --i) {


shiftDown(i);
}

return {
removeTop,
update,
arr,
}
}

function cookies(k, A) {
const h = QHeap(A);
let iters = 0;
while(h.arr[0] < k) {
if (h.arr.length < 2) {
return -1;
}
const least = h.removeTop();
h.update(0, least + h.arr[0] * 2);

iters += 1;
}

return iters;
}

Works, but too slow:

function cookies(k, A) {

let tempArr = A.slice();


let final = 0;

for (var i = 0; i < 1000000; i++) {

// get cookies to mix


tempArr.sort((a, b) => a - b);
// console.log("tempArr: ", tempArr);
let el1 = tempArr[0];
let el2 = tempArr[1];

// make new cookie


let newCookie = el1 + el2 * 2;
// console.log("newCookie: ", newCookie);

// remove first 2 index from tempArr and insert the new cookie
tempArr = tempArr.slice(2, tempArr.length);
tempArr.unshift(newCookie);

// console.log(tempArr);
if(tempArr.every(el=> el >= k)){
final = i+1;
break;
}

if(tempArr.length ===1){
if(tempArr[0] < k){
final = -1
}
}

// end of for loop i


}

console.log(final);
return final;

// ! end of function
}

let k1 = 9;
let a1 = [2, 7, 3, 6, 4, 6];

let k2 = 7;
let a2 = [1,2,3,9,10,12];

let k3 = 200;
let a3 = [5,6,7];

cookies(k3, a3);

Hackerland Radio Transmitters


Keys:

> Video with explanation 1 - basic logic (do NOT spend too much time here):
https://www.youtube.com/watch?v=1JM1wbu6xtg
> Video with explanation 2 - MAIN ONE (this one is the actual solution):
https://www.youtube.com/watch?v=9LVzFm9L95g
> Sort the houses array
> create a global variable i
> create a while loop that is OUTER loop, that will go till i < housesArr.length;
> on every OUTER while loop iteration, we add +1 to the Transmitors places count;
> first find the MID point (i.e. where we will build the transmitter): midPoint = housesArr[i]+
transmittersRange; then create a while loop that will increase i by 1, until houses[i] <=
midPoint && i < houses.length;... NOTE: I have to have i < houses.lenght; otherwise it will
keep going forever;
> after this loop, I need to do i = i -1; because it itterates 1 more than it should;
> after this I need to find lastHouse, i.e. the transmitter coverage between midPoint and
additional transmitter range; so lastHouse = houses[i] + transmitterRange; (remember, i has
now changed, so houses[i] IS THE midPoint); … when we add exactly the same loop again,
only go till lastHouse, as oppose to midPoint… so just copy the while loop from midPoint
and replace midPoint with lastHouse;
> finally at the end of the function return transmitterCount;

function hackerlandRadioTransmitters(houses, transmitterRange) {

houses.sort((a,b)=> a-b);
console.log(houses);

let transmitterCount = 0;
let i = 0;

while(i < houses.length){

transmitterCount++;

let midPoint = houses[i] + transmitterRange;


console.log("midPoint: ", midPoint);

while(i<houses.length && houses[i] <= midPoint){


i++
// console.log(houses[i]);
// console.log(i);
}

i--; // because it itterated 1 more than it should have


console.log(i);

let lastHouse = houses[i] + transmitterRange;


console.log("lastHouse: ", lastHouse);

while(i<houses.length && houses[i] <= lastHouse){


i++
}

console.log(i);

// end of first while loop


}

console.log(transmitterCount);
return transmitterCount;

// ! end of function
}

let arr1 = [1, 2, 3, 4, 5];


let n1 = 1; // 2 pass

let arr2 = [7, 2, 4, 6, 5, 9, 12, 11];


let n2 = 2; // 3 pass

let arr3 = [9, 5, 4, 2, 6, 15, 12];


let n3 = 2; // 4 pass

let arr4 = [2,2,2, 2, 1, 1, 1, 1]; // 1 pass


let n4 = 2;

let arr5 = [9, 5, 4, 2, 6, 15, 12, 17, 19];


let n5 = 2; // 4 pass
let arr6 = [7, 2, 3, 6, 5, 9, 12, 11];
let n6 = 2; // 3 pass

hackerlandRadioTransmitters(arr6, n6);

Nice solution, passes many tests, but I dunno - other tests are HUGE, so can’t figure out what
the issue is:

function hackerlandRadioTransmitters(arr, n) {

// HANDLE MULTIPLE houses at the same location with SET


arr = [...new Set(arr)];
// console.log(arr);

if(arr.length <= n){


// console.log('here')
return 1
}

let min = Math.min(...arr);


// console.log("min: ", min);

let max = Math.max(...arr);


// console.log("max: ", max);

let sorted = arr.sort((a, b) => a - b);


// console.log("sorted: ", sorted);

let road = [];

for (var i = 0; i <= max; i++) {


road.push(i + "x");
}

sorted.forEach((el) => {
road[el] = el + "H";
});

road = road.slice(min, max + 1);


// console.log(road);

// find the optimal build and slice

let count = 0;
let idx = 0;

// INFINITE LOOPS HERE


for (var loops = 0; loops < 10000; loops++) {

// break out of the main loop if we reached final element (this one
might not be necessary, cause we are checking)
if(idx === road.length-1){
// console.log('here');
count++;
break;
}

let el = road[idx];
// console.log(el);

if (el.includes("H")) {
// console.log("here");

let maxReach = idx + n;


// console.log("maxReach: ", maxReach);

for (var i = maxReach; i >= idx; i--) {


// console.log(i)
let el = road[i];
// console.log(el);

if (el.includes("H")) {
// console.log('here')
count++;
idx = i+n+1; // +1 cause we are chunking out
break;
}

// end of for loop i


}
} else {
// console.log('here')
idx = idx + 1;
}

// console.log(idx);
// console.log(count);

// break out of the main loop if we reached final element


if(idx > road.length-1){
// console.log('here');
break;
}

// ? end of for loop LOOPS


}

console.log(count);
return count;

// ! end of function
}

let arr1 = [1, 2, 3, 4, 5];


let n1 = 1; // 2 pass

let arr2 = [7, 2, 4, 6, 5, 9, 12, 11];


let n2 = 2; // 3 pass

let arr3 = [9, 5, 4, 2, 6, 15, 12];


let n3 = 2; // 4 pass

let arr4 = [2,2,2, 2, 1, 1, 1, 1]; /// this CAN NOT BE, because cities are
located at indexes
let n4 = 2;

hackerlandRadioTransmitters(arr4, n4);

Minimum Operations 4 - no JS available

Mock Test 1: Pairs

Keys:

> This video explains everything: https://www.youtube.com/watch?v=pkgNgMSPV4o


> Algorithm is called: Two Pointer approach
> Sort the array
> 3 variables: count, i and j = 0;
> while J < arr.length;
> arr[j] - arr[i] = difference
> if difference is = target increment i and j by 1 and count +1
> if difference is < target increment J
> if difference is > target increment I
> return count

function pairs(target, arr) {

arr.sort((a,b)=> a-b);
console.log(arr);

let i = 0;
let j = 0;
let count = 0;

while (j < arr.length){

let dif = arr[j] - arr[i];

if(dif === target){


count++;
j++;
i++;
} else if(dif < target){
j++
} else if(dif > target){
i++
}

// console.log(count);
return count;

// ! function end
}

let target1 = 1;
let arr1 = [1,2,3,4]; // 3

let target2 = 2;
let arr2 = [1,5,3,4,2]; // 3

let target3 = 3;
let arr3 = [1,2,3,4,7]; // 2

pairs(target3, arr3)

Passes most but fails 5, due to speed

function pairs(target, arr) {

arr.sort((a,b)=> a-b);

let count = 0;

for(var i = 0; i < arr.length; i++){

let el1 = arr[i];

let sliced = arr.slice(i, arr.length);


// console.log("sliced: ", sliced);

sliced.forEach(el2=> {
if(el2 - el1 === target){
count++
}
})

// end of for loop i


}

// console.log(count);
return count
// ! function end
}

let target1 = 1;
let arr1 = [1,2,3,4]; // 3

let target2 = 2;
let arr2 = [1,5,3,4,2]; // 3

pairs(target1, arr1)

Mock Test 2: Almost Sorted

Key:

● > There are NO hidden conditions and hiccups


● > Best video with explanation: https://www.youtube.com/watch?v=SyVUe7h4zho
● > HUGE: there can only be 1 pair that can be either swapped or reverted, because you
can only either swap or reverse 1 time, so you do NOT need to look for more than 1 pair
● > Have a sortedArr as a ‘tester’ array, I also created a helper function to check if 2
arrays are the same: return JSON.stringify(arr1)==JSON.stringify(arr2)
● > So find the LEFT element where arr[i] > arr[i+1] working forward from start of array,
save that index
● > Find the RIGHT element where arr[j] < arr[j-1] working backwards from end of array,
save that index
● > FIRST try to SWAP: tempArr1[leftIndex] = arr[rightIndex]; and
tempArr1[rightIndex] = arr[leftIndex]; then test to see if this new array is same as
SORTED array, then console.log(‘yes’) … next line: console.log(‘swap’, leftIndex+1,
rightIndex+1); REMEMBER RETURN, otherwise will move to next code
● > SECOND: try to reverse: let tempArr2Chunk = arr.slice(leftIndex, rightIndex+1); let
reverseArr = [...arr.slice(0, leftIndex), ...tempArr2Chunk.reverse(),
...arr.slice(rightIndex+1, arr.length) ]; … check to see if this new arr is same as
sortedArr; if yes then console.log(‘yes’) … next line: console.log(‘swap’, leftIndex+1,
rightIndex+1); REMEMBER RETURN, otherwise will move to next code
● > At the end return console.log(‘no’), which means there is no solution
function checkIfEqual(arr1, arr2){
return JSON.stringify(arr1)==JSON.stringify(arr2)
}

function almostSorted(arr) {

let sorted = arr.slice().sort((a,b)=> a-b);

let leftIndex = -1;


let rightIndex = -1;

for(var i = 0; i < arr.length; i++){

if(arr[i] > arr[i+1]){


leftIndex = i;
break;
}

// for loop i, end


}

for(var j = arr.length-1; j >= 0; j--){

// console.log(arr[j]);
// console.log(arr[j-1]);

if(arr[j] < arr[j-1]){


rightIndex = j;
break;
}

// end of for loop j


}

// console.log(leftIndex);
// console.log(rightIndex);
// try SWAP first
let tempArr1 = arr.slice();
// console.log(tempArr1);

tempArr1[leftIndex] = arr[rightIndex];
tempArr1[rightIndex] = arr[leftIndex];

// console.log(tempArr1);

if(checkIfEqual(sorted, tempArr1)){
console.log('yes');
console.log('swap', leftIndex+1, rightIndex+1);
return;
}

// try reverse second


let tempArr2Chunk = arr.slice(leftIndex, rightIndex+1);
// console.log("tempArr2Chunk: ", tempArr2Chunk);

let reverseArr = [...arr.slice(0, leftIndex), ...tempArr2Chunk.reverse(),


...arr.slice(rightIndex+1, arr.length) ];
// console.log("reverseArr: ", reverseArr);

if(checkIfEqual(sorted, reverseArr)){
console.log('yes');
console.log('reverse', leftIndex+1, rightIndex+1);
return
}

return console.log('no')

// ! end of function
}

let arr1 = [4,2]; // yes, swap 4 2


let arr2 = [3,1,2]; // no
let arr3 = [1, 5, 4, 3, 2, 6]; // yes reverse 2 and 5
let arr4 = [1,2,6,5,4,3,7,9]; // yes reverse 3 and 6
let arr5 = [1,2,6,4,5,3,7,8]; // yes swap 3 and 6

almostSorted(arr4);

_______________________

Week 11:

Queries with Fixed Length

Keys:

> iterate through queries array


> 2 variables max, min
> max = Math.max of arr slice of 0 to what every the query is, then assign this to MIN
> iterate through arr, starting with Query number
>CORE ALGO: if(arr[j] > max) then max = arrJ ELSE if(arr[j-QueryEl] === max) then MAX =
Math.max of arr.slice(j-queryEl+1, j+1);
> min = Math.max between min, max
> at the end of queries.forEach… push min into the finalArr;

function solve(arr, queries) {

let results = [];

for(var i = 0; i < queries.length; i++){

let el = queries[i];

let max = Math.max(...arr.slice(0, el));


// console.log("max: ", max);
let min = max;

for(let j = el; j < arr.length; ++j){

if(arr[j] > max){


// console.log('here')
max = arr[j];
} else if (arr[j-el] === max){
// console.log('here');
// let test = Math.max(arr.slice(j-el+1, j+1));
// console.log("test: ", test);
max = Math.max(...arr.slice(j-el+1, j+1))
}

min = Math.min(min, max);


// console.log(min);
// end of for loop j
}

results.push(min)

// end of for loop i


}

// console.log(results);

// ! end of function
}

let arr1 = [2,3,4,5,6];


let q1 = [2,3]; // 3,4

let arr2 = [1,2,3,4,5];


let q2 = [1,2,3,4,5];

let arr3 = [1,5,4,3,6];


let q3 = [2,3]; // 4,3 but produces 4,5 which is wrong

solve(arr3, q3);
Works but fails on time complexity:

function solve(arr, queries) {

let finalArr = [];

for(var i = 0; i < queries.length; i++){

let el = queries[i];
let tempArr = [];

for(var j = 0; j < arr.length-1; j++){

let temp1 = arr.slice().splice(j, el);


// console.log("temp1: ", temp1);

tempArr.push(Math.max(...temp1));

// break out of the loop, if I reach the END


if(temp1.includes(arr[arr.length-1])){
break;
}

// end of for loop j


}

// console.log(tempArr);
finalArr.push(Math.min(...tempArr));

// end of for loop i


}
// console.log(finalArr);
return finalArr;

// ! end of function
}

let arr1 = [2,3,4,5,6];


let q1 = [2,3]; // 3,4

let arr2 = [1,2,3,4,5];


let q2 = [1,2,3,4,5];

solve(arr2, q2);

Common Child

Keys:

> Watch this video: https://www.youtube.com/watch?v=jHGgXV27qtk


> This is called: https://en.wikipedia.org/wiki/Longest_common_subsequence_problem
> To deal with 1st row and col must be made out of zeros -> create array that is length+1 and
fill it with Zeros… then start Iterations from 1 on both for loops… finally, because we want to
start checking s1 and s2 with i-1 and j-1, because our Length is string+1; i.e. 6, but the actual
string is 5… so to get the correct letter we need i-1; otherwise we will be starting: HARRY with
A, BUT if we do i-1, we are starting with H… its dealing with the fact that array has 0 indexing,
BUT strings have 1 indexing in this problem
> outside of this, its exactly as Jenny in the video described

function commonChild(s1, s2) {

let len = s1.length;

let finalArr = Array.from({ length: len+1 }, () => Array.from({ length: len+1


}, () => 0));
// // console.log(finalArr);
for (var i = 1; i <= len; i++) {
// let el1 = s1[i];
// console.log(el1);

for (var j = 1; j <= len; j++) {


// let temp = Array.from({length: s2.length}, ()=> 0)

// let el2 = s2[j];


// console.log(el2);

// let diagnalValue = finalArr[i - 1][j - 1];


// console.log(diagnalValue);

// let upValue = finalArr[i - 1][j];


// console.log(upValue);

// let sideValue = finalArr[i][j - 1];


// console.log(sideValue);

// if elements are the same


if (s1[i-1] === s2[j-1]) {
// console.log('here')
finalArr[i][j] = 1 + finalArr[i - 1][j - 1];
} else {
finalArr[i][j] = Math.max(finalArr[i - 1][j], finalArr[i][j -
1]);
}

// if (el1 !== el2) {


// // console.log('here')
// finalArr[i][j] = Math.max(upValue, sideValue);
// }

// end for j loop


}

// end of i loop
}
// console.log('------------------------');
// console.log(finalArr);

// let longest = Math.max(...finalArr.flat(2));


// console.log("longest: ", longest);
return finalArr[len][len];

// ! end of fn
}

let str1a = "ABCDEF";


let str1b = "FBDAMN"; // 2 pass

let str2a = "ABCD";


let str2b = "ABDC"; // 3 pass

let str3a = "HARRY";


let str3b = "SALLY"; // 2 pass

let str4a = "SHINCHAN";


let str4b = "NOHARAAA"; // 3 pass

commonChild(str2a, str2b);

Works but need to refactor a bit:

function commonChild(s1, s2) {


s1 = "x" + s1;
s2 = "x" + s2;

let finalArr = Array.from({ length: s1.length }, () => []).map((el) =>


Array.from({ length: s1.length }, () => 0)
);
// // console.log(finalArr);

for (var i = 1; i < s1.length; ++i) {


let el1 = s1[i];
// console.log(el1);

for (var j = 1; j < s2.length; ++j) {


// let temp = Array.from({length: s2.length}, ()=> 0)

let el2 = s2[j];


// console.log(el2);

let diagnalValue = finalArr[i - 1][j - 1];


// console.log(diagnalValue);

let upValue = finalArr[i - 1][j];


// console.log(upValue);

let sideValue = finalArr[i][j - 1];


// console.log(sideValue);

// if elements are the same


if (el1 === el2) {
// console.log('here')
finalArr[i][j] = 1 + diagnalValue;
}

if (el1 !== el2) {


// console.log('here')
finalArr[i][j] = Math.max(upValue, sideValue);
}

// end for j loop


}

// end of i loop
}

// console.log('------------------------');
// console.log(finalArr);

let longest = Math.max(...finalArr.flat(2));


// console.log("longest: ", longest);
return longest;

// ! end of fn
}

let str1a = "ABCDEF";


let str1b = "FBDAMN"; // 2 pass

let str2a = "ABCD";


let str2b = "ABDC"; // 3 pass

let str3a = "HARRY";


let str3b = "SALLY"; // 2 pass

let str4a = "SHINCHAN";


let str4b = "NOHARAAA"; // 3 fails

commonChild(str4a, str4b);

Array Manipulation

Key:

> VooDoo algo:


> add K to arr[a]
> minus K from arr[b]
> iterate throught the resulting array using forEach and have 2 values that are global:
Accumulator and Result… accumulators adds all values in the array together, like Reduce
method… BUT at the end of the forEach iteration use Math.max(result, accumulator)
> return result at the end of the function
> NO IDEA WHY THIS WORKS, OR WHO FIGURED IT OUT

function arrayManipulation(n, queries) {

let arr = Array(n+1).fill(0);


// console.log("arr: ", arr);

for(let [a,b,k] of queries){


arr[a-1] = arr[a-1] + k;
arr[b] = arr[b] - k;
}

let acc = 0;
let result = 0;

arr.forEach(el=> {
acc = acc+el;
result = Math.max(result, acc)
})

// console.log(result);
return result;

// ! end of function
}

let n1 = 5; // length of the array


let queries1 = [ [ 1, 2, 100 ], [ 2, 5, 100 ], [ 3, 4, 100 ] ]; // number of
queries

arrayManipulation(n1, queries1);

Passes all, but TOO SLOW:

function arrayManipulation(n, queries) {

let finalArr = Array.from({length: n+1}, ()=> 0);


console.log("finalArr: ", finalArr);

for(var i = 0; i < queries.length; i++){


let a = queries[i][0];
console.log(a);
let b = queries[i][1];
console.log(b);
let k = queries[i][2];
console.log(k);

for(var j = a; j <= b; j++){


finalArr[j] = finalArr[j] + k;
}

// end of for loop


}

console.log(finalArr);
let finalMax = Math.max(...finalArr);
console.log("finalMax: ", finalMax);
return finalMax;

// ! end of function
}

let n1 = 5; // length of the array


let queries1 = [ [ 1, 2, 100 ], [ 2, 5, 100 ], [ 3, 4, 100 ] ]; // number of
queries

arrayManipulation(n1, queries1);

Highest Value Palindrome

Keys:
> Watch this video: https://www.youtube.com/watch?v=zeprQpwdCPA
> We are first checking: left and right values and moving towards the middle in a while loop…
if something does NOT match, we make the change and record that change in our Processed
array (i.e. this will tell us what INDEX has been changed) AND when we make a change we
decrement value of K - 1; because K tracks how many changes we can make, so we are
working backwards
>ones we created palindrome and made and recorded the changes in the Processed array, we
need to check if K > 0, because we can now make further changes
> so if K > 0 we reset taht values of our pointers i(left) and j(right)
> while i <= j AND k> 0 we run the new while loop
> if str[i] !== 9 we can make a change here
> we first check has ANY of the values either left or right been changed? If YES, we make 1
change, and set both str[i] and str[j] to 9 and K - 1; cause 1 change if NOT, we check if K
value is bigger than > 1, if so, we make str[i] and str[j] to 9 and K - 2, because we have now
made 2 changes.
> at the end of every while loop we i++; j = j - 1;
> on second while we have end condition that if i === j && k >=1 - i.e. we can still make 1
more change, then str[i] = 9; break; this is for test case 6, where there is middle value and
string is made up for 5 characters; because at this point we are in DEAD MIDDLE, so we need
to set this middle value to 9; we can do that by either str[i] = 9; OR str[j]=9 makes no
difference, since both i and j are dead middle at this stage
> finally, just return: s.join(‘’) and it works

function highestValuePalindrome(s, n, k) {

if (n === 1){
return k == 1 ? '9' : '-1'
}

let firstEl = s[0];

if(k===0 && [...s].every(el=> el===firstEl)){


console.log('here')
return s;
}

let i = 0;
let j = n-1;
s = Array.from(s, el=> Number(el));
console.log(s);

let processed = Array(n).fill(false);


console.log("processed: ", processed);

while(i <= j){

if(k===0){
return '-1'
}

if(s[i] > s[j]){


s[j] = s[i];
processed[j] = true;
k--;
}

if(s[i] < s[j]){


s[i] = s[j];
processed[i] = true;
k--;
}

i++;
j--;
// end of while loop 1
}

console.log(s);
console.log(processed);
console.log(k);

// now handle any remaining conditions

if(k > 0){


i = 0;
j = n-1;

while(i <=j && k > 0){

if(s[i] != 9){
if(processed[i] === true || processed[j] === true){
s[i]=9;
s[j]=9;
k--;
} else {
if(k > 1){
s[i]=9;
s[j]=9;
k = k - 2;
}
}
}

i++;
j--;

if(i===j && k >=1){


s[i]=9;
break;
}

// end of while loop 2


}

}
console.log(s.join(''));
console.log(processed);
console.log(k);

return s.join('')

// ! function end
}

let s1 = '3943';
let n1 = 4;
let k1 = 1; // 3993;

let s2 = '777';
let n2 = 3;
let k2 = 0;

highestValuePalindrome(s2,n2,k2);

Lily's Homework

Keys:

● > Watch this video: https://www.youtube.com/watch?v=W8oGaAEOeRU


● > I do NOT need to think about is ‘this the best swap possible’, because we are doing
ascending and descending, so one or the other way, will be the best way… so do NOT
need to think about them, just swap them around
● > I need to have a HASH table/MAP that will keep the current state of array in it, so I
map the ORIGINAL array to the HASH
● > then I iterate through original Array and compare it to SORTED array, if index values
match, then move to the next index if NOT then swap BOTH elements and update the
HASH first, then use HASH to update actual Array with new value and count++, i.e.
increment count by 1, because we did 1 swap… NOTE: I do NOT need to think about
restarting the iteration process, because we have now positioned smallest element first
and bigger element last, so we do NOT need to go back
● > Do this for ascending array and descending array
● > return the Smallest of the counts

function checkAscending(arr, doReverse=false){

let sorted = arr.slice().sort((a,b)=> a-b);


// console.log(arr)
// console.log("sorted: ", sorted);

if(doReverse){
sorted.reverse();
}

let hash = new Map();


arr.forEach((el, i)=> hash.set(el, i))
// console.log(hash);

let count = 0;

for(var i = 0; i < arr.length; i++){

// console.log(arr);

let elOrg = arr[i];


// console.log("elOrg: ", elOrg);
let elSorted = sorted[i];
// console.log("elSorted: ", elSorted);

if(elOrg === elSorted){


// console.log('here')
continue;
}

if(elOrg !== elSorted){


// console.log('here');

// search for position of both elements in the hash and swap them
both in Hash and in Arr
let hashSorted = hash.get(elSorted);
// console.log(hashSorted);
let hashOrg = hash.get(elOrg);
// console.log(hashOrg);

// swap hash
hash.set(elOrg, hashSorted);
hash.set(elSorted, hashOrg);

// swap the elements in the array, by mapping it to hash


arr[hash.get(elOrg)] = elOrg;
arr[hash.get(elSorted)] = elSorted;

count++

// end of for loop i


}

// console.log(hash);
// console.log(arr);
// console.log(count);
return count;

// end of check ascending


}
function lilysHomework(arr) {

let asc = checkAscending(arr.slice(), false);


let des = checkAscending(arr.slice(), true);

let min = Math.min(asc, des);


// console.log(min);

return min;

// ! end of function
}

let arr1 = [10,15,1,2,9,16,11];


let arr2 = [3,7,15,12];
lilysHomework(arr2);

Tree: Postorder Traversal - OUT OF MY LEAGUE

Tree: Preorder Traversal - OUT OF MY LEAGUE

Tree: Huffman Decoding - OUT OF MY LEAGUE

Mock Test: Connected Cells in a Grid - OUT OF MY LEAGUE

Keys:

> Watch this video: https://www.youtube.com/watch?v=VnWtjUO5Img


> Algo name is: DFS - Depth-first search - https://en.wikipedia.org/wiki/Depth-first_search

function countRegionCells(grid, row, col){


if(row < 0 || col < 0 || row >=grid.length || col >= grid[0].length){
return 0;
}

if(grid[row][col] === 0){


return 0;
}

let cellCount = 1;
grid[row][col] = 0;

for(var r = row-1; r < row+2; r++){

for(var c = col-1; c < col+2; c++){

if(r!==row || c!== col){


cellCount = cellCount + countRegionCells(grid, r,c)
}

// end of c loop
}

// end of r loop
}

return cellCount;

// ! end of countRegionCellsFn
}

function connectedCell(grid) {

let regionCellcount = 0;
let maxCellCounter = 0;
for(var row = 0; row < grid.length; row++){

console.log(row);

for(var col = 0; col < grid[0].length; col++){

if(grid[row][col] === 1){


regionCellcount = countRegionCells(grid, row, col);
maxCellCounter = Math.max(maxCellCounter, regionCellcount);
}

// end of col
}

// end of row
}

console.log(maxCellCounter);
return maxCellCounter;

// ! end of the function


}

let arr1 = [[1, 1, 0, 0], [0, 1, 1, 0], [0, 0, 1, 0], [1, 0, 0, 0]]; // 5
connectedCell(arr1);

You might also like