from itertools import product
import copy

# Grid class with basic functionality
class Grid:
	def __init__(self, scale_x, scale_y, content):
		self.ScaleX = scale_x
		self.ScaleY = scale_y
		self.Content = copy.deepcopy(content)

	def tile_get(self, index_x, index_y):
		return self.Content[index_y][index_x]

	def tile_set(self, index_x, index_y, value):
		self.Content[index_y][index_x] = value

	def tile_move(self, index_x, index_y, repetitions):
		sample_index_offsets = [
			(+0, +0),
			(+1, +0),
			(-1, +0),
			(+0, +1),
			(+0, -1),
		]

		for sample_index_offset in sample_index_offsets:
			sample_index_x = index_x + sample_index_offset[0]
			sample_index_y = index_y + sample_index_offset[1]

			sample_index_invalid = sample_index_x < 0 or sample_index_x >= self.ScaleX or sample_index_y < 0 or sample_index_y >= self.ScaleY
			if sample_index_invalid:
				continue

			sample_value_this = self.tile_get(sample_index_x, sample_index_y)
			sample_value_next = (sample_value_this - repetitions + 10) % 10

			self.tile_set(sample_index_x, sample_index_y, sample_value_next)

# Grid setup
grid_scale_x = 7
grid_scale_y = 7
grid_content = [
	[0, 0, 5, 3, 2, 2, 3],
	[3, 6, 6, 7, 5, 9, 7],
	[9, 1, 6, 0, 6, 3, 2],
	[4, 2, 3, 0, 4, 3, 3],
	[1, 6, 8, 7, 3, 1, 7],
	[3, 3, 6, 6, 2, 0, 6],
	[7, 5, 6, 2, 3, 9, 9],
]

# Iterate through all possible base row moves (cartesian product)
for grid_moves_base in product(range(10), repeat=grid_scale_x):

	# Create grid copy
	grid = Grid(grid_scale_x, grid_scale_y, grid_content)

	# Apply base row moves to grid
	for grid_index_x in range(grid_scale_x):
		grid.tile_move(grid_index_x, 0, grid_moves_base[grid_index_x])

	# Apply cascading moves to all but the last row, such that said rows have only values zero
	for grid_index_y in range(1, grid_scale_y):
		for grid_index_x in range(grid_scale_x):
			grid.tile_move(grid_index_x, grid_index_y, grid.tile_get(grid_index_x, grid_index_y - 1))

	# Check whether or not the last row is only zeroes - and thus the base moves were valid - or not
	grid_valid = True
	for grid_index_x in range(grid_scale_x):
		grid_valid = grid.tile_get(grid_index_x, grid_scale_y - 1) == 0
		if not grid_valid:
			break

	if not grid_valid:
		continue

	# Note that all the moves can be extrapolated from the base moves
	print(grid_moves_base)

	break