Римські числові відрізки


10

Напишіть програму або функцію, яка приймає ціле число в діапазоні 1..3999 як вхідне і повертає кількість сегментних рядків, необхідних для вираження цього цілого числа в стандартних римських цифрах (щоб ви використовували XL, але не VM). Приклади:

   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

Римські перетворення номера вбудованих команди будуть дозволені, але ви можете вирішити цю проблему без них шляхом багаторазового вирахування найбільшої кількості залишився з наведеного вище списку. Приклад: 1234 = 4 + 1 + 1 + 2 + 2 + 2 + 3 = 15.

Це , тому виграє найкоротша програма.


Чому 10 дворядкових сегментів замість чотирьох? Коли ви пишете X, ви зазвичай пишете лише два рядки, але хіба перетин рядків не складає чотири сегменти?
Алекс А.

@AlexA. Визначення відрізка рядків зазвичай щось на зразок: "Набір точок, що слідують за найкоротшим шляхом між двома точками". Здається, немає жодних причин вирізати X на основі цього, для його визначення потрібні лише два набори кінцевих точок. (Припускаючи, що римляни писали в першу чергу про евклідовій геометрії, я думаю)
FryAmTheEggman

@FryAmTheEggman Хм гаразд. Добре знати, дякую.
Олексій А.

Відповіді:


2

Pyth, 92 76 70 байт

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

Спробуйте тут!

Дякую @FryAmTheEggman за декілька пропозицій щодо упаковки рядків, які врятували мені кілька байтів!

Мені все ще цікаво, чи існує математичний спосіб кодування цього списку. Спробую щось розібратися.

Пояснення

Для цього використовується заданий алгоритм. Kмістить поданий список з числами та числом, що підтверджує корроспондування, у чергуванні. Цей список створюється шляхом розбиття упакованого рядка, який стає декодованим 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, на /та зіставлення кожного елемента на ціле число.

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

   c. "..." \ / # розділити рядок на /
KsM # відобразити кожне число до int та призначити K
            WQ #, а Q! = 0
                     f% 2K # беруть лише кожен 2-й елемент K і фільтрують за допомогою T
                      !> TQ # T <= Q
                  = Ne # Візьміть останній елемент цього і призначте його N
              = QQ # Q = Q - N
                                   xKN # індекс першого виникнення N в K
                                  h # приріст цього індексу, оскільки ми хочемо сегменти рядків
                              aA @ K # отримайте відрізок рядка з цього індексу і додайте його до Y
                                      ; sY # закінчити цикл і надрукувати суму всіх сегментів рядків у Y

3

C, 148 129 символів

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

Мій перший код-гольф: ^). Оскільки в запитанні зазначено, що я можу використовувати функцію, я змінив main на функцію, щоб обрізати деякі символи (головне: передайте c як параметр, а швидше scanf)

розпакований

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

Математика, 80 72 байти

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

Анонімна функція, яка просто перетворює числа в римські цифри, замінює кожен символ його кількістю сегментів і приймає загальну кількість.


2

Сітківка, 128 байт

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

Проста заміна, поки не залишилося нічого замінити. Тоді апострофи підраховуються, і це наша кількість відрізків рядків.

Якщо дозволено введення та виведення в одинаковому режимі, це 115 байт (хоча хто б хотів набрати 1234 з них?).

Спробуйте в Інтернеті!
Спробуйте в Інтернеті! (одинарний IO)


2

Python 3, 95 байт

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

Рядок Unicode складається з кодів:

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

Якщо ви перетворите цей рядок на байт- e=ord(e);
буквал,

Я не думаю, що це працює в моєму випадку. Мені потрібна рядок Unicode :( тобто я перебираю кодові точки в цій рядку, а не над байтами.
Лінн,

1
О Я бачу. Ви не хочете запропонувати шістнадцятковий дамп рядка? Він не відображається належним чином на моєму телефоні.
xsot

1

Java, 152 байти

Тому що, знаєте, Ява.

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

Проста буквальна реалізація заданого алгоритму. Масив пакує інформацію про перетворення: парні індекси на один менше, ніж римські цифри, а непарні індекси - це число для цього числа.

Це лямбда, яка бере і повертає int/ Integer. Сюди входить IntUnaryOperatorабо UnaryOperator<Integer>.


1

JavaScript (ES6), 79 байт

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

Рядки представляють кількість відрізків рядків для одиниць, десятків і сотень цифр. (Тисячі - це просто в чотири рази більше цифри.) Цей метод здається коротшим, ніж інші параметри, такі як алгоритм, запропонований у питанні.

Редагувати: збережено 2 байти завдяки @ user81655.


Це класний алгоритм. Переставляючи касти, ви можете також зберегти 2 байти:n=>"0123323453"[[,a,b,c,d]=1e4+n+'',d]-(-"0246424683"[c]-"0123323455"[b])+a*4
user81655

@ user81655 О, це приємно: проста зміна +s на -s дозволяє мені видалити ведучий +, але тоді групування зберігає інший байт.
Ніл
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.