Segmenty linii cyfr rzymskich

10

Napisz program lub funkcję, która przyjmuje na wejściu liczbę całkowitą z zakresu 1..3999 i zwraca liczbę segmentów linii wymaganych do wyrażenia tej liczby całkowitej za pomocą standardowych cyfr rzymskich (więc użyłbyś XL, ale nie VM). Przykłady:

   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

Wbudowane konwersje liczb rzymskich dozwolone, ale można rozwiązać problem bez nich, odejmując wielokrotnie największą pozostałą liczbę z powyższej listy. Przykład: 1234 = 4 + 1 + 1 + 2 + 2 + 2 + 3 = 15.

To jest , więc wygrywa najkrótszy program.

Neil
źródło
Dlaczego 10 dwóch segmentów linii zamiast czterech? Pisząc X, zwykle piszesz tylko dwie linie, ale czy przecięcie linii nie tworzy czterech segmentów?
Alex A.,
@AlexA. Definicja segmentu linii jest zwykle podobna do: „Zestaw punktów podążających najkrótszą ścieżką między dwoma punktami”. Wydaje się, że nie ma powodu do cięcia X na podstawie tego, potrzebujesz tylko dwóch zestawów punktów końcowych, aby go zdefiniować. (Zakładając, że Rzymianie pisali przede wszystkim na temat geometrii euklidesowych)
FryAmTheEggman
@FryAmTheEggman Hm dobrze. Dobrze wiedzieć, dzięki.
Alex A.,

Odpowiedzi:

2

Pyth, 92 76 70 bajtów

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

Wypróbuj tutaj!

Dzięki @FryAmTheEggman za sugestie dotyczące pakowania ciągów, które pozwoliły mi zaoszczędzić trochę bajtów!

Nadal zastanawiam się, czy istnieje matematyczny sposób kodowania tej listy. Spróbuję coś wymyślić.

Wyjaśnienie

Używa podanego algorytmu. Kzawiera podaną listę z naprzemiennie liczbami i odpowiednią liczbą segmentów linii. Ta lista jest tworzona przez dzielenie spakowanego łańcucha, który jest dekodowany 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, /włączany i odwzorowywany na każdy element na liczbę całkowitą.

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

   c. „...” \ / / podziel ciąg na /
KsM # zamapuj każdą liczbę na liczbę całkowitą i przypisz do K.
            WQ # zaś Q! = 0
                     f% 2K # bierze tylko co drugi element K i filtruje za pomocą T
                      !> TQ # T <= Q
                  = Ne # Weź ostatni element tego i przypisz go do N.
              = QQ # Q = Q - N
                                   Indeks xKN # pierwszego wystąpienia N w K
                                  h # zwiększa ten indeks, ponieważ chcemy segmentów linii
                              aA @ K # pobierz segment linii z tego indeksu i dołącz go do Y
                                      ; sY # kończy pętlę i wypisuje sumę wszystkich segmentów linii w Y
Denker
źródło
3

C, 148 129 znaków

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

Mój pierwszy golf-code: ^). Ponieważ pytanie mówi, że mogę użyć funkcji, zmieniłem main na funkcję w celu przycięcia niektórych znaków (co najważniejsze: przekaż c jako parametr raczej scanf)

rozpakowany

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
źródło
2

Mathematica, 80 72 bajtów

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

Anonimowa funkcja, która po prostu konwertuje liczby na cyfry rzymskie, zastępuje każdy znak liczbą segmentów i pobiera sumę.

LegionMammal978
źródło
2

Siatkówka, 128 bajtów

. +
$ *
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,0 $

Prosta wymiana, dopóki nie zostanie nic do wymiany. Następnie liczone są apostrofy i to jest nasza liczba segmentów linii.

Jeśli wejście i wyjście w unarnym są dozwolone, ma to 115 bajtów (chociaż kto chciałby wpisać 1234?).

Wypróbuj online!
Wypróbuj online! (jednoargumentowe IO)

daavko
źródło
2

Python 3, 95 bajtów

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

Ciąg Unicode składa się z punktów kodowych:

6004 5405 3002 2403 601 543 302 244 62 57 32 27 7
Lynn
źródło
Jeśli e=ord(e);
zamienisz
Nie sądzę, że to działa w moim przypadku. Potrzebuję ciągu Unicode :( tzn. Zapętlam punkty kodowe w tym ciągu, a nie bajty.
Lynn
1
Rozumiem. Czy masz coś przeciwko zapewnieniu zrzutu heksadecymalnego ciągu? Nie wyświetla się poprawnie na moim telefonie.
xsot
1

Java, 152 bajty

Ponieważ, wiesz, 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;}

Prosta dosłowna implementacja danego algorytmu. Tablica zawiera informacje o transformacji: parzyste indeksy są o jeden mniejsze niż liczba rzymska, a nieparzyste są liczbą dla tej liczby.

To jest lambda, która przyjmuje i zwraca int/ Integer. Obejmuje to IntUnaryOperatorlub UnaryOperator<Integer>.

CAD97
źródło
1

JavaScript (ES6), 79 bajtów

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

Ciągi reprezentują liczbę segmentów linii dla jednostek, dziesiątek i setek cyfr. (Tysiące to po prostu czterokrotność cyfry tysięcy). Ta metoda wydaje się krótsza niż inne opcje, takie jak algorytm sugerowany w pytaniu.

Edycja: Zapisano 2 bajty dzięki @ user81655.

Neil
źródło
To jest fajny algorytm. Zmiana kolejności rzutów może również zaoszczędzić 2 bajty:n=>"0123323453"[[,a,b,c,d]=1e4+n+'',d]-(-"0246424683"[c]-"0123323455"[b])+a*4
user81655 20.04.2016
@ user81655 Och, to miłe: po prostu zmiana +s na -s pozwala mi usunąć wiodące +, ale wtedy grupowanie zapisuje kolejny bajt.
Neil,