Elke oefening kan worden opgelost met de theorie/technieken die tot en met dit hoofdstuk zijn overlopen. Echter worden in de voorbeeldoplossingen soms meer geavanceerde technieken gebruikt die tot een meer elegante oplossingen leiden. Noteer bovendien dat er steeds verschillende oplossingen mogelijk zijn.

H06.1

1 2 3 4 - 4 3 2 1

t = int(input())
l = []
for _ in range(t):
    x = input()
    l.append(x)

for el in l[::-1]:
    print(el)

Intersectie

def uniek(x: list) -> list:
    r = []
    for i in x:
        if i not in r:
            r.append(i)
    return r

def intersectie(l1: list, l2: list) -> list:
    r = []
    l1 = uniek(l1)
    l2 = uniek(l2)
    for i in l1:
        if i in l2:
            r.append(i)
    return r

Priemgetallen

def deelbaar(n1: int, n2: int) -> bool:
    return n1 % n2 == 0
m = int(input())
priemgetallen = []
for i in range(2, m+1):
    priem = True
    for j in priemgetallen:
        if deelbaar(i, j):
            priem = False
    if priem:
        priemgetallen.append(i)
print(priemgetallen)

H06.2

DNA Vector

def vector(seq):

    # verplaatsingen vastleggen op basis van nucleotiden
    verplaatsing = {'A': (-1, 0), 'T': (1, 0), 'C': (0, 1), 'G': (0, -1)}
    
    # vector start in de oorsprong
    x, y = 0, 0
    vector = [(x, y)]

    # verplaatsingen uitvoeren bij het aflopen van de sequentie
    for base in seq.upper():

        # bepaal de volgende positie
        dx, dy = verplaatsing[base]
        x += dx
        y += dy

        # positie achteraan toevoegen aan de vector
        vector.append((x, y))
        
    # vector met bezochte punten teruggeven
    return vector

def replicatie(seq):

    # bepaal positie met maximale en minimale y-coördinaat
    maxy, maxp = 0, 0
    miny, minp = 0, 0
    for index, (_, y) in enumerate(vector(seq)):

        # maximale y-coördinaat bijwerken (indien nodig)
        if y > maxy:
            maxy = y
            maxp = index

        # minimale y-coördinaat bijwerken (indien nodig)
        if y < miny:
            miny = y
            minp = index
           
    # geef positie met maximale en minimale y-coördinaat terug 
    return maxp, minp

def sequentie(vector):

    # nucleotiden vastleggen op basis van verplaatsingen
    nucleotide = {(-1, 0): 'A', (1, 0): 'T', (0, 1): 'C', (0, -1): 'G'}
    
    # reeks nucleotiden afleiden uit verschil tussen twee opeenvolgende posities
    return ''.join(
        nucleotide[(x2 - x1, y2 - y1)]
        for (x1, y1), (x2, y2) in zip(vector, vector[1:])
    )

Herschikking

def verdelen(woord, groepen):
    
    # nagaan of woordlengte een veelvoud is van het aantal groepen
    assert not len(woord) % groepen, 'ongeldige verdeling'

    # lengte van elk groep bepalen
    lengte = len(woord) // groepen
    
    # woord verdelen in groepen van gelijke lengte
    return [woord[groep * lengte:(groep + 1) * lengte] for groep in range(groepen)]
    
def herschikken(woorden, groepen):
    # OPMERKING: woorden moeten niet allemaal even lang zijn, maar moeten wel allemaal in groepen van gelijke lengte
    #            kunnen verdeeld worden
    return [''.join(delen) for delen in zip(*(verdelen(woord, groepen) for woord in woorden))]
    

Bitcoins

def winst(waarden, acties):

    # OPMERKING: dit moet niet expliciet getest worden
    assert (
        isinstance(waarden, (list, tuple))
        and all(isinstance(waarde, int) and waarde >= 0 for waarde in waarden)
    ), 'ongeldige waarden'

    # definieer boodschap
    boodschap = 'ongeldige acties'

    # acties omschreven als string en evenveel acties als waarden
    assert isinstance(acties, str) and len(acties) == len(waarden), boodschap

    # geen winst en geen bitcoin bij aanvang van de periode
    winst, bitcoin = 0, False

    # bereken winst gebaseerd op waarden van bitcoins en controleer acties gedurende de periode
    for waarde, actie in zip(waarden, acties):
        if actie == 'K':
            assert not bitcoin, boodschap
            bitcoin = True
            winst -= waarde
        elif actie == 'V':
            assert bitcoin, boodschap
            bitcoin = False
            winst += waarde
        else:
            assert actie == '-', boodschap

    # controleer dat we geen bitcoin hebben op het einde van de periode
    assert not bitcoin, boodschap

    return winst

def optimalisatie(waarden):

    # OPMERKING: dit moet niet expliciet getest worden
    assert (
        isinstance(waarden, (list, tuple))
        and all(isinstance(waarde, int) and waarde >= 0 for waarde in waarden)
    ), 'ongeldige waarden'

    # initialiseer winst en acties aan het begin van de periode
    maximale_winst = 0
    optimale_acties = ''

    # bepaal optimale winst en acties door gretige strategie toe te passen
    bitcoin = False
    for index, waarde in enumerate(waarden[:-1]):
        if bitcoin and waarde > waarden[index + 1]:
            # bitcoin enkel verkopen als die de volgende dag goedkoper wordt
            bitcoin = False
            maximale_winst += waarde
            optimale_acties += 'V'
        elif not bitcoin and waarde < waarden[index + 1]:
            # enkel bitcoin kopen als die de volgende dag duurder wordt
            bitcoin = True
            maximale_winst -= waarde
            optimale_acties += 'K'
        else:
            optimale_acties += '-'

    # laatste dag bitcoin verkopen als je er één hebt
    if bitcoin:
        maximale_winst += waarden[-1]
        optimale_acties += 'V'
    else:
        optimale_acties += '-'

    return maximale_winst, optimale_acties

def maximale_winst(waarden):

    return optimalisatie(waarden)[0]

def optimale_acties(waarden):


    return optimalisatie(waarden)[1]


Ritsen

def samenvoegen(reeks1, reeks2):
    # nieuwe lege lijst aanmaken
    samengevoegd = []

    # verwerk paren elementen tot kortste reeks uitgeput is
    for paar in zip(reeks1, reeks2):

        # voeg volgende paar elementen toe aan lijst
        samengevoegd.extend(paar)

    # samengevoegde lijst teruggeven
    return samengevoegd

def weven(reeks1, reeks2):

    # nieuwe lege lijst aanmaken
    gewoven = []

    # verwerk paren elementen tot langste reeks uitgeput is
    for index in range(max(len(reeks1), len(reeks2))):

        # voeg volgende paar elementen toe aan lijst; gebruik modulo operator om telkens terug te gaan naar het begin
        # als je op het einde van een reeks komt
        gewoven.append(reeks1[index % len(reeks1)])
        gewoven.append(reeks2[index % len(reeks2)])

    # gewoven lijst teruggeven
    return gewoven

def ritsen(reeks1, reeks2):

    # eerst twee reeksen samenvoegen
    geritst = samenvoegen(reeks1, reeks2)

    # kortst en langste reeks bepalen
    kortste, langste = (reeks1, reeks2) if len(reeks1) <= len(reeks2) else (reeks2, reeks1)

    # daarna extra elementen van langste reeks toevoegen (als die er zijn)
    geritst.extend(langste[len(kortste):])

    # geritste lijst teruggeven
    return geritst

Zigzag

def iszigzag(reeks):
    # nagaan of reeks getallen zigzag-gesorteerd is
    return all(
        element == (min if index % 2 else max)(element, reeks[index + 1])
        for index, element in enumerate(reeks[:-1])
    )

def zigzag_traag(reeks):

    # reeks getallen (in place) sorteren van klein naar groot
    reeks.sort()

    # elk niet-overlappend paar getallen (in place) omwisselen
    for index in range(0, len(reeks) - 1, 2):
        reeks[index], reeks[index + 1] = reeks[index + 1], reeks[index]

def zigzag_snel(reeks):

    # voor elk getal op even positie ...
    for index in range(0, len(reeks), 2):

        # ... als kleiner dan vorige getal => omwisselen als vorige bestaat
        if index and reeks[index] < reeks[index - 1]:
            reeks[index], reeks[index - 1] = reeks[index - 1], reeks[index]

        # ... als kleiner dan volgende getal => omwisselen als volgende bestaat
        if index + 1 < len(reeks) and reeks[index] < reeks[index + 1]:
            reeks[index], reeks[index + 1] = reeks[index + 1], reeks[index]