A computer program designed to determine a series of numbers needed to complete a square grid

Given the numbers 1, 2, 3, 4, 5, 6, 7, 8, I am seeking to replace the x's in such a way that each side adds up to the number in the center.

*-*---*-*
|x| x |x|
*-*---*-*
|x| 12|x|
*-*---*-*
|x| x |x|
*-*---*-*

Initially, I have iterated over the numbers to identify all potential combinations.

var range = [1, 2, 3, 4, 5, 6, 7, 8];
var target = 12;
var matches = [];

for (x = 0; x < range.length; x ++){
    for (y = 0; y < range.length; y ++){
        if (y === x){
            continue;
        }
        for (z = 0; z < range.length; z ++){
            if (z === y || z === x){
                continue;   
            }

            if (range[x] + range[y] + range[z] === target){
              matches.push([range[x], range[y], range[z]]);
            }
        }           
    }   
}

Next, the numbers have been concatenated end to end.

for (j = 0; j < matches.length; j++){
  for (k = 0; k < matches.length; k++){
    if (j == k) continue;
    //if (matches[j][2] != matches[k][0]) continue;
    for (l = 0; l < matches.length; l++){
      if (l == j || l == k) continue;
      //if (matches[k][2] != matches[l][0]) continue;
      for (m = 0; m < matches.length; m++){
        if (m == j || m == k || m == l) continue;
        if (matches[l][2] != matches[m][0]) continue;
        if (matches[m][2] != matches[j][0]){
          console.log(matches[j], matches[k], matches[l], matches[m]);
        }

      }
    }
  }
}

Currently, there is no check in place to ensure each set of numbers is only used once, which is my proposed solution.

I am open to suggestions on a more efficient approach to solving this problem.

Answer №1

There's no need to list out all 40,320 permutations of the numbers because 4 of the 8 positions are automatically filled by subtracting the two neighboring values from the target. Therefore, there are only 4 variables and a maximum of 1,680 permutations:

A   B   C
D  12   E
F   G   H

Any choice of A and B determines C, then any choice of D determines F, and any choice of E determines H and G. Therefore, A, B, D, and E are the variables.

You can approach this iteratively with 4 nested loops, as shown below, or recursively, which will make it easier to adapt to other grid sizes.

for A is 1 to 8
    for B is any available number < target - A
        C = target - (A + B)
        if C is not available, skip to next B
        for D is any available number < target - A
            F = target - (A + D)
            if F is not available, skip to next D
            for E is any available number < target - C
                H = target - (C + E)
                if H is not available, skip to next E
                G = target - (F + H)
                if G is available, store this combination
            }
        }
    }
}

In the simplest iterative form, and following Daniel Wagner's suggestion to generate unique solutions that can be rotated and mirrored, the code example below showcases this. The code in the inner loop only runs 56 times, with a total of 142 indexOf() calls.

function numberSquare(target) {
    for (var a = 1; a < 9; a++) {
        for (var c = a + 1; c < 9 && c < target - a; c++) {
            var b = target - (a + c);
            if ([a,c].indexOf(b) > -1  || b > 8) continue;
            for (var f = c + 1; f < 9 && f < target - a; f++) {
                var d = target - (a + f);
                if ([a,b,c,f].indexOf(d) > -1 || d > 8) continue;
                for (var h = a + 1; h < 9 && h < target - c && h < target - f; h++) {
                    if ([b,c,d,f].indexOf(h) > -1) continue;
                    var e = target - (c + h);
                    if ([a,b,c,d,f,h].indexOf(e) > -1 || e > 8) continue;
                    var g = target - (f + h);
                    if ([a,b,c,d,e,f,h].indexOf(g) > -1 || g > 8) continue;
                    document.write([a,b,c] + "<br>" + [d,'_',e] + "<br>" + [f,g,h] + "<br><br>");
                }
            }
        }
    }
}

numberSquare(12);
document.write("× 4 rotations and 2 mirrorings (8 solutions per result)");

Answer №2

After taking some time to reconsider the problem, I came up with a new approach. I thought it would be beneficial to use an indexed object to streamline the process. By organizing the combinations based on the central number, I could easily determine the next number to consider. For instance, if you start with the combination [1, 3, 8], you know that the next set should begin with 8:

[1, 3, 8]

Resulting in:

{
    ...,
    8: [[8, 1, 3], [8, 3, 1]]
}

This method significantly narrows down the options to explore.

Though I believe there is room for improvement in my code, I will have to revisit it later as it is quite late!

var range = [1,2,3,4,5,6,7,8];
var target = 13;
var matches = [];
var keyedMatches = {
  "1": [],
  "2": [],
  "3": [],
  "4": [],
  "5": [],
  "6": [],
  "7": [],
  "8": []
};

let firstSteps = 0;

for (x = 0; x < range.length; x ++){firstSteps++
    for (y = 0; y < range.length; y ++){
        if (y === x){
            continue;
        }firstSteps++
        for (z = 0; z < range.length; z ++){
            if (z === y || z === x){
                continue;   
            }firstSteps++

            if (range[x] + range[y] + range[z] === target){
              matches.push([range[x], range[y], range[z]]);
              keyedMatches[range[x]].push([range[x], range[y], range[z]])
            }
        }           
    }   
}
console.log(keyedMatches);


let secondSteps = 0;

var currentSelection = [];
var usedNums = [];
for (j = 0; j < matches.length; j ++){secondSteps++;
  usedNums.push(matches[j][0]);
  usedNums.push(matches[j][1]);
  usedNums.push(matches[j][2]);


  var step2 = keyedMatches[usedNums[usedNums.length-1]];

  for (k=0; k < step2.length; k++){
    if(checkUsed(usedNums, step2[k])) continue;

    usedNums.push(step2[k][1]);
    usedNums.push(step2[k][2]);

    var step3 = keyedMatches[usedNums[usedNums.length-1]];

    for (l=0; l < step3.length; l++){
      if(checkUsed(usedNums, step3[l])) continue;
      usedNums.push(step3[l][1]);
      usedNums.push(step3[l][2]);


      var step4 = keyedMatches[usedNums[usedNums.length-1]];
      for (m=0; m < step4.length; m++){

        if(usedNums.indexOf(step4[m][1]) !== -1) continue;

        if (step4[m][2] != usedNums[0]) continue;

        usedNums.push(step4[m][1]);
        console.log(usedNums);

        // remove the used numbers
        usedNums.pop();

      }

      // remove the used numbers
      usedNums.pop();
      usedNums.pop();
    }

    // remove the used numbers
    usedNums.pop();
    usedNums.pop();
  }

  usedNums = [];

}

function checkUsed(unum, nnum){
  if (unum.indexOf(nnum[1]) === -1 && unum.indexOf(nnum[2]) === -1){
    return false;
  }
  return true;
}

Answer №3

This implementation may be considered quite simple. While a dynamic programming approach could potentially yield a more efficient solution, my current time constraints limit me to presenting a straightforward method. Despite this limitation, the method is reasonably fast, utilizing what I believe to be one of the most efficient permutation algorithms available in JS. The process is summarized as follows:

  • Generate all possible permutations of the given numbers array.
  • Evaluate each permutation to determine if it is valid.

The valid permutations obtained are then interpreted as values to be placed starting from the upper left corner and progressing clockwise.

function solve4(n,a){
  
  function perm(a){
    // Implementation of permutation function
  }
  
  function validChoices(chs,n){
    // Function to filter out valid choices based on specific conditions
  }
  
  return validChoices(perm(a),n);
}

console.log(solve4(12,[1,2,3,4,5,6,7,8]));

For the input values 12 and [1,2,3,4,5,6,7,8], this method yields 8 distinct solutions, such as:

[ [ 1, 5, 6, 4, 2, 7, 3, 8 ],
  [ 6, 4, 2, 7, 3, 8, 1, 5 ],
  [ 2, 7, 3, 8, 1, 5, 6, 4 ],
  [ 3, 8, 1, 5, 6, 4, 2, 7 ],
  [ 3, 7, 2, 4, 6, 5, 1, 8 ],
  [ 2, 4, 6, 5, 1, 8, 3, 7 ],
  [ 6, 5, 1, 8, 3, 7, 2, 4 ],
  [ 1, 8, 3, 7, 2, 4, 6, 5 ] ]

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to create an online game using JavaScript?

Hey there, I'm interested in creating a simple online game that can be played in the browser. My main question is this: if I want two players to compete against each other online, can I achieve this by using HTML for the front-end and JavaScript for t ...

Organizing a set of div elements based on their ID attributes

I am faced with the challenge of sorting a list of divs based on their ID values, which are in the format "indexNumber123". Instead of arranging them alphabetically, I want to sort them numerically as "indexNumber1", "indexNumber2", "indexNumber3" before d ...

Creating a minigame using JQuery (Javascript)

I am currently developing a collection of mini-games for my big project. The approach I've taken in creating this mini-game is similar to one I used previously. However, unlike my previous version which only had one PuzzleContainer, this new iteration ...

I'm having trouble getting my home.js to render in the outlet component

After using Material-UI to create navbar.js, I encountered an issue where the other component was not rendering in the <Outlet/> Component RootLayout.js import { Outlet } from "react-router-dom"; import NavBar from "../component/NavBa ...

Utilizing HTML5 Canvas for Shadow Effects with Gradients

Surprisingly, it seems that the canvas API does not support applying gradients to shadows in the way we expect: var grad = ctx.createLinearGradient(fromX, fromY, toX, toY); grad.addColorStop(0, "red"); grad.addColorStop(1, "blue"); ctx.strokeStyle = gra ...

Error [ERR_MODULE_NOT_FOUND]: Module could not be located in vscode

Issue with VS Code: Module Not Found Error View the image associated with the erroreN.png ...

Executing a C# method from within a .js file using a Javascript function in a .cs file

I've made some updates based on the responses provided. My main area of confusion lies in the 'data' parameter and how to handle it in the JavaScript call. C# method [HttpPost] public string GetPreviewURL(string activityID) ...

Once the window width exceeds $(window).width(), the mouseenter function is triggered exponentially

My side menu smoothly folds to the right or left based on the size of the browser window. However, I noticed that upon first reload, the mouseenter and mouseleave events are triggered twice for each action. While this isn't a major issue, it becomes p ...

Filtering rows of an HTML table that contain links in the `<href>` column data in real time

When using HTML and JavaScript, I have found a solution that works well for many of the columns I am working with. You can see the details on how to dynamically filter rows of an HTML table using JavaScript here. var filters=['hide_broj_pu',&apo ...

Is there a way for me to manage the rendering of a three.js scene?

I've noticed that most examples use a loop structure to render the scene, like so: renderer.render(scene, camera); function render(){ renderer.render(scene, camera); //code for rendering requestAnimationFrame(render); } render(); Howev ...

The universal CSS variables of Material UI

Creating reusable CSS variables for components can greatly simplify styling. In regular CSS, you would declare them like this: :root { --box-shadow: 0 2px 5px -1px rgba(0, 0, 0, 0.3); } This variable can then be utilized as shown below: .my-class { ...

Learn how to incorporate latitude and longitude coding into PHP to display a map icon that correctly redirects to the desired URL when clicked

I am in need of a table that includes buttons for adding, editing, deleting, and mapping. Everything works fine so far, but when I click on the map button, it should take me to Google Maps with coordinates linked from a MySQL database containing latitude ...

What could be causing the API link to not update properly when using Angular binding within the ngOnInit method?

Hi there, I'm currently working on binding some data using onclick events. I am able to confirm that the data binding is functioning properly as I have included interpolation in the HTML to display the updated value. However, my challenge lies in upd ...

Optimizing JavaScript performance by packaging files with Browserify

Currently, I am utilizing AngularJS for the front end of my project. Initially, I was using Grunt as my build tool but now I am interested in transitioning to npm for this purpose. I came across a useful link that discusses using npm scripts as a build too ...

Discover the most frequent value in an array by utilizing JavaScript

My array contains repeating values: [0, 1, 6, 0, 1, 0] How can I efficiently determine the highest frequency of a specific value being repeated? For example, in this array, I would like the script to return 3 since the number 0 repeats most frequently a ...

It appears that the flex-grow property is not functioning as expected

I am working with a parent div and two children divs underneath it. I noticed that when I set the flex-grow property of the first child to zero, its width remains constant. However, if I add text to the second child, the width of the first child decreases. ...

Generating and Importing Graphics through Iterations in Javascript

I apologize for my lack of experience in this matter. Can someone please guide me on how to utilize a loop to load images? For instance, could you show me how to rewrite the code below using a loop to automate the process? function loadImages() { let ...

"Enhance the visual appeal of your Vue.js application by incorporating a stylish background image

Currently, I am utilizing Vue.js in a component where I need to set a background-image and wrap all content within it. My progress so far is outlined below: <script> export default { name: "AppHero", data(){ return{ image: { bac ...

Adjusting the size of the iframe to match the dimensions of the window

Is there a way to make the iframe automatically fill up the entire space? For example, only opens the iframe up to half of the window in Mozilla Firefox and IE6. How can I ensure that it takes the maximum size of the screen? Are there any CSS or JavaScr ...

What methods can a controller use to verify the legitimacy of the scope?

I'm a bit perplexed when it comes to validation in angular. It seems like all of the validation is connected to the form. But what happens when the controller needs to ascertain if the model is valid or not? Here's an example I quickly whipped u ...