Oggi la maggior parte delle persone nel mondo usa i numeri arabi (0–9). Ma se tornassi indietro di duemila anni, scopriresti che la maggior parte degli europei usava invece i numeri romani.
Per scrivere un numero romano usiamo le seguenti lettere latine, ognuna delle quali ha un valore:
| M | D | C | L | X | V | I |
|---|---|---|---|---|---|---|
| 1000 | 500 | 100 | 50 | 10 | 5 | 1 |
Un numero romano è una sequenza di queste lettere, e il suo valore è la somma dei valori delle lettere.
Per esempio, XVIII ha il valore 18 (10 + 5 + 1 + 1 + 1 = 18).
C'è però una regola che rende le cose più complicate: la stessa lettera non può essere usata più di tre volte di seguito.
Questo significa che non possiamo esprimere numeri come 4 con il IIII che sembra così naturale.
Per quei numeri, invece, usiamo un metodo di sottrazione tra due lettere.
Quindi pensiamo a 4 non come 1 + 1 + 1 + 1, ma come 5 - 1.
E, cosa un po' confusa per la nostra mentalità moderna, scriviamo prima il numero più piccolo.
Questo vale solo nei casi seguenti: 4 (IV), 9 (IX), 40 (XL), 90 (XC), 400 (CD) e 900 (CM).
L'ordine conta nei numeri romani! Le lettere (e i composti speciali qui sopra) devono essere ordinate per valore decrescente da sinistra a destra.
Ecco alcuni esempi:
105 => CV
---- => --
100 => C
+ 5 => V
106 => CVI
---- => --
100 => C
+ 5 => V
+ 1 => I
104 => CIV
---- => ---
100 => C
+ 4 => IV
E un ultimo esempio più complesso:
1996 => MCMXCVI
----- => -------
1000 => M
+ 900 => CM
+ 90 => XC
+ 5 => V
+ 1 => I
Il tuo compito è convertire un numero dai numeri arabi ai numeri romani.
In questo esercizio ci occuperemo solo dei numeri romani tradizionali, in cui il numero più grande è MMMCMXCIX (o 3.999).
Ci sono molti modi diversi per convertire tra i numeri arabi e i numeri romani. Ti consigliamo di adottare prima un approccio ingenuo per familiarizzare con il concetto di numeri romani, per poi cercare metodi più efficienti.
Ricordati di dare un'occhiata al nostro video Deep Dive alla fine, per esplorare i diversi approcci che puoi seguire!
Per qualcosa di un po' diverso, potresti anche provare una soluzione con una funzione unfold.
Probabilmente hai già familiarità con foldLeft/Right: mappare un'intera collezione in qualcos'altro (di solito una non-collezione).
unfoldLeft/Right sono le operazioni inverse: mappare qualcosa (di solito una non-collezione) in una collezione.
Quindi unfold è un'aggiunta logica e fa parte del repertorio standard della programmazione funzionale.
Questo esercizio può essere visto come un caso d'uso per unfold: mappare un Int in una String (che ovviamente è implicitamente una Seq[Char]).
Purtroppo unfoldLeft/Right non è incluso nella libreria delle collezioni di Scala.
Ma puoi prendere l'implementazione da qui.
Iscriviti a Exercism per imparare e padroneggiare Scala con 95 esercizi e il mentoring di persone reali, tutto gratis.
Esplora una varietà di soluzioni diverse per questo esercizio insidioso, dalla ricorsione alle ricerche basate su tabelle, passando per una soluzione che usa numeri a base mista e per qualche semplice imbroglio da parte di Common Lisp.