Segmentos de línea de números romanos

10

Escriba un programa o función que acepte un número entero en el rango 1..3999 como entrada y devuelva el número de segmentos de línea necesarios para expresar ese número entero en números romanos estándar (por lo que usaría XL pero no VM). Ejemplos:

   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

Se permiten las conversiones de números romanos , pero puede resolver el problema sin ellas restando repetidamente el número restante más grande de la lista anterior. Ejemplo: 1234 = 4 + 1 + 1 + 2 + 2 + 2 + 3 = 15.

Este es el , por lo que gana el programa más corto.

Neil
fuente
¿Por qué son 10 segmentos de dos líneas en lugar de cuatro? Al escribir X, normalmente solo escribirías dos líneas, pero ¿la intersección de las líneas no lo convierte en cuatro segmentos?
Alex A.
@AlexA. La definición de segmento de línea suele ser algo así como: "El conjunto de puntos que siguen la ruta más corta entre dos puntos". No parece haber ninguna razón para cortar X en función de esto, solo necesita dos conjuntos de puntos finales para definirlo. (Suponiendo que los romanos escribieron principalmente sobre geometrías euclidianas, supongo)
FryAmTheEggman
@FryAmTheEggman Hm está bien. Es bueno saberlo, gracias.
Alex A.

Respuestas:

2

Pyth, 92 76 70 bytes

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

Pruébalo aquí!

¡Gracias a @FryAmTheEggman por algunas sugerencias de empaque de cadenas que me ahorraron algunos bytes!

Todavía me pregunto si hay una forma matemática de codificar esta lista. Intentará resolver algo.

Explicación

Esto usa el algoritmo dado. Kcontiene la lista dada con los números y el número de segmentos de línea corrosivos en alternancia. Esta lista se construye dividiendo una cadena lleno, lo que consigue decodificado a 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, en /y mapear cada elemento a un entero.

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

   c. "..." \ / # divide la cadena en /
KsM # asigna cada número a int y lo asigna a K
            WQ # mientras Q! = 0
                     f% 2K # solo toma cada segundo elemento de K y filtra con T
                      !> TQ # T <= Q
                  = Ne # Tome el último elemento de eso y asígnelo a N
              = QQ # Q = Q - N
                                   Índice xKN # de la primera aparición de N en K
                                  h # incrementa ese índice porque queremos los segmentos de línea
                              aA @ K # obtiene el segmento de línea de ese índice y lo agrega a Y
                                      ; sY # finaliza el ciclo e imprime la suma de todos los segmentos de línea en Y
Denker
fuente
3

C, 148 129 caracteres

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;}

Mi primer código de golf: ^). Como la pregunta dice que puedo usar una función, he cambiado main a una función para recortar algunos caracteres (lo más importante: pasar c como parámetro en lugar de scanf)

desempaquetado

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;
}
STDQ
fuente
2

Mathematica, 80 72 bytes

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

Función anónima que solo convierte números a números romanos, reemplaza cada carácter con su número de segmentos y toma el total.

LegionMammal978
fuente
2

Retina, 128 bytes

. +
PS
1 {1000}
t '
1 {900}
td
1 {500}
re
1 {400}
t
1 {100}
'
1 {90}
t
1 {50}
re
1 {40}
t '
1 {10}
re
1 {9}
t
1 {5}
re
1 {4}
t
1
'
t
re'
re
''
'+
$ .0

Reemplazo simple hasta que no quede nada para reemplazar. Luego se cuentan los apóstrofes y ese es nuestro número de segmentos de línea.

Si se permiten la entrada y la salida en unario, son 115 bytes (aunque ¿quién querría escribir 1234?).

Pruébalo en línea!
Pruébalo en línea! (IO unario)

daavko
fuente
2

Python 3, 95 bytes

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 cadena Unicode consta de los puntos de código:

6004 5405 3002 2403 601 543 302 244 62 57 32 27 7
Lynn
fuente
Si convierte esa cadena en un byte literal, puede omitire=ord(e);
xsot
No creo que eso funcione en mi caso. Necesito una cadena Unicode :( es decir, estoy recorriendo los puntos de código en esa cadena, no sobre los bytes.
Lynn
1
Oh ya veo. ¿Te importaría proporcionar un volcado hexadecimal de la cadena? No se muestra correctamente en mi teléfono.
xsot
1

Java, 152 bytes

Porque, ya sabes, 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;}

Implementación literal simple del algoritmo dado. La matriz empaqueta la información de transformación: los índices pares son uno menos que el número romano y los índices impares son el recuento de ese número.

Esta es una lambda que toma y devuelve un int/ Integer. Esto incluye IntUnaryOperatoro UnaryOperator<Integer>.

CAD97
fuente
1

JavaScript (ES6), 79 bytes

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

Las cadenas representan el número de segmentos de línea para las unidades, decenas y cientos de dígitos. (Miles es simplemente cuatro veces el dígito de miles). Este método parece ser más corto que otras opciones, como el algoritmo sugerido en la pregunta.

Editar: Guardado 2 bytes gracias a @ user81655.

Neil
fuente
Este es un algoritmo genial. Reorganizar los moldes también puede ahorrar 2 bytes:n=>"0123323453"[[,a,b,c,d]=1e4+n+'',d]-(-"0246424683"[c]-"0123323455"[b])+a*4
user81655
@ user81655 Oh, eso es bueno: simplemente cambiar +s a -s me permite eliminar el inicio +, pero luego la agrupación guarda otro byte.
Neil