Створіть n цифр послідовності Гійсвейта


19

Вступ

Послідовність Gijswijt ( A090822 ) справді відома, дійсно повільна. Проілюструвати:

  • Перші 3 з'являються у 9-му секторі (добре).
  • Перші 4 з'являються в 220-му терміні (далеко, але здійсненно).
  • Перші 5 з'являються у (приблизно) 10 ^ (10 ^ 23) -му терміні (просто немає).
  • Ніхто навіть не знає, де знаходиться перша 6 ... підозрюється, що це на ...

    2 ^ (2 ^ (3 ^ (4 ^ 5))) термін.

Ви можете припустити, що вам не доведеться мати справу з двозначним числом.

Послідовність генерується так:

  1. Перший термін - 1.
  2. Кожен доданок після цього - це кількість повторюваних "блоків", попередніх до нього (якщо є кілька повторюваних "блоків", використовується найбільша кількість повторюваних блоків).

Для уточнення ось кілька перших термінів.

1 -> 1, 1(один повторюваний блок ( 1), значить записана цифра є 1)

1, 1 -> 1, 1, 2(два повторювані блоки ( 1), тож записана цифра є 2)

1, 1, 2 -> 1, 1, 2, 1(один повторюваний блок ( 2або 1, 1, 2), значить записана цифра є 1)

1, 1, 2, 1 -> 1, 1, 2, 1, 1 (Ви отримуєте ідею)

1, 1, 2, 1, 1 -> 1, 1, 2, 1, 1, 2

1, 1, 2, 1, 1, 2 -> 1, 1, 2, 1, 1, 2, 2(два повторювані блоки ( 1, 1, 2), тож записана цифра є 2)

Завдання

Ваше завдання полягає у формуванні n цифр послідовності Gijswijt.

Інструкції

  • Вхід буде цілим числом n.
  • Ваш код може виводити цифри в будь-якій формі (список, кілька виходів тощо).

Це код гольфу, тому найкоротший код у байтах виграє.

Відповіді:


7

Pyth, 25 22 21 байт

t_u+eSmtfxG*Td1._GGQN

ОП підтвердило, що нам потрібно обробляти лише одноцифрові числа. Це дозволило зберегти список у вигляді рядка цифр. -> Збережено 3 байти

Спробуйте в Інтернеті: Демонстрація

Пояснення:

t_u+...GQN      implicit: Q = input number
         N      start with the string G = '"'
  u     Q       do the following Q times:
    ...            generate the next number
   +   G           and prepend it to G
 _              print reversed string at the end
t               remove the first char (the '"')

Ось як я генерую наступне число:

eSmtfxG*Td1._G
           ._G    generate all prefixes of G
  m               map each prefix d to:
    f     1          find the first number T >= 1, so that:
       *Td              d repeated T times
     xG                 occurs at the beginning of G
 S                  sort all numbers
e                   take the last one (maximum)   

21 байт зі списками

_u+eSmhhrcGd8SlGGtQ]1

Спробуйте в Інтернеті: Демонстрація

Використовує однакові ідеї Мартина та Пітера. На кожному кроці я розділяю рядок на шматки довжиною 1, шматки довжиною 2, ... Потім я кодую їх по довжині і використовую максимальний перший запуск як наступне число.

20 байт з рядками

t_u+eSmhhrcGd8SlGGQN

Спробуйте в Інтернеті: Демонстрація

Поєднує ідеї двох кодів вище.


1
Дякую, що ви навчали мене. Я завжди забуваю про ._функції та інші корисні функції в Pyth.
Leaky Nun

Мені особисто більше сподобалося оригінальне рішення, але так.
clismique

@Jakube Ах. Чи можу я подивитися? Якщо так, то дякую!
клісмік

@DerpfacePython міг переграти ще один байт до мого оригінального рішення. Я також розмістив рішення, що кодує довжину коду на основі Мартіна, а потім зміг поєднати два підходи для створення 20-байтного рішення.
Якубе

5

CJam, 33 31 30 27 байт

Дякую Пітеру Тейлору за збереження 1 байта.

1sri({),:)1$W%f/:e`$W=sc+}

Перевірте це тут.

Пояснення

1s      e# Initialise the sequence as "1".
ri(     e# Read input N and decrement.
{       e# For each I from 0 to N-1...
  )     e#   Increment to get I from 1 to N.
  ,     e#   Turn into a range [0 1 ... I-1].
  :)    e#   Increment each element to get [1 2 ... I].
  1$    e#   Copy sequence so far.
  W%    e#   Reverse the copy.
  f/    e#   For each element x in [1 2 ... I], split the (reversed) sequence
        e#   into (non-overlapping) chunks of length x. These are the potentially
        e#   repeated blocks we're looking for. We now want to find the splitting
        e#   which starts with the largest number of equal blocks.
  :e`   e#   To do that, we run-length encode each list blocks.
  $     e#   Then we sort the list of run-length encoded splittings, which primarily
        e#   sorts them by the length of the first run.
  W=    e#   We extract the last splitting which starts with the longest run.
  sc    e#   And then we extract the length of the first run by flattening
        e#   the list into a string and retrieving the first character.
  +     e#   This is the new element of the sequence, so we append it.
}/

+1 для :) (ще 5) ...
Лина монашка

5

CJam ( 30 29 27 24 байт)

'1ri{{)W$W%/e`sc}%$W>+}/

Демонстрація в Інтернеті

Це дуже багато спільних зусиль з Мартіном.

  • Уміле використання кодування довжиною пробігу ( e`) для ідентифікації повторів - це Мартін
  • Так само використання W$для спрощення управління стеком
  • Я усунув кілька операцій збільшення / зменшення за допомогою $W>+спеціального кожуха, як пояснено в розділі нижче

Мій перший 30-байтний підхід:

1ari{,1$f{W%0+_@)</{}#}$W>+}/`

Демонстрація в Інтернеті

Розсічення

1a        e# Special-case the first term
ri{       e# Read int n and iterate for i=0 to n-1
  ,1$f{   e#   Iterate for j=0 to i-1 a map with extra parameter of the sequence so far
    W%0+  e#     Reverse and append 0 to ensure a non-trivial non-repeating tail
    _@)</ e#     Take the first j+1 elements and split around them
    {}#   e#     Find the index of the first non-empty part from the split
          e#     That's equivalent to the number of times the initial word repeats
  }
  $W>+    e#   Add the maximal value to the sequence
          e#   NB Special case: if i=0 then we're taking the last term of an empty array
          e#   and nothing is appended - hence the 1a at the start of the program
}/
`         e# Format for pretty printing

3

Haskell, 97 байт

f 1=[1]
f n|x<-f$n-1=last[k|k<-[1..n],p<-[1..n],k*p<n,take(k*p)x==([1..k]>>take p x)]:x
reverse.f

Третій рядок визначає анонімну функцію, яка приймає ціле число і повертає список цілих чисел. Побачити це в дії.

Пояснення

Хелперна функція fбудує послідовність у зворотному порядку, рекурсивно перевіряючи, чи починається попередня послідовність з повторного блоку. k- кількість повторень і pдовжина блоку.

f 1=[1]                                   -- Base case: return [1]
f n|x<-f$n-1=                             -- Recursive case; bind f(n-1) to x.
  last[k|k<-[1..n],                       -- Find the greatest element k of [1..n] such that
  p<-[1..n],                              -- there exists a block length p such that
  k*p<n,                                  -- k*p is at most the length of x, and
  take(k*p)x                              -- the prefix of x of length p*k
    ==                                    -- is equal to
  ([1..k]>>take p x)                      -- the prefix of length p repeated k times.
  ]:x                                     -- Insert that k to x, and return the result.
reverse.f                                 -- Composition of reverse and f.


1

Сітківка , 66 60 байт

+1`((\d+)?(?<1>\2)*(?<!\3(?>(?<-1>\3)*)(?!.*\2)(.+)))!
$1$#1

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

Спробуйте в Інтернеті! (Крім того, для зручності ось версія, яка бере десяткове введення. )

Для цілей тестування, це може бути прискорене багато з невеликою модифікацією, яка дозволяє тестувати введення 220 протягом однієї хвилини:

+1`((\d+)?(?<1>\2)*(?=!)(?<!\3(?>(?<-1>\3)*)(?!.*\2)(.+)))!
$1$#1

Спробуйте в Інтернеті! ( Десяткова версія. )

Якщо ви хочете перевірити ще більшу кількість, то краще просто подати на нього якийсь масивний вхід і поставити :після початкового +. Це змусить Retina друкувати поточну послідовність кожного разу, коли вона закінчує обчислення нової цифри (з усіма цифрами окремо).

Пояснення

Рішення складається з єдиної заміни регулярних виразів, яка застосовується до вводу неодноразово, поки результат не перестане змінюватися, що в цьому випадку відбувається, тому що регулярний вираз більше не відповідає. На +початку вводиться ця петля. Це 1межа, яка говорить Ретіні лише про заміну першого матчу (це стосується лише першої ітерації). У кожній ітерації етап замінює одну !(зліва) наступною цифрою послідовності.

Як завжди, якщо вам потрібен праймер на балансуючих групах, я посилаюсь на свою відповідь SO .

Ось анотована версія регулярного виразу. Зауважте, що мета - захопити максимальну кількість повторних блоків у групі 1.

(                 # Group 1, this will contain some repeated block at the end
                  # of the existing sequence. We mainly need this so we can
                  # write it back in the substitution. We're also abusing it
                  # for the actual counting but I'll explain that below.
  (\d+)?          # If possible (that is except on the first iteration) capture
                  # one of more digits into group 2. This is a candidate block
                  # which we're checking for maximum repetitions. Note that this
                  # will match the *first* occurrence of the block.
  (?<1>\2)*       # Now we capture as many copies of that block as possible
                  # into group 1. The reason we use group 1 is that this captures
                  # one repetition less than there is in total (because the first
                  # repetition is group 2 itself). Together with the outer
                  # (unrelated) capture of the actual group one, we fix this
                  # off-by-one error. More importantly, this additional capture
                  # from the outer group isn't added until later, such that the
                  # lookbehind which comes next doesn't see it yet, which is
                  # actually very useful.
                  # Before we go into the lookbehind note that at the end of the
                  # regex there's a '!' to ensure that we can actually reach the
                  # end of the string with this repetition of blocks. While this 
                  # isn't actually checked until later, we can essentially assume
                  # that the lookbehind is only relevant if we've actually counted
                  # repetitions of a block at the end of the current sequence.

  (?<!            # We now use a lookbehind to ensure that this is actually the
                  # largest number of repetitions possible. We do this by ensuring
                  # that there is no shorter block which can be matched more
                  # often from the end than the current one. The first time this
                  # is true (since, due to the regex engine's backtracking rules,
                  # we start from longer blocks and move to shorter blocks later),
                  # we know we've found the maximum number of repetitions.
                  # Remember that lookbehinds are matched right-to-left, so
                  # you should read the explanation of the lookbehind from
                  # bottom to top.
    \3            # Try to match *another* occurrence of block 3. If this works,
                  # then this block can be used more often than the current one
                  # and we haven't found the maximum number of repetitions yet.
    (?>           # An atomic group to ensure that we're actually using up all
                  # repetitions from group 1, and don't backtrack.
      (?<-1>\3)*  # For each repetition in group 1, try to match block 3 again.
    )
    (?!.*\2)      # We ensure that this block isn't longer than the candidate
                  # block, by checking that the candidate block doesn't appear
                  # right of it.
    (.+)          # We capture a block from the end into group 3.
  )               # Lookbehind explanation starts here. Read upwards.
)
!                 # As I said above, this ensures that our block actually reaches
                  # the end of the string.

Нарешті, після того, як це все зроблено, ми записуємо назад $1(тим самим видаляючи !), а також кількість знімків у групі, з $#1якими відповідає максимальна кількість повторень.


Чому Retina приймає одинарні рішення замість чисел?
клісмік

@DerpfacePython Тому що це дешевше і дозволено консенсусом . Ви можете перекрити це, вказавши, що вхід повинен бути десятковим числом (в такому випадку я радий змінити рішення).
Мартін Ендер

Ах, дякую за уточнення. Хоча з цікавості, чи можете ви поставити (у коментарях) відповідь на десяткові? Якщо так, дякую.
клісмік

@DerpfacePython Додано окремі посилання за допомогою десяткового введення.
Мартін Ендер

Пояснення, коли я займаюся гольфом?
CalculatorFeline

0

Рубін, 84 байти

Відповідь Retina надихнула мене зробити рішення на основі регулярних виразів, щоб знайти найкращу послідовність замість того, щоб якось рахувати послідовності в масиві, але з меншою кількістю геніальностей (негативні погляди з кількісними показниками не здаються в Ruby, тому я сумніваюся Я можу безпосередньо передати відповідь Retina у будь-якому випадку)

->n{s='';n.times{s+=(1..n).map{|i|s=~/(\d{#{i}})\1+$/?$&.size/i: 1}.max.to_s};s[-1]}

Враховуючи вже сформовану послідовність s, вона відображає всі iвід від 1до s.length( nвикористовувався в даному випадку для збереження байтів з того часу n>=s.length), а потім використовує цей регулярний вираз, щоб допомогти обчислити кількість повторень послідовності з довжиною i:

/(.{#{i}})\1+$/
/(                 # Assign the following to group 1
  .{#{i}}          # Match `i` number of characters
         )         # End group 1
          \1+      # Match 1 or more repetitions of group 1
             $/    # Match the end of string

Якщо відповідність знайдена такої довжини, вона обчислює кількість повторень, діливши довжину заданої відповідності $&на i, тривалість послідовності; якщо не знайдено відповідності, це трактується як 1. Потім функція знаходить максимальну кількість повторень із цього відображення і додає це число до кінця рядка.

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