Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
joltdx
Active Contributor
About two weeks ago, I posted this about FizzBuzz in ABAP, and solving programming puzzles. It seems it was well received, so here's another one that may or may not be simple to solve.

 

Narcissistic numbers


In number theory, a narcissistic number is a number where the sum of each of its digits raised to the power of the total number of digits equals the number itself. This is the case for instance for the number 153. It has 3 digits, so when each digit is raised to the power 3, then the sum equals 153.

1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153

(Narcissistic numbers are also known as Armstrong numbers or plus perfect numbers.)

 

The suggested task here is to implement a program that lists all narcissistic numbers with 5 or less digits, i.e. between 0 and 99999.

These are, for reference 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208, 9474, 54748, 92727 and 93084

 

I have made some examples solution and posted in this ABAP puzzle repository.

 

Have fun, and enjoy your process!
23 Comments
Hendrik
Active Participant
Hi Jörgen,

nice challenge - especially because I haven't solved it yet. Will give it a try in the coming days and once solved have a look at your solutions 😉

 

Cheers

Hendrik
Abinathsiva
Active Contributor
Nice ...
former_member736527
Active Participant
Interesting puzzle!

Here is something that I have tried. It is similar to your solution, except I have stored the powers of all numbers from 1 to 9 in internal tables and used a dynamic read statement to get the powers during summation.

My solution

 

Let me know what you think!
joltdx
Active Contributor
0 Kudos
Lovely! Hope you enjoy it!
joltdx
Active Contributor
That's a creative and overly complex solution. Love that, thank you for sharing. I'll add a link to your solution from my repository as well!
SuhaSaha
Advisor
Advisor

Here goes my solution: 

types TT_NUMBER type sorted table of I with unique key TABLE_LINE.
data(ARMSTRONG_NUMBERS)
= value TT_NUMBER(
for N = 0 while N < 100000
for M = 1
while M = 1
and N = reduce I(
let STR = |{ N }|
LEN = STRLEN( STR ) in
init SUM = 0
for OFF = 0 while OFF < LEN
next SUM += IPOW( BASE = STR+OFF(1) EXP = LEN ) )
( N ) ).

Few points about the solution:

  • The solution uses string operations to find out the digits of the number. Similar to your solution 2
  • The first iteration (for N) just generates the number sequentially
  • The second iteration (for M) runs once and evaluates the sum of the powers of the digits of N

PS - I cannot create a pull request for the repo. Am i doing something wrong? 🤷‍♂️

joltdx
Active Contributor
0 Kudos
Oh, nice one suhassaha with the reduce!

You probably need to create a branch of the repository, add your changes there, and then create a pull request for that branch. Or did you do that already? I'm not that well versed in Git...

Otherwise, I'll happily add your solution in there...
DATA number TYPE string VALUE '99999'.
DATA sum TYPE int8.

WHILE number >= 0.

CONDENSE number.
DATA(number_lengthstrlennumber ).

DATA(counter0.

WHILE counter < number_length.
sum += number+counter(1** number_length.
counter += 1.
ENDWHILE.

IF sum number.
WRITE number.
ENDIF.

number -1.
sum 0.

ENDWHILE.
SuhaSaha
Advisor
Advisor
0 Kudos
I cannot create a branch 🤦‍♂️ Pretty sure i am doing something wrong, i am n00b when it comes to Git.

If you think that my solution deserves to be in your list, please add it.
joltdx
Active Contributor
I added a link to your solution in the repository.

And I realized also that you can not create a branch there. You would have needed to FORK to a repository of your own, then make your changes there, and create a pull request for your fork...

https://docs.github.com/en/github/getting-started-with-github/fork-a-repo
joltdx
Active Contributor
0 Kudos
Thanks for sharing!

You used the type conversions from string to number, I used from number to string. I like how many ways there are to do the same thing... 👍
SuhaSaha
Advisor
Advisor
0 Kudos
Thanks jorgen_lindqvist41

I had initially thought of forking your repo too, but wasn't sure if it was right way. Just saw that jacques.nomssi had created a fork of his own. I am learning something new about Git every day.

But honestly why can't i create a branch? 🤔 Any pointers lars.hvam ?
joltdx
Active Contributor
It would be the right thing. Since it's "my" repository, you don't have write access to it, and therefore can not create branches in there. That's why you instead need to create a fork into your own repository, where you have write access...
ABAPMarty
Participant
0 Kudos
Arnold did you run this code in an ABAP system? My ABAP Editor did not accept your += and -= syntax. It would be great to see your program output from a screen capture.
ABAPMarty
Participant
0 Kudos
Hi Suhas, did you run this as an ABAP program? It doesn't output anything. Also my ABAP does not accept your syntax "+=". Is this a higher version which accepts this syntax. I am on 750. Would be interesting to see your output if it is working.
ABAPMarty
Participant

Hi Jörgen, I thought I would give this a try. It was surprisingly tricky.

DATA: lv_offset     TYPE i,
lv_answer TYPE i,
lv_f_answer TYPE i,
lv_multiplier TYPE i.
WRITE: / `0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208, 9474, 54748, 92727, 93084`,
/ .
DATA(lv_loop) = 0 . "start from 0
DO 99999 TIMES.
lv_answer = lv_f_answer = lv_offset = 0 .
DATA(lv_char) = |{ lv_loop }| .
DATA(lv_exponent) = strlen( lv_char ) . "exponent and length
DO lv_exponent TIMES.
lv_multiplier = lv_char+lv_offset(1) .
lv_answer = lv_multiplier ** lv_exponent .
lv_f_answer = lv_f_answer + lv_answer .
lv_offset = lv_offset + 1 .
ENDDO.
IF lv_f_answer = lv_loop .
WRITE: CONV string( lv_f_answer ) .
ENDIF.
lv_loop = lv_loop + 1 .
ENDDO.

Here is the output. The first line is the reference result and the program output is below that.

Program output

Regards, Martin.

SuhaSaha
Advisor
Advisor

Hi Martin,

Yes, i did execute my solution before posting it here.

As per the documentation, the assignment operators +=, -= et al. are available since release 754. You can replace SUM += IPOW(... with SUM = SUM + IPOW(... to check if it runs on your ABAP release.

This was just the algorithm to get the numbers. The complete solution is posted here.

 

Hi Martin ,

For the reason that your GUI Version might be lower than 7.50-7.60, the syntax += and -= is not recognized.

 

You can use

  • sum = sum + ( number+counter(1** number_length ) instead of the existing code 
  • counter = counter + 1 instead of counter += 1
  • number = number - 1 instead of number -1

I can not send a capture right now, I am having problems with uploading an image here, but apply the changes that I explained above and you will have a functining report too.

 

Regards

Arnold

ABAPMarty
Participant
Lol. I know how to add and subtract in ABAP Arnold. Thanks. I was just curious, I had always wanted this syntax in ABAP now I know it is available in a future version. Still don't know why they didn't go for the universally recognised C++ syntax of my_var++ or my_var--.
joltdx
Active Contributor
Thanks for sharing, martin.coetzee2! Yes there is some hidden 'trickiness' in this one... 😊
ABAPMarty
Participant
0 Kudos
Thanks Suhas. I took a look at the documentation you referenced and your more extended solution. Very good.
pokrakam
Active Contributor

Hey Jörgen,

Interesting puzzle, I notice nobody tried the recursive approach so had a go. I am also trying to use immutable data rather than changing variables.

Full source is here , core logic below:

CLASS lcl_narcissist IMPLEMENTATION.

METHOD run.
check( i_number = 0
i_sum_of_powers = 0
i_pos = i_length ).
ENDMETHOD.

METHOD check.
CHECK i_sum_of_powers <= i_number. "Performance

DO 10 TIMES.
DATA(digit) = sy-index - 1.

IF i_pos > 1.
check( i_number = i_number + digit * 10 ** ( i_pos - 1 )
i_sum_of_powers = i_sum_of_powers + digit ** power
i_pos = i_pos - 1 ).

IF power < i_pos.
power = i_pos.
ENDIF.

ELSE.
IF i_number + digit = i_sum_of_powers + digit ** power.
WRITE |{ i_number + digit } |.
ENDIF.
ENDIF.

ENDDO.

ENDMETHOD.

ENDCLASS.

Regards,
Mike

joltdx
Active Contributor
0 Kudos
Awesome. Thanks for sharing, I love this.

Totally different solution from all the others. 😊
Labels in this area