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.
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.
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.
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
|
Aragorn
|
Boromir
|
Samwise
|
Frodo
|
Meriadoc
|
Legolas
|
Gimli
|
Peregrin
|
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-kleuren1: 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.txt2):
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. Verderop3 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.txt4):
<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>
Scalable Vector Graphics (SVG5) is een op XML6 gebaseerd bestandsformaat dat vectorafbeeldingen7 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: hoofding8, diamant9 en voettekst10. 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.
<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.
<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:
De $$x$$-coördinaat van de diamant wordt berekend als $$\frac{i}{2}$$. De $$x$$-coördinaat moet als een natuurlijk getal voorgesteld worden (zonder decimale cijfers) als $$i$$ even is, en met één cijfer na de komma als $$i$$ oneven is. De $$x$$-coördinaat moet ingevuld worden voor het argument x van de use-tag, maar ook nog een keer als tweede argument van de functie rotate voor het argument transform van de use-tag.
De $$y$$-coördinaat van de diamant is resp. 0, 0.866, 0 en -0.866 als $$i\!\!\!\!\mod{4}$$ resp. gelijk is aan 0, 1, 2 en 3. De $$y$$-coördinaat moet ingevuld worden voor het argument y van de use-tag, maar ook nog een keer als derde argument van de functie rotate voor het argument transform van de use-tag.
De bewerking $$m\!\!\!\!\mod{n}$$ staat voor de rest na (gehele) deling van $$m$$ door $$n$$.
De lichte kleur die correspondeert met letter $$w_i$$ moet als opvulkleur (fill) ingevuld worden in het sjabloon. Bij het opzoeken van de lichte kleur die correspondeert met letter $$w_i$$ mag geen onderscheid gemaakt worden tussen hoofdletters en kleine letters.
De donkere kleur die correspondeert met letter $$w_i$$ moet als kleur (color) ingevuld worden in het sjabloon. Bij het opzoeken van de donkere kleur die correspondeert met letter $$w_i$$ mag geen onderscheid gemaakt worden tussen hoofdletters en kleine letters.
De rotatiehoek van de diamant is resp. 30, 90, -30 en 90 als $$i\!\!\!\!\mod{4}$$ resp. gelijk is aan 0, 1, 2 en 3. De rotatiehoek moet ingevuld worden als eerste argument van de functie rotate voor het argument transform van de use-tag.
Voor elke letter van woord $$w$$ (van links naar rechts) moet een regel volgens dit sjabloon toegevoegd worden aan de SVG-afbeelding.
</svg>
Dit laatste sjabloon sluit de SVG-afbeelding af met een SVG stop-tag.
Deze interactieve sessie toont hoe het script colorhoney moet kunnen gebruikt worden. Daarbij gaan we ervan uit dat het tekstbestand alphabet.txt11 zich in de huidige directory bevindt.
$ colorhoney "Gandalf" alphabet.txt12
<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>