Сегменты римской числовой линии


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

С, 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

Mathematica, 80 72 байта

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

Анонимная функция, которая просто преобразует числа в римские цифры, заменяет каждый символ количеством сегментов и получает общее количество.


2

Сетчатка, 128 байт

. +
$ *
1 {1000}
т»
1 {900}
тд
1 {500}
d
1 {400}
T
1 {100}
'
1 {90}
T
1 {50}
d
1 {40}
т»
1 {10}
d
1 {9}
T
1 {5}
d
1 {4}
T
1
'
T
d»
d
«»
«+
$ 0,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);
xsot

Я не думаю, что это работает в моем случае. Мне нужна строка в Юникоде :( т.е. я зацикливаюсь на кодовых точках в этой строке, а не на байтах.
Линн

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

1

Java, 152 байта

Потому что, вы знаете, 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;}

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

Это лямбда, которая принимает и возвращает 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.