Как можно поместить все камни в матрицу
Весь код внизу.
У меня есть определенные фигуры, определенного цвета.
Например, фигура цветом 6 имеет форму квадрата 2х2
[6, 6, 0, 0, 0]
[6, 6, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
Фигура цветом 5 имеет форму
[5, 5, 0, 0, 0]
[5, 5, 5, 0, 0]
[5, 5, 5, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
(все остальные фигуры увидите если запустите код).
На самом деле у меня txt файл
5
5
6 0 4 0 5 -1 5 -1 4
5 4 2 4 1 4 0 3 1 3 2 3 0 2 1 2 0
2 6 4 7 4 7 3
3 -2 9 -3 9
4 7 10 8 10 8 11 9 10 6 10 5 10
1 4 14 4 13
Первые две строки показывают размер матрицы, в которую надо поместить все фигуры. Первый столбец каждой строки показывает цвет фигуры, а следом идущие числа - это координаты в матрице, такие, что в конце получится фигура.
def readStones(filename):
stones = []
f = open(filename,"r")
numRows = int(f.readline().strip()) #1 ряд файла
numCols = int(f.readline().strip()) #2 ряд файла
for line in f:
numbers = list(map(int, line.strip().split())) #все числа после этих двух рядов
color = numbers[0] #первый столбец это цвета
coords = numbers[1:] #r1 c1 ... rn cn
cells = [] #[r1,c1 ... rn,cn] = [[r1,c1],...,[rn,cn]]
for i in range(len(coords)//2):
cells.append( [ coords[2*i+0], coords[2*i+1] ] )
stones.append( [ color, cells ] )
f.close()
return numRows, numCols, stones;
def shape_of_stones(numRows, numCols, stones, n):
'''find out the shape of the stones '''
matrix_for_shape = [0] * numRows
for k in range(numRows):
matrix_for_shape[k] = [0] * numCols
rows = []
cols = []
for cellindex in range(len(stones[n][1])):
row, col = stones[n][1][cellindex]
rows.append(row)
cols.append(col)
for cell in range(len(stones[n][1])):
r, c = stones[n][1][cell]
i = stones[n][0]
matrix_for_shape[r - min(rows)][c - min(cols)] = i
print(*matrix_for_shape, sep='\n')
def main():
M,N, stones = readStones("stones.txt")
#информация о камнеstones[n]
#его цвет stones[n][0], его координаты stones[n][1]
for n in range(len(stones)):
shape_of_stones(M, N, stones, n)
print('--------'*2)
main()
Не могу придумать рекурсивную функцию, которая бы поместила все фигуры.
Вот как можно собрать все эти фигуры
[4, 5, 5, 1, 1]
[4, 5, 5, 5, 3]
[4, 5, 5, 5, 3]
[4, 4, 2, 6, 6]
[4, 2, 2, 6, 6]
Как по мне, то лучше начинать с камней, которые имеют наибольшую площадь. (по мере выполнения, буду добавлять код)
Ответы (2 шт):
Если без вращения фигур, то, например, можно так.
import copy
def readStones(filename):
stones = {}
with open(filename,"r") as f:
numRows = int(f.readline().strip()) #1 ряд файла
numCols = int(f.readline().strip()) #2 ряд файла
for line in f:
numbers = list(map(int, line.strip().split())) #все числа после этих двух рядов
color = numbers[0] #первый столбец это цвета
coords = numbers[1:] #r1 c1 ... rn cn
cells = [coords[i:i + 2] for i in range(0, len(coords), 2)] #[r1,c1 ... rn,cn] = [[r1,c1],...,[rn,cn]]
stones[color] = cells
return numRows, numCols, stones;
def stone_normalize(coords, color=None):
'''find out the shape of the stones '''
rows, cols = zip(*coords)
min_row, max_row = min(rows), max(rows)
min_col, max_col = min(cols), max(cols)
height = max_row - min_row + 1
width = max_col - min_col + 1
norm_rows = map(lambda row: row - min_row, rows)
norm_cols = map(lambda col: col - min_col, cols)
norm_coords = list(zip(norm_rows, norm_cols))
if color is not None: # print figures just for debug
matrix_for_shape = [[0]*width for _ in range(height)]
for row, col in norm_coords:
matrix_for_shape[row][col] = color
print(*map(" ".join, (map(lambda x: str(x) if x else " ", row) for row in matrix_for_shape)), sep="\n")
return (width, height, norm_coords)
def place_stone(stones, n_rows, n_cols, field=None):
if not stones: # всё разместили, выходим
return field
if field is None: # создаём поле при первом вызове
field = [[0]*n_cols for _ in range(n_rows)]
for color in stones:
rest_stones = stones.copy() # оставшиеся камни
width, height, coords = rest_stones.pop(color)
for row in range(n_rows - height + 1):
for col in range(n_cols - width + 1):
if all(field[row+r][col+c] == 0 for r, c in coords): # можно разместить
new_field = copy.deepcopy(field)
for r, c in coords:
new_field[row+r][col+c] = color
result = place_stone(rest_stones, n_rows, n_cols, new_field)
if result:
return result
def main():
ROWS,COLS, stones = readStones("210.txt")
#информация о камне stones[color]
#ключ - его цвет, значение - его размер и координаты его частей
for color in stones:
stones[color] = stone_normalize(stones[color], color)
print('-'*10)
# сортируем камни от большего к меньшему
#stones = {k: v for k, v in sorted(stones.items(), key=lambda item: len(item[1][-1]), reverse=True)}
stones = {k: v for k, v in sorted(stones.items(), key=lambda item: (item[1][0]*item[1][1], len(item[1][-1])), reverse=True)}
result = place_stone(stones, ROWS, COLS)
if result:
print(*map(" ".join, (map(str, row) for row in result)), sep="\n")
else:
print("Невозможно разместить!")
main()
у меня получилось очень похожее решение (видимо потому что использовал ту же логику):
with open('matr.txt') as f:
n_row = int(f.readline().strip())
n_col = int(f.readline().strip())
st = [[*map(int, l.split())] for l in f.readlines()]
def tetr(matr, stones):
if not stones: return matr
c, *coords = stones.pop()
f = lambda x,y: [i-y for i in x] # определяем форму (положение) камней
row, col = f(coords[::2],min(coords[::2])), f(coords[1::2],min(coords[1::2]))
for x in range(n_row-len(set(row))+1):
for y in range(n_col-len(set(col))+1):
if all(matr[i+x][j+y]==0 for i,j in zip(row,col)):
matr2 = [m.copy() for m in matr]
for i,j in zip(row,col):
matr2[i+x][j+y] = c
res = tetr(matr2, stones.copy()) # рекурсивно перебираем комбинации
if res: return res
return None
field = [[0]*n_col for _ in range(n_row)] # исходное поле
res = tetr(field, st)
print(*res or ['нет решения'], sep='\n')
результат:
[4, 5, 5, 1, 1]
[4, 5, 5, 5, 3]
[4, 5, 5, 5, 3]
[4, 4, 2, 6, 6]
[4, 2, 2, 6, 6]