Дизаріумна дилема


31

Дизаріумна дилема

Дізаріум визначається як число, чиє:

сума його цифр, що працюють на відповідній позиції, дорівнює початковій кількості


Ваше завдання :

У вас є дивна одержимість номерами, класифікованими як дезаріум. Необхідність дотримуватися способів дезаріуму настільки велика у вас, що ви відмовляєтесь читати будь-які недизаріумні пронумеровані сторінки в будь-якій книзі. У вас двоє великі проблеми:

  1. Ваш професор щойно призначив вам читати підручник зі сторінки n на сторінкуm
  2. Минулого тижня ти дуже сильно вдарився головою і, здається, не пам'ятаєш, як програмно визначити, чи вважається число дезаріумом.

Час - це суть, тому код для визначення сторінок, які вам потрібно буде прочитати, повинен бути якомога коротшим.

Ви повинні визначити всі disarium в інклюзивної діапазоні nнаскрізним m.

Приклади дезаріуму :

89 = 8 1 + 9 2

135 = 1 1 + 3 2 + 5 3

518 = 5 1 + 1 2 + 8 3

Це код-гольф, тому виграє найменша кількість байтів!

Ось повна послідовність A032799 .


@Fatalize Діапазон включно, я відредагую питання, щоб це відобразити.
CraigR8806

Чи є гарантовані межі на nі m? Існує дуже великий дизаріум (12157692622039623539), чи повинні відповіді мати можливість його ідентифікувати?
Лінн

@Lynn З огляду на те, що вже існує ряд рішень, я б сказав, що у діапазону не повинно бути меж.
CraigR8806

2
@Lynn Немає дезаріуму> 22 цифри, тому певним чином діапазон вже обмежений.
Божевільний фізик

3
@MistahFiggins Перейдіть за посиланням OEIS внизу питання. Ви знайдете доказ, який показує, що послідовність Дізаріуму справді є кінцевою.
CraigR8806

Відповіді:


11

Perl 6 , 40 39 байт

{grep {$_==sum .comb Z**1..*},$^a..$^b}

Спробуйте в Інтернеті!

Як це працює

{                                     }  # A lambda.
                              $^a..$^b   # Range between the two lambda arguments.
 grep {                     },           # Return numbers from that range which satisfy:
               .comb Z  1..*             #  Digits zipped with the sequence 1,2,3,...,
                      **                 #  with exponentiation operator applied to each pair,
           sum                           #  and those exponents summed,
       $_==                              #  equals the number.

8

Python2, 98 89 88 84 байт

lambda n,m:[x for x in range(n,m+1)if sum(int(m)**-~p for p,m in enumerate(`x`))==x]

Жахливий. Стане коротше. Почав виглядати краще

Ось моя рекурсивна спроба (86 байт):

f=lambda n,m:[]if n>m else[n]*(sum(int(m)**-~p for p,m in enumerate(`n`))==n)+f(n+1,m)

Дякуємо @Rod за збереження 4 байтів! rangeдо enumerateтощо.


перехід на enumerate, ви можете використовувати int(n)замість цьогоint(`x`[p])
Rod

7

Perl, 43 байти

map{say if$_==eval s/./+$&**$+[0]/gr}<>..<>

Спробуйте в Інтернеті!

Ви, хлопці, Regex справді потужний.

Пояснення

Перше, що робить код - це прочитати два цілих числа як вхід через <>, і створює діапазон від першого до другого за допомогою ... Потім він використовує стандартну mapфункцію для перебору цього діапазону, і застосовує наступний код для кожного значення: say if$_==eval s/./+$&**$+[0]/gr. Це схоже на хитрість, і це все-таки є, але ось що насправді відбувається.

mapнеявно зберігає своє поточне значення у змінній $_. Багато функцій та операцій perl використовують це значення, коли жодна не задана. Сюди входять регулярні вирази, такі як s///оператор заміни.

До регексу заміщення є чотири частини:

  1. Рядок маніпулювати. Зазвичай оператор =~використовується для застосування регулярного вираження до рядка, але якщо цей оператор відсутній, то регулярний вираз застосовується до неявної змінної $_, яка містить наше поточне число черезmap функцію.
  2. Рядок пошуку. У цьому випадку ми шукаємо будь-який єдиний символ, що не є новим рядком, позначається символом підстановки .. Насправді ми фіксуємо кожну окрему цифру.
  3. Рядок для заміни на. Ми підміняємо знак плюс, який +супроводжується математичним виразом, змішаним з деякими магічними змінними Perl, що значно полегшує все.

Спеціальна скалярна змінна $&завжди містить всю останню вдалу зйомку регулярних виразів, яка в даному випадку є однозначною. Спеціальна змінна масив @+завжди містить список компенсацій після матчу за останній успішний матч, тобто індекс тексту після матчу. $+[0]- це індекс $_тексту, що знаходиться безпосередньо за ним $&. У випадку з цим 135ми фіксуємо цифру 1, а індекс 135тексту відразу після цього (а саме 35) дорівнює 1, що є нашим показником. Отже, ми хочемо підняти $&(1) до влади$+[0] (1) і отримати 1. Ми хочемо підняти 3 до сили 2 і отримаємо 9. Ми хочемо підняти 5 до сили 3 і отримати 125.

Якщо вхід був 135, отриманий рядок є +1**1+3**2+5**3.

  1. Прапори, що змінюють Regex. Тут ми використовуємо два прапори регулярних виразів - /gі /r. /gвказує інтерпретатору продовжувати заміни після того, як буде знайдена перша (інакше ми б закінчилися +1**135). /rвказує інтерпретатору не змінювати початковий рядок , а замість цього повертати те, що було б після рядків. Це важливо, тому що в іншому випадку воно буде переписане $_, і нам це потрібно для порівняння.

Після того, як виконана вся підміна, ми отримуємо математичний вираз, який оцінюється за допомогою evalфункції. +1**1+3**2+5**3оцінюється в 1 + 9 + 125 = 135, що порівнюється з початковим числом 135. Оскільки ці два рівні, код друкує число.


Прекрасне рішення. (Зауважте, що це не спрацює. Перший вхід дорівнює 0, але я не впевнений, що це має значення). Кілька байтів для гольфу:map$_-eval s/./+$&**$+[0]/gr||say,<>..<>
Дада,

І "@+"на 1 байт коротший за $+[0]:)
Дада,

7

JavaScript (ES7), 105 91 89 88 83 79 82 81 байт

Дякуємо Arnauld за економію 20B, та ETHProductions за економію 6B!

a=>b=>[...Array(b).keys()].filter(c=>c>=a&([...c+''].map(d=>c-=d**++e,e=0),!c))

Використання

Призначте функцію змінної та наведіть їй як мінімум та максимум як аргументи. Приклад:

f=a=>b=>[...Array(b).keys()].filter(c=>c>=a&([...c+''].map(d=>c-=d**++e,e=0),!c))
f(0)(90)

Вихідні дані

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 89]

Подальше гольф

Це здається досить добре гольф, але завжди є можливість для вдосконалення ... Я думаю.


Так, це насправді трохи коротше. Спасибі!
Лука

1
Ви можете змінити , d**(e+1)щоб d**-~eврятувати два байта.
ETHproductions

Дякую за пораду, додав її. Ще 2 байти до того, як ми побили Пітона ...
Лука

Ви можете використовувати &замість &&. Ще один байт ...
Арнальд,

Я просто змінив це в моїй місцевій копії ... Здогадайтесь, ви були швидшими.
Лука

6

JavaScript (Firefox 52+), 68 байт

f=(n,m)=>(e=0,[for(d of t=n+'')t-=d**++e],t||alert(n),n-m&&f(n+1,m))

Рекурсивна функція, яка виводить через alert. Працює у версії для розробників Firefox, яку ви можете завантажити на цій сторінці . Попередні версії Firefox не підтримують **оператора, і жоден інший браузер не підтримує[for(a of b)c] синтаксис.

Фрагмент тесту

Для цього використовується .mapзамість розуміння масиву, а Math.powзамість цього **, тому він повинен працювати у всіх браузерах, які підтримують ES6.



5

Python 3, 100 байт

lambda n,m:{*range(10),89,135,175,518,598,1306,1676,2427,2646798,0xa8b8cd06890f2773}&{*range(n,m+1)}

Не найкоротший підхід, але досить милий. Кінцево багато дізаріумів; дивіться сторінку OEIS для гарного підтвердження. Це всі вони.


Це використання жорсткого кодування, яке є лазівкою meta.codegolf.stackexchange.com/a/1063/55243, я б рекомендував вам змінити свою відповідь, щоб відповідати стандартним правилам
Джордж

5
Я не думаю, що це порушує правило жорсткого кодування, оскільки програма все ще "працює", а вихід не є жорстким.
Олексій Хованський

4

R, 100 байт

function(n,m,x=n:m)x[sapply(x,function(y)sum(as.integer(el(strsplit(c(y,""),"")))^(1:nchar(y)))==y)]

Безіменна функція, яка приймає nі m. Як завжди в R, розщеплення цілих чисел на числовий цифровий вектор є стомлюючим і з'їдає багато байтів. Це робить функцію відносно повільною і працює лише для 32-бітних цілих чисел.


4

Желе , 11 байт

D*J$S⁼
rÇÐf

Спробуйте в Інтернеті!

Знесло це з 16 до 11, за допомогою @miles!

Пояснення:

rÇÐf    Main link, arguments are m and n
r       Generate a list from m to n
 Ç      Invoke the helper link
  Ðf    And filter out all that don't return 1 on that link

D*J$S⁼  Helper link, determines if item is Disarium
D       Break input (the current item of our list in Main) into digits (135 --> [1, 3, 5])
  J$    Create a range from 1 to x, where x is the number of digits             [1, 2, 3]
 *      Raise each digit to the power of their respective index 
    S⁼  And return a 1 if the sum of powers is equal to the helper-link's input

Ви можете використовувати Jдля отримання індексів. Коротшим способом може бути D*J$S⁼поєднання двох ваших посилань в одну
миль

Прийшов точно до такого висновку близько 20 секунд тому. Thnx!
steenbergh

3

CJam , 23 байти

q~),\>{_Ab_,,:).#:+=},p

Спробуйте в Інтернеті!

Пояснення

q~                      Get and eval all input
  ),\>                  Get the range between m and n, inclusive
      {                 For each number in the range...
       _Ab               Duplicate and get the list of digits
          _,,:)          Duplicate the list, take its length, make the range from 1 to length
               .#        Vectorize with exponentiation; computes first digit^1, second^2, etc
                 :+      Sum the results
                   =     Compare to the original number
                    },  Filter the range to only numbers for which the above block is true
                      p Print nicely


3

Python 2.X, 92 байти

lambda m,n:[k for k in range(m,n+1)if sum(int(j)**(i+1) for i,j in enumerate(list(`k`)))==k]

Марно пробіл після (i+1), але це не проблема, коли ви позбудетеся дужок, роблячи це -~i.
Yytsi

Це зробить мою спробу точно такою ж, як і ваша!
hashcode55

Майже. У вас є list('k'), чого я не маю. Однак ви все одно можете видалити пробіл :)
Yytsi

3

Пітон 2 , 84 байти

Повний програмний підхід, наразі такий самий, як і лямбда-рішення.

a,b=input()
while a<=b:
 t=p=0
 for x in`a`:p+=1;t+=int(x)**p
 if t==a:print a
 a+=1

Спробуйте в Інтернеті!


Хм. Я думав про майже точну відповідь, але відкинуто через плутанину з input(). Дуже хороша! +1.
Yytsi

3

Japt, 15 байт

òV f_¥Zì £XpYÄÃx

Перевірте це в Інтернеті! Це була співпраця між @obarakon та мною.

Як це працює

òV f_¥Zì £XpYÄÃx   // Implicit: U, V = input integers
òV                 // Create the inclusive range [U...V].
   f_              // Filter to only the items Z where...
               x   //   the sum of
      Zì           //   the decimal digits of Z,
         £XpYÄÃ    //   where each is raised to the power of (index + 1),
     ¥             //   is equal to Z.
                   // Implicit: output result of last expression

В останній версії Japt, xв якості аргументу приймається функція, яка дозволяє нам грати в інший байт:

òV f_¥Zì x@XpYÄ

Перевірте це в Інтернеті!


2

Clojure, 107 байт

#(for[i(range %(inc %2)):when(=(int(apply +(map(fn[i v](Math/pow(-(int v)48)(inc i)))(range)(str i))))i)]i)

Реалізація рівняння страшенно довга.


Ви можете зберегти пару байтів, виконуючи(.pow(-(int v)48M)
cliffroot

2

TI-Basic, 85 байт

Input 
For(I,X,Y
If I<=9 or sum(I={89,135,175,518,598,1306,1676,2427,2646798,12157692622039623539
Disp I
End

Я не знав, що жорстке кодування дозволено. :)
Абель Том

@AbelTom Ну, це справді допомагає, що ця серія має лише 20 термінів. Крім того, перетворення числа в рядок в TI-Basic займає багато байтів. Єдине інше рішення буде для int(log(кожного числа, а потім виконувати повноваження. Можливо, це коротше, але я сумніваюся в цьому.
Timtech

Цей метод введення дуже розумний, але начебто схематичний. Потрібно перебувати в FUNCрежимі, і вікно повинно бути налаштоване для включення точки введення. Мені це здається недостатньо портативним.
Якоб

@JakobCornell За замовчуванням calc знаходиться в FUNCрежимі, хоча я бачу, що ви говорите про вхідну роздільну здатність. Але цей метод досить поширений у гольфі. Ви завжди могли Prompt X,Yзамість цього.
Timtech

2

Haskell, 61 байт

n#m=[i|i<-[n..m],i==sum(zipWith(^)(read.pure<$>show i)[1..])]

Приклад використання 5 # 600-> [5,6,7,8,9,89,135,175,518,598].

Перевірте кожне число iв діапазоні [n..m]. Цифри витягуються, перетворюючись iу рядок ( show) і роблячи кожен char єдиним рядком елемента ( pure), який знову перетворюється на ціле число ( read). Зіпсуйте цей елемент елементами з [1..]допомогою функції ^і візьміть sum.


2

PHP, 92 91 88 байт

3 байти збережено завдяки @AlexHowansky

for([,$n,$m]=$argv;$n<=$m;$s-$n++?:print"$s,")for($i=$s=0;_>$b=($n._)[$i++];)$s+=$b**$i;

приймає дані з аргументів командного рядка; виводить коду в кінці. Бігайте з -r.


1
Збережіть трьох сfor([,$n,$m]=$argv;$n<=$m;
Олексій Хованський

Дивно, що там працює друк, але відлуння немає. Я здогадуюсь, тому що відлуння нічого не повертає - навіть недійсне, як не дивно.
Олексій Хованський

@AlexHowansky: Це також дивно, що "$n"[index]і "_$n"[index]створюють помилки синтаксичного аналізу, "89"[index]і $s="$n";$s[index]вони є прекрасними.
Тит

Хм, так, спочатку це здається дивним, але після перевірки документів видно, що вони прямо говорять, що функція працює лише для рядкових літералів.
Олексій Хованський

Хе-хе, це добре працює, але це, ймовірно, не врятує вас жодних байтів:("_$n")[index]
Алекс Хованський,

2

Математика, 59 байт

Select[Range@##,Tr[(d=IntegerDigits@#)^Range@Length@d]==#&]&

Unnamed function taking two integer arguments and returning a list of integers. (d=IntegerDigits@#)^Range@Length@d produces the list of digits of a number to the appropriate powers; Tr[...]==# detects whether the sum of those digit-powers equals the original number.


2

MATLAB, 88 73 байт

@(n,m)find(arrayfun(@(n)n==sum((num2str(n)-48).^(1:log10(n)+1)),n:m))+n-1

Оригінальна відповідь:

function g(n,m);a=n:m;a(arrayfun(@(n)n==sum((num2str(n)-'0').^(1:floor(log10(n))+1)),a))

num2str(n)-'0'розбиває a nна вектор його цифр і 1:floor(log10(n))+1є вектором, що містить одне число цифр у n. Завдяки входу в гольф до анонімної функції, економлячи 15 байт.


1

Haskell , 82 76 75 байт

n!m=[x|x<-[n..m],x==x#(length.show)x]
0#i=0
n#i=(div n 10)#(i-1)+mod n 10^i

Спробуйте в Інтернеті! Використання:5 ! 175

Це перевіряє кожне число в діапазоні nна те, mчи є його дезаріумним числом, а значить, досить великим для великого m.


Швидша версія: (93 байти)

n!m=[x|x<-[0..9]++[89,135,175,518,598,1306,1676,2427,2646798,12157692622039623539],x>=n,x<=m]

Спробуйте в Інтернеті!


1

C (gcc), 136 bytes

r[]={0,0};f(n){if(n)f(n/10),r[1]=pow((n%10),*r)+r[1]+.5,r[0]++;else*r=1,r[1]=0;}g(m,x){for(;m<=x;m++){f(m);if(m==r[1])printf("%d,",m);}}

Header defining pow on TIO because for some reason it didn't auto include pow. My computer did, so I'm going to roll with that.

Try it online!


1

MATL, 16 bytes

&:"@tFYAtn:^s=?@

Try it online!

&:        % Input two n, m implicitly. Push array [n n+1 ... m]
"         % For each k in that array
  @       %   Push k
  tFYA    %   Duplicate. Convert to decimal digits
  tn:     %   Duplicate. Push [1 2 ... d], where d is the number of digits
  ^       %   Element-wise power
  s       %   Sum of array
  =       %   Compare with previous copy of k: is it equal?
  ?       %   If so
    @     %     Push k
          %   End, implicit
          % End, implicit
          % Display stack, implicit

1

Batch, 115 bytes

@for %%d in (0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798)do @if %%d geq %1 if %%d leq %2 echo %%d

Batch only has 32-bit arithmetic which has no way of comparing the last disarium number, but if you insist on string comparisons, then for 402 bytes:

@echo off
for %%d in (0 1 2 3 4 5 6 7 8 9 89 135 175 518 598 1306 1676 2427 2646798 12157692622039623539)do call:c %1 %%d&&call:c %%d %2&&echo %%d
exit/b
:c
call:p %1 %2
set r=%s%
call:p %2 %1
:g
if %r:~,1% lss %s:~,1% exit/b0
if %r:~,1% gtr %s:~,1% exit/b1
if %r%==%s% exit/b0
set r=%r:~1%
set s=%s:~1%
goto g
:p
set s=%1
set t=%2
:l
set s=0%s%
set t=%t:~1%
if not "%t%"=="" goto l

1

Python 2, 100 bytes

for i in range(input(),input()+1):x=sum(int(`i`[n])**-~n for n in range(len(`i`)));print("",x)[x==i]

I haven't had a chance to run this yet (doing this on my phone).


This doesn't work. Incorrect syntax and when corrected, would print only boolean values. Starts from the exponent 0, which is also incorrect. Also, you don't need the square brackets inside sum.
Yytsi

This isn't checking for disarium numbers.
hashcode55

@hashcode55, fixed (?)
Daniel

@TuukkaX, now it should work I think
Daniel

I'm not on computer, but this should print a newline on each iteration, where i is a Disarium. I have no idea whether this is allowed, but I would say no, since the output gets very blank.
Yytsi

1

Scala, 132 129 bytes

(% :Int,^ :Int)=>for(i<- %to^)if(((0/:(i+"").zipWithIndex)((z,f)=>{z+BigInt(f._1.toInt-48).pow(f._2+1).intValue}))==i)println(i)

129 edit: Changing the for loop's variable name from & to i saved three spaces.


Explanation

For each value in the input range:

  • convert it to a string with +""
  • use zipWithIndex to produce a list of tuples containing a char of the digit and its index
  • fold the list by returning each char's int value minus 48 (lines up to 0-9) to the power of its list index plus one (to start at ^1)
  • if the result matches the input, print it

Comments

Finally got around to learning how fold and zipWithIndex work. I'm unhappy with the int conversions, but I am pleased with the succinctness of fold and zipWithIndex.


1

Octave, 88 87 bytes

Thanks to MattWH for saving a byte (f(x)-48 vs f(x)-'0')

@(n,m,f=@num2str,a=n:m)a(a==cell2mat(arrayfun(@(x){sum((f(x)-48).^(1:nnz(f(x))))},a)))

To run:

>> f=@(n,m,f=@num2str,a=n:m)a(a==cell2mat(arrayfun(@(x){sum((f(x)-'0').^(1:nnz(f(x))))},a))) 
>> f(0,1000)
ans = 
      1     2     3     4     5     6     7     8     9    89   135   175   518   598

Explanation

@(n,m,                                              % Create an anonymous function and pass it n and m as paramteres
    f=@num2str,                                     % Will be using the num2str mehtod twice, set the variable f to the handle to save on bytes
        a=n:m)                                      % Create a vector 'a' and populate it with the numbers n through m
            a(a==                                   % Logically index into a, where the values of a match Disarium numbers
                cell2mat(                           % Convert the cell array returned by arrayfun into a matrix, so we can use it in the logical index
                    arrayfun(@(x){                  % Call the following function on every element of a, using the index named 'x'
                        sum(                        % Sum the matrix that results from the following computation
                            (f(x)-'0')              % Convert the value at index x into a string, then break it into a matrix by subtracting the string '0'.
                                                    % This results in the matrix [1 3 5] for the number 135.
                                .^                  % Compute the element-wise power with the following matrix
                                    (1:nnz(f(x)))   % Create a matrix with the range 1 to the length of the number at index x. This results in the matrix 
                                                    % [1 2 3] for the number 135.
                        )                           % Closes the sum statement
                    },a)                            % Closes the arrayfun statement, passing the matrix a to be operated on
                )
            )

1

C 175 169 bytes

f(a,b){for(j=a;j<b;j++){n,i=0,x=0;s=0;n=j;while(n!=0){n/=10;i++;}a[i];n=j;while(n!=0){a[i-x-1]=n%10;n/=10;x++;}for(x=0;x<i;x++)s+=(int)pow(a[x],x+1);if(j==s)printf("%d ",s);}}

Ungolfed version:

void f(int a, int b)
{

  for(int j=a; j<b;j++)
  {
    int n,i=0,x=0;
    int s=0;
    n=j;

   //Convert each number from 'n' to 'm' and store it in an int array 
   while(n)
   {
     n/=10;
     i++;     
   }
   int a[i]; 

   n=j;       
   while(n)
   {
    a[i-x-1]=n%10;
    n/=10;
    x++;     
   }

  //Calculate sum of digits powered with their respective position
  for(x=0;x<i;x++)
   s+=(int)pow(a[x], x+1);

   //Print Desarium
   if(j==s)
    printf("%d ", sum);     
 }

}

Can be shortened in some way, but I don't see it at the moment.

@TuukkaX Thanks for saving 6 bytes.


Both n!=0 can be changed to n.
Yytsi

You're right, that does make sense!
Abel Tom

0

Java

s->{long i=0,j=0,c,d;for(;j!=s;){String []f=Long.toString(i).split("");for(d=0,c=0;d<f.length;)c+=Math.pow(Long.valueOf(f[d]),++d);if(i==c)j++;}return i;}

Explanation

s    - index
i    - iteration variable
j    - matches
c    - sum of each digit^its index
d    - index of digit in i

0

Python 3: 131 Bytes

n=int(input())
m=int(input())
R=[x for x in range(n,m+1)]
O=[sum(map(int,str(x)))for x in R]
F=[(x**(O.index(x)))for x in O]
L=[x for x in F for w in R if x==w]
print(list(set(L)))

After creating this code, it's become apparent that there are a limited number of disariums, so it might be more feasible to check for these explicitly rather than using so much list comprehension which is tough on big inputs to this solution.

Try it online!

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