Как решить эту задачу от яндекса?

Дана доска размером M × N клеток. Клетка может находиться в одном из двух состояний: 1 — живая, 0 — мёртвая. Каждая клетка взаимодействует с восемью соседями. Правила таковы:

Живая клетка, у которой меньше двух живых соседей, погибает.

Живая клетка, у которой два или три живых соседа, выживает.

Живая клетка, у которой больше трёх живых соседей, погибает.

Мёртвая клетка, у которой три живых соседа, возрождается.

Напишите программу, которая будет:
— случайным образом генерить стартовое состояние;
— уметь получать его из файла (способ выбирается через параметры запуска в консоли);
— каждую секунду выводить в консоль новое состояние доски.

Вот мой код, генерирующий матрицу с рандомными столбцами и строками:

import random

class Matrix:

    def __init__(self, row, col):
        self.n = row
        self.matrix = [[random.randrange(0, 2) for a in range(col)] for b in range(row)]

    def print(self):
        matrix = self.matrix
        for im in range(len(matrix)):
            print(matrix[im])

Matrix(random.randint(5, 10), random.randint(5, 10)).print()


Как мне лучше сделать остальную часть? Не понятны две вещи:
1) Как написать условия? Вроде должно выглядеть так: если у клетки, допустим, три мертвых соседа, то она меняет значение с мертвой(0) на живую(1), то есть возрождается. И тому подобные условия. Я не понимаю, как клетку научить опознавать значения по соседству. Но есть еще усложнение - клетки должны менять состояния каждую секунду, то есть вся таблица будет обновляться ежесекундно, это еще больше сбивает с толку.
2) Что значит программа должна уметь получать стартовое состояние из файла? То есть, допустим, матрицу сохранять в csv файл, а потом из него получать таблицу и её использовать с помощью метода open, верно?
  • Вопрос задан
  • 878 просмотров
Решения вопроса 2
@kunjut19
поищите игра "жизнь". В интернете куча решений.

А вообще:
1) берете клетку (в цикле обходите каждую клетку поля)
2) циклом обозреваете клетки вокруг нее
3) если соседняя клетка живая, увеличиваете счетчик живых соседей на 1
4) после обхода всех соседних клеток (а их 8), смотрите - если клетка, которую вы рассматриваете живая, то
а) оставляете живой, если счетчик живых соседей равен 2 или 3 - оставляете все как есть
б) если другое значение - меняете ее значение на 0
5) если клетка изначально мертвая, то при значении счетчика живых соседей, равного 3, оживляете

Прошлись таким образом по всем клеткам доски, подождали секунду и заново запустили весь этот процесс

Стартовое значение из файла (как я понимаю) - это изначалое расположение живых и мертвых клеток.

У меня есть решение на javascript. Если понимаете этот язык, могу скинуть вам код, а вы переделаете под python
Ответ написан
kshnkvn
@kshnkvn Куратор тега Python
t.me/kshnkvn
Смотри что на г-кодил. Но чую где то напортачил, 100%
from random import randint, randrange
from pprint import pprint
from os import system
from copy import deepcopy


class CellLife:

    def __init__(self, x = None, y = None):
        self.x, self.y = [randrange(10, 25) for _ in range(2) if x is None or y is None]
        self.field = [[randint(0, 1) for _ in range(self.x)] for _ in range(self.y)]
        self.field_state = None

    def environment(self, row, index):
        left_neighbors = row[:index][-8:]
        right_neighbors = row[index:][1:9:]
        while len(left_neighbors + right_neighbors) > 8:
            if left_neighbors < right_neighbors:
                right_neighbors = right_neighbors[:-1]
            else:
                left_neighbors = left_neighbors[1:]
        return left_neighbors + right_neighbors

    def dead_or_alive(self, env, cell):
        state = None
        if cell == 1:
            if env.count(1) < 2 or env.count(1) > 3:
                state = False
            elif env.count(1) in (2, 3):
                state = True
        else:
            if env.count(1) == 3:
                state = True
        return state

    def start_survival(self):
        while self.field_state != self.field:
            self.field_state = deepcopy(self.field)
            for r_index, row in enumerate(self.field):
                for c_index, cell in enumerate(row):
                    env = self.environment(row, c_index)
                    state = self.dead_or_alive(env, cell)
                    if state is not None:
                        if state is True:
                            self.field[r_index][c_index] = 1
                        else:
                            self.field[r_index][c_index] = 0
                        system('cls')
                        pprint(self.field)
        

cell_field = CellLife()
cell_field.start_survival()
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
Сдаётся мне, что задача для реализации в несколько потоков: ограничение времени и произвольный размер поля - не спроста!
Ответ написан
@Al6xand6r
Просто еще один вариант "Жызни"))) Не благодарите)))

import os
import random
import time

class Colony:
  def __init__(self, width, height):
    self.width = width
    self.height = height
    self.field = [
      [random.randint(0,1) for i in range(width)] for j in range(height)
      ]

  def live(self):
    """
    Check cell's neighbors and modify cell's state.
    """
    for row in range(0,self.height):
      for col in range(0,self.width):
        live_neighbours = self.check_neighbours(row, col)
        if live_neighbours < 2:
          # die
          self.field[row][col] = 0
        # elif live_neighbours in (2,3):
          # remain as is
        elif live_neighbours == 3:
          # raise
          self.field[row][col] = 1
        elif live_neighbours > 3:
          # die
          self.field[row][col] = 0

  def check_neighbours(self, row, col):
    live_neighbours = 0
    for r in (row - 1, row, row + 1):
      for c in (col - 1, col, col + 1):
        if c >=0 and c < self.width and r >=0 and r < self.height:
          if self.field[r][c] and not (c == col and r == row):
            live_neighbours += 1
    return live_neighbours


  def redraw(self):
    """
    Clears screen and draws actual field state.
    """
    os.system('clear')
    for row in self.field:
      for cell in row:
        print(cell, end='')
      print('', end='\n')


if __name__ == '__main__':
  # TODO: check for filename or field dimensions in comand line parameters
  # dimensions are hardcoded for now.
  start_time = time.time()
  first_loop = 1
  width = 20
  height = 20
  colony = Colony(width, height)
  while True:
    colony.live()
    if time.time() - start_time > 0.99 or first_loop:
      first_loop = 0
      start_time = time.time()
      colony.redraw()
      print('Ctrl + C to stop')


Куда ходить в Яднекс за своей кучей денег?))))
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы