Een rebus is een puzzel die één of meer woorden beschrijft aan de hand van een reeks emoji. Bij elke emoji horen ook nul of meer acties die aangeven welke letters toegevoegd, verwijderd of vervangen moeten worden door andere letters. De rebus groepeert emoji (en bijhorende acties) die samen één woord van de oplossing vormen. Zo beschrijft onderstaande rebus twee woorden: het eerste woord wordt beschreven door de eerste drie emoji en het tweede woord door de laatste twee emoji.
In tekstformaat beschrijven we een rebus aan de hand van een reeks patronen. Zo wordt bovenstaande voorbeeldrebus beschreven door deze patronen, waarbij we elk patroon ingesloten hebben tussen een paar dubbele aanhalingstekens:
"🐸 f=p" "🚊 -t" "💍 r=m" " " "✋ h=l -d" "🍇 r=u p=g"
Elk patroon beschrijft een deel van de oplossing. Die oplossing bekom je door alle delen te vinden en samen te voegen. Er zijn twee verschillende soorten patronen:
een spatie: dit patroon beschrijft letterlijk één spatie in de oplossing en scheidt dus twee groepen van elkaar
een emoji gevolgd door nul of meer acties, die telkens van elkaar gescheiden worden door één spatie (acties bevatten zelf nooit spaties): dit patroon beschrijft een reeks letters in de oplossing
Het bepalen van de letters die beschreven worden door een emoji en de bijhorende acties gebeurt in twee stappen. Eerst moet in een lexicon het woord opgezocht worden dat hoort bij de emoji. Een lexicon is een tekstbestand waarvan elke regel bestaat uit een emoji, een spatie en het woord dat bij die emoji hoort. Elke emoji komt hoogstens één keer in een lexicon voor. Dit is bijvoorbeeld een deel van een lexicon waarin alle emoji uit de voorbeeldrebus voorkomen:
… 🐸 frog 🚊 tram 💍 ring ✋ hand 🍇 grapes …
Deze opgave gebruikt de UTF-81 (8-bit Unicode Transformation Format) tekencodering om Unicode-tekens voor te stellen als een stroom van bytes. Daarbij is het belangrijk om weten dat een emoji uit meerdere bytes kan bestaan. Je mag er dus niet van uitgaan dat elke emoji bestaat uit één enkel karakter.
Als we het woord gevonden hebben dat bij de emoji hoort, dan moeten we daar vervolgens alle bijhorende acties op toepassen. Het is belangrijk om te onderstrepen dat de acties in de gegeven volgorde (van links naar rechts) moeten toegepast worden. We onderscheiden vier soorten acties:
prefix: één of meer letters gevolgd door een plusteken (abc+); de letters (abc) moeten aan het begin van het woord toegevoegd worden
suffix: een plusteken gevolgd door één of meer letters (+abc); de letters (abc) moeten aan het einde van het woord toegevoegd worden
deletie: een minteken gevolgd door één of meer letters (-abc); de substring van letters (abc) moet uit het woord verwijderd worden
substitutie: een gelijkteken dat voorafgegaan en gevolgd wordt door één of meer letters (abc=def); de substring van letters voor het gelijkteken (abc) moet in het woord vervangen worden door de substring van letters na het gelijkteken (def)
Onderstaande tabel geeft aan hoe de voorbeeldrebus kan opgelost worden door elk patroon in twee stappen om te zetten naar een deel van de oplossing.
patroon | woord (stap 1) | acties (stap 2) | deel van oplossing |
---|---|---|---|
🐸 f=p | frog | frog → prog | prog |
🚊 -t | tram | tram → ram | ram |
💍 r=m | ring | ring → ming | ming |
" " | " " | ||
✋ h=l -d | hand | hand → land → lan | lan |
🍇 r=u p=g | grapes | grapes → guapes → guages | guages |
Als we alle delen samenvoegen dan krijgen we dus de oplossing van de voorbeeldrebus: programming languages.
Schrijf een bash shell script rebus waarmee rebussen kunnen opgelost worden. Aan het script moeten twee of meer argumenten doorgegeven worden: i) de padnaam van een lexicon en ii) één of meer patronen die een rebus beschrijven. Het script moet de oplossing van de rebus uitschrijven naar standard output (stdout). Bij het oplossen van de rebus moet het script ervan uitgaan dat er enkel kleine letters gebruikt worden in de woorden van het lexicon, in de acties en dus ook in de oplossing van de rebus.
Het script moet de volgende foutafhandeling voorzien:
als er niet minstens twee argumenten doorgegeven worden, dan moet het script de boodschap Syntax: rebus [FILE] [PATTERN]... uitschrijven naar standard error (stderr) en eindigen met exit status 1
als het eerste argument geen gewoon leesbaar bestand is, dan moet het script de boodschap rebus: invalid lexicon uitschrijven naar standard error (stderr) en eindigen met exit status 2
als er een patroon is waarvan de emoji niet in het lexicon voorkomt, dan moet het script de boodschap rebus: invalid emoji uitschrijven naar standard error (stderr) en eindigen met exit status 3
als er een deletie (-abc) of een substitutie (abc=def) is waarvan de substring (abc) niet juist één keer in het woord voorkomt, dan moet het script de boodschap rebus: invalid action uitschrijven naar standard error (stderr) en eindigen met exit status 4; bij het bepalen van het aantal voorkomens van een substring moet rekening gehouden worden met het feit dat deze voorkomens kunnen overlappen (zo komt oxo bijvoorbeeld drie keer voor in oxoxoxo)
als de actie van een patroon geen beschrijving heeft die overeenkomt met één van de vier soorten acties (prefix, suffix, deletie of substitutie), dan moet het script de boodschap rebus: invalid pattern uitschrijven naar standard error (stderr) en eindigen met exit status 5
In al deze gevallen mag er ook niets uitgeschreven worden naar standard output (stdout).
Onderstaande voorbeeldsessie toont hoe het shell script rebus moet kunnen gebruikt worden. Hierbij gaan we ervan uit dat het bestand emoji.txt2 zich in de huidige directory bevindt.
$ rebus
Syntax: rebus [FILE] [PATTERN]...
$ echo $?
1
$ rebus fake.txt "🍕" # bestand fake.txt bestaat niet
rebus: invalid lexicon
$ echo $?
2
$ rebus emoji.txt3 "🎃 o=x" # emoji komt niet voor in lexicon
rebus: invalid emoji
$ echo $?
3
$ rebus emoji.txt4 "🍕 -q" # letter q komt niet voor in woord pizza
rebus: invalid action
$ echo $?
4
$ rebus emoji.txt5 "🍕 z=ti" # letter z komt twee keer voor in woord pizza
rebus: invalid action
$ echo $?
4
$ rebus emoji.txt6 "🍕 ?" # onbekende actie
rebus: invalid pattern
$ echo $?
5
$ rebus emoji.txt7 "🐸 f=p" "🚊 -t" "💍 r=m" " " "✋ h=l -d" "🍇 r=u p=g"
programming languages
$ rebus emoji.txt8 🐎 👞
horseshoe