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
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:
Er zijn nog ruim 20 andere methoden en functies |
|||
Methoden in dictionaries |
|||
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).
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
|
|||
teksta = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ tekstb = 'zyxwvutsrqponmlkjihgfedcba # maak dict met als keys de teksta en tekstb 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 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 |
|||
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 tekstb = 'zyxwvutsrqponmlkjihgfedcba eerste zin uit het boekenweekgeschenk 2019 van Jan Siebelink εερστε ζιν υιτ ηετ βοεκενwεεκγεσσηενκ 2019 ωαν Ιαν Σιεβελινκ
ΙΑΣ ΩΑΝ ΒΕΛΟΦΤΕ:
Ομ τιεν υυρ ωανοσητενδ wασ ερ νογ νιετσ ααν δε ηανδ
'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'}
while True: rev = fp.readline() if rev == "": break fp.close() print(rev,end='') 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’.
Niet alleen Griekse letters, ook brailleschrift en morsecode |
|
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.
|
||||||
|
||||||
Invoer: jasvanbelofte.txt eerste zin uit het boekenweekgeschenk 2019 JAS VAN BELOFTE: Om tien uur vanochtend was er nog niets aan de hand
eerste zin uit het boekenweekgeschenk 2019
|
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.