Последовательность Add-Multiply-Add


27

( Связано )

Дано целое число n > 1:
1) Построить диапазон чисел n, n-1, n-2, ... 3, 2, 1и вычислить сумму.
2) Возьмите отдельные цифры этого числа и рассчитать произведение.
3) Возьмите отдельные цифры этого числа и рассчитайте сумму.
4) Повторяйте шаги 2 и 3, пока достичь одной цифры. Эта цифра является результатом.

Первые двадцать членов последовательности приведены ниже:

3, 6, 0, 5, 2, 7, 9, 2, 7, 9, 1, 9, 0, 0, 9, 6, 7, 0, 0, 6

Примечание: эта последовательность НЕ в OEIS.

I / O и правила

  • Числа быстро становятся очень большими, поэтому решение должно иметь возможность обрабатывать входные числа до 100 000 без сбоев (хорошо, если ваш код может справиться с этим).
  • Вход и выход могут быть заданы любым удобным способом .
  • Допустимы либо полная программа, либо функция. Если функция, вы можете вернуть вывод, а не распечатать его.
  • Стандартные лазейки запрещены.
  • Это поэтому применяются все обычные правила игры в гольф, и выигрывает самый короткий код (в байтах).

Примеры

n     output
1234   9
3005   3
5007   5
9854   8
75849  8
100000 0

3
+1 за вызов последовательности, которого нет в OEIS
JAD

2
Всякий раз, когда n ≤ 100000 , для получения результата достаточно только двух итераций шагов 2 и 3. Можем ли мы воспользоваться этим преимуществом или алгоритм, который мы выбрали, будет работать для больших значений n ?
Деннис

2
@Dennis Алгоритм должен работать для любого значения n. Размещенное решение должно работать до n = 100000.
AdmBorkBork

3
Numbers will get very large quicklyнет, это не так
l4m2

3
@ l4m2 Не выход. Но 100000 + 99999 + ... + 1 = 5000050000 - это 33-разрядное число, которое может представлять или не отображаться на вашем языке.
Деннис

Ответы:


10

Python 2 , 77 72 71 62 60 байт

lambda n:reduce(lambda x,c:eval(c.join(`x`)),'*+'*n,-n*~n/2)

Спасибо @xnor за 2 байта!

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


Я просто переключился на цикл for, но мне придется запомнить этот трюк на будущее.
Деннис

Где repeat until you reach a single digit?
Тит

2
@ Titus Я просто выполняю n итераций шагов 2 и 3, чего всегда достаточно. Фактически, поскольку n ≤ 100000 , трех итераций будет достаточно.
Деннис

Теперь, когда вы упомянули это: на самом деле, наименьший вход, который потребовал бы три итерации, является 236172; и это единственный ниже 1 миллиона.
Тит



4

Желе , 8 байт

RSDPDƲÐL

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

Полная программа (возвращает одноэлементный массив, содержащий результат, но скобки не отображаются в STDOUT).


Это самый «естественный» ответ желе, который я когда-либо видел. Есть только 2 не ASCII символа
RedClover


Не могли бы мы обсудить это здесь, спасибо. : P TNB может быть альтернативным местом для обсуждения этого, если не будет шума. ;)
Эрик Outgolfer

4

MATL , 15 13 байт

В честь языка месяца :

:`sV!UpV!Utnq

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

Я не думаю, что есть более простой способ получить цифры числа, чем преобразовать число в строку V, затем транспонировать его !и преобразовать этот вертикальный вектор обратно в числовой U.

Сохранено 2 байта благодаря самому Создателю 1 ! Я забыл неявный конец, то есть мог удалить ], и вместо того, чтобы сравнивать количество элементов с 1, я мог просто уменьшить это значение и использовать его как логическое значение напрямую.

Итак, объяснение выглядит так:

                 % Grab input n implicitly
:                % Range from 1 ... n inclusive
 `               % Do ... while
  s               % sum the vector
   V!U            % Convert the number to digits
      p           % Take the product of these digits
       V!U        % Convert the product into digits
          t       % Duplicate the result
           n      % Count the number of elements
            q     % Decrement the number of elements
                  % Loop until the number of elements is 1
                 % Implicit end

1 ... из MATL, Луис Мендо.


3

JavaScript (ES6), 60 байт

f=(n,k=n*++n/2)=>k>9?f(!n,eval([...k+''].join('*+'[+!n]))):k

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

комментарии

f = (                     // f = recursive function taking:
  n,                      //   n = original input
  k = n * ++n / 2         //   k = current value, initialized to sum(i=1..n)(i)
) =>                      //
  k > 9 ?                 // if k has more than 1 digit:
    f(                    //   recursive call to f() with:
      !n,                 //     a logical NOT applied to n
      eval(               //     the result of the expression built by:
        [...k + '']       //       turning k into a list of digits
        .join('*+'[+!n])  //       joining with '*' on even iterations or '+' on odd ones
      )                   //     end of eval()
    )                     //   end of recursive call
  :                       // else:
    k                     //   stop recursion and return the last value

Альтернативная версия, 59 байт (не конкурирует)

Нерекурсивная версия, которая работает только для n <236172 . (Он охватывает запрошенный диапазон, но не может считаться допустимым универсальным алгоритмом.)

n=>[...'*+*+'].map(o=>n=eval([...n+''].join(o)),n*=++n/2)|n

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


ваша основная версия ломается, когда N> = 77534568790. Работает, когда N = 7753456879; точно не знаю, где находится точка останова. Конечно, это не имеет значения, потому что требование только для обработки до N = 100 000, поэтому я не уверен, почему я написал это ...
Росс Прессер

1
@RossPresser В качестве приблизительной оценки, я бы сказал, что это работает до Number.MAX_SAFE_INTEGER ** 0.5 ~= 94906265.
Арно


2

Stax , 14 13 10 байт

ñu┌↕a√äJ²┐

Запустите и отладьте его

Было довольно весело сделать. Интересно, есть ли более краткий способ сделать сравнение в конце.

объяснение

|+wE:*E|+c9>                 # Full Program Unpacked
|+                           # Create range and sum it
   wE:*                      # Start loop, digitize number, product of digits
       E|+                   # Digitize number, sum digits
          c9>                # Duplicate, check length is = 1
                             # Otherwise loop back to the 'w' character

-1 байт благодаря овсу

-3 байта благодаря Скрублу


2

R , 152 130 109 байт

function(w,x=w*(w+1)/2,y=prod(d(x)),z=sum(d(y)))"if"(z>9,f(,z),z)
d=function(x)x%/%10^(0:max(0,log10(x)))%%10

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

@Giuseppe нашел 21 42 байта с различными R- объектами, к которым я еще не привык, а также со способом получения цифр числа без принуждения к строке и назад и с меньшим количеством байтов!

# Old
d=function(x)strtoi(el(strsplit(paste(x),"")))
# New
d=function(x)x%/%10^(0:max(0,log10(x)))%%10

options(scipen=9) это требуется для случая 9854 для старой функции, потому что сцена первого продукта заканчивается как 80000, который печатает R как 8e + 05.


Ах я вижу. Вывод научной нотации. Хороший улов!
AdmBorkBork

1
Наконец-то обошлось scipen: попробуйте онлайн ! обратите внимание, max(0,log10(x))что если x=0, то, log10(0)=-Infчто вызывает ошибку.
Джузеппе

1

Pyth , 11 байт

usj*FjGTTsS

Попробуй это здесь!

usj * FjGTTSS - Полная программа. N = вход.
          S - Диапазон. Выход [1, N] ⋂ ℤ.
         с - сумма.
u - Хотя никакие две последовательные итерации не дают одинакового результата, выполните (var: G):
   * FjGT - Цифровой продукт.
 sj T - Цифровая сумма.

1

Древесный уголь , 18 байт

≔Σ…·¹NθW›θ⁹≔ΣΠθθIθ

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

≔Σ…·¹Nθ

Суммируйте целые числа до входных данных.

 W›θ⁹≔ΣΠθθ

Пока результат больше 9, возьмите сумму цифр с произведением цифр.

Iθ

Приведите результат в строку и неявно напечатайте его.


1

Gaia , 8 байт

┅⟨Σ₸∨Π⟩°

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

Старое объяснение (перед исправлением ошибки, по вине Гайи ИМО: P):

Π⟩ΣΠ⟩ ° - Полная программа. N = вход.
Range - Диапазон. Нажмите [1, N] ⋂ ℤ в стек.
 While⟩ ° - хотя никакие две последовательные итерации не дают одинакового результата, выполните:
  Σ - сумма (или цифровая сумма, когда применяется к целому числу).
   Digital - Цифровой продукт.

Спас 1 байт благодаря Денису .


┅⟨ΣΠ⟩°сохраняет байт.
Деннис

Это не работает для значений, где цифровая сумма равна 0, например4
Джо Кинг

@JoKing Исправлено, спасибо, что заметили это. К сожалению, в Gaia, принимая цифры 0результатов []по какой-то причине :(
Мистер Xcoder

1

F #, 175 байт

let d n=seq{for i in(string n).ToCharArray() do yield string i|>uint64}
let c n=
 let mutable r=Seq.sum{1UL..n}
 while r>9UL do r<-d r|>Seq.reduce(fun a x->x*a)|>d|>Seq.sum
 r

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

Единственное предостережение для функции заключается в том, что входное значение должно иметь тип uint64.

Разоблаченный это немного похоже на это:

let d n=seq{for i in(string n).ToCharArray() do yield string i|>uint64}

let c n =
 let mutable r = Seq.sum {1UL..n}
 while r > 9UL do
  r<-d r
  |> Seq.reduce(fun a x->x*a)
  |> d
  |> Seq.sum
 r

Функция d nпреобразует число nв свои составляющие цифры. Сначала он преобразуется в строку, а затем получает каждый символ в строке. Затем каждый символ должен быть преобразован обратно в строку, иначе символы будут преобразованы в их значения ASCII вместо их «реальных» значений.

c nФункция является основной функцией, с в nкачестве начального значения. В этой функции rнаша текущая ценность. whileЦикл выполняет следующие действия :

  • Преобразовать rв составляющие цифры ( d r).
  • Получите произведение всех этих цифр. Это использует, Seq.reduceкоторый берет функцию с накопленным значением ( a) и следующим значением в sequence ( x) и в этом случае возвращает продукт. Начальное значение является первым элементом в последовательности.
  • Преобразуйте значение этого продукта в его составляющие цифры ( d).
  • Суммируйте цифры до и назначьте это r.

1

Befunge, 136 байт

101p&::*+2/>:82+%01g*01p82+/:#v_$01gv
X      v_v# #:/+82p10+g10%+82: <p100<
v:g10$ >#<#^                 #<^
>82+/#v_.@
      >101p^

Вы можете попробовать это здесь .

Хотя не все переводчики имеют достаточно большой размер ячейки, он работает с небольшими числами практически для любого человека. Для большего числа nвам может понадобиться переводчик, как BefunExec .


1

Gol> <> , 35 33 байта

1AY:P*2,TYMR*YR+:a(?Bt
:a(qlBaSD$

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

-2 байта от Джо Кинга.

Широкое использование функций и неявных бесконечных циклов.

Пример полной программы и как она работает

1AGIE;GN
2AY:P*2,YlMR*YlR+:a(?B8R!
:a(?BaSD$

<main program>
1AG       Register row 1 as function G
   IE;    Take number input; halt on EOF
      GN  Call G and print the result as number
          Repeat indefinitely

<function G>
2AY            Register row 2 as function Y
   :P*2,       Sum of 1 to n
        Y      Call Y (break into digits)
         lMR*  Product
Y              Call Y
 lR+           Sum (an implicit zero is used)
    :a(?B      Return if the result is less than 10
         8R!   Skip initial 8 commands
               Repeat indefinitely

<function Y>
:a(?B      Return if the top is less than 10
     aSD   Divmod by 10; [... n] => [... n/10 n%10]
        $  Swap top two, so the "div" goes to the top


1

Japt, 16 14 13 байт

_ì ×ìx}gN®õ x

Попытайся


объяснение

                  :Implicit input of integer U
         ®        :Map
        N         :The array of inputs (which just contains U)
          õ       :  Range [1,U]
            x     :  Reduce by addition
_     }g          :Take the last element of N, run it through the following function and push the result to N
                  : Repeat U times and then return the last element of N
 ì                :  Split to an array of digits
   ×              :  Reduce by multiplication
    ìx            :  Split to an array of digits and reduce by addition

Аккуратно, я пытался решить это сам, но не нашел хорошего решения, так что интересно увидеть ваше.
Нить

Спасибо, @Nit. Должен быть более короткий путь, хотя.
Лохматый

@ Нет, понял! Все еще убежденный, что должен быть более короткий путь, все же.
Лохматый


0

PHP 7, 89 байт

for($a=$argn*-~+$argn/2;$a>9;)$a=array_sum(($s=str_split)(array_product($s($a))));echo$a;

Запустите как трубу с -rили попробуйте онлайн .

  • PHP всегда принимает ввод как строку, поэтому я должен использовать +приведение к int, ~чтобы работать так, как хотел.
  • Предварительное увеличение не будет работать: независимо от того, где я его поместил, оно будет влиять на оба операнда.
  • Но: не имеет значения, будет ли одна цифра иметь место до или после итерации (дополнительные итерации ничего не изменит); так что я могу использовать for()вместо do ... while().
  • PHP 7 или более поздняя версия требуется для встроенного назначения имени функции.
    В более старом PHP требуется еще один байт: for($s=str_split,$a=...;$a>9;)$a=array_sum($s(...));
    (Если str_splitвообще не присвоить переменную, тратится еще один байт.)



0

PowerShell Core , 91 101 93 байта

Function F($a){$o=$a*($a+1)/2;1,2|%{$o=[char[]]"$([char[]]"$o"-join'*'|iex)"-join'+'|iex};$o}

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

Немного растянулся ...

Function F ($a)
{
    $o=$a*($a+1)/2;
    1..2 | % {
        $o = [char[]]"$o"-join '*' | iex;
        $o = [char[]]"$o"-join '+' | iex;
    }
    $o | Write-Output
}

Первыми шагами было разделение целых чисел на цифры - это делалось путем разбиения целого числа на массив символов строк . После этого вставьте операнд, а затем оцените строку как команду. Затем необходимо выполнить цикл множественного добавления, пока ввод не станет одной цифрой.

iexэто псевдоним, для Invoke-Commandкоторого вычисляется строка, переданная в первую позицию параметра.

Редактировать: по запросу @AdmBorkBork я добавил заголовок функции к счетчику байтов. Кроме того, я немного подсчитал и понял, что верхняя граница числа итераций такова < log log 10^6 < log 6 < 2, что сохранил еще шесть байтов.

Изменить x2: @AdmBorkBork нашел более краткий способ преобразования целого числа в математическое выражение, а затем предложил добавить его в строкуiex . Это сэкономило 8 байтов. Спасибо!


Приятно видеть еще одного PowerSheller вокруг! Тем не менее, я думаю, что вам нужно включить определение функции Function F($a){ }в ваш счетчик байтов. Тем не менее, вы должны быть в состоянии сохранить некоторые использования [char[]]вместо -split''-ne'', я думаю.
AdmBorkBork

[char[]]1234=Ӓ, который является недействительным; Я мог бы заставить это работать, но это не могло бы быть очевидным только сейчас. Спасибо за предложение!
Джефф Фриман

Извините, я не был ясен - [char[]]"$o"и |iexскорее чем iex( ).
AdmBorkBork

Этот совет сбил 8% моего кода. Потрясающе. Благодарность!
Джефф Фриман



0

Java 8, 129 байт

n->{long r=1,i=n;for(;i>1;r+=i--);for(;r>9;r=(i+"").chars().map(p->p-48).sum(),i=1)for(int s:(r+"").getBytes())i*=s-48;return r;}

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

Объяснение:

n->{            // Method with integer parameter and long return-type
  long r=1,     //  Result-long, starting at 1
       i=n;     //  Temp integer, starting at the input `n`
  for(;i>1;     //  Loop as long as `i` is not 1 yet
      r+=i--);  //   And increase `r` by `i`
  for(;r>9      //  Loop as long as `r` is not a single digit yet
      ;         //    After every iteration:
       r=(i+"").chars().map(p->p-48).sum(),
                //     Set `r` to the sum of digits of `i`
       i=1)     //     And reset `i` to 1
    for(int s:(r+"").getBytes())i*=s-48;
                //    Set `i` to the product of the digits of `r`
  return r;}    //  Return `r` as result

0

Юлия 0,6 , 56 байт

f(n,k=(n+1)n÷2)=k>9?f(0,sum(digits(prod(digits(k))))):k

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

Довольно просто: вычислите (n+1)n÷2сумму из 1..n, проверьте, является ли это однозначным числом ( >9), если нет, попробуйте еще раз с k, установленным на сумму цифр произведения цифр k, иначе верните k.

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