Here is a number grid:
And here is the rule for how to move:
A move consists of selecting two adjacent squares (either vertically, horizontally or diagonally) and dividing the sum of the two numbers evenly among those two squares. In the case that the sum of the numbers is odd, add an extra one in the square which originally had the greatest number.
Your challenge is to find the minimum number of moves it takes for all the squares in the grid to be greyed out without all the numbers ending with 22. (Note: Now I'm going to use the word lose to describe freezing the whole grid without each square in the grid ending with 22.)
Here is an example of me losing on the spot, the first one at normal speed, the second one a time lapse. I ended up with 45, though that was a random no-strategy play:
I programmed the app/tool/game I used in the example above using python. You can use the code to also have access to the program:
import pygame
# You can change the grid & size to whatever you like
grid = [[33, 7, 35, 26, 30],
[1, 8, 38, 29, 17],
[16, 19, 9, 37, 21],
[20, 36, 3, 11, 15],
[32, 14, 34, 31, 28]]
size = 80
line = 5
win = sum([c for r in grid for c in r]) // len([c for r in grid for c in r])
pygame.init()
pygame.font.init()
font = pygame.font.SysFont("Arial", size-10)
wn = pygame.display.set_mode((600, 600))
grid = [c for c in zip(*grid)]
class Square():
def __init__(self, pos, num):
self.x = pos[0] * size + line
self.y = pos[1] * size + line
self.num = num
self.color = (255, 255, 255)
self.rect = pygame.Rect(self.x, self.y, size-line, size-line)
self.frozen = False
def clear(self):
self.color = (255, 255, 255)
def draw(self):
if self.frozen:
pygame.draw.rect(wn, (150, 150, 150), self.rect)
else:
pygame.draw.rect(wn, self.color, self.rect)
if self.num == win:
pygame.draw.circle(wn, (100, 255, 100), (self.x+size//2, self.y+size//2), size//4)
text = font.render(str(self.num), True, (0, 0, 0))
if len(str(self.num)) == 1:
wn.blit(text, (self.x+size*.25, self.y*.98))
else:
wn.blit(text, (self.x+size*.055, self.y*.98))
class Box():
def __init__(self, grid, square=None):
self.square = square
self.grid = grid
self.clicked = []
def box(self): # Returns a list of all adjancent squares that can change the number of the selected square
x, y = self.square.x//size, self.square.y//size
y1 = x-1 if x else 0
y2 = len(self.grid)+2 if x > len(self.grid)+2 else x+2
x1 = y-1 if y else 0
x2 = len(self.grid[0])+2 if y > len(self.grid[0])+2 else y+2
b = []
for r in self.grid[y1:y2]:
for c in r[x1:x2]:
if abs(c.num - self.grid[x][y].num) > 1:
b.append(c)
elif c != self.square:
c.clear()
return b
def color(self, color):
for square in self.box():
square.color = color
def clear(self):
for c in self.clicked:
c.clear()
self.clicked.clear()
def show_moves(num):
moves = f'{num} move' if num == 1 else f'{num} moves'
text = font.render(moves, True, (255, 255, 255))
wn.blit(text, (line, size*len(squares)))
def avg(n1, n2):
n = n1 + n2
if n % 2:
if n1 > n2:
return n // 2 + 1, n // 2
return n // 2, n // 2 + 1
return n // 2, n // 2
def won(grid):
if all(square.num == win for row in grid for square in row):
return 'You Win!'
return 'You Lose!'
squares = [[Square((i, j), col) for j, col in enumerate(row)] for i, row in enumerate(grid)]
box = Box(squares)
box2 = Box(squares)
total = 0
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
if event.type == pygame.MOUSEBUTTONDOWN:
for row in squares:
for square in row:
if square.rect.collidepoint(pygame.mouse.get_pos()):
if not square.frozen:
if not box.clicked:
box.clicked.append(square)
square.color = (140, 255, 255)
box.square = square
box.color((255, 255, 140))
else:
if square in box.box():
box.clicked.append(square)
if square == box.clicked[0]:
box.color((255, 255, 255))
box.clear()
if len(box.clicked) == 2:
total += 1
box.clicked[0].num, box.clicked[1].num = avg(box.clicked[0].num, box.clicked[1].num)
box.color((255, 255, 255))
box.clear()
wn.fill((0, 0, 0))
for i in range(len(squares)):
for j in range(len(squares[i])):
adjacent = []
for k in range(max(0,i-1), min(len(squares), i+2)):
for l in range(max(0,j-1), min(len(squares[k]), j+2)):
if i != k or j != l:
adjacent.append((k, l))
if not any((k, l) for (k, l) in adjacent if abs(squares[i][j].num - squares[k][l].num) > 1):
squares[i][j].frozen = True
elif squares[i][j].frozen:
squares[i][j].frozen = False
for row in squares:
for square in row:
square.draw()
show_moves(total)
pygame.display.update()
if all(square.frozen for row in squares for square in row):
wn.fill((0, 0, 0))
text = font.render(won(squares), True, (255, 255, 255))
wn.blit(text, (line, size*len(squares)//2))
show_moves(total)
pygame.display.update()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
break