Basis: een volgende rastertoestand

Deze pagina bevat uitvoerbare code.

Een raster stelt bezette (1) en lege (0) vakken voor. Bereken een volgende toestand zonder het invoerbord onderweg te veranderen. Gebruik een rechthoekige lijst van lijsten. Coördinaten buiten het bord tellen als 0 en worden nooit geschreven.

Voorbeeld en interfaces

Bij een 5x5-blinker wordt de verticale lijn horizontaal:

00000       00000
00100       00000
00100  ->   01110
00100       00000
00000       00000

Werk in deze volgorde: count_neighbors, next_cell, next_generation. De laatste functie is functiecompositie: zij gebruikt de eerste twee.

1. Buren tellen

Ontwerp de functie. Loop over de acht relatieve posities, tel buiten het bord als 0 en test een hoek, rand en binnen-cel.

Tussenstap. Voor bord[0][0] kijk je naar de acht posities rond de hoek. Alleen (0, 1) en (1, 0) liggen binnen dit bord; de waarden daar zijn 1 en 0, dus de telling is 1. Schrijf dit eerst als een zin op en vertaal het daarna naar je lus.

def count_neighbors(board, row, col):
    # loop over de acht relatieve buurposities
    # tel buiten het bord als 0
    pass

bord = [[1, 1, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
assert count_neighbors(bord, 0, 0) == 1
assert count_neighbors(bord, 0, 2) == 2
assert count_neighbors(bord, 2, 2) == 2

2. De regel voor één cel

Schrijf next_cell(board, row, col). Een levende cel blijft leven met twee of drie buren. Een dode cel wordt levend met precies drie buren. Anders is de uitkomst 0.

def next_cell(board, row, col):
    # gebruik count_neighbors en de vier regels hierboven
    pass

3. Een volledige generatie

Gebruik deze gegeven kopieerfunctie. Bereken elke cel uit board en schrijf alleen naar result. Voeg assertions toe voor de blinker en het onveranderde invoerbord.

def copy_board(board):
    result = []
    for row in board:
        result = result + [row[:]]
    return result

def next_generation(board):
    result = copy_board(board)
    # bereken elke cel uit board en schrijf naar result
    pass

blinker = [[0, 0, 0, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 0, 0]]
verwacht = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
origineel = copy_board(blinker)
assert next_generation(blinker) == verwacht
assert blinker == origineel

4. Korte functiecompositie

Maak generaties(board, aantal) door next_generation herhaald toe te passen.

Controleer eerst je tussenstap: na één toepassing op de verticale blinker verwacht je een horizontale rij levende cellen in de middelste rij. Controleer daarna pas dat twee generaties weer gelijk zijn aan het oorspronkelijke bord.

def generaties(board, aantal):
    huidig = board
    for _ in range(aantal):
        huidig = next_generation(huidig)
    return huidig
assert generaties(blinker, 2) == blinker