Een regex kruiswoordraadsel is een puzzel waarbij letters of andere symbolen moeten ingevuld worden op een rechthoekig m x n rooster met m rijen en n kolommen. In tegenstelling tot een klassiek kruiswoordraadsel wordt de omschrijving van het woord dat moet ingevuld worden op een rij of een kolom gegeven aan de hand van een reguliere expressie waaraan het woord moet voldoen.

Regex kruiswoordraadsel

In bovenstaand voorbeeld zie je bijvoorbeeld dat op de eerste rij van het 3 x 3 rooster een drieletterwoord moet ingevuld worden dat matcht met de reguliere expressie /[DEF][MNO]*/. Merk hierbij op dat het woord dat moet ingevuld worden volledig moet matchen met de opgegeven reguliere expressie, of anders gezegd, dat het woord in dit geval moet matchen met de reguliere expressie /^[DEF][MNO]*$.

De reguliere expressies leggen dus beperkingen op aan de letters of symbolen die je in de cellen van een rij of een kolom mag invullen. Een oplossing van de puzzel moet voldoen aan alle opgelegde beperkingen. Hieronder vind je alvast een geldige oplossing van bovenstaande puzzel.

Opgelost regex kruiswoordraadsel

Opgave

Schrijf een bash shell script regexkruis dat kan gebruikt worden om na te gaan of een gegeven oplossing van een regex kruiswoordraadsel al dan niet geldig is. Hierbij moeten drie argumenten doorgegeven worden aan het shell script. Het eerste argument is de padnaam van een tekstbestand dat de oplossing van de puzzel bevat. Deze oplossing moet bestaan uit m regels die elk n karakters bevatten. Het tweede en derde argument zijn de padnamen van tekstbestanden met reguliere expressies, elk op een afzonderlijke regel, die in de opgave van de puzzel respectievelijk staan bij de rijen (van boven naar onder) en de kolommen (van links naar rechts). Merk dus op dat het aantal reguliere expressies in deze bestanden dus ook respectievelijk het aantal rijen m en het aantal kolommen n van de puzzel aangeeft.

Wanneer er geen drie argumenten worden doorgegeven aan het shell script, of wanneer deze argumenten niet wijzen naar leesbare tekstbestanden, dan moet een gepaste foutboodschap (zie onderstaande voorbeeldsessie) uitgeschreven worden naar standaard error, en moet het shell script eindigen met exit status 1.

Wanneer er wel drie geldige argumenten worden doorgegeven aan het shell script, dan moet het script voor elke rij (horizontaal) en kolom (vertikaal) van de oplossing een regel uitschrijven naar standaard uitvoer die aangeeft of de opeenvolging van letters en symbolen matcht met de corresponderende reguliere expressie. Deze omschrijving moet beginnen met de letter H (horizontaal) of V (vertikaal), gevolgd door het volgnummer van de rij of de kolom (waarbij de nummering start vanaf 1), een dubbelpunt, een spatie en de tekst correct of fout die aangeeft of de opeenvolging van letters en symbolen al dan niet matcht met de corresponderende reguliere expressie.

Indien het script bij het testen van de oplossing merkt dat de oplossing te veel of te weinig rijen of kolommen bevat ten opzichte van de opgave, dan moet een gepaste foutboodschap (zie onderstaande voorbeeldsessie) uitgeschreven worden naar standaard error, en moet het shell script eindigen met exit status 2.

Onderstaande voorbeeldsessie geeft aan hoe het shell script regexkruis moet kunnen gebruikt worden. De bestanden die in deze voorbeeldsessie gebruikt worden zijn beschikbaar in het meegeleverde ZIP-bestand. Merk op dat de opgave in deze voorbeeldsessie correspondeert met de opgave van het voorbeeld uit de inleiding van deze oefening.

Opmerking: Bij de implementatie van het shell script regexkruis mag je gebruik maken van het meegeleverde Python script transpose1 dat de rijen en de kolommen van een gegeven tekstbestand omwisselt. Onderstaande voorbeeldsessie toont hoe dit Python script kan gebruikt worden.

$ cat opgave.oplossing1.txt
DON
TPA
NIC
$ transpose < opgave.oplossing1.txt
DTN
OPI
NAC
$ cat opgave.horizontaal.txt
[DEF][MNO]*
[^DJNU]P[ABC]
[ICAN]*
$ cat opgave.vertikaal.txt
[JUNDT]*
APA|OPI|OLK
(NA|FE|HE)[CV]
$ regexkruis opgave.oplossing1.txt
Gebruik: regexkruis <oplossing> <opgave horizontaal> <opgave vertikaal>
$ echo $?
1
$ regexkruis opgave.oplossing1.txt opgave.horizontaal.txt xxx
xxx kan niet gelezen worden
$ echo $?
1
$ regexkruis opgave.oplossing1.txt opgave.horizontaal.txt opgave.vertikaal.txt
H1: correct
H2: correct
H3: correct
V1: correct
V2: correct
V3: correct
$ echo $?
0
$ cat opgave.oplossing2.txt
DON
TP?
NIC
$ regexkruis opgave.oplossing2.txt opgave.horizontaal.txt opgave.vertikaal.txt
H1: correct
H2: fout
H3: correct
V1: correct
V2: correct
V3: fout
$ echo $?
0
$ cat opgave.oplossing3.txt
DON?
TP??
NIC?
????
$ regexkruis opgave.oplossing3.txt opgave.horizontaal.txt opgave.vertikaal.txt
H1: fout
H2: fout
H3: fout
regexkruis: oplossing heeft te veel rijen
$ echo $?
2

Bestanden: opgave.oplossing1.txt2, opgave.horizontaal.txt3, opgave.vertikaal.txt4, opgave.oplossing2.txt5 en opgave.oplossing3.txt6