Свертывание чисел


23

Давайте определим функцию a на натуральных числах , записанных в виде 10 основных цифр , следующим образом:NdКdК-1...d1d0

Пока есть равные соседние цифры , замените их на их сумму слева направо. Если были такие цифры, повторите ту же процедуру.dяdя-1dя+dя-1

Другими словами, в каждой итерации мы жадно берем все пары равных соседних цифр и заменяем их на их сумму одновременно (используя крайнюю левую пару, если они перекрываются).

пример

Давайте возьмем например:9988

  1. Первые соседние цифры , которые равны являются два 9
  2. Таким образом, мы заменим их на 9 + 9знак равно18 что дает нам 1888
  3. Так как мы все еще находимся в первом обходе влево и вправо, а еще осталось два нам нужно сначала заменить эти8
  4. Итак, мы получаем1816
  5. Что-то изменилось, поэтому нам нужно сделать еще одну итерацию
  6. Но таких цифр нет, поэтому остановимся

Поэтому число в этой последовательности равно .9988го1816

Вызов

Первые 200 терминов:

0,1,2,3,4,5,6,7,8,9,10,2,12,13,14,15,16,17,18,19,20,21,4,23,24,25,26,27,28,29,30,31,32,6,34,35,36,37,38,39,40,41,42,43,8,45,46,47,48,49,50,51,52,53,54,10,56,57,58,59,60,61,62,63,64,65,12,67,68,69,70,71,72,73,74,75,76,14,78,79,80,81,82,83,84,85,86,87,16,89,90,91,92,93,94,95,96,97,98,18,10,101,102,103,104,105,106,107,108,109,20,21,4,23,24,25,26,27,28,29,120,121,14,123,124,125,126,127,128,129,130,131,132,16,134,135,136,137,138,139,140,141,142,143,18,145,146,147,148,149,150,151,152,153,154,20,156,157,158,159,160,161,162,163,164,165,4,167,168,169,170,171,172,173,174,175,176,24,178,179,180,181,182,183,184,185,186,187,26,189,190,191,192,193,194,195,196,197,198,28

Ваша задача - сгенерировать эту последовательность, либо

  • если задано , вернуть номер в этой последовательности,NNго
  • заданный , вернуть первые чисел в этой последовательностиNN
  • или генерировать последовательность бесконечно.

Вы можете выбрать отправку, чтобы использовать или индексирование, но, пожалуйста, укажите, какие именно.01

Контрольные примеры

Вы можете использовать приведенные выше термины, но вот некоторые из них:

222 -> 42
1633 -> 4
4488 -> 816
15519 -> 2019
19988 -> 2816
99999 -> 18189
119988 -> 21816
100001 -> 101
999999 -> 181818

Ответы:




5

Желе , 11 байт

DŒg+2/€FVµ¡

Это излишне медленная, полная программа.

Попробуйте онлайн!

Альтернативная версия, 12 байт

DŒg+2/€FVµƬṪ

Один байт длиннее, но намного быстрее. Работает как программа или функция.

Попробуйте онлайн!

Как это работает

DŒg+2/€FVµƬṪ  Main link. Argument: n (integer)

         µ    Combine the previous links into a chain. Begin a new one.
D               Decimal; yield n's digit array in base 10.
 Œg             Group adjacent, identical digits into subarrays.
   +2/€         Map non-overlapping, pairwise sum over the subarrays.
                If there is an odd number of digits in a subarray, the
                last digit will remain untouched.
       F        Flatten; dump all sums and digits into a single array.
        V       Eval; turn the result into an integer.
          Ƭ   Execute the chain 'til the results are no longer unique.
              Return all unique results.
           Ṫ  Tail; extract the last result.

11-байтовая версия делает то же самое, за исключением того, что она вызывает ссылку n раз для ввода n , а не вызывает ее, пока не будет достигнута фиксированная точка.


3
В этом нет необходимости, если он экономит 1 байт :-)
Луис Мендо

4

Haskell, 70 байт

until((==)=<<f)f
f(a:b:c)|a==b=show(2*read[a])++f c|1<2=a:f(b:c)
f a=a

Ввод принимается в виде строки.

Попробуйте онлайн!


Пока это ничего не спасет, но с такой же длиной вы можете заменить второе предложение на |x<-b:c=a:f xили даже f(a:c)=a:f c, в случае, если одно или другое действительно может привести к улучшению :)
flawr


3

Perl 6 , 37 байт

{($_,{S:g[(\d)$0]=2*$0}...*==*)[*-1]}

Попробуйте онлайн!

Это функция, которая генерирует n-й член последовательности, заданный n в качестве аргумента.

($_, { ... } ... * == *)является последовательностью последовательных изменений входного номера, сгенерированной выражением в скобках (простая подстановка регулярного выражения) и прекращением, когда * == *, то есть когда последние два числа в последовательности равны. Затем [*-1]принимает только последний элемент этой последовательности в качестве возвращаемого значения.


Вы можете сохранить байты пути удаления ==*и замены *-1с $_, так как всегда меньше , чем nдля замены ряда n. 33 байта
Джо Кинг

3

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

+`(.)\1
$.(2*$1*

Попробуйте онлайн! Ссылка включает в себя тестовые случаи. Объяснение:

+`

Повторяйте, пока вход не перестанет меняться.

(.)\1

Заменить пары соседних цифр ...

$.(2*$1*

... с двойной цифрой. ( $1*генерирует строку $1 _s, 2*дублирует ее и $.(принимает длину. На самом деле, движок Retina умнее этого и просто удваивается $1.)


3

C # (.NET Core) , 231 , 203 , 200 , 196 , 192 байта

РЕДАКТИРОВАТЬ: функция теперь в 185 байтов плюс 18 для using System.Linq;

Благодаря BMO (для 1> 0 равно true плюс удаление новой строки) и Mr. XCoder (для операторов f =! F)!

РЕДАКТИРОВАТЬ 2: до 182 байтов плюс 18 за using System.Linqспасибо Дане за то, что поделились несколькими советами по гольфу!

EDIT3: Спасибо Embodiment of Ignorance за int [] -> var, устранение короткого замыкания && -> & и изменение ToArray -> ToList! (178 байт + 18 с использованием)

РЕДАКТИРОВАТЬ 4: Embodiment of Ignorance отбросил 4 байта, изменив назначение. Пустышка меня должна посчитать! Еще раз спасибо: D

p=>{var f=1>0;while(f){var t=p.Select(n=>n-48).ToList();p="";f=!f;for(var j=0;j<t.Count;j++){if(j<t.Count-1&t[j]==t[1+j]){p+=t[j]+t[++j];f=!f;continue;}p+=t[j];}};return p;};

Попробуйте онлайн!




2

Japt v2.0a0 -h, 15 14 байт

Возвращает nthтермин последовательности.

Æ=s_r/(.)\1/ÏÑ

Попытайся

Это должно работать на 10 байтов, но, похоже, есть ошибка в методе рекурсивной замены Japt.

e/(.)\1/ÏÑ


2

05AB1E , 11 байт

Δγε2ôSO}˜J

Попробуйте онлайн или проверьте все контрольные примеры .

Объяснение:

Δ             # Continue until the (implicit) input no longer changes:
 γ            #  Split the integer in chunks of the same adjacent digits
              #   i.e. 199999889 → [1,99999,88,9]
  ε     }     #  Map each to:
   2ô         #   Split it into parts of size 2
              #    i.e. 99999 → [99,99,9]
     S       #   Split each part into digits
              #    i.e. [99,99,9] → [[9,9],[9,9],[9]]
       O      #   And take the sum of each part
              #    i.e. [[9,9],[9,9],[9]] → [18,18,9]
         ˜    #  Flatten the list
              #   i.e. [[1],[18,18,9],[16],[9]] → [1,18,18,9,16,9]
          J   #  Join everything together
              #   i.e. [1,18,18,9,16,9] → 118189169
              # (And output the result implicitly at the end)
              #  i.e. output = 28189169

2

Wolfram Language 108 байтов

ToExpression[""<>ToString/@Total/@Flatten[Partition[#,UpTo@2]&/@Split@IntegerDigits@#,1]]&~FixedPoint~#&

объяснение

IntegerDigits преобразует входной номер в список его цифр.

Split группы последовательных повторяющихся цифр.

Partition[#, UpTo@2]&/@ разбивает серии одинаковых цифр на списки, максимум, длиной 2.

Flatten[...,1] исключает случайные чрезмерно вложенные скобки - например, {{2,2}} становится {2,2}

Total/@итоговые суммы парных цифр. Отдельные цифры не нужно суммировать.

ToString преобразует итоги (и изолированные цифры) в строки.

""<> объединяет все строки в списке.

ToExpression преобразует результат в целое число.

...~FixedPoint~#& применяет функцию, пока результат не перестанет меняться.


2

C # (интерактивный компилятор Visual C #) с флагом /u:System.Text.RegularExpressions.Regex, 70 байт

s=>{for(;s[0]!=(s[0]=Replace(s[0],@"(.)\1",m=>m.Value[0]*2-96+"")););}

Выходы путем изменения входа. Берет список, содержащий одну строку для ввода.

Спасибо @dana за игру в гольф всего 23 байта!

Попробуйте онлайн!


95 + 34 - 33 + 1 для дополнительного пространства, необходимого вам в аргументах командной строки, iirc
только ASCII

Сначала должны быть определены рекурсивные анонимные функции, и определение включено в число байтов.
Воплощение Невежества

О, это рекурсивно
только для ASCII

1
Ницца! Я думаю, что я могу получить это немного больше
Воплощение невежества

Это довольно хороший результат, учитывая, что это C # :)
Дана

1

Чисто , 118 байт

import StdEnv,Data.List
$[a,b:t]|a==b=[1,(a*2)rem 10]%(1-a/5,1)++ $t=[a: $[b:t]]
$l=l

limit o iterate$o map digitToInt

Попробуйте онлайн!

Принимает первое повторное значение ( limit) из бесконечного списка приложений ( iterate) лямбды, выполняющих один шаг процесса свертывания. Вклад принимается как [Char].


1

Красный , 84 83 80 байт

func[n][if parse s: form n[to some change[copy d skip d](2 * do d)to end][f s]s]

Попробуйте онлайн!

Возвращает nthтермин последовательности.

Объяснение:

Red[]
f: func [ n ] [
    if parse s: form n [  ; parse the input converted to a string
        to some change [  ; find and change one or more
            copy d skip   ; digit (in fact any character, no predefined character classes)
            d             ; followed by itself
        ] (2 * do d)      ; with its doubled numeric value 
        to end            ; go to the end of the string
    ] [ f s ]             ; call the function with the altered string if parse returned true
    s                     ; finally return the string 
]


1

C # (интерактивный компилятор Visual C #) , 111 байт

s=>{var t=s;do{s=t;t="";for(int i=0;i<s.Length;)t+=s[i]%48*(s[i++]!=(s+0)[i]?1:2*++i/i);}while(t!=s);return t;}

Попробуйте онлайн!

Огромный кредит @ASCIIOnly за игру в гольф ~ 30;) Сначала мы оба публиковали обновления одновременно, но в какой-то момент он явно отправился в город!

-2 благодаря @EmbodimentOfIgnorance!

Меньше гольф-кода ...

// s is the input as a string
s=>{
  // t is another string used
  // to hold intermediate results
  var t=s;
  // the algorithm repeatedly
  // processes s and saves the
  // result to t
  do{
    // copy the last result to s
    // and blank out t
    s=t;
    t="";
    // iterate over s
    for(int i=0;i<s.Length;)
      // append either 1 or 2 times
      // the current digit to t
      t+=s[i]%48*
        // compare the current digit
        // to the next digit. to prevent
        // an out-of-bounds exception,
        // append a 0 to s which either
        // gets ignored or collapses
        // to 0
        (s[i++]!=(s+0)[i]
          // if they are different, then
          // the multiplier is 1
          ?1
          // if they are the same, then
          // the multiplier is 2, and we
          // have to increment i
          :2*++i/i);
  }
  // continue this until the input
  // and output are the same
  while(t!=s);
  return t;
}



@ASCIIOnly - Хороший ход :) (s[i++]-48)*2=>s[i++]*2-96
Дана


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.