Смотри-и-говори последовательность: издание римских цифр

20

Описание задачи

У нас было несколько проблем, связанных с последовательностью Look-and-say . Быстрое напоминание:

  • Последовательность начинается с 1,
  • Последующие члены этой последовательности генерируются путем перечисления каждой группы повторяющихся цифр в предыдущем термине,

Итак, первые несколько терминов:

1        "one"
11       "one one" (we look at the previous term)
21       "two ones"
1211     "one two, one one"
111221   "one one, one two, two ones"
312211   "three ones, two twos, one one"

Теперь давайте сделаем то же самое, но вместо этого будем использовать римские цифры . Мы начинаем с Iи следуем тем же правилам (вместо символов мы применяем правило подсчета цифр, поэтому читаем IVXкак one one, one five, one tenвместо one four, one tenили каким-либо другим способом):

I           "one"
II          "one one"
III         "two ones" = "II" + "I"
IIII        "three ones" = "III" + "I"
IVI         "four ones" = "IV" + "I"
IIIVII      "one one, one five, one one"
IIIIIVIII   "three ones, one five, two ones" = ("III" + "I") + ("I" + "V") + ("II" + "I")

Учитывая положительное целое число N, либо:

  • Выведите первые Nцифры этой последовательности (любой разумный разделитель в порядке, а также["I", "II", "III", ...]
  • Выведите Nth член этой последовательности (он может быть 0-индексирован).

Не забудьте сделать свой код как можно короче, так как это вызов !

РЕДАКТИРОВАТЬ: Я считаю, что всегда есть один стандартный / предпочтительный способ выражения целых чисел в виде римских цифр (например, 95-> XCVвместо VC). Несколько конвертеров римских цифр, которые я нашел в Интернете, подтверждают мое мнение. Если вы сомневаетесь, используйте онлайн-конвертер , поскольку перечисление всех возможных крайних случаев и конкретных правил написания римских цифр не является целью этой проблемы.

EDIT2: @PeterTaylor и @GregMartin отметили, что только цифры меньше или равно 5в последовательности, так что вам не придется беспокоиться о неоднозначности римских цифр (номер 1- 8это I, II, III, IV, V, VI, VII, и VIII)

shooqie
источник
Не существует уникального римского числового выражения для каждого целого числа. Какие числа могут потребоваться для выражения, и какие выражения этих чисел действительны?
Питер Тейлор
Что вы подразумеваете под "не существует уникального римского числового выражения для каждого целого числа"? Нравится 4/ IV/ IIII? Или 95/ XCV/ VC? Не всегда может быть уникальный способ выразить целое число, но я уверен, что всегда есть предпочтительный (стандартный) способ - поправьте меня, если я ошибаюсь.
shooqie
1
как далеко мы должны идти с нашими римскими цифрами?
Maltysen
Да, оба этих случая. Во втором случае, я думаю, что это очень вопрос мнения, который является предпочтительным.
Питер Тейлор
9
@shooqie, если бы эти детали не были разъяснены, как бы вы сравнили ответы? Если есть определенные крайние случаи, оставленные до интерпретации, фактические оценки становятся бессмысленными, потому что они могут иметь большее значение, чем любые уловки игры в гольф, которые вы могли бы придумать.
Мартин Эндер

Ответы:

17

Perl, 49 байт

Включает +1 для -p

Запустите с индексом на основе 0 для STDIN, например

ecce.pl <<< 14

ecce.pl:

#!/usr/bin/perl -p
s,(.)\1*,$&/$1%182 .$1,eg for($_=/$/)x$`;y;19;IV

Магические формулы так волшебны.

Обычно я бы использовал, ($_=//)x$'чтобы сделать управление циклом на один байт короче, но оценка на этом сайте дает 2 гандикапа, поэтому он заканчивается на 1 байт длиннее. На старых версиях вы можете оставить место раньше for. Некоторые версии Perl вынуждают вас добавлять финал, ;чтобы закрыть транслитерацию. Но выше приведен код, который работает в моей системе.

объяснение

Работа в обратном направлении от решения к коду:

Строковые преобразования нам нужны:

I     -> II
II    -> III
III   -> IIII
IIII  -> IVI
IIIII -> VI

V     -> IV
VV    -> IIV

Каждая замена заканчивается повторяющимся символом. Я получу последовательность одинаковых символов с помощью регулярных выражений /(.)\1*/, так что это можно сделать, добавив $1. Часть до ->находится в $&. С этим мне еще нужно:

I     -> I
II    -> II
III   -> III
IIII  -> IV
IIIII -> V

V     -> I
VV    -> II

Напишите Iкак 1и Vкак 9:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

9     -> 1
99    -> 11

При делении части до ->повторяющейся цифры это становится:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

1     -> 1
11    -> 11

Так что теперь повторение оригинала Vбольше не является исключением. Итак, я хочу выражение, которое делает это:

1     -> 1
11    -> 11
111   -> 111
1111  -> 19
11111 -> 9

И это может быть сделано простым модулем 182:

1     % 182 = 1
11    % 182 = 11
111   % 182 = 111
1111  % 182 = 19
11111 % 182 = 9

(это даже получает IIIIIIв VIправе , хотя он здесь не нужен)

Все , что осталось инициализирует рабочую переменную 1для индекса 0, повторить это преобразование в цикле и в конце заменить 1на Iи 9наV

1, 9И 182является единственным параметром комбинации , для которых эта простая формула работает.

Тон Хоспел
источник
2
Это гений! :)
Линн
10

Mathematica, 113 90 83 байта

Спасибо Martin Ender за предложения, которые сократили длину более чем на 25%!

Хвастовство команд высокого уровня в Mathematica.

Nest[Flatten[Characters@{RomanNumeral@#,#2}&@@@Reverse@@@Tally/@Split@#]&,{"I"},#]&

Чистая функция, принимающая аргумент N и выводящая N-й элемент этой (0-индексированной) последовательности в виде списка символов. Выкладываю немного:

Nest[
  Flatten[
    Characters @ {RomanNumeral@#,#2}& @@@
      Reverse @@@ Tally /@ Split@ #
    ]& ,
  {"I"}, #]&

Внешний Nestитерирует среднюю четырехстрочную функцию, начиная с {"I"}N раз. Строка 4 разбивает список символов входной римской цифры на серии одинаковых символов, отсчитывает каждый цикл с помощью Tallyи ставит счет перед символами, которые они считают. Строка 3 отображает счет как римские цифры, а затем разбивает эти римские цифры на списки символов. Команда Flattenсокращает весь список списков до одномерного списка.

Вот начальная версия:

Nest[
  "" <> Flatten[{RomanNumeral@#[[1]], #[[2]]} & /@
    (Reverse@#[[1]] & /@ 
      Tally /@
        Split@Characters@#)] &,
  "I", #] &
Грег Мартин
источник
3
Grrr Mathematica;)
бета-распад
Если вы используете @@@вместо, /@вы можете использовать #и #2вместо #[[1]]и #[[2]]. Кроме того, списки символов являются приемлемыми строковыми типами, так что вы можете работать с ними и избегать их использования Characters@.
Мартин Эндер
@MartinEnder Ага, я знал, что, должно быть, было @@@похоже на ярлык! Что касается списков символов, являющихся допустимыми строковыми типами (что, я согласен, приведет к сокращению кода): есть ли на этом сайте сообщение, на которое вы можете указать мне, где описываются стандарты сообщества?
Грег Мартин
1
Еще несколько сбережений: Charactersпотоки автоматически, так что вы можете использовать @, Reverse@#&конечно же, как обычный Reverse, и в этом случае вам также не нужны эти скобки. И префиксная нотация (в случае Flatten) ничего не сохраняет, если вам нужно добавить скобки, чтобы она работала. Объединяя все это:Nest[Flatten[Characters@{RomanNumeral@#,#2}&@@@Reverse@@@Tally/@Split@#]&,{"I"},#]&
Мартин Эндер
8

CJam ( 33 30 байт)

"I"{e`{(4md1$^'I*\'V*@}%e_}ri*

Онлайн демо

Ключом к правильности реализации является следующая теорема:

Если первое поколение I, длина пробега не превышает пяти

Лемма: если первое поколение I, строка никогда не содержит VVV. Доказательство от противного. Предположим, что существует первый индекс, nдля которого nсодержится поколение VVV. Если это VVVсломается как (a)V VVтогда, преобразование от предыдущего поколения плохо: это должно было быть (a+5)V. Так и должно быть VV V(d), и предыдущее поколение сдерживало VVVVV, противоречащее выбору n.

Теперь предположим, что существует первый индекс, mдля которого mсодержится поколение ...IIIIII.... Обратите внимание, что в строке не может быть никаких цифр, кроме Iи V, потому что ни у одного предыдущего поколения не было серий девяти Iили девяти Vсекунд. Максимум четыре из Is происходят из ряда Is в предыдущей строке, поэтому соответствующий раздел предыдущей строки должен быть ...IIIVV...задан ... IIII IIV .... Поскольку VVпоколение in m-1не происходит VVVVV(см. Лемму), второе число Vдолжно быть длиной разряда I, поэтому в поколении m-1мы имеем ...IIIVVI.... И так как мы хотим, чтобы начальные Is дать, IIIIа не IVIилиVI, ему предшествует либо начало строки, либо a V.

Если мы имеем (...V)?IIIVVI...в поколении m-1, что мы имеем в поколении m-2? Мы уже наблюдали, что VVген. m-1должен быть разобран как (a)V V(I).

Предположим, мы берем a=2: (...V)?I IIV VI...На самом деле это так ...VI IIV VI..., хотя это Vможет быть частью лидерства IV; так и в предыдущем поколении , мы имеем либо (...V)? IIII VV IIIII...или (...V)? IIIII VV IIIII. В любом случае мы столкнемся с проблемой VVIIIII: второй Vдолжен быть длиной цикла, но затем ...VI IIII...требуется следующая пара (длина серии, цифра) с той же цифрой.

Так должно быть a=1: (...V)?II IV VI.... Так как поколение mявляется первым с пробегом шести Iсекунд, это должно быть (...V)? II IV VI..., так что поколение m-2это (...V)? I V IIIII.... ...VIVIIIII...невозможно: однако мы решаем интерпретировать секунду, в результате Vмы получаем две последовательные пары (длина серии, цифра) с одной и той же цифрой.

Следовательно, поколение m-2должно быть ^IVIIIII...проанализировано как ^IV IIII I(V)...или ^IV III II(V).... Они дают соответственно поколение m-3как ^V III V ...или ^V II VV....

Но если мы посмотрим на начало строки, начинающейся с первой, которая начинается с V, мы получим цикл:

    VI IV I...
    IV III IV ...
    II IV IVI ...
    IIII IV II IV ...

и поэтому ни одно поколение никогда не начинается ни с VIIIVили VIIVV. Надо сделать вывод, что такого нет m.

рассечение

"I"          e# Initial generation
{            e# Loop...
  e`         e#   Run-length encode
  {          e#   Foreach [run-length char] pair...
    (        e#     Extract the run-length r
    4md1$^   e#     Get the number of Vs and the number of Is
             e#     The number of Vs is r/4 ; the number of Is is (r%4)^(r/4)
    'I*\'V*@ e#     Repeat strings the appropriate number of times and reorder
  }%
  e_         e#  Flatten to a simple string
}ri*         e# ... n times, where n is taken from stdin
Питер Тейлор
источник
6

Python 3, 195 байт

На римских цифрах потрачено много байтов, так что, скорее всего, там можно поиграть в гольф.

Спасибо @ El'endiaStarman, @ Sherlock9 и @Shooqie

import re
def f(x,r=""):
 for v,i in(5,"V"),(4,"IV"),(1,"I"):a,x=divmod(x,v);r+=i*a
 return r
s="I"
for i in[0]*int(input()):print(s);s=re.sub(r'(.)\1*',lambda m:f(len(m.group()))+m.group()[0],s)

Идео это!

Бета распад
источник
Вы можете опустить квадратные скобки:for v,i in(5,"V"),(4,"IV"),(1,"I")
shooqie
@shooqie Я понятия не имел, что вы могли бы сделать это: D
бета-распад
for v,i in(5,"V"),(4,"IV"),(1,"I"):a,x=divmod(x,v);r+=i*aсохраняет байт.
Sherlock9
@ βετѧΛєҫαγ: Кроме того, вы, кажется, не используете i(как в for i in range(...)). Я пытался поболтать, execно этот 1метод, который не вошел в 'sub', кажется, испортил код, я не смог найти обходной путь.
shooqie
@shooqie Я немного сократил его, избавившись отrange
Beta Decay
4

R 110 107 байт

as.romanв сочетании с rleделает это легко. Злоупотребление ограничением и встроенное поведение кошки <<-экономит несколько байтов.

x="I"
replicate(scan(),{r=rle(strsplit(x,"")[[1]])
x<<-paste(rbind(paste(as.roman(r$l)),r$v),collapse="")})

Берет N с консоли. Выводит первые от 2 до N членов последовательности (что, я думаю, находится в пределах спецификации ...)

 [1] "II"                                                                                                                                                                                                                                     
 [2] "III"                                                                                                                                                                                                                                    
 [3] "IIII"                                                                                                                                                                                                                                   
 [4] "IVI"                                                                                                                                                                                                                                    
 [5] "IIIVII"                                                                                                                                                                                                                                 
 [6] "IIIIIVIII"                                                                                                                                                                                                                              
 [7] "VIIVIIII"                                                                                                                                                                                                                               
 [8] "IVIIIIVIVI"                                                                                                                                                                                                                             
 [9] "IIIVIVIIVIIIVII"                                                                                                                                                                                                                        
[10] "IIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                                                                                               
[11] "VIIVIIIIIVIVIIVVIIVIIII"                                                                                                                                                                                                                
[12] "IVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                                                                                                          
[13] "IIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                                                                                                                                   
[14] "IIIIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                                                                      
[15] "VIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                                                                                                                                                 
[16] "IVIIIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                                                                         
[17] "IIIVIVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                                                                                            
[18] "IIIIIVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                                                                                           
[19] "VIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                                                                                              
[20] "IVIIIIVVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                                                                                                                    
[21] "IIIVIVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"                                                                                             
[22] "IIIIIVIIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIIVIVIIVIIIIIVVIIVVIIVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVIVIIVVIIIVIIIIVIIIVIIIIVIIIIIVIII"                                                                      
[23] "VIIVIIIIIVVIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIIVVIIVIVIIVVIIVIIIVIIIIIVVIIVIIIVIIIIVVIIIVIIIIIVIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVIVIIVIIIIIVIVIIVVIIVIIII"                                                   
[24] "IVIIIIVVIIIVIIIIIVVIIVIIIVIIIIIVIIIIIVVIIVVIIIVIIIIVIIIVIIIIIVIIIIVIIIIIVVIIIVIIIIVIIIIIVIVIIIVIIIIIVVIIVIVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIVIIIVIIIIIVIIIIVIVI"                             
[25] "IIIVIVIIIVIIIIIVVIIIVIIIIVIIIIIVVIIVVIIIVIIIIIVIIIIIVIVIIVIIIIIVVIIVIVIIVVIIIVIIIIIVIVIIVVIIVIIIVIIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVVIIVVIIVIIIVIIIIVVIIIVIIIIVIIIVIIIIIVIIIIIVIVIIVVIIIVIIIIIVIIIIVIIIIIVIVIIIVIIIIVIIIIIVVIIVIVIIVIIIVII"
Vlo
источник
1

JavaScript (ES6), 107

Рекурсивная функция, возвращающая N-й член 0 на основе

f=(n,r='I')=>n?f(n-1,r.match(/I+|V+/g).map(x=>((n=x.length)-4?'VIII'.slice(n<5,1+n%5):'IV')+x[0]).join``):r

Тестовое задание

f=(n,r='I')=>n?f(n-1,r.match(/I+|V+/g).map(x=>((n=x.length)-4?'VIII'.slice(n<5,1+n%5):'IV')+x[0]).join``):r

function update() {
  O.textContent=f(I.value)
}

update()
<input id=I value=25 type=number oninput='update()'><pre id=O></pre>

edc65
источник
1

Perl 6 , 62 байта

{("I",{S:g/(.)$0*/{<I II III IV V>[$/.chars-1]~$0}/}...*)[$_]}

Анонимная функция, которая принимает индекс с нуля.

Используется тот факт, что римские числа выше 5 не нужны, потому что единственные группы повторяющихся цифр, которые могут встречаться, это:

I     -> II
II    -> III
III   -> IIII
IIII  -> IVI
IIIII -> VI

V     -> IV
VV    -> IIV

( попробуйте онлайн )

SMLS
источник