In 2009 bedacht Kim Godgul een visuele code om woorden voor te stellen. Hij noemde ze ColorHoney omdat elke letter van een woord voorgesteld wordt als een diamant die samengesteld is uit twee gekleurde driehoeken. De twee kanten van de diamant worden respectievelijk de lichte kleur en de donkere kleur genoemd.

diamant

Standaard worden er zes kleuren gebruikt om de driehoeken in te kleuren: rood, groen, blauw, cyaan, magenta en geel. Daarmee kan dus een alfabet van maximaal 36 symbolen (letters, cijfers, leestekens, spaties) voorgesteld worden, waarbij elk symbool correspondeert met een combinatie van twee kleuren.

alfabet

ColorHoney gebruikt een vaste layout om de diamanten voor de opeenvolgende symbolen van een woord te plaatsen: de vier diamanten voor elke groep van vier opeenvolgende symbolen vormen een patroon dat zich steeds blijft herhalen.

layout

Daardoor heeft de weergave van de code wat weg van een veelkleurige honingraat. Hier zijn negen voorbeelden van woorden die voorgesteld worden met hun ColorHoney-code:

Gandalf (ColorHoney)
Gandalf
Aragorn (ColorHoney)
Aragorn
Boromir (ColorHoney)
Boromir
Samwise (ColorHoney)
Samwise
Frodo (ColorHoney)
Frodo
Meriadoc (ColorHoney)
Meriadoc
Legolas (ColorHoney)
Legolas
Gimli (ColorHoney)
Gimli
Peregrin (ColorHoney)
Peregrin

Opgave

Schrijf een bash shell script colorhoney waaraan twee argumenten moeten doorgegeven worden: i) een woord $$w$$ dat enkel bestaat uit letters (hoofdletters en kleine letters) en ii) de padnaam van een tekstbestand dat twee kleuren associeert met elke letter van het alfabet. Het script mag ervan uitgaan dat beide argumenten geldig zijn, zonder dat dit expliciet moet gecontroleerd worden. Het tekstbestand bestaat uit 26 regels die elk een unieke letter van het alfabet bevatten en twee HTML-kleuren: de corresponderende lichte en donkere kleur. Deze drie informatievelden worden telkens van elkaar gescheiden door één tab. De eerste paar regels van zo'n bestand zouden er bijvoorbeeld als volgt kunnen uitzien (alphabet.txt):

G	red	blue
A	magenta	magenta
N	green	red
D	magenta	green
L	green	magenta
F	red	green
R	yellow	blue
K	green	cyan
…

Het script moet de ColorHoney-code van woord $$w$$ in SVG-formaat uitschrijven naar standaard uitvoer (stdout). Daarbij moet gebruikgemaakt worden van de kleurencombinaties die vastgelegd zijn in het tekstbestand dat als tweede argument aan het script wordt doorgegeven. Verderop bespreken we stap voor stap hoe de SVG-afbeelding opgebouwd wordt. Het script moet bijvoorbeeld kunnen gebruikt worden om de afbeeldingen uit de inleiding van deze opgave te genereren. Dit is bijvoorbeeld de SVG-afbeelding met de ColorHoney-code van het woord Gandalf die het script moet uitschrijven, op basis van de kleurencombinaties die we hierboven als voorbeeld gebruikt hebben (alphabet.txt):

<svg xmlns="http://www.w3.org/2000/svg" height="300" viewBox="-0.6 -1.5433 4.2 3.086">
<style>.border{stroke:#F5F1EB;stroke-width:0.05;stroke-linejoin:round}</style>
<defs><g id="diamond">
<polygon points="0,-1 -0.5773,0 0.5773,0 0,-1"/>
<polygon points="0,1 -0.5773,0 0.5773,0 0,1" fill="currentColor"/>
<polygon class="border" points="0,1 -0.5773,0 0,-1 0.5773,0 0,1" fill="none"/>
</g></defs>
<rect x="-0.6" y="-1.5433" rx="0.1" width="4.2" height="3.086" fill="#F5F1EB"/>
<use href="#diamond" x="0" y="0" fill="red" color="blue" transform="rotate(30,0,0)"/>
<use href="#diamond" x="0.5" y="0.866" fill="magenta" color="magenta" transform="rotate(90,0.5,0.866)"/>
<use href="#diamond" x="1" y="0" fill="green" color="red" transform="rotate(-30,1,0)"/>
<use href="#diamond" x="1.5" y="-0.866" fill="magenta" color="green" transform="rotate(90,1.5,-0.866)"/>
<use href="#diamond" x="2" y="0" fill="magenta" color="magenta" transform="rotate(30,2,0)"/>
<use href="#diamond" x="2.5" y="0.866" fill="green" color="magenta" transform="rotate(90,2.5,0.866)"/>
<use href="#diamond" x="3" y="0" fill="red" color="green" transform="rotate(-30,3,0)"/>
</svg>

Opbouw van de SVG-afbeelding

Scalable Vector Graphics (SVG) is een op XML gebaseerd bestandsformaat dat vectorafbeeldingen tekstueel beschrijft aan de hand van eenvoudige meetkundige bouwstenen zoals punten, lijnen, cirkels en veelhoeken.

Je moet geen SVG of XML kennen om deze opgave op te lossen. We bespreken stap voor stap hoe de ColorHoney-code van een woord opgebouwd wordt in SVG-formaat aan de hand van drie sjablonen: hoofding, diamant en voettekst. Daarbij zullen we de variabele onderdelen van elk sjabloon in het groen weergeven. Daar moet het script de juiste waarden invullen. Het is belangrijk dat elk sjabloon exact overgenomen wordt, zodat het resultaat dat het script uitschrijft precies overeenkomt met de beschreven specificatie.

Hoofding
<svg xmlns="http://www.w3.org/2000/svg" height="300" viewBox="-0.6 -1.5433 4.2 3.086">
<style>.border{stroke:#F5F1EB;stroke-width:0.05;stroke-linejoin:round}</style>
<defs><g id="diamond">
<polygon points="0,-1 -0.5773,0 0.5773,0 0,-1"/>
<polygon points="0,1 -0.5773,0 0.5773,0 0,1" fill="currentColor"/>
<polygon class="border" points="0,1 -0.5773,0 0,-1 0.5773,0 0,1" fill="none"/>
</g></defs>
<rect x="-0.6" y="-1.5433" rx="0.1" width="4.2" height="3.086" fill="#F5F1EB"/>

Dit sjabloon bevat enkele vaste ingrediënten voor alle SVG-bestanden die de ColorHoney-code van een woord $$w$$ voorstellen: de SVG start-tag (svg), algemene opmaak van de afbeelding (style), een definitie van de manier waarop diamanten weergegeven worden (defs), en een gekleurde rechthoek die dienst doet als achtergrond voor de afbeelding (rect).

Alle afbeeldingen hebben een vaste hoogte, maar hun breedte hangt af van de lengte $$|w|$$ van woord $$w$$. Die breedte moet op twee plaatsen in het sjabloon ingevuld worden. Ze wordt berekend als \[ 1.2 + \left\lfloor \frac{|w|}{2} \right\rfloor  \] waarbij $$\left\lfloor x \right\rfloor$$ staat voor het grootste geheel getal dat kleiner is dan of gelijk aan $$x \in \mathbb{R}$$. Die breedte moet altijd voorgesteld worden met één cijfer na de komma.

Diamant
<use href="#diamond" x="0" y="0" fill="red" color="blue" transform="rotate(30,0,0)"/>

Deze regel tekent de diamant voor de $$i$$-de letter $$w_i$$ van woord $$w$$. Daarbij worden de letters van woord $$w$$ van links naar rechts genummerd vanaf 0. Hierbij moet de volgende informatie in het sjabloon ingevuld worden:

Voor elke letter van woord $$w$$ (van links naar rechts) moet een regel volgens dit sjabloon toegevoegd worden aan de SVG-afbeelding.

Voettekst
</svg>

Dit laatste sjabloon sluit de SVG-afbeelding af met een SVG stop-tag.

Voorbeeld

Deze interactieve sessie toont hoe het script colorhoney moet kunnen gebruikt worden. Daarbij gaan we ervan uit dat het tekstbestand alphabet.txt zich in de huidige directory bevindt.

$ colorhoney "Gandalf" alphabet.txt
<svg xmlns="http://www.w3.org/2000/svg" height="300" viewBox="-0.6 -1.5433 4.2 3.086">
<style>.border{stroke:#F5F1EB;stroke-width:0.05;stroke-linejoin:round}</style>
<defs><g id="diamond">
<polygon points="0,-1 -0.5773,0 0.5773,0 0,-1"/>
<polygon points="0,1 -0.5773,0 0.5773,0 0,1" fill="currentColor"/>
<polygon class="border" points="0,1 -0.5773,0 0,-1 0.5773,0 0,1" fill="none"/>
</g></defs>
<rect x="-0.6" y="-1.5433" rx="0.1" width="4.2" height="3.086" fill="#F5F1EB"/>
<use href="#diamond" x="0" y="0" fill="red" color="blue" transform="rotate(30,0,0)"/>
<use href="#diamond" x="0.5" y="0.866" fill="magenta" color="magenta" transform="rotate(90,0.5,0.866)"/>
<use href="#diamond" x="1" y="0" fill="green" color="red" transform="rotate(-30,1,0)"/>
<use href="#diamond" x="1.5" y="-0.866" fill="magenta" color="green" transform="rotate(90,1.5,-0.866)"/>
<use href="#diamond" x="2" y="0" fill="magenta" color="magenta" transform="rotate(30,2,0)"/>
<use href="#diamond" x="2.5" y="0.866" fill="green" color="magenta" transform="rotate(90,2.5,0.866)"/>
<use href="#diamond" x="3" y="0" fill="red" color="green" transform="rotate(-30,3,0)"/>
</svg>