Combinations of N numbers in sets of K with R repeated elements
Posted: 26 May 2023 00:11
1- Using random numbers to generate combinations
At this SO question an interesting Statistical Combinations problem is stated:
This problem is solved via two basic steps: 1- Generate lines with six non-repeating numbers between 1 and 39 (a numeric combination), and 2- Compare the new line versus all previously generated lines to count the numbers in common with each one. If the number is less or equal 2 in all previous lines, insert the new line in the solution. When 300 lines are generated this way, stop. This problem in complicated because the huge number of possible combinations and the number of operations involved. In the SO question the skeleton of a simple solution based on random numbers is included (in the most rudimentary and slowest way).
My first solution was also based on random numbers, but just to take 6 anyone numbers from the 39 available ones (using 6 random numbers only). After 6 numbers are taken, they are compared versus the numbers of all previously generated lines. If a number caused to have 3 or more repeated numbers with a previous line, it is eliminated and the process go back to get another available number. If the 6 numbers are correct, a new line is generated. The creation of lines continue while available numbers exists in this set. When the available numbers ends, a new set of 39 numbers is created and the whole process is repeated. (Ok, my first method certainly was not a very good one)...
I run this program for 1 hour and 50 minutes in my old-and-slow machine until it generates 100 sets. Obviously, the first sets are generated very fast and the time increases as the number of sets aument. This is the listing of the first 100 results (with timing of each line):
Antonio
At this SO question an interesting Statistical Combinations problem is stated:
The OP requested that 300 lines be generated this way. I liked the problem a lot, so I wrote a solution (and several additional solutions later). I posted this thread here in order to have documented and ordered these programs (and to invite you to write a solution of your own).SO_question wrote: Generating lines of six different numbers between 1 and 39 that have no more than two numbers in common with any previous line.
This problem is solved via two basic steps: 1- Generate lines with six non-repeating numbers between 1 and 39 (a numeric combination), and 2- Compare the new line versus all previously generated lines to count the numbers in common with each one. If the number is less or equal 2 in all previous lines, insert the new line in the solution. When 300 lines are generated this way, stop. This problem in complicated because the huge number of possible combinations and the number of operations involved. In the SO question the skeleton of a simple solution based on random numbers is included (in the most rudimentary and slowest way).
My first solution was also based on random numbers, but just to take 6 anyone numbers from the 39 available ones (using 6 random numbers only). After 6 numbers are taken, they are compared versus the numbers of all previously generated lines. If a number caused to have 3 or more repeated numbers with a previous line, it is eliminated and the process go back to get another available number. If the 6 numbers are correct, a new line is generated. The creation of lines continue while available numbers exists in this set. When the available numbers ends, a new set of 39 numbers is created and the whole process is repeated. (Ok, my first method certainly was not a very good one)...
Code: Select all
@echo off
setlocal EnableDelayedExpansion
rem The 300 lines are generated as a 2-dimensional matrix called "n" with this shape:
rem n[%line%][%num%]=1
rem Where "line" is the index of the line: from 1 to 300
rem and "num" is *each number* (value between 1 and 39) that comprise such a line
rem
rem Each new line is previously generated in "num" array with 6 elements in the same way
rem Randomize
for /L %%i in (0,1,%time:~-1%) do set "x=!random!"
rem Generate 300 lines with 6 numbers each
set "line=0"
set "num[0]=0"
:nextLine
rem Set numbers 1..39 as "available"
for /L %%i in (1,1,39) do set "avail[%%i]=%%i"
set "numsAvail=39"
rem Remove previously generated numbers
for /F "tokens=2 delims==" %%n in ('set num[') do set "num[%%n]="
set "numbers=0"
rem Generate 6 random numbers (from "available" ones):
rem Get the index of anyone (random order) of available numbers
rem Insert such available number in "num" array
rem Move to the (position of the) used available number the *last one*, and eliminate (the last) one available number
rem And pass to the next number
:nextAvail
set /A indexAvail=%random% %% numsAvail + 1
set /A num[!avail[%indexAvail%]!]=avail[%indexAvail%], avail[%indexAvail%]=avail[%numsAvail%], numsAvail-=1, numbers+=1
if %numbers% lss 6 (
if %numsAvail% gtr 0 (
goto nextAvail
) else (
goto nextLine
)
)
rem Compare the new 6 numbers vs. *all* previously generated lines
rem and eliminate the (last) number that cause to have more than 2 repeated numbers:
for /L %%i in (1,1,%line%) do (
set "repeated=0"
for /F "tokens=2 delims==" %%j in ('set num[') do (
if defined n[%%i][%%j] set /A repeated+=1
if !repeated! gtr 2 (
set "num[%%j]="
set /A numbers-=1
if %numsAvail% gtr 0 (
goto nextAvail
) else (
goto nextLine
)
)
)
)
rem Insert (and show) the new line:
set /A line+=1
< NUL (
set /P "=%time:~0,-3% %line%- "
for /F "tokens=2 delims==" %%n in ('set num[') do (
set "n[%line%][%%n]=1"
set /P "=%%n "
))
echo/
if %line% lss 300 goto nextLine
Code: Select all
21:52:36 1- 15 18 21 34 5 6
21:52:36 2- 10 14 15 26 33 6
21:52:36 3- 13 16 25 30 32 33
21:52:36 4- 14 23 29 2 35 39
21:52:36 5- 14 25 27 34 36 4
21:52:37 6- 12 18 20 22 36 7
21:52:37 7- 12 20 21 24 27 37
21:52:37 8- 22 28 30 35 6 9
21:52:38 9- 12 18 28 35 38 5
21:52:38 10- 18 23 25 30 36 8
21:52:39 11- 15 17 24 3 5 8
21:52:39 12- 17 22 24 26 29 31
21:52:40 13- 21 2 32 37 39 7
21:52:41 14- 11 23 28 2 33 7
21:52:41 15- 16 19 1 30 34 36
21:52:43 16- 15 21 32 38 4 9
21:52:43 17- 12 21 25 33 34 39
21:52:44 18- 16 24 32 6 8 9
21:52:46 19- 12 1 27 35 36 8
21:52:48 20- 15 18 20 33 35 3
21:52:49 21- 11 14 18 28 34 37
21:52:51 22- 20 22 25 26 35 39
21:52:53 23- 10 11 26 34 35 38
21:52:54 24- 18 19 22 28 2 39
21:52:56 25- 12 16 20 30 31 5
21:52:57 26- 15 16 23 27 36 6
21:52:59 27- 10 12 23 32 39 4
21:53:09 28- 17 23 26 28 34 4
21:53:11 29- 16 17 1 25 26 9
21:53:14 30- 12 13 15 16 2 7
21:53:15 31- 10 20 24 2 36 3
21:53:20 32- 10 11 17 1 20 23
21:53:24 33- 11 13 15 20 21 22
21:53:28 34- 14 15 20 28 29 36
21:53:30 35- 15 16 18 19 25 31
21:53:33 36- 10 15 17 18 32 37
21:53:47 37- 11 14 15 25 2 32
21:53:49 38- 19 21 28 7 8 9
21:53:55 39- 11 1 22 24 27 30
21:53:58 40- 10 14 18 20 30 4
21:54:01 41- 1 21 26 27 28 39
21:54:03 42- 10 13 25 34 6 9
21:54:04 43- 19 23 27 30 33 38
21:54:17 44- 10 12 13 18 27 3
21:54:25 45- 11 18 26 29 30 32
21:54:28 46- 13 14 15 37 38 39
21:54:30 47- 14 18 1 23 3 9
21:54:36 48- 12 13 20 23 28 6
21:54:48 49- 11 15 1 26 7 8
21:55:05 50- 11 12 13 17 26 39
21:55:10 51- 11 18 21 24 35 36
21:55:23 52- 10 12 15 29 38 8
21:55:46 53- 10 11 12 14 5 7
21:55:50 54- 13 26 27 2 33 36
21:55:58 55- 16 17 20 22 34 37
21:56:20 56- 10 11 13 31 33 4
21:56:23 57- 13 18 29 2 4 5
21:56:25 58- 1 22 23 2 31 5
21:56:30 59- 14 16 17 19 35 6
21:56:53 60- 10 12 16 17 21 36
21:57:29 61- 13 1 20 25 5 7
21:57:51 62- 10 14 17 24 25 38
21:58:03 63- 11 13 14 16 1 29
21:58:13 64- 10 15 16 28 30 39
21:58:20 65- 10 16 19 37 3 4
21:59:37 66- 10 11 21 25 37 8
21:59:40 67- 19 1 28 31 38 3
21:59:46 68- 15 25 26 27 30 3
22:00:10 69- 11 12 19 20 3 8
22:01:36 70- 11 13 30 35 3 7
22:02:09 71- 24 29 34 4 6 7
22:03:36 72- 24 26 35 37 7 9
22:05:18 73- 11 12 15 24 28 4
22:05:41 74- 22 23 24 33 34 36
22:07:15 75- 12 17 1 30 33 7
22:07:17 76- 19 25 32 4 5 6
22:07:35 77- 10 12 19 1 22 6
22:07:57 78- 12 14 15 17 22 23
22:08:57 79- 10 11 19 27 32 36
22:08:59 80- 11 25 31 36 5 9
22:10:39 81- 13 1 22 26 32 3
22:11:41 82- 11 12 22 29 33 35
22:11:54 83- 12 14 24 31 34 8
22:15:02 84- 12 13 14 19 30 9
22:17:18 85- 10 19 24 28 29 33
22:19:24 86- 17 1 24 37 39 6
22:21:04 87- 11 16 17 18 27 33
22:21:14 88- 12 1 20 2 32 38
22:22:37 89- 11 16 22 38 39 7
22:22:50 90- 10 18 1 29 31 39
22:27:39 91- 15 17 19 1 27 2
22:29:04 92- 13 19 21 23 24 2
22:36:51 93- 12 14 32 33 36 3
22:43:11 94- 13 18 20 24 31 32
22:53:34 95- 16 18 20 21 23 38
23:00:23 96- 11 14 30 31 38 6
23:02:39 97- 10 1 27 34 37 7
23:04:17 98- 13 16 17 23 31 3
23:08:38 99- 19 20 21 29 31 4
23:42:58 100- 10 12 26 28 31 37