Описание задачи
У нас было несколько проблем, связанных с последовательностью 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", ...]
- Выведите
N
th член этой последовательности (он может быть 0-индексирован).
Не забудьте сделать свой код как можно короче, так как это вызов для игры в гольф !
РЕДАКТИРОВАТЬ: Я считаю, что всегда есть один стандартный / предпочтительный способ выражения целых чисел в виде римских цифр (например, 95
-> XCV
вместо VC
). Несколько конвертеров римских цифр, которые я нашел в Интернете, подтверждают мое мнение. Если вы сомневаетесь, используйте онлайн-конвертер , поскольку перечисление всех возможных крайних случаев и конкретных правил написания римских цифр не является целью этой проблемы.
EDIT2: @PeterTaylor и @GregMartin отметили, что только цифры меньше или равно 5
в последовательности, так что вам не придется беспокоиться о неоднозначности римских цифр (номер 1
- 8
это I
, II
, III
, IV
, V
, VI
, VII
, и VIII
)
источник
4
/IV
/IIII
? Или95
/XCV
/VC
? Не всегда может быть уникальный способ выразить целое число, но я уверен, что всегда есть предпочтительный (стандартный) способ - поправьте меня, если я ошибаюсь.Ответы:
Perl, 49 байт
Включает +1 для
-p
Запустите с индексом на основе 0 для STDIN, например
ecce.pl
:Магические формулы так волшебны.
Обычно я бы использовал,
($_=//)x$'
чтобы сделать управление циклом на один байт короче, но оценка на этом сайте дает 2 гандикапа, поэтому он заканчивается на 1 байт длиннее. На старых версиях вы можете оставить место раньшеfor
. Некоторые версии Perl вынуждают вас добавлять финал,;
чтобы закрыть транслитерацию. Но выше приведен код, который работает в моей системе.объяснение
Работа в обратном направлении от решения к коду:
Строковые преобразования нам нужны:
Каждая замена заканчивается повторяющимся символом. Я получу последовательность одинаковых символов с помощью регулярных выражений
/(.)\1*/
, так что это можно сделать, добавив$1
. Часть до->
находится в$&
. С этим мне еще нужно:Напишите
I
как1
иV
как 9:При делении части до
->
повторяющейся цифры это становится:Так что теперь повторение оригинала
V
больше не является исключением. Итак, я хочу выражение, которое делает это:И это может быть сделано простым модулем 182:
(это даже получает
IIIIII
вVI
праве , хотя он здесь не нужен)Все , что осталось инициализирует рабочую переменную
1
для индекса 0, повторить это преобразование в цикле и в конце заменить1
наI
и9
наV
1
,9
И182
является единственным параметром комбинации , для которых эта простая формула работает.источник
Mathematica,
1139083 байтаСпасибо Martin Ender за предложения, которые сократили длину более чем на 25%!
Хвастовство команд высокого уровня в Mathematica.
Чистая функция, принимающая аргумент N и выводящая N-й элемент этой (0-индексированной) последовательности в виде списка символов. Выкладываю немного:
Внешний
Nest
итерирует среднюю четырехстрочную функцию, начиная с{"I"}
N раз. Строка 4 разбивает список символов входной римской цифры на серии одинаковых символов, отсчитывает каждый цикл с помощьюTally
и ставит счет перед символами, которые они считают. Строка 3 отображает счет как римские цифры, а затем разбивает эти римские цифры на списки символов. КомандаFlatten
сокращает весь список списков до одномерного списка.Вот начальная версия:
источник
@@@
вместо,/@
вы можете использовать#
и#2
вместо#[[1]]
и#[[2]]
. Кроме того, списки символов являются приемлемыми строковыми типами, так что вы можете работать с ними и избегать их использованияCharacters@
.@@@
похоже на ярлык! Что касается списков символов, являющихся допустимыми строковыми типами (что, я согласен, приведет к сокращению кода): есть ли на этом сайте сообщение, на которое вы можете указать мне, где описываются стандарты сообщества?Characters
потоки автоматически, так что вы можете использовать@
,Reverse@#&
конечно же, как обычныйReverse
, и в этом случае вам также не нужны эти скобки. И префиксная нотация (в случаеFlatten
) ничего не сохраняет, если вам нужно добавить скобки, чтобы она работала. Объединяя все это:Nest[Flatten[Characters@{RomanNumeral@#,#2}&@@@Reverse@@@Tally/@Split@#]&,{"I"},#]&
CJam (
3330 байт)Онлайн демо
Ключом к правильности реализации является следующая теорема:
Если первое поколение
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
секунд. Максимум четыре изI
s происходят из рядаI
s в предыдущей строке, поэтому соответствующий раздел предыдущей строки должен быть...IIIVV...
задан... IIII IIV ...
. ПосколькуVV
поколение inm-1
не происходитVVVVV
(см. Лемму), второе числоV
должно быть длиной разрядаI
, поэтому в поколенииm-1
мы имеем...IIIVVI...
. И так как мы хотим, чтобы начальныеI
s дать,IIII
а неIVI
илиVI
, ему предшествует либо начало строки, либо aV
.Если мы имеем
(...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
, мы получим цикл:и поэтому ни одно поколение никогда не начинается ни с
VIIIV
илиVIIVV
. Надо сделать вывод, что такого нетm
.рассечение
источник
Python 3, 195 байт
На римских цифрах потрачено много байтов, так что, скорее всего, там можно поиграть в гольф.
Спасибо @ El'endiaStarman, @ Sherlock9 и @Shooqie
Идео это!
источник
for v,i in(5,"V"),(4,"IV"),(1,"I")
for v,i in(5,"V"),(4,"IV"),(1,"I"):a,x=divmod(x,v);r+=i*a
сохраняет байт.i
(как вfor i in range(...)
). Я пытался поболтать,exec
но этот1
метод, который не вошел в 'sub', кажется, испортил код, я не смог найти обходной путь.range
R
110107 байтas.roman
в сочетании сrle
делает это легко. Злоупотребление ограничением и встроенное поведение кошки<<-
экономит несколько байтов.Берет N с консоли. Выводит первые от 2 до N членов последовательности (что, я думаю, находится в пределах спецификации ...)
источник
JavaScript (ES6), 107
Рекурсивная функция, возвращающая N-й член 0 на основе
Тестовое задание
источник
Perl 6 , 62 байта
Анонимная функция, которая принимает индекс с нуля.
Используется тот факт, что римские числа выше 5 не нужны, потому что единственные группы повторяющихся цифр, которые могут встречаться, это:
( попробуйте онлайн )
источник