Boter, kaas en eieren

Deze pagina bevat uitvoerbare code.

De acht functies controleren of er drie of n keer hetzelfde karakter op een rij staat, vanaf een startpositie en in een gegeven richting, in een 2D-lijst array.

De cel hieronder is de gegeven code uit het practicum, woordelijk overgenomen. Hier draait ze wél, zodat we zeker weten dat wat de student overneemt ook werkt.

# een functie om een 2D-lijst af te drukken
def print_2d(array):
    """Drukt de 2D-lijst array af, met een regel per rij.

    Argument: array, een 2D-lijst
    Resultaat: None (geen returnwaarde)
    """
    n_rows = len(array)
    n_cols = len(array[0])

    for row_ix in range(n_rows):  # n_rows == aantal rijen
        for col_ix in range(n_cols):  # n_cols == aantal kolommen
            print(array[row_ix][col_ix], end=" ")
        print()

    return None  # dit is impliciet aanwezig
    # als er geen return-statement aanwezig is


# een paar tests voor print_2d
array = [["X", " ", "O"], ["O", "X", "O"]]
print("2-row, 3-col array is")
print_2d(array)

array = [["X", "O"], [" ", "X"], ["O", "O"], ["O", "X"]]
print("4-row, 2-col array is")
print_2d(array)


# maak een 2D-lijst van een eendimensionale string
def create_array(n_rows, n_cols, s):
    """Geeft een 2D-lijst terug met n_rows rijen en n_cols kolommen.

    De gegevens komen uit de string s: eerst de eerste rij vol,
    dan de tweede, enzovoort. We testen alleen met genoeg gegevens!
    """
    array = []
    for _ in range(n_rows):
        new_row = []
        for _ in range(n_cols):
            new_row += [s[0]]  # voeg dat karakter toe
            s = s[1:]  # verwijder het eerste karakter
        array += [new_row]
    return array


# een paar tests voor create_array:
array = [["X", " ", "O"], ["O", "X", "O"]]
new_array = create_array(2, 3, "X OOXO")
assert new_array == array
print("Is new_array == array? moet True zijn:", new_array == array)

array = [["X", "O"], [" ", "X"], ["O", "O"], ["O", "X"]]
new_array = create_array(4, 2, "XO XOOOX")
assert new_array == array
2-row, 3-col array is
X   O 
O X O 
4-row, 2-col array is
X O 
  X 
O O 
O X 
Is new_array == array? moet True zijn: True

Drie op een rij

Alle vier de functies hebben dezelfde vorm: eerst de grenscontroles, dan een lus over drie posities.

Opdracht 1

def in_a_row_3_east(char, row_start, col_start, array):
    """Geeft True terug als er vanaf (row_start, col_start) drie keer char naar het oosten staat."""
    n_rows = len(array)  # aantal rijen is len(array)
    n_cols = len(array[0])  # aantal kolommen is len(array[0])

    if row_start >= n_rows:
        return False  # buiten de grenzen van de rijen

    # andere grenscontroles...
    if col_start > n_cols - 3:
        return False  # buiten de grenzen van de kolommen

    # zijn alle gegevenselementen correct?
    for ix in range(3):  # lusindex is ix
        if array[row_start][col_start + ix] != char:  # controleer op fouten
            return False  # fout gevonden; geef False terug

    return True  # geen fouten gevonden in de lus; geef True terug
# tests voor in_a_row_3_east
array = create_array(3, 4, "XXOXXXOOOOOO")
assert not in_a_row_3_east("X", 0, 0, array)
assert in_a_row_3_east("O", 2, 1, array)
assert not in_a_row_3_east("X", 2, 1, array)
assert not in_a_row_3_east("O", 2, 2, array)

Opdracht 2

def in_a_row_3_south(char, row_start, col_start, array):
    """Geeft True terug als er vanaf (row_start, col_start) drie keer char naar het zuiden staat."""
    n_rows = len(array)
    n_cols = len(array[0])

    if col_start >= n_cols:
        return False  # buiten de grenzen van de kolommen

    if row_start > n_rows - 3:
        return False  # buiten de grenzen van de rijen

    for ix in range(3):
        if array[row_start + ix][col_start] != char:
            return False

    return True
# tests voor in_a_row_3_south
array = create_array(4, 4, "XXOXXXOXXOO OOOX")
assert in_a_row_3_south("X", 0, 0, array)
assert not in_a_row_3_south("O", 2, 2, array)
assert not in_a_row_3_south("X", 1, 3, array)
assert not in_a_row_3_south("O", 42, 42, array)

Opdracht 3

def in_a_row_3_southeast(char, row_start, col_start, array):
    """Geeft True terug als er vanaf (row_start, col_start) drie keer char naar het zuidoosten staat."""
    n_rows = len(array)
    n_cols = len(array[0])

    if col_start > n_cols - 3:
        return False

    if row_start > n_rows - 3:
        return False

    for ix in range(3):
        if array[row_start + ix][col_start + ix] != char:
            return False

    return True
# tests voor in_a_row_3_southeast
array = create_array(4, 4, "XOOXXXOXX XOOOOX")
assert in_a_row_3_southeast("X", 1, 1, array)
assert not in_a_row_3_southeast("X", 1, 0, array)
assert in_a_row_3_southeast("O", 0, 1, array)
assert not in_a_row_3_southeast("X", 2, 2, array)

Opdracht 4

def in_a_row_3_northeast(char, row_start, col_start, array):
    """Geeft True terug als er vanaf (row_start, col_start) drie keer char naar het noordoosten staat."""
    n_rows = len(array)
    n_cols = len(array[0])

    if col_start > n_cols - 3:
        return False

    if row_start < 3 - 1:  # naar het noorden is er te weinig ruimte
        return False

    if row_start >= n_rows:
        return False

    for ix in range(3):
        if array[row_start - ix][col_start + ix] != char:
            return False

    return True
# tests voor in_a_row_3_northeast
array = create_array(4, 4, "XOXXXXOXXOXOOOOX")
assert in_a_row_3_northeast("X", 2, 0, array)
assert in_a_row_3_northeast("O", 3, 0, array)
assert not in_a_row_3_northeast("O", 3, 1, array)
assert not in_a_row_3_northeast("X", 3, 3, array)

Van 3 naar N: N op een rij

Het generaliseren zit op drie plekken: de grenscontrole rekent met n in plaats van met 3, de lus loopt n keer, en de richting blijft precies zoals ze was.

Opdracht 5

def in_a_row_n_east(char, row_start, col_start, array, n):
    """Geeft True terug als er vanaf (row_start, col_start) n keer char naar het oosten staat."""
    n_rows = len(array)
    n_cols = len(array[0])

    if row_start >= n_rows:
        return False

    if col_start > n_cols - n:
        return False

    for ix in range(n):
        if array[row_start][col_start + ix] != char:
            return False

    return True
# tests voor in_a_row_n_east
array = create_array(5, 5, "XXOXXXOOOOOOXXXX XXXOOOOO")
assert in_a_row_n_east("O", 1, 1, array, 4)
assert in_a_row_n_east("O", 1, 3, array, 2)
assert not in_a_row_n_east("X", 3, 2, array, 4)
assert in_a_row_n_east("O", 4, 0, array, 5)

Opdracht 6

def in_a_row_n_south(char, row_start, col_start, array, n):
    """Geeft True terug als er vanaf (row_start, col_start) n keer char naar het zuiden staat."""
    n_rows = len(array)
    n_cols = len(array[0])

    if col_start >= n_cols:
        return False

    if row_start > n_rows - n:
        return False

    for ix in range(n):
        if array[row_start + ix][col_start] != char:
            return False

    return True
# tests voor in_a_row_n_south
array = create_array(5, 5, "XXOXXXOOOOOOXXXXOXXXOOOXO")
assert not in_a_row_n_south("X", 0, 0, array, 5)
assert in_a_row_n_south("O", 1, 1, array, 4)
assert not in_a_row_n_south("O", 0, 1, array, 6)
assert in_a_row_n_south("X", 4, 3, array, 1)

Opdracht 7

def in_a_row_n_southeast(char, row_start, col_start, array, n):
    """Geeft True terug als er vanaf (row_start, col_start) n keer char naar het zuidoosten staat."""
    n_rows = len(array)
    n_cols = len(array[0])

    if col_start > n_cols - n:
        return False

    if row_start > n_rows - n:
        return False

    for ix in range(n):
        if array[row_start + ix][col_start + ix] != char:
            return False

    return True
# tests voor in_a_row_n_southeast
array = create_array(5, 5, "XOO XXXOXOOOXXXXOXXXOOOXX")
assert in_a_row_n_southeast("X", 1, 1, array, 4)
assert not in_a_row_n_southeast("O", 0, 1, array, 3)
assert in_a_row_n_southeast("O", 0, 1, array, 2)
assert not in_a_row_n_southeast("X", 3, 0, array, 2)

Opdracht 8

def in_a_row_n_northeast(char, row_start, col_start, array, n):
    """Geeft True terug als er vanaf (row_start, col_start) n keer char naar het noordoosten staat."""
    n_rows = len(array)
    n_cols = len(array[0])

    if col_start > n_cols - n:
        return False

    if row_start < n - 1:  # naar het noorden is er te weinig ruimte
        return False

    if row_start >= n_rows:
        return False

    for ix in range(n):
        if array[row_start - ix][col_start + ix] != char:
            return False

    return True
# tests voor in_a_row_n_northeast
array = create_array(5, 5, "XOO XXXOXOOOXOXXXOXXXOOXX")
assert in_a_row_n_northeast("X", 4, 0, array, 5)
assert in_a_row_n_northeast("O", 4, 1, array, 4)
assert not in_a_row_n_northeast("O", 2, 0, array, 2)
assert not in_a_row_n_northeast("X", 0, 3, array, 1)

Randgevallen

# een randgeval per functie: een positie net buiten de grenzen
array = create_array(3, 3, "XXXXXXXXX")

assert not in_a_row_3_east("X", 0, 1, array)
assert not in_a_row_3_south("X", 1, 0, array)
assert not in_a_row_3_southeast("X", 1, 1, array)
assert not in_a_row_3_northeast("X", 1, 0, array)

assert not in_a_row_n_east("X", 0, 1, array, 3)
assert not in_a_row_n_south("X", 1, 0, array, 3)
assert not in_a_row_n_southeast("X", 1, 1, array, 3)
assert not in_a_row_n_northeast("X", 1, 0, array, 3)

# n gelijk aan 1 vindt altijd het element op de startpositie zelf
assert in_a_row_n_east("X", 2, 2, array, 1)
assert in_a_row_n_northeast("X", 0, 0, array, 1)