Solving JavaScript Algorithm Problems in HackerRank: Forming a Magic Square (Work In Progress)
Although I enjoy figuring out questions on LeetCode and HackerRank, there are times were I get stumped. This medium level question on HackerRank titled “Forming a Magic Square” is very tricky. Working alongside my other Flatiron colleagues, we ended up passing the two sample test cases. However, when submitting the code, we failed 18/23 test cases! How come? Well it’s better that I start off with the code that I worked on but first the word problem.
Problem: https://www.hackerrank.com/challenges/magic-square-forming/problem
We are given a 3x3 matrix where the numbers within the matrix must be the integers of 1–9. These integers may only be used once. This makes up the magic square because the summation of the numbers diagonally, horizontally, and vertically all equal to 15. This is only possible if the number 5 is in the middle of the matrix and the diagonal pairs are the even amounts ((2,8) & (4,6)). While the numbers that make up the inner-cross of the matrix are ((1,9) & (3,7)). It’s also good to note that this is because all these paired amounts equal to 10 and with 5 being in the center the total would result in 15.
Our Approach:
function formingMagicSquare(s) {
let n = s[0].length
let newArr = []
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
newArr.push(s[i][j])
}
}}
To get the length of the array, we needed to set n to equal to s[0].length. Then we create a new array called newArr. Next we wanted to iterate through the matrix and add each element to newArr. We iterate again in order to go one more level deeper to then push the element over to newArr.
Next we wanted to create another empty array to hold the changes that will be made for any number that is incorrect in our matrix. We titled this array as changes. And the result that we will be adding all the changes is titled appropriately as result. We wanted to then iterate towards the center of the matrix so that we can evaluate both ends of the matrix at the same time. If the value is changed, then we record that it was changed. For these cases we decided to go with using switch in order to list out all the case scenarios and check to see if the acceptable pairs are where they should be. Once we change the numbers that should not be in that spot on the matrix, we then calculated the absolute value difference between the amount before the change (beforeChange) and the newArr amount that we placed in it’s spot. We then push that over to our changes array and use the reduce method to add up all values in the array to come up with the sum of all the cost amounts that we changed in out matrix.
The Issue: Although we have taken to account all the possible correct pairs from the outer points of the matrix and setting the middle amount to 5, we did not think to write in our code that if in the event we have two of the same number on opposite ends of the matrix, return the pair only once.
If there is any advice on how I can better approach this problem, please feel free to contact me through the Slack:
Slack: Perezchristian1012
Our Answer (Work in progress):
function formingMagicSquare(s) {
// Length of array
let n = s[0].length
let newArr = []
// iterate through matrix, add each element to newArr
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
newArr.push(s[i][j])
}
}
// print all corner numbers (index: 0,2,6,8) (values: 2–8,4–6,8–2,6–4)
// candidate pairs
// (1,9)(9,1)
// (3,7)(7,3)
// (2,8)(8,2)
// (4,6)(6,4)
let changes = []
let result = 0
for (let i = 0; i < newArr.length; i++) {
// Iterate towards the center of matrix
// so we evaluate both ends at the same
// arr[0] — arr[8]
// arr[2] — arr[6]
// if pair value is changed, record that it was changed
// 4 9 2
// 3 5 7
// 8 1 5
// NOTE: Work on writing a dynamic code block to make changes in matrix as opposed to hardcoding if statements
switch (i) {
case 0: {
if (newArr[i] == 8) {
let beforeChange = newArr[8]
newArr[8] = 2
changes.push(Math.abs(beforeChange — newArr[8]))
}
if (newArr[i] == 2) {
let beforeChange = newArr[8]
newArr[8] = 8
changes.push(Math.abs(beforeChange — newArr[8]))
}
if (newArr[i] == 4) {
let beforeChange = newArr[8]
newArr[8] = 6
changes.push(Math.abs(beforeChange — newArr[8]))
}
if (newArr[i] == 6) {
let beforeChange = newArr[8]
newArr[8] = 4
changes.push(Math.abs(beforeChange — newArr[8]))
}
}
break;
case 1:
if (newArr[i] == 1) {
let beforeChange = newArr[7]
newArr[7] = 9
changes.push(Math.abs(beforeChange — newArr[7]))
}
if (newArr[i] == 9) {
let beforeChange = newArr[7]
newArr[7] = 1
changes.push(Math.abs(beforeChange — newArr[7]))
}
if (newArr[i] == 3) {
let beforeChange = newArr[7]
newArr[7] = 7
changes.push(Math.abs(beforeChange — newArr[7]))
}
if (newArr[i] == 7) {
let beforeChange = newArr[7]
newArr[7] = 3
changes.push(Math.abs(beforeChange — newArr[7]))
}
break;
case 2: {
if (newArr[i] == 8) {
let beforeChange = newArr[6]
newArr[6] = 2
changes.push(Math.abs(beforeChange — newArr[6]))
}
if (newArr[i] == 2) {
let beforeChange = newArr[6]
newArr[6] = 8
changes.push(Math.abs(beforeChange — newArr[6]))
}
if (newArr[i] == 4) {
let beforeChange = newArr[6]
newArr[6] = 6
changes.push(Math.abs(beforeChange — newArr[6]))
}
if (newArr[i] == 6) {
let beforeChange = newArr[6]
newArr[6] = 4
changes.push(Math.abs(beforeChange — newArr[6]))
}
}
break;
case 3: {
if (newArr[i] == 1) {
let beforeChange = newArr[5]
newArr[5] = 9
changes.push(Math.abs(beforeChange — newArr[5]))
}
if (newArr[i] == 9) {
let beforeChange = newArr[5]
newArr[5] = 1
changes.push(Math.abs(beforeChange — newArr[5]))
}
if (newArr[i] == 3) {
let beforeChange = newArr[5]
newArr[5] = 7
changes.push(Math.abs(beforeChange — newArr[5]))
}
if (newArr[i] == 7) {
let beforeChange = newArr[5]
newArr[5] = 3
changes.push(Math.abs(beforeChange — newArr[5]))
}
break;
}
case 4: {
let beforeChange = newArr[i]
newArr[i] = 5
changes.push(Math.abs(beforeChange — newArr[i]))
break;
}
case 5: {
if (newArr[i] == 1) {
let beforeChange = newArr[3]
newArr[3] = 9
changes.push(Math.abs(beforeChange — newArr[3]))
}
if (newArr[i] == 9) {
let beforeChange = newArr[3]
newArr[3] = 1
changes.push(Math.abs(beforeChange — newArr[3]))
}
if (newArr[i] == 3) {
let beforeChange = newArr[3]
newArr[3] = 7
changes.push(Math.abs(beforeChange — newArr[3]))
}
if (newArr[i] == 7) {
let beforeChange = newArr[3]
newArr[3] = 3
changes.push(Math.abs(beforeChange — newArr[3]))
}
break;
}
case 6: {
if (newArr[i] == 8) {
let beforeChange = newArr[2]
newArr[2] = 2
changes.push(Math.abs(beforeChange — newArr[2]))
}
if (newArr[i] == 2) {
let beforeChange = newArr[2]
newArr[2] = 8
changes.push(Math.abs(beforeChange — newArr[2]))
}
if (newArr[i] == 4) {
let beforeChange = newArr[2]
newArr[2] = 6
changes.push(Math.abs(beforeChange — newArr[2]))
}
if (newArr[i] == 6) {
let beforeChange = newArr[2]
newArr[2] = 4
changes.push(Math.abs(beforeChange — newArr[2]))
}
}
break;
case 7:
if (newArr[i] == 1) {
let beforeChange = newArr[1]
newArr[1] = 9
changes.push(Math.abs(beforeChange — newArr[1]))
}
if (newArr[i] == 9) {
let beforeChange = newArr[1]
newArr[1] = 1
changes.push(Math.abs(beforeChange — newArr[1]))
}
if (newArr[i] == 3) {
let beforeChange = newArr[1]
newArr[1] = 7
changes.push(Math.abs(beforeChange — newArr[1]))
}
if (newArr[i] == 7) {
let beforeChange = newArr[1]
newArr[1] = 3
changes.push(Math.abs(beforeChange — newArr[1]))
}
break;
case 8: {
if (newArr[i] == 8) {
let beforeChange = newArr[0]
newArr[0] = 2
changes.push(Math.abs(beforeChange — newArr[0]))
}
if (newArr[i] == 2) {
let beforeChange = newArr[0]
newArr[0] = 8
changes.push(Math.abs(beforeChange — newArr[0]))
}
if (newArr[i] == 4) {
let beforeChange = newArr[0]
newArr[0] = 6
changes.push(Math.abs(beforeChange — newArr[0]))
}
if (newArr[i] == 6) {
let beforeChange = newArr[0]
newArr[0] = 4
changes.push(Math.abs(beforeChange — newArr[0]))
}
}
break;
default:
}
result = changes.reduce((acc, cur) => {
return acc + cur
})
console.log(newArr)
}
console.log(“Result: “, result)
return result
}