Segmenti di linea numerica romana


10

Scrivi un programma o una funzione che accetta un numero intero compreso nell'intervallo 1-399 come input e restituisce il numero di segmenti di linea richiesti per esprimere quel numero intero in numeri romani standard (quindi utilizzeresti XL ma non VM). Esempi:

   1 -> 1
   4 -> 3
   5 -> 2
   9 -> 3
  10 -> 2
  40 -> 4
  50 -> 2
  90 -> 3
 100 -> 1
 400 -> 3
 500 -> 2
 900 -> 5
1000 -> 4

I built-in di conversione dei numeri romani sono consentiti, ma è possibile risolvere il problema senza di essi sottraendo ripetutamente il numero più grande rimanente dall'elenco precedente. Esempio: 1234 = 4 + 1 + 1 + 2 + 2 + 2 + 3 = 15.

Questo è , in modo che il programma di breve vince.


Perché 10 segmenti a due righe anziché quattro? Quando si scrive X, in genere si scrivono solo due righe, ma l'intersezione delle linee non lo rende quattro segmenti?
Alex A.

@AlexA. La definizione del segmento di linea è in genere simile a: "L'insieme di punti che segue il percorso più breve tra due punti". Non sembra esserci alcun motivo per tagliare X in base a questo, sono necessari solo due set di punti finali per definirlo. (Supponendo che i romani
abbiano

@FryAmTheEggman Hm ok. Buono a sapersi, grazie.
Alex A.

Risposte:


2

Pyth, 92 76 70 byte

KsMc."/9hæ²z³Þ§ªW×Oû[Tnè,O¤"\/WQ=Q-Q=Nef!>TQ%2K aY@KhxKN;sY

Provalo qui!

Grazie a @FryAmTheEggman per alcuni suggerimenti sull'imballaggio delle stringhe che mi hanno salvato alcuni byte!

Mi chiedo ancora se esiste un modo matematico per codificare questo elenco. Proverà a capire qualcosa.

Spiegazione

Questo utilizza l'algoritmo dato. Kcontiene l'elenco fornito con i numeri e il numero corrispondente di segmenti di linea in alternanza. Questo elenco viene creato dividendo una stringa compressa, che viene decodificata 0/0/1/1/4/3/5/2/9/3/10/2/40/4/50/2/90/3/100/1/400/3/500/2/900/5/1000/4, /attivata e mappata ogni elemento su un numero intero.

KsMc. "..." \ / WQ = QQ = Nef!> TQ% 2K aY @ KhxKN; sY # Q = input

   c. "..." \ / # divide la stringa in /
KsM # mappa ogni numero su int e lo assegna a K
            WQ # while Q! = 0
                     f% 2K # prende solo ogni 2 ° elemento di K e filtra con T
                      !> TQ # T <= Q
                  = Ne # Prendi l'ultimo elemento e assegnalo a N
              = QQ # Q = Q - N
                                   xKN # indice della prima occorrenza di N in K
                                  h # incrementa quell'indice perché vogliamo i segmenti di linea
                              aA @ K # ottiene il segmento di linea da quell'indice e lo aggiunge a Y
                                      ; sY # termina il ciclo e stampa la somma di tutti i segmenti di linea in Y

3

C, 148 129 caratteri

d,x,n[]={1000,900,500,400,100,90,50,40,10,9,5,4,1,4,5,2,3,1,3,2,4,2,3,2,3,1};f(c){while(d+=(c/n[x])*n[x+13],c%=n[x++]);return d;}

Il mio primo codice-golf: ^). Poiché la domanda afferma che posso usare una funzione, ho cambiato main in una funzione per tagliare alcuni caratteri (cosa più importante: passare c come parametro piuttosto che scanf)

spacchettato

d,x,n[]={1000,900,500,400,100,90,50,40,10,9,5,4,1,4,5,2,3,1,3,2,4,2,3,2,3,1};
f(c){
  while(d+=(c/n[x])*n[x+13],
        c%=n[x++]);
  return d;
}

2

Matematica, 80 72 byte

Tr[Characters[#~IntegerString~"Roman"]/.{"I"|"C"->1,"M"->4,_String->2}]&

Funzione anonima che converte i numeri in numeri romani, sostituisce ogni carattere con il suo numero di segmenti e prende il totale.


2

Retina, 128 byte

. +
$ *
1 {1000}
t'
1 {900}
TD
1 {500}
d
1 {400}
t
1 {100}
'
1 {90}
t
1 {50}
d
1 {40}
t'
1 {10}
d
1 {9}
t
1 {5}
d
1 {4}
t
1
'
t
d'
d
''
'+
$ .0

Sostituzione semplice fino a quando non è rimasto nulla da sostituire. Quindi vengono contati gli apostrofi e questo è il nostro numero di segmenti di linea.

Se sono consentiti input e output in unario, sono 115 byte (anche se chi vorrebbe digitarne 1234?).

Provalo online!
Provalo online! (IO unario)


2

Python 3, 95 byte

def f(a,b=0):
 for e in'᝴ᔝ஺ॣəȟĮô>9 ':e=ord(e);d=e//6;b+=a//d*(e%6);a%=d
 return b

La stringa Unicode è costituita dai punti di codice:

6004 5405 3002 2403 601 543 302 244 62 57 32 27 7

Se trasformi quella stringa in un letterale byte puoi ometteree=ord(e);
xsot

Non penso che funzioni nel mio caso. Ho bisogno di una stringa Unicode :( cioè sto eseguendo il ciclo sopra i punti di codice in quella stringa, non sopra i byte.
Lynn

1
Oh, capisco. Ti dispiace fornire un dump esadecimale della stringa? Non viene visualizzato correttamente sul mio telefono.
xsot

1

Java, 152 byte

Perché, sai, Java.

n->{int c=0;int[]r={999,4,899,5,499,2,399,3,99,1,89,3,49,2,39,4,9,2,8,3,4,2,3,3,0,1};for(int i=0;i<26;i+=2)while(n>r[i]){n-=r[i]+1;c+=r[i+1];}return c;}

Semplice implementazione letterale dell'algoritmo dato. L'array racchiude le informazioni di trasformazione: gli indici pari sono uno in meno del numero romano e gli indici dispari sono il conteggio per quel numero.

Questo è un lambda che accetta e restituisce un int/ Integer. Questo include IntUnaryOperatoro UnaryOperator<Integer>.


1

JavaScript (ES6), 79 byte

n=>"0123323453"[[,a,b,c,d]=1e4+n+'',d]-(-"0246424683"[c]-"0123323455"[b])+a*4

Le stringhe rappresentano il numero di segmenti di linea per le unità, decine e centinaia di cifre. (Migliaia sono semplicemente quattro volte le cifre delle migliaia.) Questo metodo sembra essere più breve di altre opzioni come l'algoritmo suggerito nella domanda.

Modifica: salvato 2 byte grazie a @ user81655.


Questo è un algoritmo interessante. Riorganizzare i cast può salvare anche 2 byte:n=>"0123323453"[[,a,b,c,d]=1e4+n+'',d]-(-"0246424683"[c]-"0123323455"[b])+a*4
user81655

@ user81655 Oh, è carino: semplicemente cambiando la +s in -s mi permette di rimuovere il comando iniziale +, ma il raggruppamento salva un altro byte.
Neil,
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.