De programmeertaal Python is heel geschikt voor het schrijven van eenvoudige programma’s, maar biedt bovendien verrassende mogelijkheden voor ‘eigen vindingrijkheid’. Zoals het achterstevoren en ondersteboven typen van teksten!

Jan Bouwknegt

1024px Python logo notext.svg
Je komt op internet en social media wel eens ‘ondersteboven’ getypte teksten tegen. Met een beetje inspanningen kan iedereen de letters op zo’n afwijkende manier op scherm en papier toveren, maar hoe pak je dat aan? De zoektermen ‘achterstevoren’ en ‘ondersteboven’ geven in zoekmachines een schrale oogst. Enkele hits leveren wel een tekstvakje waar de tekst ingetypt moet worden, waarna de website het trucje voor je uitvoert, maar dat is niet wat we zoeken. De Engelse synoniemen ‘reverse’ en ‘upside down’ geven wat al meer resultaat, maar helaas toch voornamelijk invuloefeningen.

Op zoek naar informatie over het gebruik van de terminal in Linux, stuitten we op commando’s waarin dit trucje werd gedemonstreerd (https://help.ubuntu.com/community/UsingTheTerminal). Daardoor realiseerden we ons dat dit ook in de programmeertaal Python moet kunnen. En inderdaad zijn er veel uitgewerkte voorbeelden op internet te vinden. In dit artikel demonstreren we je hoe je met Python voortaan zelf je teksten ondersteboven en achterstevoren kunt typen.

Het gebruik van Python
Python is begin jaren 90 ontworpen door de Nederlander Guido van Rossum; de huidige ontwikkeling wordt geleid door de Python Software Foundation. Python is vrije software en draait op Windows 10, Apple OSX en Linux. Het is een ‘interpreter’ en dus langzamer dan programma’s gebouwd met een compiler, maar dankzij IDLE (Intergrated Development and Learning Environment) wordt het gebruik van Python wel weer erg gemakkelijk. In ons experiment met ‘omgekeerde letters’ zorgt IDLE voor het afvangen van fouten, het noodzakelijke inspringen en voor de vereiste platte tekst.

Veel computerbezitters hebben Python voor het oprapen: bij Linux zit het al standaard in de softwarepakketten en bezitters van Raspberry Pi kunnen het direct gebruiken, zelfs compleet met het handige IDLE. Verder is het gratis te downloaden via www.python.org om te installeren op Windows10-machines en Mac OSX-systemen. Het gratis Nederlandstalige boek De Programmeursleerling maakt zelfstudie (met gebruik van IDLE) echt mogelijk en plezierig.

    

Strings in Python

           
 

Een paar belangrijke methoden zijn:

  • len(reeks): geeft lengte van de reeks
  • upper(reeks): geeft alleen hoofdletters
  • lower(reeks): geeft alleen kleine letters
  • strip(reeks): verwijdert voor en achter tekens
  • join(): voegt reeksen samen

Er zijn nog ruim 20 andere methoden en functies
beschikbaar. Bedenk dat een string onveranderbaar is.
Een verandering levert altijd een nieuwe string
op (kopie) van het origineel.

 
     
 

Methoden in dictionaries

 
 
  • keys(): geeft overzicht van de keys
  • values(): geeft nieuw overzicht van de values
  • items(): toont de elementen (keys en values)
    in de dict.
  • clear(): verwijdert alle elementen uit de dict
  • get(key): geeft de waarde (value) van de
    opgegeven key

De verzameling gegevens (items) in een dictionary is niet geordend. De uitgeprinte waarden zien er telkens anders uit.

Een dictionary kan wel veranderen, zowel qua waarden als qua keys. Maar de keys moeten wel uniek zijn.

 

Datastructuren in Python
Voordat we daadwerkelijk aan de slag gaan, eerst wat informatie over de werking van Python. De eenvoudigste datastructuren bestaan uit integers, floats, strings en Booleans. Voor het spelen met getallen zijn strings en directories van belang. In Python wordt een string gemakkelijk herkend door een tekst tussen enkele of dubbele aanhalingstekens: ’dit is een string’ of “dit is een string”. Python kent een aantal mogelijkheden om strings te manipuleren (zie kader).


In dit artikel gebruiken we verder nog de dictionary-datastructuur. Een dictionary wordt ook eenvoudig gedefinieerd door paarsgewijs sleutel en bijbehorende waarde op te geven (key and value). Het zoeken naar de sleutel levert de waarde als resultaat. Een dictionary opent met een accolade en sluit daar ook mee af: { }. Een voorbeeld: namen = {´Jan´:10,´Piet´:3,´Kees´:15}. Zoeken naar de sleutel Jan levert de waarde 10, etc. Ook voor dictionaries bestaan enkele handige methoden (zie kader).

 

       ascii codering 2
Deel uit een tabel
uit het (vrij verkrijgbare
boek) De Programmeurs-
leerling van Sponck

Coderingen in Python
Computers werken met de ASCII-codering voor het weergeven van de codes die op bijna elk toetsenbord voorkomen. Daarbij zijn geen tekens voor letters/cijfers die ‘ondersteboven’ staan, Een vraagteken (?) op de kop gaat nog wel (¿) en zo zijn er nog enkele tekens te vinden. Maar veel verder kom je niet.

Hier komt Python te hulp. Python ondersteunt namelijk Unicode en meer specifiek de UTF-8-code (Unicode Transformation Format), die veel meer tekens en symbolen kent. UTF-8 gebruikt één byte voor de bekende ASCII-tekens en voor alle andere tekens meerdere bytes. Het plezierige hiervan is dat de ASCII-codes zodoende eenvoudig zijn opgenomen in de UTF-8 codering.

De kunst is nu om voor elke normale code (letter of cijfer) een ‘op-de-kop’-representant te vinden. Bijvoorbeeld: a wordt ɐ en A wordt ∀. Het boek De Programmeursleerling geeft ook over het gebruik van de UTF-8-coderingen uitstekende aanwijzingen en voorbeelden. Het praktische nut hiervan is dat een nagenoeg onuitputtelijke bron van symbolen beschikbaar komt. Sommigen gebruiken deze nieuwe symbolen voor het maken van wachtwoorden. In dit artikel worden ze alleen gebruikt voor spelletjes met letters en cijfers, om zo de toepasbaarheid van UTF-8, in combinatie met Python, te demonstreren.

Een UTF-8-code ziet er als volgt uit: A=\u0041; a=\u0061; ɐ=\u0250; ∀=\u1D7E; ¼=\u00BC; ±=\u00B1. De laatste twee zijn ook als invoegcodes in Word beschikbaar (Invoegen > Symbolen > Symbool > Meer symbolen). Het gebruik van hoofd- en kleine letters voor de codes is niet relevant. Het aanroepen van de codes verschilt per computersysteem en per programmeertaal. In dit artikel gebruiken we de codes op de Python-manier.

Een volledig overzicht van de Unicode UTF-8 is te vinden op www.fileformat.info/info/charset/UTF-8/list.htm

    

Voorbeeld van string en substring        

           
 

reeks =”Dit is een substring”

reeks[7:10] = ‘een’;  reeks[:10]  = ‘Dit is een ’,

reeks[11:18] = ‘substring’; ‘

reeks[11:] =’substring’.

De gehele tekst ‘reeks’ uit het voorbeeld

kan dus ook worden weergegeven met

reeks[::]=’Dit is een substring’

 
     
 

Afsluiten printstatement

 
 

# tekst achterstevoren weergeven

#2 oplossingen in de Python taal

tekst = 'dit is een teststring'

# 1: oplossing met while

i = len(tekst)

while i:

    i -= 1

    print(tekst[i],end='')

# resultaat: gnirtstset nee si tid

# print(tekst[i],end=’,’)

# resultaat: g,n,i,r,t,s,t,s,e,t, ,n,e,e, ,s,i, ,t,i,d,                               

# 2: oplossing met eigen functie backstr

def backstr(tekst):

    return tekst[::-1]

print(backstr(tekst))

# resultaat: gnirtstset nee si tid

 

Het werken met codes: achterstevoren
De spelregels voor een string zijn streng, maar er is toch heel veel mogelijk door het concept substring, of deelstring. Van een substring moet, tussen vierkante haken, worden opgegeven, gescheiden door een dubbele punt (:) het begin, het einde en de stapgrootte (die standaard op “1” staat). De algemene notatie voor een substring is dus; string[begin:eind;stapgrootte] of string[start:stop:step]. Lastig daarbij is dat het tellen van de elementen van een string altijd moet beginnen met 0 (nul).

Blijft nog over de stapgrootte. Het verrassende is nu dat de stapgrootte ook negatief mag zijn, dus ook -1. Daarmee wordt de reeks achterstevoren uitgeprint: reeks[::-1] = ‘gnirtsbus nee si tiD’.

Hiermee is het achterstevoren printen in Python wel heel eenvoudig geworden. Maar het kan nog iets worden verfraaid of uitgebreid. Het printstatement kan worden afgesloten met end=” “. Tussen de aanhalingstekens (enkel of dubbel) kan een komma, een of meerdere spaties of een willekeurige tekst staan, die dan bij iedere letter van de tekst wordt afgedrukt (zie kader 'Afsluiten printstatement'). 

 

 

 

 

 

 

Eenvoudige versleuteling
voor wachtwoorden

   
   

teksta = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ                       
abcdefghijklmnopqrstuvwxyz'

tekstb = 'zyxwvutsrqponmlkjihgfedcba
ZYXWVUTSRQPONMLKJIHGFEDCBA'

# maak dict met als keys de teksta en tekstb
# als bijbehorende values

i = 0

l = len(tekstb)

lettertab = {} # begin met lege directory

for lettera in teksta:

    if i< l:

        letterb =tekstb[i]

    else:

        letterb = ' '

    lettertab[lettera] = letterb  # voeg element toe
                                             # aan dictionary

    i+=1

# print(lettertab)

# voer nu de bewerking uit:

for letter in 'JasVanBelofte':

    char = lettertab.get(letter)

    if char == None:

        char = letter

    print(char,end='')

“”” invoer voor dit programma is JasVanBelofte
     en de uitvoer is qZHeZMyVOLUGV.
     Deze uitvoer als invoer geeft weer
     het originele wachtwoord”””

                
       

Gebruik van eenvoudige dictionaries

Python biedt vaak meerdere oplossingen voor een probleem. En meestal zit daar een geheel eigen, verrassende ‘Python-oplossing’ tussen. Dergelijke verrassingen komen ook voor bij het gebruik van dictionaries.

Eerst bekijken we daarom het, soepele, gebruik van dictionaries (dicts). Ze zijn bijvoorbeeld handig bij het maken van een wachtwoord. Een string bestaande uit alle hoofd- en kleine letters van het alfabet wordt teksta genoemd. De tegenovergestelde reeks heet tekstb (zie kader). Met een for-loop worden deze twee strings (tekenreeksen) omgebouwd tot de dictionary lettertab. Dit gebeurt met de methode: lettertab[key] = value, waarbij key en value natuurlijk beide ook stringelementen zijn. Het tussengevoegde commentaar of tekst (voorafgegaan door #) dient ter verduidelijking. De # bij het print statement kan verwijderd worden, waardoor de tussentijdse uitvoer toont hoe de dictionary is opgebouwd. Bedenk daarbij wel dat een dictionary niet geordend is. Dat wil zeggen: de print van de dictionary ziet er iedere keer anders uit, zonder dat wijzigingen zijn aangebracht. Neem als wachtwoord: JasVanBelofte. In het kader is te lezen hoe dit wachtwoord wordt gecodeerd. Ter controle kan nu dit gecodeerde wachtwoord als invoer worden opgegeven. De uitkomst is dan het oorspronkelijke wachtwoord.

 

Het Griekse alfabet                                                  

   
   

teksta = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ                       
abcdefghijklmnopqrstuvwxyz'

tekstb = 'zyxwvutsrqponmlkjihgfedcba
ZYXWVUTSRQPONMLKJIHGFEDCBA'

eerste zin uit het boekenweekgeschenk 2019 van Jan Siebelink

εερστε ζιν υιτ ηετ βοεκενwεεκγεσσηενκ 2019 ωαν Ιαν Σιεβελινκ


JAS VAN BELOFTE:

ΙΑΣ ΩΑΝ ΒΕΛΟΦΤΕ:


Om tien uur vanochtend was er nog niets aan de hand

Ομ τιεν υυρ ωανοσητενδ wασ ερ νογ νιετσ ααν δε ηανδ


griektab=   {'a':'\u03b1','b':'\u03b2','c':'\u03c3','d':'\u03b4','e':'\u03b5',

'f':'\u03c6','g':'\u03b3','h':'\u03b7','i':'\u03b9','j':'\u03be',

'k':'\u03ba','l':'\u03bb','m':'\u03bc','n':'\u03bd','o':'\u03bf',

'p':'\u03c0','q':'\u03d9','r':'\u03c1','s':'\u03c3','t':'\u03c4',

'u':'\u03c5','v':'\u03c9','w':'\u0077','x':'\u03c7','y':'\u03c5',

'z':'\u03b6',

'A':'\u0391','B':'\u0392','C':'\u03a8','D':'\u0394','E':'\u0395',

'F':'\u03a6','G':'\u0393','H':'\u0397','I':'\u0399','J':'\u0399',

'K':'\u039a','L':'\u039b','M':'\u039c','N':'\u039d','O':'\u039f',

'P':'\u03a0','Q':'\u03d8','R':'\u03a1','S':'\u03a3','T':'\u03a4',

'U':'\u03a5','V':'\u03a9','W':'\u0057','X':'\u03a7','Y':'\u03a5',

'Z':'\u0396'}


fp = open("jasvanbelofte.txt")

while True:

    rev = fp.readline()

    if rev == "":

        break

        fp.close()

    print(rev,end='')

   
    for letter in rev:

        char = griektab.get(letter)

        if char == None:

            char = letter

        print(char,end='')

    print(" ")

                

 

In de twee tekenreeksen zijn de letters tegengesteld weergegeven. Door de letters in tekstb te vervangen door de UTF-8-codes voor het Griekse alfabet, wordt de toepassing veel interessanter. Wanneer de kennis van de Griekse taal niet verder gaat dan de symbolen uit de wis- en natuurkunde, levert dit Nederlandse tekst op met Grieks letters, zoals weergegeven in het kader. Griekse letters zijn te vinden in de UTF-8-coderingen tussen ‘\u0391’ en ‘\u03ce’.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

      Braille code 2
 

Niet alleen Griekse letters, ook brailleschrift en morsecode
zijn eenvoudig te vinden en gebruiken

  Brailleschrift 2
  Braille code

Maar je hoeft je niet te beperken tot het Grieks. Ook het morsealfabet is bijvoorbeeld eenvoudig te vinden op internet. Zelfs brailleschrift (unicode ‘\u2800’ tot ‘\u28ff’) kan eenvoudig worden gebruikt voor het vertalen van hele boekwerken. 

 

 

 

 

 

 

 

Ondersteboven
Ondersteboven printen is een aardigheid zonder een duidelijk doel. Eigenlijk is het meer een verkenning van de mogelijkheden van Python met Unicode. We gaan aan de slag!

De invoer is afkomstig uit een file en de resultaten zijn naar een file en naar het scherm gestuurd. Ook voor grote bestanden (bladzijde of hoofdstuk uit een boek) is deze techniek bruikbaar.

 

  jas van belofte             


De directory fliptab

 

fliptab={

'a':'\u0250','b':'\u0253','c':'\u0254','d':'\u0256','e':'\u01DD',
'f':'\u025F','g':'\u0183','h':'\u0265','i':'\u0131','j':'\u027E',
'k':'\u029E','l':'\u026D','m':'\u026F','n':'\u1d0e','o':'\u006F',
'p':'\u0064','q':'\u0062','r':'\u0279','s':'\u0c6d','t':'\u0287',
'u':'\u006E','v':'\u028C','w':'\u028D','x':'\u0078','y':'\u028E',
'z':'\u007A',

'A':'\ua4ef','B':'\ua4ed','C':'\uA4DB','D':'\uA4F7','E':'\uA4F1',
'F':'\uA4DE','G':'\uA4E8','H':'\u0048','I':'\u0049','J':'\uA4E9',
'K':'\uA4D8','L':'\uA4F6','M':'\u026f','N':'\uA4E0','O':'\u004f',
'P':'\uA4D2','Q':'\u0070','R':'\u1589','S':'\u0C6D','T':'\ua4d5',
'U':'\u006E','V':'\u028C','W':'\u028D','X':'\u0058','Y':'\u028E',
'Z':'\u005A',

'0':'\u0030','1':'\u0031','2':'\u1105','3':'\u0033','4':'\u152d',
'5':'\u0C6D','6':'\u0039','7':'\u0037','8':'\u0038','9':'\u0036',
'.':'\u002E','[':'\u005B',']':'\u005D','{':'\u007B','}':'\u007D',
'(':'\u0028',')':'\u0029','?':'\u00bf','!':'\u00a1','&':'\u0026',
'/':'\u005C','<':'\u003c','>':'\u003e','_':'\u005F',
';':'\u061b','"':'\u201E',':':'\u003A','±':'\u2213','\\':'u002F'}


fp = open("jasvanbelofte.txt")

fw = open("jas van resultaat.txt","w")

while True:

    zin = fp.readline()

    if zin == "":

        break

        fp.close()

    print(zin,end='')

    fw.write(zin)

  
    rev =  zin[len(zin)-2::-1]

    for letter in rev:

        char = fliptab.get(letter)

        if char == None:

            char = letter

        print(char,end='')

        fw.write(char)

    print("")

    fw.writelines(' '+'\n')

fw.close()

   
 


De tekstbestanden
voor invoer en uitvoer
 

             
   

Invoer: jasvanbelofte.txt

eerste zin uit het boekenweekgeschenk 2019
van Jan Siebelink

JAS VAN BELOFTE:

Om tien uur vanochtend was er nog niets aan de hand


Uitvoer: jas van resultaat.txt

eerste zin uit het boekenweekgeschenk 2019
van Jan Siebelink


ʞᴎıɭǝɓǝı౭ ᴎɐꓩ ᴎɐʌ 610ᄅ ʞᴎǝɥɔ౭ǝƃʞǝǝʍᴎǝʞǝoɓ
ʇǝɥ ʇın ᴎız ǝʇ౭ɹǝǝ


JAS VAN BELOFTE:


:ꓱꓕꓞOꓶꓱꓭ ꓠꓯʌ ౭ꓯꓩ


Om tien uur vanochtend was er nog niets
aan de hand


ɖᴎɐɥ ǝɖ ᴎɐɐ ౭ʇǝıᴎ ƃoᴎ ɹǝ ౭ɐʍ ɖᴎǝʇɥɔoᴎɐʌ
ɹnn ᴎǝıʇ ɯO

          




In rev wordt de zin achterstevoren geschreven omdat dat weer gemakkelijker leest als je de zin ondersteboven print. De laatste 2 tekens van een zin zijn voor aanduiding van een nieuwe regel (\n).

Voor enkele tekens (b.v. 2, 4) zijn geen mooie vervangers te vinden. Op het scherm bezitten de teksten nog opmaakinstructies, die verdwijnen bij gebruik van teksteditors voor ‘platte teksten’.

Aan de opmaak voor de dictionary fliptab is veel zorg besteed. Door deze dict redelijk compleet te maken, hoeft in het programma geen rekening te worden gehouden met allerlei uitzonderingen, waardoor het programma zelf redelijk overzichtelijk blijft.