Дизариум Дилемма


31

Дизариум Дилемма

Дисариум определяется как число, чье:

сумма его цифр, приведенных в соответствие с их положением, равна исходному числу


Ваша задача :

У вас странная одержимость числами, классифицированными как дизариум. Необходимость следовать путям дисариума настолько велика в вас, что вы отказываетесь читать любые страницы, не пронумерованные дисарием, в любой книге. У вас есть две большие проблемы:

  1. Ваш профессор только что поручил вам читать ваш учебник со страницы nна страницуm
  2. На прошлой неделе вы сильно ударились головой и, похоже, не помните, как программно определить, считается ли число дисариумом.

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

Вы должны идентифицировать весь дисарий в пределах широкого диапазона до 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), должны ли ответы быть в состоянии его идентифицировать?
Линн

@ Линн Учитывая, что уже есть ряд решений, я бы сказал, что не должно быть никаких границ диапазона.
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])
Род

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 байта, прежде чем мы
Лука

Вы можете использовать &вместо &&. Еще один байт идти ...
Arnauld

Я просто изменил это в своей локальной копии ... Думаю, ты был быстрее.
Лука

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.


6

05AB1E , 12 байтов

Сохранено 2 байта благодаря Emigna

ŸvygLySmOyQ—

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

Ÿ            # push [a .. b]
 vy          # for each
   gL        # push [1 .. num digits]
     yS      # push [individual digits]
       m     # push [list of digits to the power of [1..num digits] ]
        O    # sum
         yQ— # print this value if equal

ŸvygLySmOyQ—должно работать на 12 байтов.
Emigna

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!
Стинберг

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

Python 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 По умолчанию калькулятор находится в 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) и превращения каждого символа в строку из одного элемента ( 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

Mathematica, 59 байт

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

Безымянная функция, принимающая два целочисленных аргумента и возвращающая список целых чисел. (d=IntegerDigits@#)^Range@Length@dвыдает список цифр номера с соответствующими полномочиями; Tr[...]==#определяет, равна ли сумма этих цифр-степеней исходному числу.


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

Хаскелл , 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 байтов

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);}}

Заголовок, определяющий pow на TIO, потому что по какой-то причине он автоматически не включает pow. Мой компьютер сделал, так что я собираюсь катиться с этим.

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


1

MATL , 16 байт

&:"@tFYAtn:^s=?@

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

&:        % 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

Пакетный, 115 байт

@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

Пакет имеет только 32-битную арифметику, которая не может сравнивать последнее число дизария, но если вы настаиваете на сравнении строк, то для 402 байтов:

@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 байт

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

У меня еще не было возможности запустить это (делая это на моем телефоне).


Это не работает Неправильный синтаксис и при исправлении выводит только логические значения. Начинается с показателя степени 0, что также неверно. Кроме того, вам не нужны квадратные скобки внутри sum.
Yytsi

Это не проверка номера дисариума.
hashcode55

@ hashcode55, исправлено (?)
Даниэль

@TuukkaX, теперь это должно работать, я думаю
Даниэль

Я не на компьютере, но это должно печатать новую iстроку на каждой итерации, где находится Disarium. Я понятия не имею, разрешено ли это, но я бы сказал нет, так как вывод становится очень пустым.
Yytsi

1

Scala, 132 129 байт

(% :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 Редактирование: Изменение для имени переменной передачи контура от &к iсохраненным трех пространств.


объяснение

Для каждого значения в диапазоне ввода:

  • преобразовать его в строку с +""
  • используется zipWithIndexдля создания списка кортежей, содержащих символ цифры и ее индекс
  • сверните список, возвращая значение int каждого символа минус 48 (строки до 0-9) в степень индекса списка плюс один (для начала в ^ 1)
  • если результат соответствует вводу, распечатайте его

Комментарии

Наконец-то дошли руки до изучения как foldи как zipWithIndexработать. Я недоволен intобращениями, но я доволен краткостью foldи zipWithIndex.


1

Октава, 88 87 байт

Спасибо MattWH за сохранение байта (f (x) -48 против f (x) - '0')

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

Бежать:

>> 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

объяснение

@(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 байт

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);}}

Безголовая версия:

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);     
 }

}

Можно как-то укоротить, но пока не вижу.

@TuukkaX Спасибо за сохранение 6 байтов.


Оба n!=0могут быть изменены на n.
Yytsi

Вы правы, это имеет смысл!
Абель Том

0

Джава

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;}

объяснение

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

0

Python 3: 131 байт

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)))

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

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

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