2

The Situation

I have a certain amount of squares. I want these square to always from a square like grid but it can't have any empty spaces. I'd use JavaScript to do this. The grid would be stored like so

var gridLayout = [[1, 2], [3, 4]];

This would result in this grid

2 by 2 grid

The Problem

If I have 16 squares it would result with

var gridLayout = [[1, 2, 3, 4],[5, 6, 7, 8],[9, 10, 11, 12],[13, 14, 15, 16]];

And the visual

4 by 4 grid

Now all that's easy to do, but what if there's 3 squares? I'd like it to do something like this, favoring the horizontal over the vertical layout.

var gridLayout = [[1, 2, 3]];

with the visual

1 by 3 grid

If I had 8 squares it couldn't make the perfect square so I'd like to be

var gridLayout = [[1, 2, 3, 4], [5, 6, 7, 8]];

And the visual

2 by 4 grid

What I've tried

I've looked at this but it seems to be working with rectangles instead of squares. I also have a very hard time following without the visuals of what they want.

I have also looked at this which is kinda similar but seem to be a bit irrelevant to my situation.

Conclusion

How would I create the gridLayout in such a way as what I want? Any help is appreciated.

Community
  • 1
  • 1
Jack
  • 1,893
  • 1
  • 11
  • 28
  • It looks like you always want as many columns as elements in the subarrays and as many rows as elements in the array. This should be possible very easily with CSS grid: https://css-tricks.com/snippets/css/complete-guide-grid/ . Or is the problem generating the arrays? – Felix Kling Sep 26 '18 at 22:09
  • What is the actual question? – lucas Sep 26 '18 at 22:10
  • I don't know about the graphical part, but this seems straightforward enough. You have an array of *rows* (first level), each row being composed of *cells* (second level). I'm not sure what logic issue you have with that. – Jeto Sep 26 '18 at 22:10
  • @FelixKling Thanks for the link. But yes, I am having the issue with generating the arrays. – Jack Sep 26 '18 at 22:10
  • It wasn't clear from your post that this is part of your question. – Felix Kling Sep 26 '18 at 22:12
  • @FelixKling Sorry, edited. – Jack Sep 26 '18 at 22:13
  • 1
    A starting point https://stackoverflow.com/questions/8495687/split-array-into-chunks. Choose a chunk size that divides the number of elements evenly. Then change the chunk size to get the right number of rows (which atm I'm not sure how to determine, e.g. should columns be always be larger or equal than rows? If so choose a chunk size where `#elements / chunk_size < chunk_size`). *edit:* Maybe choose `chunk_size` such that `chunk_size > Math.sqrt(#elements) && #elements % chunk_size === 0` – Felix Kling Sep 26 '18 at 22:14
  • 1
    if the number of elements is a prime number you'll always have to use a single row. Is that OK? – Barmar Sep 26 '18 at 22:28

1 Answers1

1

You can use a solution from Split array into chunks, to split an array of elements. Now we just need to determine the correct chunk size.

It looks like the criteria is:

  • Each chunk must be the same size. This can be achieved by requiring that the number of elements is evenly divisible by the chunk size (i.e. #elements % chunk_size === 0).
  • There should be at most as many rows as columns. In other words, the chunk size must be larger than the number of chunks. We can fulfill that by starting with a chunk size that is at least Math.sqrt(#elements).

// Implementation

function chunk (arr, len) {
  var chunks = [],
      i = 0,
      n = arr.length;

  while (i < n) {
    chunks.push(arr.slice(i, i += len));
  }

  return chunks;
}

function gridify(arr) {
  let size = Math.ceil(Math.sqrt(arr.length));
  while (arr.length % size !== 0) {
    size += 1;
  }
  return chunk(arr, size);
}

// Helper functions for example

function range(n) {
   return Array.from({length: n}, (_,i) => i+1);
}

function run(size) {
  console.log(JSON.stringify(gridify(range(size))));
}

// Create examples

run(4);
run(16);
run(3);
run(8);

There is hopefully a better way to determine the chunk size than just iterating and increasing size, but that's what I came with in this short time.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143