⍝ R o m a n N u m e r a l s See →notes.roman← ← .() ⍝ digit binding: 7 → V.I.I ⍴() ⍺() ⍝ Roman ←→ Arabic: C.X.L.I.X ←→ 1.4.9 ← ×() ÷() %() ⍝ mul div rem ← +() -() ⍝ add sub ⍝ Pattern sets: s p q r :: ⍝ match anything. n m :: I V X L C D M ⍝ match single digit. k :: absurdus nimius ⍝ too small, too big. i :: nulla ⍝ nothing. j :: I V X L C D M absurdus nulla nimius ⍝ any atomic value. ⍝ Auxiliary functions for expanded digit strings: \() ⍝ expand (remove subtractive prefixes). /() ⍝ compress (apply subtractive prefixes). ← ∘() ⍝ expanded digit separator (disables normalisation). ⍝ Add p + q = /(\p ++ \q) ⍝ Add expanded digit strings. ← ++() ⍝ merge strings, preserving order. p ++ k = k ⍝ special values. k ++ p = k i ++ q = q p ++ i = p p ++ I = p∘I ⍝ First, collect Is, then I ++ q = q∘I p ++ q∘I = (p ++ q)∘I p∘I ++ q = (p ++ q)∘I p ++ V = p∘V ⍝ collect Vs, then V ++ q = q∘V p ++ q∘V = (p ++ q)∘V p∘V ++ q = (p ++ q)∘V p ++ X = p∘X ⍝ collect Xs, then X ++ q = q∘X p ++ q∘X = (p ++ q)∘X p∘X ++ q = (p ++ q)∘X p ++ L = p∘L ⍝ collect Ls, then L ++ q = q∘L p ++ q∘L = (p ++ q)∘L p∘L ++ q = (p ++ q)∘L p ++ C = p∘C ⍝ collect Cs, then C ++ q = q∘C p ++ q∘C = (p ++ q)∘C p∘C ++ q = (p ++ q)∘C p ++ D = p∘D ⍝ collect Ds, then D ++ q = q∘D p ++ q∘D = (p ++ q)∘D p∘D ++ q = (p ++ q)∘D p ++ M = p∘M ⍝ collect Ms. M ++ q = q∘M p ++ q∘M = (p ++ q)∘M p∘M ++ q = (p ++ q)∘M ⍝ Sub p - q = /(\p -- \q) ⍝ Subtract expanded digit strings. ← --() ⍝ remove common digits. V -- I = I∘I∘I∘I ⍝ sub I X -- I = V∘I∘I∘I∘I L -- I = X∘X∘X∘X∘V∘I∘I∘I∘I C -- I = L∘X∘X∘X∘X∘V∘I∘I∘I∘I D -- I = C∘C∘C∘C∘L∘X∘X∘X∘X∘V∘I∘I∘I∘I M -- I = D∘C∘C∘C∘C∘L∘X∘X∘X∘X∘V∘I∘I∘I∘I X -- V = V ⍝ sub V L -- V = X∘X∘X∘X∘V C -- V = L∘X∘X∘X∘X∘V D -- V = C∘C∘C∘C∘L∘X∘X∘X∘X∘V M -- V = D∘C∘C∘C∘C∘L∘X∘X∘X∘X∘V L -- X = X∘X∘X∘X ⍝ sub X C -- X = L∘X∘X∘X∘X D -- X = C∘C∘C∘C∘L∘X∘X∘X∘X M -- X = D∘C∘C∘C∘C∘L∘X∘X∘X∘X C -- L = L ⍝ sub L D -- L = C∘C∘C∘C∘L M -- L = D∘C∘C∘C∘C∘L D -- C = C∘C∘C∘C ⍝ sub C M -- C = D∘C∘C∘C∘C M -- D = D∘C∘C∘C∘C ⍝ sub D p∘m -- m = p ⍝ subtract multi-digit nos. p -- q∘m = p -- q -- m p∘m -- r = (p -- r) ++ m (p--p)∘m = m m -- m = nulla ⍝ nothing left. m -- n = absurdus ⍝ less than nothing left. p -- i = p ⍝ special values. i -- q = absurdus p -- k = absurdus k -- q = k ⍝ Mul p × q = /(\p ×× \q) ⍝ Multiply expanded digit strings. ← ××() ⍝ auxiliary function. p ×× I = p ⍝ I × ··· I ×× q = q ⍝ ··· × I V ×× V = X∘X∘V ⍝ V × ··· V ×× X = L V ×× L = C∘C∘L V ×× C = D V ×× D = M∘M∘D X ×× V = L ⍝ X × ··· X ×× X = C X ×× L = D X ×× C = M L ×× V = C∘C∘L ⍝ L × ··· L ×× X = D L ×× L = M∘M∘D C ×× V = D ⍝ C × ··· C ×× X = M D ×× V = M∘M∘D ⍝ D × ··· i ×× q = i ⍝ special values p ×× i = i k ×× q = k p ×× k = k p∘m ×× q∘n = (p××q)++(p××n)++(m××q)++(m××n) p ×× q∘n = (p××q)++(p××n) p∘m ×× q = (p××q)++ (m××q) p ×× q = nimius ⍝ not already covered: overflow. ⍝ Intermediate simplification of expanded strings, speeds up multiply: I∘I∘I∘I∘I = V p∘I∘I∘I∘I∘I = p∘V V∘V = X p∘V∘V = p∘X X∘X∘X∘X∘X = L p∘X∘X∘X∘X∘X = p∘L L∘L = C p∘L∘L = p∘C C∘C∘C∘C∘C = D p∘C∘C∘C∘C∘C = p∘D D∘D = M p∘D∘D = p∘M ⍝ Div ⍝ Integer divide. p ÷ q = /(div(qr(\p; \q))) ⍝ div expanded strings. div() ⋄ div(q; r) = q ⍝ extract quotient ⍝ Rem ⍝ Integer remainder. p % q = /(rem(qr(\p; \q))) ⍝ rem expanded strings. rem() ⋄ rem(q; r) = r ⍝ extract remainder ⍝ Auxiliary functions for division: ← ;() ⍝ tuple item separation. qr() ⋄ qr(p; q) = dv(p; (sh(p; q; ⊥)); nulla) ⍝ quotient and remainder. ⍝ Long division: dv() dv'() dv"() ⍝ division. dv p; ⊥; r = nulla; p ⍝ dividend too small: done. dv p; (q; s); r = dv' r; s; (sb p; q; nulla) dv' r; s; (p; q) = dv" q; s; (p++(10 r)) dv" r; ⊥; q = q; r ⍝ finished. dv" p; q; r = dv p; q; r sb() sb'() ⍝ repeated subtraction. sb p; q; r = sb' p; q; r; (p?q) ⍝ dividend ? subtrahend: sb' p; q; r; lt = r; p ⍝ p<q: sb' p; q; r; s = sb p--q; q; r∘I ⍝ p≥q: sh() sh'() ⍝ divisor "shift". sh p; q; r = sh' p; q; r; (p?q) sh' p; q; r; lt = r sh' p; q; r; s = sh p; (10 q); (q; r) ⍝ Tenfold (note that "10" is a function). 10() ⍝ tenfold. 10 I = X 10 V = L 10 X = C 10 L = D 10 C = M 10 D = nimius ⍝ too big 10 M = nimius ⍝ too big 10 j = j ⍝ ten nothings are still nothing, etc. 10(p∘n) = (10 p)∘(10 n) ⍝ Compare ← ?() ??() ⍝ compare expanded strings. p ? q = (⌽p)??(⌽q) ⍝ ⌽: compare more significant values first. m ?? m = eq I ?? n = lt m ?? I = gt V ?? n = lt m ?? V = gt X ?? n = lt m ?? X = gt L ?? n = lt m ?? L = gt C ?? n = lt m ?? C = gt D ?? n = lt m ?? D = gt M ?? n = lt m ?? M = gt p ?? nimius = lt ⍝ compare with "too big" nimius ?? q = gt p ?? absurdus = gt ⍝ compare with "too small" absurdus ?? q = lt p ?? nulla = gt ⍝ compare with "nothing" nulla ?? q = lt m∘p ?? n = (m??n)∘gt m ?? n∘q = (m??n)∘lt m∘p ?? n∘q = (m??n)∘(p??q) eq∘q = q lt∘q = lt gt∘q = gt ⍝ Reverse expanded string binding: ((a∘b)∘c)∘d → a∘(b∘(c∘d)) ⌽() ⌽j = j ⌽(p∘q) = ⌽⌽(p;q) ⌽⌽() ⌽⌽(j;r) = j∘r ⌽⌽(p∘q;r) = ⌽⌽(p;q∘r) ⍝ Expand (remove subtractive prefixes). See →notes.roman← \j = j \I.V = I∘I∘I∘I \I.X = V∘I∘I∘I∘I \X.L = X∘X∘X∘X \X.C = L∘X∘X∘X∘X \C.D = C∘C∘C∘C \C.M = D∘C∘C∘C∘C \p.I.V = \p∘I∘I∘I∘I \p.I.X = \p∘V∘I∘I∘I∘I \p.X.L = \p∘X∘X∘X∘X \p.X.C = \p∘L∘X∘X∘X∘X \p.C.D = \p∘C∘C∘C∘C \p.C.M = \p∘D∘C∘C∘C∘C \p.n = \p∘n ⍝ Compress: replace '∘' with '.' to enable renormalisation. /j = j /(p∘n) = (/p).n ⍝ Normalise (per norma) I.I.I.I = I.V p.I.I.I.I = p.I.V I.V.I = V p.I.V.I = p.V V.I.I.I.I = I.X p.V.I.I.I.I = p.I.X I.X.I = X p.I.X.I = p.X V.I.V = I.X p.V.I.V = p.I.X X.X.X.X = X.L p.X.X.X.X = p.X.L X.L.X = L p.X.L.X = p.L X.X.X.X.I.X = X.L.I.X p.X.X.X.X.I.X = p.X.L.I.X L.X.L = X.C p.L.X.L = p.X.C X.C.X = C p.X.C.X = p.C C.C.C.C = C.D p.C.C.C.C = p.C.D C.D.C = D p.C.D.C = p.D D.C.C.C.C = C.M p.D.C.C.C.C = p.C.M D.C.D = C.M p.D.C.D = p.C.M C.M.C = M p.C.M.C = p.M V.V = X p.V.V = p.X L.L = C p.L.L = p.C D.D = M p.D.D = p.M M.M.M.M = nimius ⍝ overflow (too big) p.i = p ⍝ special values. i.q = q p.k = k k.q = k ⍝ Roman from Arabic 1 ·· 3,999 ⍴⍴() ⍝ Auxiliary function ⍴ p = ⍴⍴(p∘I) ⍝ start with I units ⍴⍴(0∘I) = nulla ⍝⍝⍝⍝ ⍴⍴(1∘I) = I ⍝ ⍴⍴(2∘I) = I.I ⍝ ⍴⍴(3∘I) = I.I.I ⍝ ⍴⍴(4∘I) = I.V ⍝ ⍴⍴(5∘I) = V ⍝ ⍴⍴(6∘I) = V.I ⍝ ⍴⍴(7∘I) = V.I.I ⍝ ⍴⍴(8∘I) = V.I.I.I ⍝ ⍴⍴(9∘I) = I.X ⍝ ⍝ 1 ·· 9 ⍴⍴(p.0∘I) = ⍴⍴(p∘X) ⍝ ⍴⍴(p.1∘I) = (⍴⍴(p∘X)).I ⍝ ⍴⍴(p.2∘I) = (⍴⍴(p∘X)).I.I ⍝ ⍴⍴(p.3∘I) = (⍴⍴(p∘X)).I.I.I ⍝ ⍴⍴(p.4∘I) = (⍴⍴(p∘X)).I.V ⍝ ⍴⍴(p.5∘I) = (⍴⍴(p∘X)).V ⍝ ⍴⍴(p.6∘I) = (⍴⍴(p∘X)).V.I ⍝ ⍴⍴(p.7∘I) = (⍴⍴(p∘X)).V.I.I ⍝ ⍴⍴(p.8∘I) = (⍴⍴(p∘X)).V.I.I.I ⍝ ⍴⍴(p.9∘I) = (⍴⍴(p∘X)).I.X ⍝⍝⍝⍝ ⍴⍴(1∘X) = X ⍝⍝⍝⍝ ⍴⍴(2∘X) = X.X ⍝ ⍴⍴(3∘X) = X.X.X ⍝ ⍴⍴(4∘X) = X.L ⍝ ⍴⍴(5∘X) = L ⍝ ⍴⍴(6∘X) = L.X ⍝ ⍴⍴(7∘X) = L.X.X ⍝ ⍴⍴(8∘X) = L.X.X.X ⍝ ⍴⍴(9∘X) = X.C ⍝ ⍝ 1.0 ·· 9.0 ⍴⍴(p.0∘X) = ⍴⍴(p∘C) ⍝ ⍴⍴(p.1∘X) = (⍴⍴(p∘C)).X ⍝ ⍴⍴(p.2∘X) = (⍴⍴(p∘C)).X.X ⍝ ⍴⍴(p.3∘X) = (⍴⍴(p∘C)).X.X.X ⍝ ⍴⍴(p.4∘X) = (⍴⍴(p∘C)).X.L ⍝ ⍴⍴(p.5∘X) = (⍴⍴(p∘C)).L ⍝ ⍴⍴(p.6∘X) = (⍴⍴(p∘C)).L.X ⍝ ⍴⍴(p.7∘X) = (⍴⍴(p∘C)).L.X.X ⍝ ⍴⍴(p.8∘X) = (⍴⍴(p∘C)).L.X.X.X ⍝ ⍴⍴(p.9∘X) = (⍴⍴(p∘C)).X.C ⍝⍝⍝⍝ ⍴⍴(1∘C) = C ⍝⍝⍝⍝ ⍴⍴(2∘C) = C.C ⍝ ⍴⍴(3∘C) = C.C.C ⍝ ⍴⍴(4∘C) = C.D ⍝ ⍴⍴(5∘C) = D ⍝ ⍴⍴(6∘C) = D.C ⍝ ⍴⍴(7∘C) = D.C.C ⍝ ⍴⍴(8∘C) = D.C.C.C ⍝ ⍴⍴(9∘C) = C.M ⍝ ⍝ 1.0.0 ·· 9.0.0 ⍴⍴(p.0∘C) = ⍴⍴(p∘M) ⍝ ⍴⍴(p.1∘C) = (⍴⍴(p∘M)).C ⍝ ⍴⍴(p.2∘C) = (⍴⍴(p∘M)).C.C ⍝ ⍴⍴(p.3∘C) = (⍴⍴(p∘M)).C.C.C ⍝ ⍴⍴(p.4∘C) = (⍴⍴(p∘M)).C.D ⍝ ⍴⍴(p.5∘C) = (⍴⍴(p∘M)).D ⍝ ⍴⍴(p.6∘C) = (⍴⍴(p∘M)).D.C ⍝ ⍴⍴(p.7∘C) = (⍴⍴(p∘M)).D.C.C ⍝ ⍴⍴(p.8∘C) = (⍴⍴(p∘M)).D.C.C.C ⍝ ⍴⍴(p.9∘C) = (⍴⍴(p∘M)).C.M ⍝⍝⍝⍝ ⍴⍴(1∘M) = M ⍝⍝⍝⍝ ⍴⍴(2∘M) = M.M ⍝ 1.0.0.0 ·· 3.0.0.0 ⍴⍴(3∘M) = M.M.M ⍝⍝⍝⍝ ⍴⍴(p) = nimius ⍝⍝⍝⍝ otherwise: too big ⍝ Arabic from Roman ⍺⍺() ⍝ Auxiliary function. ← <+>() ⍝ add multi-digit Arabic numbers. a b :: 0 1 2 3 4 5 6 7 8 9 ⍝ Arabic digits ⍺ r = ⍺⍺(\r) ⍺⍺ i = 0 ⍺⍺ I = 1 ⍺⍺ V = 5 ⍺⍺ X = 1.0 ⍺⍺ L = 5.0 ⍺⍺ C = 1.0.0 ⍺⍺ D = 5.0.0 ⍺⍺ M = 1.0.0.0 ⍺⍺ nulla = 0 ⍺⍺ nimius = too_big ⍺⍺ absurdus = negative ⍺⍺(p∘m) = ⍺⍺p <+> ⍺⍺m a <+> 0 = a 0 <+> b = b 1 <+> 1 = 2 2 <+> 1 = 3 3 <+> 1 = 4 4 <+> 1 = 5 5 <+> 1 = 6 6 <+> 1 = 7 7 <+> 1 = 8 8 <+> 1 = 9 p.a <+> b = p.(a<+>b) p.a <+> q.b = (p<+>q).(a<+>b) ⍝ Equivalence functions ← =() ≡() ⍝ reduction equivalence/trace ⍝ Test Cases ⍝ ⍝ I.I.I.I -> I.V ⍝ normalisation ⍝ I.I.I.I.I -> V ⍝ I.I.I.I.I.I -> V.I ⍝ ⍝ I+I+I+I+I+I -> V.I ⍝ addition ⍝ I.V + I -> V ⍝ V.I.I + V.I.I -> X.I.V ⍝ I.X + I.X -> X.V.I.I.I ⍝ X.L.I.X + X.L.I.X -> X.C.V.I.I.I ⍝ M+M+M+M -> nimius ⍝ ⍝ X.X - I -> X.I.X ⍝ subtraction. ⍝ V.I - V -> I ⍝ X-I.I.I.I.I.I.I.I.I -> I ⍝ X.X - I.I -> X.V.I.I.I ⍝ X.I.V - V.I -> V.I.I.I ⍝ C.I - V -> X.C.V.I ⍝ M.M - I -> M.C.M.X.C.I.X ⍝ X-V-V -> nulla ⍝ X-V-V-V -> absurdus ⍝ ⍝ X.I.V × X.I.V -> C.X.C.V.I ⍝ multiplication ⍝ X×X×X -> M ⍝ X×X×X×X -> nimius ⍝ I.I × nulla -> nulla ⍝ ⍝ V ÷ I -> V ⍝ division ⍝ C ÷ X -> X ⍝ X.I ÷ I.I -> V ⍝ C.X.L.V ÷ V.I -> X.X.I.V ⍝ V ÷ X -> nulla ⍝ X.I.I ÷ V -> I.I ⍝ ⍝ C.X.L.V % V.I -> I ⍝ remainder ⍝ X % V -> nulla ⍝ V % X -> V ⍝ X.I.I % V -> I.I ⍝ ⍝ ⍴ 1.9.9.9 -> M.C.M.X.C.I.X ⍝ Roman from Arabic ⍝ ⍴ 3.9.9.9 -> M.M.M.C.M.X.C.I.X ⍝ ⍴ 4.0.0.0 -> nimius ⍝ (number too big) ⍝ ⍝ ⍺ M.C.M.X.C.I.X -> 1.9.9.9 ⍝ Arabic from Roman ⍝ ⍺ M.M.M.C.M.X.C.I.X -> 3.9.9.9 ⍝ ⍝ ⍺⍴ 4.9 -> 4.9 ⍝ round trip. ⍝ ⍴⍺ C.M.X.C.I.X -> C.M.X.C.I.X ⍝ .. .. ⍝ ⍴⍺ C.D.X.L.I.V -> C.D.X.L.I.V ⍝ .. .. ⍝ ⍝ M + I.X × C.X.I -> M.C.M.X.C.I.X ⍝ misc ⍝ ⍝ Back to: Contents