创建一个 M*N 矩阵,由 1-90 的唯一数字组成
Creating an M*N matrix of unique numbers from 1-90
我想在 python 中开发一种算法,该算法 returns 使用某些 rules/conditions 随机填充 1 到 90 的数字的 18x9 矩阵。
规则
#1 - Maintain an array of 18x9 between 1 and 90.
#2 - First column contains 1-10, second column contains 11-20, etc.
#3 - Each row must have 5 numbers. Other columns should be set to 0.
#4 - Numbers must be arranged in ascending order from top to bottom in a column
到目前为止我做了什么?
import numpy as np
columns = 9
rows = 18
n_per_row = 5
matrix = np.zeros((rows, columns), dtype=int)
# Keep track of available places at each row.
available_places = {k: n_per_row for k in range(rows)}
# Shuffle order in which we fill the columns.
col_order = np.arange(columns)
np.random.shuffle(col_order)
for column in col_order:
# Indices of available rows.
indices = [c for c in available_places if available_places[c]]
# Sample which row to use of the available.
indices = np.random.choice(indices, size=min(len(indices), 10), replace=False)
# print(indices)
# Values for this column.
col_values = np.random.choice(list(np.arange(1, 10+1)), size=min(len(indices), 10), replace=False) + column*10
# Fill in ascending order.
matrix[sorted(indices), column] = sorted(col_values)
for idx in indices:
available_places[idx] -= 1
print(matrix)
结果
[[ 0 0 0 31 0 51 0 71 81]
[ 1 11 0 0 0 52 61 72 0]
[ 0 0 21 32 41 0 62 73 0]
[ 0 0 22 33 0 0 0 74 82]
[ 0 12 23 0 42 0 63 0 83]
[ 2 13 24 34 0 53 0 0 0]
[ 3 0 0 0 43 54 64 0 84]
[ 4 0 0 0 44 55 65 0 85]
[ 5 14 0 0 45 0 66 0 86]
[ 6 0 25 35 46 0 0 75 0]
[ 7 15 26 36 0 0 0 0 87]
[ 8 16 0 0 47 0 0 76 88]
[ 0 17 27 0 48 0 0 77 89]
[ 0 18 0 0 49 56 67 78 0]
[ 9 0 28 39 0 57 0 79 0]
[ 0 0 29 0 50 58 68 80 0]
[ 0 19 30 40 0 59 69 0 0]
[10 20 0 0 0 60 70 0 90]]
预期结果:https://images.meesho.com/images/products/56485141/snksv_512.jpg
4条规则的最终结果
每行 5 个值
每列 10 个值,以 1、11、21 等开始,按升序排列
(请注意,如图所示,这些规则不适用于宾果游戏)
============ final matrix ===============
--------------------------------
[1, 11, 21, 31, 41, 0, 0, 0, 0]
[2, 12, 0, 32, 42, 0, 61, 0, 0]
[0, 13, 0, 33, 0, 0, 62, 71, 81]
[3, 0, 0, 34, 0, 0, 63, 72, 82]
[0, 0, 22, 0, 0, 51, 64, 73, 83]
[4, 14, 23, 35, 0, 52, 0, 0, 0]
[5, 0, 24, 0, 43, 53, 0, 0, 84]
[6, 15, 0, 36, 44, 54, 0, 0, 0]
[7, 0, 0, 37, 0, 0, 65, 74, 85]
[0, 0, 0, 0, 45, 55, 66, 75, 86]
[8, 16, 25, 0, 0, 0, 67, 76, 0]
[0, 0, 26, 0, 46, 56, 0, 77, 87]
[9, 17, 0, 0, 0, 0, 68, 78, 88]
[10, 18, 0, 0, 0, 57, 0, 79, 89]
[0, 19, 27, 38, 47, 0, 0, 80, 0]
[0, 20, 28, 39, 48, 58, 0, 0, 0]
[0, 0, 29, 0, 49, 59, 69, 0, 90]
[0, 0, 30, 40, 50, 60, 70, 0, 0]
--------------------------------
原则:
首先建立一个矩阵,其中 0 和 1 设置为未来值的占位符。
随机化矩阵中每个单元格的 0 或 1,但调查一行中的 1 个和列中的 1 个以遵守约束。
由于 random 可能会提前给出足够的 1,因此在第一次尝试时无法满足这两个约束。 Prog 自动重试并跟踪每次尝试以进行观察。 (在我的测试中看到的最大值:10 个循环,平均:<=3 个循环)
一旦获得令人满意的 0 & 1 矩阵,将每个 1 替换为每个列的相应值。
解决方案:
import random
# #1 - Maintain an array of 18x9 (between 1 and 90)
maxRow = 18
maxCol = 9
# #2 - First column contains 1-10, second column contains 11-20, etc.
# ie first column 1 start from 1 and have 10 entries, column 2 start from 11 and have 10 entries, etc.
origins = [i*10 +1 for i in range(maxCol)] #[1, 11, 21, 31, 41, 51, 61, 71, 81]
maxInCol = [10 for i in range(maxCol)] #[10, 10, 10, 10, 10, 10, 10, 10, 10]
# comfort : display matrix
def showMatrix():
print('--------------------------------')
for row in range(len(matrix)):
print(matrix[row])
print('--------------------------------')
# comfort : count #values in a col
def countInCol(col):
count = 0
for row in range(maxRow):
count+=matrix[row][col]
return count
# verify the rules of 5 per row and 10 per cols
def verify():
ok = True
showMatrix()
# count elements in a col
for col in range(maxCol):
count = 0
for row in range(maxRow):
count+= matrix[row][col]
if(count!= maxInCol[col]):
print ('*** wrong # of elements in col {0} : {1} instead of {2}'.format(col, count,maxInCol[col]))
ok = False
# count elements in a row
for row in range(maxRow):
count = 0
for col in range(maxCol):
count+= matrix[row][col]
if(count!=5):
print('***** wrong # of elements in row {0} : {1}'.format(row, count))
ok = False
if (not ok): print( '********************************************')
return ok
# -- main ----
# need to iterate in case of no more value to complete a col
tour = 1
maxTour = 100 #security limit
while True:
# prepare a matrix of rows of cols of 0
matrix = [[0 for i in range(maxCol)] for i in range(18)]
# begin to fill some places with 1 instead of 0
for row in range(maxRow):
count = 0
for col in range(maxCol):
if (count==5): break # line is already full with 5 elt
# random a 0 or 1
placeHolder = random.choice([0,1])
# if the remaining cols of this row needs to be 1 to complete at 5/row
if (5-count) == (maxCol-col):
placeHolder = 1 # must complete the row
else:
inCol = countInCol(col)
# 10 places max in col
if (inCol)==maxInCol[col]: placeHolder = 0 # this col is full
# constraint : if the remaining rows of this col need to be 1 to complete the expected 10 values
if(maxRow-row) == (maxInCol[col]-inCol): placeHolder = 1
matrix[row][col] = placeHolder
count+= placeHolder
#-------- some case are not correct . prog loops
if verify():
print(' ok after {0} loop(s)'.format(tour))
break
# security infinite loop
if (tour>=maxTour): break
tour +=1
# now replace the placeholders by successive values per col
print('\n============ final matrix ===============')
for row in range(maxRow):
for col in range(maxCol):
if matrix[row][col]==1:
matrix[row][col] = origins[col]
origins[col]+=1
showMatrix()
HTH
我想在 python 中开发一种算法,该算法 returns 使用某些 rules/conditions 随机填充 1 到 90 的数字的 18x9 矩阵。
规则
#1 - Maintain an array of 18x9 between 1 and 90.
#2 - First column contains 1-10, second column contains 11-20, etc.
#3 - Each row must have 5 numbers. Other columns should be set to 0.
#4 - Numbers must be arranged in ascending order from top to bottom in a column
到目前为止我做了什么?
import numpy as np
columns = 9
rows = 18
n_per_row = 5
matrix = np.zeros((rows, columns), dtype=int)
# Keep track of available places at each row.
available_places = {k: n_per_row for k in range(rows)}
# Shuffle order in which we fill the columns.
col_order = np.arange(columns)
np.random.shuffle(col_order)
for column in col_order:
# Indices of available rows.
indices = [c for c in available_places if available_places[c]]
# Sample which row to use of the available.
indices = np.random.choice(indices, size=min(len(indices), 10), replace=False)
# print(indices)
# Values for this column.
col_values = np.random.choice(list(np.arange(1, 10+1)), size=min(len(indices), 10), replace=False) + column*10
# Fill in ascending order.
matrix[sorted(indices), column] = sorted(col_values)
for idx in indices:
available_places[idx] -= 1
print(matrix)
结果
[[ 0 0 0 31 0 51 0 71 81]
[ 1 11 0 0 0 52 61 72 0]
[ 0 0 21 32 41 0 62 73 0]
[ 0 0 22 33 0 0 0 74 82]
[ 0 12 23 0 42 0 63 0 83]
[ 2 13 24 34 0 53 0 0 0]
[ 3 0 0 0 43 54 64 0 84]
[ 4 0 0 0 44 55 65 0 85]
[ 5 14 0 0 45 0 66 0 86]
[ 6 0 25 35 46 0 0 75 0]
[ 7 15 26 36 0 0 0 0 87]
[ 8 16 0 0 47 0 0 76 88]
[ 0 17 27 0 48 0 0 77 89]
[ 0 18 0 0 49 56 67 78 0]
[ 9 0 28 39 0 57 0 79 0]
[ 0 0 29 0 50 58 68 80 0]
[ 0 19 30 40 0 59 69 0 0]
[10 20 0 0 0 60 70 0 90]]
预期结果:https://images.meesho.com/images/products/56485141/snksv_512.jpg
4条规则的最终结果
每行 5 个值
每列 10 个值,以 1、11、21 等开始,按升序排列
(请注意,如图所示,这些规则不适用于宾果游戏)
============ final matrix ===============
--------------------------------
[1, 11, 21, 31, 41, 0, 0, 0, 0]
[2, 12, 0, 32, 42, 0, 61, 0, 0]
[0, 13, 0, 33, 0, 0, 62, 71, 81]
[3, 0, 0, 34, 0, 0, 63, 72, 82]
[0, 0, 22, 0, 0, 51, 64, 73, 83]
[4, 14, 23, 35, 0, 52, 0, 0, 0]
[5, 0, 24, 0, 43, 53, 0, 0, 84]
[6, 15, 0, 36, 44, 54, 0, 0, 0]
[7, 0, 0, 37, 0, 0, 65, 74, 85]
[0, 0, 0, 0, 45, 55, 66, 75, 86]
[8, 16, 25, 0, 0, 0, 67, 76, 0]
[0, 0, 26, 0, 46, 56, 0, 77, 87]
[9, 17, 0, 0, 0, 0, 68, 78, 88]
[10, 18, 0, 0, 0, 57, 0, 79, 89]
[0, 19, 27, 38, 47, 0, 0, 80, 0]
[0, 20, 28, 39, 48, 58, 0, 0, 0]
[0, 0, 29, 0, 49, 59, 69, 0, 90]
[0, 0, 30, 40, 50, 60, 70, 0, 0]
--------------------------------
原则:
首先建立一个矩阵,其中 0 和 1 设置为未来值的占位符。
随机化矩阵中每个单元格的 0 或 1,但调查一行中的 1 个和列中的 1 个以遵守约束。
由于 random 可能会提前给出足够的 1,因此在第一次尝试时无法满足这两个约束。 Prog 自动重试并跟踪每次尝试以进行观察。 (在我的测试中看到的最大值:10 个循环,平均:<=3 个循环)
一旦获得令人满意的 0 & 1 矩阵,将每个 1 替换为每个列的相应值。
解决方案:
import random
# #1 - Maintain an array of 18x9 (between 1 and 90)
maxRow = 18
maxCol = 9
# #2 - First column contains 1-10, second column contains 11-20, etc.
# ie first column 1 start from 1 and have 10 entries, column 2 start from 11 and have 10 entries, etc.
origins = [i*10 +1 for i in range(maxCol)] #[1, 11, 21, 31, 41, 51, 61, 71, 81]
maxInCol = [10 for i in range(maxCol)] #[10, 10, 10, 10, 10, 10, 10, 10, 10]
# comfort : display matrix
def showMatrix():
print('--------------------------------')
for row in range(len(matrix)):
print(matrix[row])
print('--------------------------------')
# comfort : count #values in a col
def countInCol(col):
count = 0
for row in range(maxRow):
count+=matrix[row][col]
return count
# verify the rules of 5 per row and 10 per cols
def verify():
ok = True
showMatrix()
# count elements in a col
for col in range(maxCol):
count = 0
for row in range(maxRow):
count+= matrix[row][col]
if(count!= maxInCol[col]):
print ('*** wrong # of elements in col {0} : {1} instead of {2}'.format(col, count,maxInCol[col]))
ok = False
# count elements in a row
for row in range(maxRow):
count = 0
for col in range(maxCol):
count+= matrix[row][col]
if(count!=5):
print('***** wrong # of elements in row {0} : {1}'.format(row, count))
ok = False
if (not ok): print( '********************************************')
return ok
# -- main ----
# need to iterate in case of no more value to complete a col
tour = 1
maxTour = 100 #security limit
while True:
# prepare a matrix of rows of cols of 0
matrix = [[0 for i in range(maxCol)] for i in range(18)]
# begin to fill some places with 1 instead of 0
for row in range(maxRow):
count = 0
for col in range(maxCol):
if (count==5): break # line is already full with 5 elt
# random a 0 or 1
placeHolder = random.choice([0,1])
# if the remaining cols of this row needs to be 1 to complete at 5/row
if (5-count) == (maxCol-col):
placeHolder = 1 # must complete the row
else:
inCol = countInCol(col)
# 10 places max in col
if (inCol)==maxInCol[col]: placeHolder = 0 # this col is full
# constraint : if the remaining rows of this col need to be 1 to complete the expected 10 values
if(maxRow-row) == (maxInCol[col]-inCol): placeHolder = 1
matrix[row][col] = placeHolder
count+= placeHolder
#-------- some case are not correct . prog loops
if verify():
print(' ok after {0} loop(s)'.format(tour))
break
# security infinite loop
if (tour>=maxTour): break
tour +=1
# now replace the placeholders by successive values per col
print('\n============ final matrix ===============')
for row in range(maxRow):
for col in range(maxCol):
if matrix[row][col]==1:
matrix[row][col] = origins[col]
origins[col]+=1
showMatrix()
HTH