2

I have 98000 5-digit numbers, from 00001 to 98000. I need to distribute these 98000 numbers in 14000 5x5 matrices.

A matrix cell must contain only a digit from 0 to 9.

Each matrix must receive 7 numbers from the 98000: one number in each line and two in the diagonals.

All 98000 numbers must be distributed in all 14000 matrices, without repetition.

The distribution can't feel like it is sequential, it must appear "random".

Here is an example:

0 1 2 3 0
7 6 5 4 3
0 0 8 1 2
3 7 5 6 0
4 5 5 0 0

Line 1: Number 01230
Line 2: Number 76543
Line 3: Number 00812
Line 4: Number 37560
Line 5: Number 45500
Main Diagonal (from top-left to bottom-right): 06860
Secondary Diagonal (from bottom-left to top-right): 47840

Another example:

3 9 4 0 5
1 3 2 0 9
0 0 0 0 1
9 7 4 5 4
1 2 7 7 8

Line 1: Number 39405
Line 2: Number 13209
Line 3: Number 00001
Line 4: Number 97454
Line 5: Number 12778
Main Diagonal (from top-left to bottom-right): 33058
Secondary Diagonal (from bottom-left to top-right): 17005

Is it mathematically possible? I mean, one can distribute all 98000 numbers in 14000 matrices without repetition? If it is, how can I write an algorithm to do the distribution?

I tried to write a program in C# to do this task, but I couldn't find a good strategy to do it. My program always try to fill a number which was already filled.

Thanks in advance!

EDIT:

Posted the same question on Mathematics StackExchange, in case you want to follow.

Community
  • 1
  • 1
wind39
  • 441
  • 4
  • 14

2 Answers2

1

Here is one non-deterministic but easy-to-implement algorithm:

Generate a random permutation of the numbers from 1 to 98000. Out of this permutation, take only the first 70000 (which is 14000 * 5, that is just enough numbers to build 14000 5x5 matrices).

Create an array of booleans of size 98000, initially all equal to false. This array will be used to mark which numbers are already in use. Let this array is denoted as F.

Then, iterate over the selected 70000 numbers, one number at a time. For each 5-digit number N considered, mark F[N] = true.

Next, iterate over the same selected 70000 numbers, but now consider five numbers at a time, sequentially. These five numbers constitute a 5x5 matrix. It's guaranteed that the rows of the matrix are not repeated, but no such guarantee can be made about the diagonals. Besides, there is no guarantee that the diagonal numbers, let call them D1 and D2, are less than 98000, or they are not equal.

So, let's check the diagonal numbers then. Extract the digits corresponding to each diagonal, and combine them into the 5-digit numbers, D1 and D2. If either of D1 and D2 is greater than 98000, or they are equal, the random permutation does not result in a solution, and you need to start from scratch, now with another random permutation. Otherwice, proceed with the checking of the diagonal numbers. Now, check the F array: if either of F[D1] and F[D2] is true, you have a repetition, and you have to start with another random permutation. If both F[D1] and F[D2] are false, set them to true and proceed to the next matrix. If you're lucky enough, you might find a good permutation (make sure to write it to a file because the above random search could take some time, and it would be a pity to lose the permutation after hours (weeks?) of search).

If you managed to get at this stage, your diagonal numbers and all rows are unique, and all are from 1 to 98000. This implies that you have used ALL numbers from 1 to 98000. That is, none of the remaining 98000-70000=28000 numbers is missing.

I'm not sure whether there is a solution: it could be that your problem is overconstrained (i.e., ALL permutations fail to satisfy your conditions). But, at least, you can start with this random search. While it's in progress, you can think about a better, deterministic algorithm ;)

Oleg
  • 1,037
  • 7
  • 13
  • The total permutations of the numbers from 1 to 98000 is 98000!, I guess, which is an unthinkable number, lol. But you wrote in a very didactic way, thank you. I didn't think in discard all the process and start over from scratch. It may work, but I need to find a strategy to reduce the number of total possible permutations. – wind39 Jun 17 '14 at 03:59
1

Note exactly an answer, but not suitable for a comment and it may help. I'd just like to quickly point out another way to look at the problem.

For simplicity of explanation, I'll use the following matrix as the template.

A # # # B
# C # D #
# # E # #
# F # G #
H # # # I

This template leads to groupings based on the diagonal digits in each row:

Row-Diagonals Groupings:

Row 1: (A,B)
Row 2: (C,D)
Row 3: (E)
Row 4: (F,G)
Row 5: (H,I)

You matrices are constrained by the diagonal numbers, in that each row choice constrains a digit from each of the diagonals (the letters). However, it still leaves 3-4 digits of the numbers uncontrained. It may be possible to use those uncontrained numbers to change a diagonal at least early on. Although, I think in the end this is going to be rather hard unless you can find some useful pattern in smaller set sizes that can be translated to larger set sizes. However, this should at least help with more efficient searching for valid digits for a given row.

Edit:

I suspect if it can be done, then there is likely a pattern that must be followed as to how the digits are assigned, but hard to say what it would be.

You are currently trying to find a solution in the case of numbers from 1 thru K with D digits, where K=98000, D=5 and K is a multiple of 7. Perhaps you should try to slowly build up a list of solutions. Perhaps you should brute force for K=i*7 for the first couple or so values of i. If their are any solutions, then it should give you some ideas as to patterns you might be able to exploit to solve this. Using those you should be able to find solutions to higher multiples of 7 until you finally reach i=14000. It also might help with determining which multiples of 7 may not have solutions.

Nuclearman
  • 5,029
  • 1
  • 19
  • 35
  • Thank you for your answer. I tried this X pattern. My program ran in two steps. First, I filled all diagonals of all 14000 matrices, and checked these 28000 numbers as "already used". The second step was use the remaining 70000 numbers to fill the rows, "anchoring" the digits of the diagonals. But at the last ~5000 matrices, the program couldn't "anchor" anymore without using a number which already was used in another previous matrix. – wind39 Jun 17 '14 at 03:55
  • But your statement is very useful, I'm going to try smaller sets first, to see if I can get some pattern. Thanks – wind39 Jun 17 '14 at 03:56
  • I don't see a way around that off the top of my head. However, you swap a row number for diagonal number. You just need to build up a data structure containing the groupings, like a dictionary or hash map. IE use a data structure that takes in the row, and two numbers and returns the set of elements for which that is valid. Such as unused[4][2][3] would provide a set of all unused numbers that could be used in row 4 where F=2 and G=3. Set intersections on those can thus be used to determine what to swap them with. I also added an edit to my question with some approaches to pattern finding. – Nuclearman Jun 17 '14 at 07:23
  • Thank you for your complements, your "unused" structure is a good idea, it seems fast to retrieve sets to do the anchoring. Now I'm guessing I'm going to need a similar structure called "used_in_diagonal", and try to balance both of them. – wind39 Jun 17 '14 at 11:52
  • You'll also probably want a "used_in_row". Though you could just use a function that returns True if it isn't in both "unused" and "used_in_diagonal". You also might want to include another map that takes in a number and returns a set of unused rows that number could be placed in (ignoring matrices with no chosen diagonals). This should make it easier to find cases where selecting a diagonal (or even part of one) makes it excessively harder or impossible for one or more digits to fit in the matrices. Although, I'm fairly sure that leads to NP-Competeness, so best to try to find a pattern. – Nuclearman Jun 17 '14 at 19:55