Munchausen numbers
- Definition of Munchausen numbers
A Munchausen number is a natural number n the sum of whose digits (in base 10), each raised to the power of itself, is n itself.
- Task requirements
Finds all Munchausen numbers between 1 and 5000
ALGOL 68
<lang algol68># Find Munchausen Numbers between 1 and 5000 #
- note that 6^6 is 46 656 so we only need to cosider numbers consisting of 0 to 5 #
- table of Nth powers - note 0^0 is 0 for Munchausen numbers, not 1 #
[]INT nth power = ([]INT( 0, 1, 2 * 2, 3 * 3 * 3, 4 * 4 * 4 * 4, 5 * 5 * 5 * 5 * 5 ))[ AT 0 ];
INT number := 0; FOR d1 FROM 0 TO 5 WHILE number < 5001 DO
INT d1 part = d1 * 1000; FOR d2 FROM 0 TO 5 DO INT d2 part = d2 * 100; FOR d3 FROM 0 TO 5 DO INT d3 part = d3 * 10; FOR d4 FROM 0 TO 5 DO INT digit power sum := nth power[ d1 ] + nth power[ d2 ] + nth power[ d3 ] + nth power[ d4 ]; number := d1 part + d2 part + d3 part + d4; IF digit power sum = number THEN IF number > 0 THEN print( ( whole( number, 0 ), newline ) ) FI FI OD OD OD
OD</lang>
- Output:
1 3435
AppleScript
<lang AppleScript>
on run
filter(isMunchausen, range(1, 5000)) --> {1, 3435}
end run
-- isMunchausen :: Int -> Bool on isMunchausen(n)
(class of n is integer) and ¬ foldl(my digitPowerSum, 0, characters of (n as string)) = n
end isMunchausen
-- digitPowerSum :: Int -> Character -> Int on digitPowerSum(a, c)
set d to c as integer a + (d ^ d)
end digitPowerSum
-- GENERIC LIBRARY FUNCTIONS
-- filter :: (a -> Bool) -> [a] -> [a] on filter(f, xs)
set mf to mReturn(f) set lst to {} set lng to length of xs repeat with i from 1 to lng set v to item i of xs if mf's lambda(v, i, xs) then set end of lst to v end if end repeat return lst
end filter
-- foldl :: (a -> b -> a) -> a -> [b] -> a on foldl(f, startValue, xs)
set mf to mReturn(f) set v to startValue set lng to length of xs repeat with i from 1 to lng set v to mf's lambda(v, item i of xs, i, xs) end repeat return v
end foldl
-- range :: Int -> Int -> [Int]
on range(m, n)
if n < m then set d to -1 else set d to 1 end if set lst to {} repeat with i from m to n by d set end of lst to i end repeat return lst
end range
-- Lift 2nd class handler function into 1st class script wrapper
-- mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then return f script property lambda : f end script
end mReturn </lang>
- Output:
<lang AppleScript>{1, 3435}</lang>
C
Adapted from Zack Denton's code posted on Munchausen Numbers and How to Find Them. <lang C>#include <stdio.h>
- include <math.h>
int main() {
for (int i = 1; i < 5000; i++) { // loop through each digit in i // e.g. for 1000 we get 0, 0, 0, 1. int sum = 0; for (int number = i; number > 0; number /= 10) { int digit = number % 10; // find the sum of the digits // raised to themselves sum += pow(digit, digit); } if (sum == i) { // the sum is equal to the number // itself; thus it is a // munchausen number printf("%i\n", i); } } return 0;
}</lang>
- Output:
1 3435
C#
<lang csharp>Func<char, int> toInt = c => c-'0';
foreach (var i in Enumerable.Range(1,5000) .Where(n => n == n.ToString() .Sum(x => Math.Pow(toInt(x), toInt(x))))) Console.WriteLine(i);</lang>
- Output:
1 3435
Haskell
<lang haskell>import Data.List (unfoldr)
isMunchausen :: Integer -> Bool isMunchausen n = (n ==) $ sum $ map (\x -> x^x) $ unfoldr digit n where
digit 0 = Nothing digit n = Just (r,q) where (q,r) = n `divMod` 10
main :: IO () main = print $ filter isMunchausen [1..5000]</lang>
- Output:
[1,3435]
J
Here, it would be useful to have a function which sums the powers of the digits of a number. Once we have that we can use it with an equality test to filter those integers:
<lang J> munch=: +/@(^~@(10&#.inv))
(#~ ] = munch"0) 1+i.5000
1 3435</lang>
Note that wikipedia claims that 0=0^0 in the context of Munchausen numbers. It's not clear why this should be (1 is the multiplicative identity and if you do not multiply it by zero it should still be 1), but it's easy enough to implement. Note also that this does not change the result for this task:
<lang J> munch=: +/@((**^~)@(10&#.inv))
(#~ ] = munch"0) 1+i.5000
1 3435</lang>
Java
Adapted from Zack Denton's code posted on Munchausen Numbers and How to Find Them. <lang Java> public class Main {
public static void main(String[] args) { for(int i = 0 ; i <= 5000 ; i++ ){ int val = String.valueOf(i).chars().map(x -> (int) Math.pow( x-48 ,x-48)).sum(); if( i == val){ System.out.println( i + " (munchausen)"); } } }
}
</lang>
- Output:
1 (munchausen) 3435 (munchausen)
JavaScript
ES6
<lang javascript>for (let i of [...Array(5000).keys()] .filter(n => n == n.toString().split() .reduce((a, b) => a+Math.pow(parseInt(b),parseInt(b)), 0))) console.log(i);</lang>
- Output:
1 3435
Or, composing reusable primitives:
<lang JavaScript>(function () {
'use strict';
// isMunchausen :: Int -> Bool let isMunchausen = n => !isNaN(n) && ( n.toString() .split() .reduce((a, c) => { let d = parseInt(c, 10); return a + Math.pow(d, d); }, 0) === n ),
// range(intFrom, intTo, intStep?) // Int -> Int -> Maybe Int -> [Int] range = (m, n, step) => { let d = (step || 1) * (n >= m ? 1 : -1);
return Array.from({ length: Math.floor((n - m) / d) + 1 }, (_, i) => m + (i * d)); };
return range(1, 5000) .filter(isMunchausen);
})();</lang>
- Output:
<lang JavaScript>[1, 3435]</lang>
Lua
<lang Lua>function isMunchausen (n)
local sum, nStr, digit = 0, tostring(n) for pos = 1, #nStr do digit = tonumber(nStr:sub(pos, pos)) sum = sum + digit ^ digit end return sum == n
end
for i = 1, 5000 do
if isMunchausen(i) then print(i) end
end</lang>
- Output:
1 3435
Perl 6
<lang perl6>sub is_munchausen ( Int $n ) {
constant @powers = 0, |map { $_ ** $_ }, 1..9; $n == @powers[$n.comb].sum;
} .say if .&is_munchausen for 1..5000;</lang>
- Output:
1 3435
REXX
<lang rexx>Do n=0 To 10000
If n=m(n) Then Say n End
Exit m: Parse Arg z res=0 Do While z>
Parse Var z c +1 z res=res+c**c End
Return res</lang>
- Output:
D:\mau>rexx munch 1 3435
Scala
Adapted from Zack Denton's code posted on Munchausen Numbers and How to Find Them. <lang Scala> object Munch {
def main(args: Array[String]): Unit = { import scala.math.pow (1 to 5000).foreach { i => if (i == (i.toString.toCharArray.map(d => pow(d.asDigit,d.asDigit))).sum) println( i + " (munchausen)") } }
} </lang>
- Output:
1 (munchausen) 3435 (munchausen)
Sidef
<lang ruby>func is_munchausen(n) {
n.digits.map{|d| d**d }.sum == n
}
say (1..5000 -> grep(is_munchausen))</lang>
- Output:
[1, 3435]
zkl
<lang zkl>[1..5000].filter(fcn(n){ n==n.split().reduce(fcn(s,n){ s + n.pow(n) },0) }) .println();</lang>
- Output:
L(1,3435)