Quando a Roma, conta come fanno i romani?


20

sfondo

Questa sfida è ispirata a questo sito Web, che ha pubblicato il seguente diagramma:

inserisci qui la descrizione dell'immagine

Questo diagramma ci mostra che la più lunga espressione numerica romana inferiore a 250 è quella di 188, che richiede 9 numeri per esprimersi.

Sfida

I simboli standard utilizzati per esprimere numeri più romani sono i seguenti: { I, V, X, L, C, D, M}, dove i valori numerici dei personaggi sono M= 1000, D= 500, C= 100, L= 50, X= 10, V= 5, I= 1.

In questa sfida, il tuo obiettivo è, dato un numero intero positivo n , calcolare il numero di rappresentazioni numerali romane valide che possono essere composte concatenando n dei simboli standard.

Quindi, il tuo programma deve produrre il risultato di questo calcolo!

Input : un numero intero positivo n .

Output : il numero di espressioni numeriche romane valide di lunghezza n .

Regole per le espressioni numerali romane

I numeri romani originariamente avevano solo un accoppiamento "additivo", il che significa che i numeri erano sempre scritti in ordine decrescente, e la somma dei valori di tutti i numeri era il valore del numero.

In seguito, l'associazione sottrattiva, l'uso di posizionare un numero più piccolo davanti a un più grande per sottrarre il più piccolo dal più grande, divenne un luogo comune per abbreviare le espressioni numerali romane. Coppie sottrattivi non possono essere concatenati, come nel seguente espressione non valida: IXL.

Di seguito sono riportate le regole moderne per l'accoppiamento additivo e sottrattivo.

  1. Solo un I, X e C può essere usato come numero iniziale in parte di una coppia sottrattiva.
  2. Posso essere piazzato solo prima di V o X in una coppia sottrattiva.
  3. X può essere posizionato solo prima di L o C in una coppia sottrattiva.
  4. C può essere posizionato solo prima di D o M in una coppia sottrattiva.
  5. Oltre alle coppie sottrattive, i numeri devono essere in ordine decrescente (il che significa che se si rilascia il numero iniziale di ciascuna coppia sottrattiva, i numeri saranno in ordine decrescente).
  6. M, C e X non possono essere eguagliati o superati con tagli più piccoli.
  7. D, L e V possono apparire solo una volta.
  8. Solo M può essere ripetuto 4 o più volte.

Ulteriori note

  • Non useremo la notazione a barre ; piuttosto, aggiungeremo semplicemente più M per esprimere qualsiasi numero.

  • Queste sono le uniche regole che seguiremo per i nostri numeri romani. Ciò significa che anche espressioni dispari, come quelle IVI, saranno considerate valide nel nostro sistema.

  • Ricorda inoltre che non stiamo contando il numero di numeri che hanno espressioni di lunghezza n , poiché alcuni numeri hanno espressioni multiple. Invece, contiamo solo il numero di espressioni valide.

Casi test

17

231

3105

Ho controllato manualmente quanto sopra, quindi assicurati di ricontrollare i casi di test e aggiungerne altri se puoi!

Criteri vincenti

Questo è un sfida di , quindi divertiti! Accetterò solo soluzioni in grado di gestire almeno input da 1 a 9. Un altro bonus!

modificare

Come richiesto dai commentatori, trova di seguito, o in questo link pastebin, le 105 combinazioni che ho contato per n = 3

III IVI IXI IXV IXX VII XII XIV XIX XVI XXI XXV XXX XLI XLV XLX XCI XCV XCX XCL XCC LII LIV LIX LVI LXI LXV LXX CII CIV CIX CVI CXI CXV CXX CXL CXC CLI CLV CLX CCI CCV CCX CCL CDC CDC CDC CMI CMV CMX CML CMC CMD CMM DII DIV DIX DIV DVI DXI DXV DXX DXL DXC DLI DLV DLX DCI DCV DCX DCL DCC MII MIV MIX MVI MXI MXV MXX MXL MXC MLI MLV MLX MCI MCV MCX MCL MCC MCD MCM MDI MDV MDV MMX MML MMC MMD MMM

Modifica 2:

Utilizzare il seguente codice non golfato , per gentile concessione di Jonathan Allan per verificare i risultati.

Modifica 3:

Mi scuso per tutti gli errori in questa sfida. La prossima volta mi assicurerò di fare un lavoro migliore!


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat .
Mego

Risposte:


3

Retina , 111 byte

~(`.+
*$(CM)CDXCXCXCXLIXIXIXIVII
.(.)
.+¶$$&$¶$$&$1$¶$$&$&¶L`.{0,$+}\b¶D`¶
¶$
¶.+¶$$&$¶$$&I¶L`[A-Z]{$+}\b¶D`¶.+

Provalo online! Si tratta di una riscrittura completa, come ho frainteso regola 1. a significare che si potrebbe usare solamente uno ciascuno dei sottrattiva I, Xe C. Spiegazione: La prima parte dello script espande l'input in una stringa di CMcoppie seguita dalle altre possibili coppie sottrattive. Ogni coppia è facoltativa e anche il primo carattere di ciascuna coppia è facoltativo all'interno della coppia. Il terzo stadio espande quindi l'elenco delle coppie in un elenco di comandi Retina che accettano l'input e creano tre copie con l'opzione del secondo o entrambi i caratteri della coppia, quindi taglia e deduplica i risultati. La fase finale quindi aggiunge il codice per eseguire le attività finali: prima di espandere l'input per aggiungere eventualmente una finaleI, quindi per filtrare i risultati di lunghezza errata, quindi per deduplicare i risultati e infine per contare i risultati. Lo script Retina risultante viene quindi valutato.

Nota: in teoria 15 byte potrebbero essere salvati dalla fine della 4a riga, ma questo rende lo script troppo lento per essere dimostrato anche su TIO n=1.


@JonathanAllan Ah, allora stai includendo più coppie sottrattive con lo stesso numero iniziale, che è sbagliato.
Neil,

2
@JonathanAllan Nuova riscrittura, per coincidenza per lo stesso esatto numero di byte!
Neil,

5

Python 2 , 177 168 162 byte

import re,itertools as q
f=lambda n:sum(None!=re.match("^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$",(''.join(m)))for m in q.product('MDCLXVI',repeat=n))

Provalo online!

Sono abbastanza nuovo, aiutami a giocare a golf! Questo controlla i numeri romani effettivi, la regex deve essere adattata per tenere conto di casi strani comeIVI

-9 byte grazie a @Dead Possum!

-6 byte grazie a @ovs


Sì, penso che il caso n = 3 potrebbe essere sbagliato nell'esempio. Mi è stato originariamente ottenendo 93 con^M*(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$
Easton Bornemeier


1
@JonathanAllan Ho passato circa due giorni a chiedere in giro su Math stackexchange cercando di assicurarmi che queste regole avessero senso. Suppongo di non aver fatto abbastanza :(
Don Mille

1
@RushabhMehta Questa è una sfida ben formattata e divertente da programmare, non sentirti male per una sfortunata sfumatura nella nitidezza dei numeri romani. È la tua sfida, specificala come ritieni opportuno. è realizzabile nell'altro senso, solo più difficile
Easton Bornemeier,

1
Questo non sembra dare la risposta giusta per 3. 93invece di105
Jo King l'

3

JavaScript (ES7), 133 byte

Modifica : corretto per corrispondere ai risultati restituiti dal codice di Jonathan Allan , che era stato fornito come implementazione di riferimento dall'OP.


n=>[...Array(m=k=7**n)].reduce(s=>s+/^1*5?4{0,3}3?2{0,3}6?0{0,3}$/.test((--k+m).toString(7).replace(/0[62]|2[34]|4[51]/g,s=>s[1])),0)

Provalo online!

Come?

N1

[...Array(m = k = 7 ** n)].reduce(s => … (--k + m).toString(7) …, 0)

D'ora in poi, ogni cifra verrà interpretata come un simbolo numerico romano:

0io,1M,2X,3L,4C,5D,6V

2) Sostituiamo tutte le coppie sottrattive valide del modulo ABcon B:

.replace(/0[62]|2[34]|4[51]/g, s => s[1]))  // in the code
.replace(/I[VX]|X[LC]|C[DM]/g, s => s[1]))  // with Roman symbols

Esempi:

  • XLIXIV diventa LXV
  • XIIVdiventa XIV, lasciando un Iche farà fallire il test successivo
  • ICrimane invariato, il che lascia invariato anche un Iposto

3) Controlliamo che i simboli rimanenti siano nell'ordine corretto e non vengano visualizzati più volte di quanto non siano autorizzati a:

/^1*5?4{0,3}3?2{0,3}6?0{0,3}$/.test(…)  // in the code
/^M*D?C{0,3}L?X{0,3}V?I{0,3}$/.test(…)  // with Roman symbols

Vacca santa, non mi aspettavo che questo fosse fatto in meno di 200 byte in lingue non esoteriche! Ti dispiace spiegare come funziona?
Don Mille

Tuttavia, ho notato che questo non funziona per * n *> 4 su TIO, il che è piuttosto sfortunato.
Don Mille

@RushabhMehta Ho aggiunto una versione non ricorsiva per testare valori più alti. Aggiungerò una spiegazione quando avrò finito di giocare a golf.
Arnauld,

0

C, 150 123 byte

Non ho letto abbastanza attentamente la descrizione, quindi questo produce il numero di numeri romani standard (dove le espressioni come IVInon vengono contate). Da quando ci ho messo qualche sforzo, ho pensato di condividere comunque.

#define F(X) for(X=10;X--;)
x[]={0,1,2,3,2,1,2,3,4,2};f(i,o,a,b,c){for(i++;i--;)F(a)F(b)F(c)o+=i==x[a]+x[b]+x[c];return o;}

Originale (150 byte):

#define F(X) for(X=10;X--;)
i,o,a,b,c,x[]={0,1,2,3,2,1,2,3,4,2};main(){scanf("%i",&i);for(i++;i--;)F(a)F(b)F(c)o+=i==x[a]+x[b]+x[c];printf("%i\n",o);}

1
Puoi pubblicare solo invii validi.
Okx,

@CurtisBechtel Puoi mantenere la soluzione qui, suppongo, ma proverei a modificarla per soddisfare le regole della sfida.
Don Mille

1
Penso che puoi rimuovere lo spazio tra F(X)efor(X=10;X--;)
Zacharý
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.