Semafoorseinen is een manier van communiceren die vroeger vooral in de scheepvaart gebruikt werd. Daarbij houdt een seingever in elke hand een vlaggetje vast dat in acht mogelijke posities kan gehouden worden. De posities worden genummerd vanaf nul, te beginnen bij de positie recht naar boven en dan telkens 45° gedraaid in wijzerzin.
Een semafoorsein (of kortweg semafoor) wordt voorgesteld als een string (str) met twee cijfers tussen 0 en 7 (grenzen inbegrepen) die de posities van beide vlaggetjes aangeven. De volgorde van de cijfers maakt geen verschil, omdat het niet uitmaakt met welke hand de posities aangenomen worden. Zo stellen 17 en 71 bijvoorbeeld dezelfde semafoor voor.
Een semafooralfabet bestaat uit 28 verschillende semaforen: 26 semaforen die de hoofdletters (A–Z) voorstellen, en dan nog twee semaforen die een spatie en een hekje (#) voorstellen. Tien semaforen die hoofdletters voorstellen (maar niet de hoofdletter J) stellen daarnaast ook nog de 10 cijfers (0–9) voor. Er bestaan verschillende semafooralfabetten, maar dit alfabet is internationaal het meest gangbaar.
Bij het interpreteren van opeenvolgende semaforen kunnen we ons in lettermodus of in cijfermodus bevinden. Als we beginnen seinen dan bevinden we ons altijd in lettermodus. In lettermodus gebruiken we de hoofdletter voor semaforen die twee symbolen (een hoofdletter en een cijfer) voorstellen. De semafoor die het hekje (#) voorstelt zorgt ervoor dat we in cijfermodus terechtkomen (die semafoor stelt dus verder geen symbool voor). In cijfermodus gebruiken we het cijfer voor semaforen die twee symbolen (een hoofdletter en een cijfer) voorstellen. In cijfermodus zorgt de semafoor die de hoofdletter J voorstelt ervoor dat we terug in lettermodus terechtkomen (die semafoor stelt dus verder geen symbool voor). Voor semaforen die slechts één symbool voorstellen (een hoofdletter of een spatie, maar geen J of #) maakt het geen verschil of we ons in lettermodus of in cijfermodus bevinden.
We stellen de weergave van een tijdstip op een digitale 24-uursklok voor als een string (str) in het formaat uu:mm. Daarbij worden de uren $$u$$ ($$0 \leq u < 24$$) en de minuten $$m$$ ($$0 \leq m < 60$$) altijd met twee cijfers weergegeven door waar nodig voorloopnullen toe te voegen. Bijvoorbeeld 13:50 of 07:03.
Als we een tijdstip weergeven op een analoge klok, dan kunnen we de stand van de uurwijzer en de minuutwijzer interpreteren als een semafoor. De hoeken $$\alpha_u$$ en $$\alpha_m$$ (in graden) die de uur- en minutenwijzers maken, kunnen berekend worden als \[ \begin{align} \alpha_u &= 30\,(u\!\!\!\!\!\mod{12}) + \frac{m}{2} \\ \alpha_m &= 6\,m \end{align} \] Daarna gebruiken we deze formule om de semafoorpositie $$p_\alpha$$ te bepalen die correspondeert met de hoek $$\alpha$$ (in graden) van de wijzer van een analoge klok: \[ p_\alpha = \left[\frac{\alpha}{45}\right]\!\!\!\!\!\mod{8} \] Hierbij stelt $$\left[x\right]$$ de afronding van $$x \in \mathbb{R}$$ naar het dichtsbijzijnde gehele getal voor.
We werken met tekstbestanden die een semafooralfabet beschrijven. Zo'n bestand bestaat uit 28 regels, waarvan elke regel bestaat uit één van de twee mogelijke voorstellingen van een semafoor, gevolgd door een tab en één of twee symbolen die door de semafoor voorgesteld worden. Bij semaforen die corresponderen met twee symbolen, staat de hoofdletter altijd voor het cijfer. Dit zijn bijvoorbeeld enkele regels uit het bestand met het internationaal meest gangbare semafooralfabet (alfabet.txt1):
54 A1 64 B2 74 C3 04 D4 14 E5 … 15 L 25 M 35 N 67 O 60 P … 12 W 13 X 23 Z 44 01 #
Merk op dat semafoor 44 in dit alfabet een spatie voorstelt, waardoor er op de voorlaatste regel van het bestand nog een spatie staat na de tab.
Het is jouw opdracht om een reeks tijdstippen zoals
17:55 01:59 22:29 03:03 21:01 12:08 00:38
te interpreteren als een bericht dat met semaforen doorgeseind wordt. Hieronder zie je hoe we de reeks tijdstippen die we als voorbeeld gebruikt hebben, kunnen interpreteren als het bericht C3P02.
Merk op dat semafoor 06 volgens dit semafooralfabet enkel de hoofdletter P voorstelt (en geen cijfer), waardoor het niet strikt nodig was om tussen het doorseinen van de cijfers 3 en 0 (in cijfermodus) terug te keren naar lettermodus. We hadden C3P0 dus ook kunnen voorstellen met deze reeks tijdstippen
17:55 01:59 22:29 21:01 00:38
Gevraagd wordt:
Schrijf een functie semafooralfabet waaraan de locatie (str) moet doorgegeven worden van een tekstbestand met een semafooralfabet. De functie moet de dictionaryvoorstelling van het semafooralfabet teruggeven. Dit is een dictionary (dict) die elke voorstelling (str) van elke semafoor in het bestand afbeeldt op een string (str) met alle symbolen die door de semafoor voorgesteld worden. Als een semafoor twee voorstellingen heeft, dan moeten beide voorstellingen als sleutels in de dictionary voorkomen. Als een semafoor twee symbolen voorstelt, dan moeten ze hun volgorde uit het tekstbestand behouden.
Schrijf een functie tijdstip2semafoor waaraan een tijdstip $$t$$ (str) moet doorgegeven worden. De functie moet een voorstelling (str) van de semafoor teruggeven die correspondeert met tijdstip $$t$$, waarbij het eerste cijfer de positie van de uurwijzer aangeeft en het tweede cijfer de positie van de minuutwijzer.
Schrijf een functie semafoor2tijdstippen waaraan de voorstelling (str) van een semafoor $$s$$ moet doorgegeven worden. De functie moet een verzameling (set) teruggeven met alle tijdstippen die corresponderen met een voorstelling van semafoor $$s$$ (rekening houdend met de twee mogelijke voorstellingen van de semafoor).
Schrijf een functie tijdstip2symbool waaraan een tijdstip $$t$$ (str) en de dictionaryvoorstelling $$\mathcal{A}$$ van een semafooralfabet moeten doorgegeven worden. De functie heeft ook nog een derde optionale parameter cijfermodus waaraan een Booleaanse waarde (bool) kan doorgegeven worden (standaardwaarde: False). Als er volgens semafooralfabet $$\mathcal{A}$$ geen symbolen corresponderen met tijdstip $$t$$, dan moet een AssertionError opgeworpen worden met boodschap ongeldig tijdstip. Anders moet de functie het symbool (str) teruggeven dat volgens semafooralfabet $$\mathcal{A}$$ correspondeert met tijdstip $$t$$ in lettermodus (cijfermodus=False) of in cijfermodus (cijfermodus=True).
Schrijf een functie kloklezen waaraan twee argumenten moeten doorgegeven worden: i) een reeks tijdstippen (str) die telkens van elkaar gescheiden worden door een spatie en ii) de dictionaryvoorstelling $$\mathcal{A}$$ van een semafooralfabet. De functie moet het bericht (str) teruggeven die de reeks tijdstippen voorstellen als ze geïnterpreteerd worden als semaforen volgens semafooralfabet $$\mathcal{A}$$. Als de reeks een tijdstip bevat die volgens semafooralfabet $$\mathcal{A}$$ niet als een symbool kan geïnterpreteerd worden, dan moet een AssertionError opgeworpen worden met boodschap ongeldig tijdstip.
In onderstaande voorbeeldsessie gaan we ervan uit dat het tekstbestand alfabet.txt3 zich in de huidige directory bevindt.
>>> alfabet = semafooralfabet('alfabet.txt4')
>>> alfabet['24']
'F6'
>>> alfabet['42']
'F6'
>>> alfabet['26']
'R'
>>> alfabet['44']
' '
>>> alfabet['10']
'#'
>>> alfabet['37']
Traceback (most recent call last):
KeyError: '37'
>>> tijdstip2semafoor('12:43')
'06'
>>> tijdstip2semafoor('05:17')
'42'
>>> tijdstip2semafoor('04:45')
'36'
>>> semafoor2tijdstippen('06')
{'00:42', '00:43', '00:44', '00:45', '08:57', '08:58', '08:59', '09:00', '09:01', '09:02', '09:03', '11:42', '11:43', '11:44', '11:45', '11:46', '11:47', '11:48', '12:42', '12:43', '12:44', '12:45', '20:57', '20:58', '20:59', '21:00', '21:01', '21:02', '21:03', '23:42', '23:43', '23:44', '23:45', '23:46', '23:47', '23:48'}
>>> semafoor2tijdstippen('42')
{'02:27', '02:28', '02:29', '02:30', '02:31', '02:32', '02:33', '03:27', '03:28', '03:29', '03:30', '03:31', '03:32', '03:33', '05:15', '05:16', '05:17', '05:18', '06:12', '06:13', '06:14', '06:15', '06:16', '06:17', '06:18', '14:27', '14:28', '14:29', '14:30', '14:31', '14:32', '14:33', '15:27', '15:28', '15:29', '15:30', '15:31', '15:32', '15:33', '17:15', '17:16', '17:17', '17:18', '18:12', '18:13', '18:14', '18:15', '18:16', '18:17', '18:18'}
>>> semafoor2tijdstippen('36')
{'03:46', '03:47', '03:48', '04:42', '04:43', '04:44', '04:45', '04:46', '04:47', '04:48', '08:19', '08:20', '08:21', '08:22', '08:23', '08:24', '08:25', '08:26', '09:19', '09:20', '09:21', '09:22', '09:23', '09:24', '09:25', '09:26', '15:46', '15:47', '15:48', '16:42', '16:43', '16:44', '16:45', '16:46', '16:47', '16:48', '20:19', '20:20', '20:21', '20:22', '20:23', '20:24', '20:25', '20:26', '21:19', '21:20', '21:21', '21:22', '21:23', '21:24', '21:25', '21:26'}
>>> tijdstip2symbool('22:30', alfabet)
'C'
>>> tijdstip2symbool('12:07', alfabet)
'#'
>>> tijdstip2symbool('10:30', alfabet, cijfermodus=True)
'3'
>>> tijdstip2symbool('12:15', alfabet, cijfermodus=True)
'J'
>>> tijdstip2symbool('09:03', alfabet)
'P'
>>> tijdstip2symbool('12:08', alfabet)
'#'
>>> tijdstip2symbool('12:37', alfabet, cijfermodus=True)
'0'
>>> tijdstip2symbool('15:13', alfabet)
Traceback (most recent call last):
AssertionError: ongeldig tijdstip
>>> kloklezen('17:55 01:59 22:29 03:03 21:01 12:08 00:38', alfabet)
'C3P0'
>>> kloklezen('17:55 01:59 22:29 21:01 00:38', alfabet)
'C3P0'
>>> kloklezen('10:02 22:37 14:41 13:30 18:28 19:56 16:46 17:32 19:16 22:47 19:25 06:06 23:12', alfabet)
'TIME IS MONEY'
>>> kloklezen('11:51 19:54 07:17 18:06 05:28 06:49 16:49 18:27 18:43 11:04 04:39 11:36', alfabet)
Traceback (most recent call last):
AssertionError: ongeldig tijdstip
Het internationaal symbool voor de vrede (☮) werd in 1958 ontworpen door de Britse ontwerper en kunstenaar Gerald Holtom5. Het is een cirkel met een verticale streep in het midden van waaruit twee schuine strepen naar beide zijden lopen. Het symbool is gebaseerd op het semafooralfabet: de twee schuine strepen naar beide zijden staat voor de letter N van nuclear (nucleair) en de verticale streep staat voor de letter D van disarmament (ontwapening).