Disarium Dilemma

Disarium Dilemma

A Disarium is defined as a number whose:

sum of its digits powered with their respective position is equal to the original number

You have a strange obsession with numbers classified as being a disarium. The need to follow the ways of disarium is so great in you that you refuse to read any non-disarium numbered pages in any given book. You have two BIG problems:

1. Your professor just assigned you to read your textbook from page n to page m
2. You hit your head really hard last week and can't seem to remember how to programmatically determine if a number is considered to be a disarium.

Time is of the essence so the code to determine the pages you will need to read needs to be as short as possible.

You need to identify all of the disarium within an inclusive range of n through m.

Examples of a disarium:

89 = 81 + 92

135 = 11 + 32 + 53

518 = 51 + 12 + 83

This is code-golf, so the least number of bytes wins!

Here is the full sequence of A032799.

• @Fatalize The range is inclusive, I will edit the question to reflect this. – CraigR8806 Jan 19 '17 at 13:51
• Are there any guaranteed bounds on n and m? There’s a very big disarium (12157692622039623539), should answers be able to identify it? – Lynn Jan 19 '17 at 15:12
• @Lynn Given that there are already a number of solutions, I would say there should be no bounds on the range. – CraigR8806 Jan 19 '17 at 15:17
• @Lynn. There is no disarium >22 digits, so in a way the range is already bounded. – Mad Physicist Jan 19 '17 at 16:21
• @MistahFiggins Please go to the OEIS link at the bottom of the question. You will find a proof that shows the Disarium sequence is indeed finite. – CraigR8806 Jan 19 '17 at 20:58

Perl 6, 40 39 bytes

{grep {$_==sum .comb Z**1..*},$^a..$^b}  Try it online! How it works { } # 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.


Python2, 988988 84 bytes

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


Horrible. Will get shorter. Starting to look better

Here's my recursive attempt (86 bytes):

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


Thanks to @Rod for saving 4 bytes! range to enumerate and so on.

• switching to enumerate, you can use int(n) instead int(x[p]) – Rod Jan 19 '17 at 14:41

Perl, 43 bytes

map{say if$_==eval s/./+$&**$+[0]/gr}<>..<>  Try it online! Regex is really powerful, you guys. Explanation The first thing the code does is read two integers as input via <>, and creates a range from the first to the second with ... It then uses the standard map function to iterate through this range, and applies the following code to each value: say if$_==eval s/./+$&**$+[0]/gr. This looks like gibberish, and it kind of is, but here's what's really happening.

map implicitly stores its current value in the variable $_. Many perl functions and operations use this value when none is given. This includes regular expressions, such as the s/// substitution operator. There are four parts to a substitution regex: 1. String to be manipulated. Ordinarily, the operator =~ is used to apply a regex to a string, but if this operator is absent, then the regex is applied to the implicit variable $_, which contains our current number via the map function.
2. String to search for. In this case, we're searching for any single non-newline character, denoted by the wildcard .. In effect, we're capturing each individual digit.
3. String to replace with. We're substituting a plus sign + followed by a mathematical expression, mixed in with some magical Perl variables that make everything significantly easier.

The special scalar variable $& always contains the entirety of the last successful regex capture, which in this case is a single digit. The special array variable @+ always contains a list of postmatch offsets for the last successful match, i.e. the index of the text after the match. $+[0] is the index in $_ of the text immediately following $&. In the case of 135, we capture the digit 1, and the index in 135 of the text immediately afterwards (namely, 35) is 1, which is our exponent. So, we want to raise $& (1) to the power of $+[0] (1) and get 1. We want to raise 3 to the power of 2 and get 9. We want to raise 5 to the power of 3 and get 125.

If the input was 135, the resulting string is +1**1+3**2+5**3.

1. Regex-modifying flags. Here we're using two regex flags -- /g and /r. /g tells the interpreter to continue replacements after the first is found (otherwise we'd end up with +1**135). /r tells the interpreter not to modify the original string, and instead return what the string would be after the replacements. This is important, because otherwise, it would overwrite $_, and we need it for comparison purposes. Once the entire substitution is done, we get a mathematical expression, which is evaluated with the eval function. +1**1+3**2+5**3 is evaluated into 1 + 9 + 125 = 135, which is compared to the original number 135. Since these two are equal, the code prints the number. • Beautiful solution. (Note that this won't work is the first input is 0, but I'm not sure it matters). A few bytes to golf: map$_-eval s/./+$&**$+[0]/gr||say,<>..<> – Dada Jan 22 '17 at 21:50
• And "@+" is 1 byte shorter than $+[0] :) – Dada Jan 22 '17 at 22:15 JavaScript (ES7), 105918988837982 81 bytes Thanks to Arnauld for saving 20B, and ETHProductions for saving 6B! a=>b=>[...Array(b).keys()].filter(c=>c>=a&([...c+''].map(d=>c-=d**++e,e=0),!c))  Usage Assign the function to a variable, and give it the minimum and the maximum as arguments. Example: f=a=>b=>[...Array(b).keys()].filter(c=>c>=a&([...c+''].map(d=>c-=d**++e,e=0),!c)) f(0)(90)  Output [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 89]  Further golfing This seems pretty well-golfed, but there's always room for improvement... I think. • Yeah, that's actually quite a bit shorter. Thanks! – Luke Jan 19 '17 at 14:05 • You can change d**(e+1) to d**-~e to save two bytes. – ETHproductions Jan 19 '17 at 14:10 • Thanks for the tip, added it. Only 2 more bytes before we've beaten Python... – Luke Jan 19 '17 at 14:19 • You can use & instead of &&. One more byte to go... – Arnauld Jan 19 '17 at 14:23 • I just changed that in my local copy... Guess you were faster. – Luke Jan 19 '17 at 14:24 JavaScript (Firefox 52+), 68 bytes f=(n,m)=>(e=0,[for(d of t=n+'')t-=d**++e],t||alert(n),n-m&&f(n+1,m))  Recursive function that outputs via alert. Works in the Developer Edition of Firefox, which you can download on this page. Previous versions of Firefox don't support the ** operator, and no other browser supports [for(a of b)c] syntax. Test snippet This uses .map instead of an array comprehension, and Math.pow instead of **, so it should work in all browsers that support ES6. f=(n,m)=>(e=0,[...t=n+''].map(d=>t-=Math.pow(d,++e)),t||alert(n),n-m&&f(n+1,m)) f(0,100) 05AB1E, 12 bytes Saved 2 bytes thanks to Emigna ŸvygLySmOyQ—  Try it online! Ÿ # 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— should work for 12 bytes. – Emigna Jan 19 '17 at 16:00 Python 3, 100 bytes lambda n,m:{*range(10),89,135,175,518,598,1306,1676,2427,2646798,0xa8b8cd06890f2773}&{*range(n,m+1)}  Not the shortest approach, but a pretty cute one. There are finitely many disariums; see the OEIS page for a nice proof. These are all of them. • This is use of hard-coding which is a loophole meta.codegolf.stackexchange.com/a/1063/55243 I would recommended you change your answer to fit with the standard rules – george Jan 19 '17 at 16:13 • I don't think this violates the hard-coding rule, as the program still "does work" and the output is not hard-coded. – Alex Howansky Jan 19 '17 at 16:21 R, 100 bytes function(n,m,x=n:m)x[sapply(x,function(y)sum(as.integer(el(strsplit(c(y,""),"")))^(1:nchar(y)))==y)]  Unnamed function that takes n and m. As always in R, splitting integers into a numeric digit vector is tedious and eats up a lot of bytes. This makes the function relatively slow and only works for 32-bit integers. Jelly, 11 bytes D*J$S⁼
rÇÐf


Try it online!

Got this down from 16 to 11, with some help from @miles!

Explanation:

rÇÐf    Main link, arguments are m and n
r       Generate a list from m to n
Ð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

• You can use J to get indices. A shorter way might be D*J$S⁼ to combine your two links into one – miles Jan 19 '17 at 14:00 • Arrived at exactly that conclusion about 20 sec ago. Thnx! – steenbergh Jan 19 '17 at 14:02 CJam, 23 bytes q~),\>{_Ab_,,:).#:+=},p  Try it online! Explanation 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  05AB1E, 18 bytes Ÿvy©SDgLsmO®Qi®}})  Try it online! Python 2.X, 92 bytes 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]  • Useless whitespace after (i+1), but this is not a problem, when you get rid of the parentheses by doing -~i. – Yytsi Jan 19 '17 at 15:26 • That'd make my attempt exact same as yours! – hashcode55 Jan 19 '17 at 17:44 • Almost. You have list('k'), which I don't have. However, you can still remove the whitespace :) – Yytsi Jan 19 '17 at 18:48 Python 2, 84 bytes A full program approach, currently the same length as the lambda solution. a,b=input() while a<=b: t=p=0 for x ina:p+=1;t+=int(x)**p if t==a:print a a+=1  Try it online! • Hmm. I thought about the almost exact answer, but discarded due to confusion with input(). Very nice! +1. – Yytsi Jan 19 '17 at 20:50 Japt, 15 bytes òV f_¥Zì £XpYÄÃx  Test it online! This was a collaboration between @obarakon and myself. How it works ò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  In the latest version of Japt, x accepts a function as an argument, which allows us to golf another byte: òV f_¥Zì x@XpYÄ  Test it online! Clojure, 107 bytes #(for[i(range %(inc %2)):when(=(int(apply +(map(fn[i v](Math/pow(-(int v)48)(inc i)))(range)(str i))))i)]i)  Implementing the equation is terribly long. • can save a couple of bytes by doing (.pow(-(int v)48M) – cliffroot Jan 30 '17 at 15:17 TI-Basic, 85 bytes Input For(I,X,Y If I<=9 or sum(I={89,135,175,518,598,1306,1676,2427,2646798,12157692622039623539 Disp I End  • I did not know hard-coding was permitted. :) – Abel Tom Jan 19 '17 at 15:58 • @AbelTom Well, it really helps that this series only has 20 terms. Also, converting number to string in TI-Basic takes lots of bytes. Only other solution would be to int(log( every number and then do the powers. Perhaps this is shorter, but I doubt it. – Timtech Jan 19 '17 at 16:14 • That input method is very clever but kind of sketchy. You need to be in FUNC mode and the window has to be set up to include your input point. Doesn't seem portable enough to me. – Jakob Jan 19 '17 at 20:48 • @JakobCornell By default the calc is in FUNC mode, although I do see what you're saying about the input resolution. But, this method is pretty common in golfing. You could always Prompt X,Y instead. – Timtech Jan 20 '17 at 22:13 Haskell, 61 bytes n#m=[i|i<-[n..m],i==sum(zipWith(^)(read.pure<$>show i)[1..])]


Usage example 5 # 600 -> [5,6,7,8,9,89,135,175,518,598].

Check each number i in the range [n..m]. The digits are extracted by turning i into a string (show) and making each char a one element string (pure) which is turned into an integer again (read). Zip those numbers element wise with [1..] via the function ^ and take the sum.

PHP, 9291 88 bytes

3 bytes saved thanks @AlexHowansky

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


takes input from command line arguments; prints a trailing comma. Run with -r.

• Save three with for([,$n,$m]=$argv;$n<=$m; – Alex Howansky Jan 19 '17 at 16:31 • Strange that print works there but echo doesn't. I guess because echo doesn't return anything -- not even null, oddly. – Alex Howansky Jan 19 '17 at 16:50 • @AlexHowansky: It´s also strange that "$n"[index] and "_$n"[index] produce parse errors while "89"[index] and $s="$n";$s[index] are perfectly fine. – Titus Jan 19 '17 at 17:17
• Hmm yes, that does seem odd at first, but after checking the docs, it appears they do explicitly say that the feature works only for string literals. – Alex Howansky Jan 19 '17 at 17:20
• Heh heh well this works, but it probably doesn't save you any bytes: ("_\$n")[index] – Alex Howansky Jan 19 '17 at 17:24

Mathematica, 59 bytes

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.

MATLAB, 88 73 bytes

@(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' splits a n into a vector of its digits, and 1:floor(log10(n))+1 is a vector holding one to the number of digits in n. Thanks to log for the golf down to an anonymous function, saving 15 bytes.

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


Try it online! Usage: 5 ! 175

This checks each number in the range n to m if its a disarium number and is hence quite slow for big m.

Faster version: (93 bytes)

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


Try it online!

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!

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


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


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 Jan 19 '17 at 14:37
• This isn't checking for disarium numbers. – hashcode55 Jan 19 '17 at 14:52
• @hashcode55, fixed (?) – Daniel Jan 19 '17 at 14:58
• @TuukkaX, now it should work I think – Daniel Jan 19 '17 at 14:59
• 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 Jan 19 '17 at 15:04

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

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.

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


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 Jan 19 '17 at 20:48
• You're right, that does make sense! – Abel Tom Jan 27 '17 at 9:52

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


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!