Skip to content

Instantly share code, notes, and snippets.

@coderodde
Last active April 22, 2024 03:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save coderodde/cd4f7b8b4a6f45662348f4a9ee73a208 to your computer and use it in GitHub Desktop.
Save coderodde/cd4f7b8b4a6f45662348f4a9ee73a208 to your computer and use it in GitHub Desktop.
A class for generating snail matrices.
type Matrix = list[list[int]]
"""
This class is responsible for generating snail matrices of dimensions n * n.
"""
class SnailMatrixGenerator:
"""
Constructs this generator.
"""
def __init__(self, n):
self.n = n
self.matrix = [[0] * n for _ in range(n)]
self.deltas = [(1, 0), (0, 1), (-1, 0), (0, -1)]
self.delta_index = 0
self.current_coordinate_x = 0
self.current_coordinate_y = 0
"""
Sets the given value at the current cursor location.
"""
def set_value_at_cursor(self, value):
self.matrix[self.current_coordinate_y][self.current_coordinate_x] = value
"""
Moves the current cursor location to the next valid position.
"""
def move_cell_cursor_to_next_location(self):
save_cx = self.current_coordinate_x
save_cy = self.current_coordinate_y
while True:
x = save_cx + self.deltas[self.delta_index][0]
y = save_cy + self.deltas[self.delta_index][1]
if self.check_current_coordinate_is_valid(x, y):
self.current_coordinate_x = x
self.current_coordinate_y = y
return
self.get_next_direction()
"""
Makes sure that (x, y) is within the matrix and is not yet set.
"""
def check_current_coordinate_is_valid(self, x, y):
# Here, the only possible range for x is [-1, self.n].
if x == -1 or x == self.n:
return False
# Here, the only possible range for y is [-1, self.n].
if y == -1 or y == self.n:
return False
# Make sure that the current position is not yet set:
return self.matrix[y][x] == 0
"""
Changes the current progression direction.
"""
def get_next_direction(self):
if self.delta_index == len(self.deltas) - 1:
# Go wrap around:
self.delta_index = 0
else:
# Just proceed to the next one:
self.delta_index += 1
"""
Generates the snail pattern matrix.
"""
def generate(self):
value = 1
while True:
self.set_value_at_cursor(value)
if value == self.n * self.n:
# Here, the matrix is full.
return self.matrix
value += 1
# Move to the next cursor location:
self.move_cell_cursor_to_next_location()
if __name__ == "__main__":
def print_matrix(m: Matrix) -> None:
padding = len(str(len(m) ** 2))
for row in m:
print(" ".join(f"{num:>{padding}}" for num in row))
smg = SnailMatrixGenerator(4)
m = smg.generate()
print_matrix(m)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment