Послідовність перегляду: видання римських цифр


20

Опис виклику

У нас було декілька проблем, пов’язаних із послідовністю "Подивись і скажи" . Швидке нагадування:

  • Послідовність починається з 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цей термін цієї послідовності (він може бути індексований 0).

Не забудьте зробити свій код якомога коротшим, адже це завдання з з !

EDIT: Я вважаю, що завжди існує один стандартний / бажаний спосіб вираження цілих чисел як римських цифр, (наприклад 95-> XCVзамість VC). Кілька перетворювачів римських цифр, які я знайшов в Інтернеті, підтверджують свою думку. Якщо ви сумніваєтеся, використовуйте Інтернет-конвертер , оскільки перелік усіх можливих кращих справ та конкретних правил написання римських цифр не є суть цього завдання.

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


Існує не унікальний римський числовий вираз для кожного цілого числа. Які числа, можливо, потрібно виразити, і які вираження цих чисел є дійсними?
Пітер Тейлор

Що ви маєте на увазі під "не існує унікального римського числового виразу для кожного цілого числа"? Як 4/ IV/ IIII? Або 95/ XCV/ VC? Можливо, не завжди існує унікальний спосіб виразити ціле число, але я впевнений, що завжди є кращий (стандартний) - виправте мене, якщо я помиляюся.
shooqie

1
як далеко нам треба пройти з нашими римськими цифрами?
Мальтісен

Так, обидва ці випадки. У другому випадку я вважаю, що це дуже важливо питання думки.
Пітер Тейлор

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

Математика, 113 90 83 байт

Дякуємо Мартіну Ендеру за пропозиції, які скоротили довжину понад 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в поколінні m-1не походить VVVVV(див. Лема), друге Vповинно бути довжиною розряду цифри I, тому в поколінні m-1ми маємо ...IIIVVI.... А оскільки ми хочемо, щоб початкові Is давали, IIIIа не IVIабоVI, цьому передує або початок рядка, або а 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є першим із пробігом у шість Is, це повинно бути (...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

Пітон 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зберігає байт.
Шерлок9

@ βετѧΛєҫαγ: Крім того, ви, схоже, не використовуєте i(як в for i in range(...)). Я спробував поспішати, execале це втекло 1методом "під", схоже, псує код, я не зміг знайти рішення.
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"

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>


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

( спробуйте в Інтернеті )

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