Programmeermethoden 2022
Tweede programmeeropgave: Pincode

De tweede programmeeropgave van het vak Programmeermethoden in het najaar van 2022 heet Pincode; zie ook het vierde werkcollege, vijfde werkcollege (de betreffende WWW-bladzijde bevat handige tips) en zesde werkcollege, en lees geregeld deze pagina op WWW.


We gaan een file coderen en decoderen met behulp van een eenvoudige pincode. Maar de pincode kan tijdens het (de)coderen veranderen, en wat doen trouwens die Lychrel-getallen in de invoerfile? En als we de pincode niet meer weten?

Aan de gebruiker wordt gevraagd of het om coderen of decoderen gaat en hoe de originele file en de "doelfile" heten. De ge(de)codeerde invoerfile komt in deze doelfile terecht; de invoerfile zelf blijft onveranderd. Verder wordt de pincode gevraagd, waarbij bij het decoderen een optie is om aan te geven dat deze onbekend is, bijvoorbeeld door als pincode -1 te geven; het programma stopt meteen als de gebruiker een getal groter dan 9999 of kleiner dan -1 invoert. Stel eenvoudige vragen om deze gegevens van de gebruiker te weten te komen. Het programma leest dan eenmalig (uitzondering: (*)) de opgegeven invoerfile, en schrijft de uitvoer symbool voor symbool weg naar de uitvoerfile. Elk symbool uit de invoerfile mag en moet precies één maal (met invoer.get (...)) gelezen worden.
De pincode is een geheel getal tussen 0 en 9999, waarbij zo nodig voorloopnullen gebruikt worden. Zo wordt bijvoorbeeld 42 opgevat als 0042. Als in de te coderen file een getal kleiner dan 10000 en ongelijk 0 gedetecteerd wordt, wordt dit dynamisch de nieuwe pincode (waarin weer vooraan begonnen wordt). Let op: het eerste niet-cijfer na de nieuwe pincode wordt nog met de oude pincode gecodeerd. Hierbij letten we niet op voorloopnullen: 0000042 wordt dus opgevat als 42.
Na het (de)coderen worden nog afgedrukt het aantal regels en het aantal karakters van de originele file.

Het coderen geschiedt regel voor regel, en gaat als volgt. Neem even aan dat de pincode 4281 is. Het eerste karakter van de invoerfile wordt dan gecodeerd als het 4 verderop in de ASCII-tabel gelegen karakter, het tweede als het 2 verderop gelegen karakter, ..., het vijfde weer als het 4 verderop gelegen karakter, etcetera. We nemen hierbij aan dat de invoerfile bestaat uit tabs, carriage returns, line feeds, en verder gewone karakters met ASCII-waarde tussen 32 en 126, grenzen inbegrepen. We rekenen verder modulo 95, dus karakter 127 wordt karakter 32, etcetera. Zo wordt Slaap zzzzz! met pincode 1289 gecodeerd als Tnijq"#${|#*. Regelovergangen ('\n' en eventueel '\r') blijven onderanderd, evenals tabs ('\t'). Na een regelovergang begin je weer vooraan in de pincode.

Verder moet het programma van elk geheel getal ongelijk nul dat bij het coderen in de invoerfile voorkomt controleren of dit wellicht een Lychrel-getal is (zie deze link voor een definitie). Op het scherm wordt het desbetreffende getal afgedrukt, en daarnaast wat het aantal iteraties is om tot een palindroom te komen (voor 545 is dit 0, voor 113 is dit 1), of het nummer van de iteratie waarvan het resultaat boven INT_MAX (gebruik include <climits>) uitkomt (voor 196 is dit (waarschijnlijk) 18). Als dit gebeurt, wordt dit erbij vermeld, bijvoorbeeld als "potentieel Lychrel-getal".
De tekst 123abcd-"qqq 5"+++uvw-77.088ddd//vb5656 bevat de gehele getallen 123, 5, 77, 88 en 5656; deze moeten dus gecontroleerd worden. Neem aan dat de getallen in de tekst zelf hooguit INT_MAX zijn.

Als we bij het decoderen de pincode niet weten, moeten alle pincodes 0...9999 geprobeerd worden. Een pincode waarbij het vaakst de lettercombinatie "the" (hoofdletters of kleine letters, bijvoorbeeld "tHe") in de decodering voorkomt wordt als de juiste beschouwd, en de bijbehorende decodering wordt opgeleverd. Als er meerdere pincodes even goed decoderen, gebruiken we de kleinste.
Let op: hierbij moet 10000 maal gedecodeerd worden, en wordt de invoerfile dus 10000 maal gelezen (*). Zorg ervoor dat er in deze situatie niet naar een uitvoerfile wordt weggeschreven, anders duurt het te lang!

Ter verdere inspiratie, zie het vijfde werkcollege, en een aantal voorbeelden:

Let op: kopiëren door met rechter muisknop op de links te klikken, anders (met markeer-copy-paste) gaan spaties/tabs wellicht fout!

Opmerkingen

Uiterste inleverdatum: maandag 17 oktober 2022, 17:00 uur.

Manier van inleveren:

  1. Digitaal de C++-code inleveren: stuur een email naar pm@liacs.leidenuniv.nl.
    Stuur geen executable's, lever alleen de C++-file digitaal in! Noem deze bij voorkeur zoiets als kaagrutte2.cc, dit voor de tweede opdracht van het duo Rutte-van Kaag. De laatst voor de deadline ingeleverde versie wordt nagekeken.
  2. En ook een papieren versie van het verslag (inclusief de C++-code) deponeren in de speciaal daarvoor bestemde doos "Programmeermethoden" bij kamer 159 van het Snellius-gebouw.
    Overal duidelijk datum en namen van de (maximaal twee) makers vermelden, in het bijzonder als commentaar in de eerste regels van de C++-code. Lees bij het zesde werkcollege hoe het verslag eruit moet zien en wat er in moet staan.
Te gebruiken compiler: als hij maar C++ vertaalt; het programma moet in principe zowel op een Linux-machine (met g++) als onder Windows met Code::Blocks draaien. Test dus in principe op beide systemen! Normering: verslag 1; layout 1; commentaar 1; overzichtelijkheid/modulariteit 2; werking 5. Eventuele aanvullingen en verbeteringen: lees deze WWW-bladzijde: www.liacs.leidenuniv.nl/~kosterswa/pm/op2pm.php.