Munchausen numbers

From Rosetta Code
Revision as of 19:12, 23 September 2016 by Walterpachl (talk | contribs) (add REXX)
Munchausen numbers is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.


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 #

  1. note that 6^6 is 46 656 so we only need to cosider numbers consisting of 0 to 5 #
  1. 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>

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

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)