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: 
maheshpalavalli
Active Contributor
1,529
When the ABAP community coding challenge was first announced, the only thing that I thought was how to write in as fewer lines as possible 😄

 
Is it good to write like that? No, I don't think so and you all know the reason

But did I have fun writing like that? Hell yeah!!

 

And the best thing I have done is that I didn't stop trying out new ways after I submitted my first solution, I read the documentation many times to improve my approaches and I ended up sending 5 emails with 5 different solutions.


Although I didn't make it to finals, I really loved and enjoyed doing this challenge.


 

Now I will show the 5 different approaches I used to solve this challenge.

Solution #1


Highlights:

  • One-Line solution

  • Used REGEX

  • Used CL_ABAP_REGEX class ( 😄 )

  • Most Ugliest?


out->write( data = VALUE string_table(
" Declaring the string & extracting the words from the string
LET sentence = `ABАP is excellent `
words = VALUE string_table(
FOR rawword IN NEW cl_abap_regex( pattern = '(\b\w+\b)'
)->create_matcher( text = sentence )->find_all( )
( substring( val = sentence off = rawword-offset len = rawword-length ) ) )
" Filling the below additional value using base as the below for loop will
" only get executed max words times,
" But our output needs max words + 1 lines
IN BASE VALUE string_table( ( |Number of Words: { lines( words ) }| ) )
" Loop all the words and extract the unique characters
FOR word IN words ( |Number of unique characters in the word: { word } -
{ lines( NEW cl_abap_regex( pattern = '(\w)(?!.*\1)'
)->create_matcher( text = word )->find_all( ) ) }| )
) ).

 

I really thought I cracked the SAP coding challenge after doing this solution there  😄

As I was not aware of regex compatible string functions that were available at that point in time, I tried using CL_ABAP_REGEX class, it worked surprisingly. You can see that I used create_matcher and find_all to figure out pattern matches.

And I used "FOR" to loop and fill the final string table (no concatenation) and I used a similar approach in all other solutions.

 

Solution #2


So after going through the documentation, again and again, I found that I can use String Functions that support REGEX and I now can completely remove the usage of the above classes.

Highlights:

  • One-Line Solution

  • Regex String functions


   out->write( data = VALUE string_table(
" Data declaration & finding the total no of words
LET sentence = `ABАP is excellent `
totalWords = count( val = sentence regex = `(\b\w+\b)` )
" Filling the base table with Total no of words as we will loop words times
IN BASE VALUE string_table( ( |Number of Words: { totalWords }| ) )
" Looping total words for unique characters count
FOR i = 1 UNTIL i > totalWords (
" Getting the word
CONV #( LET word = match( val = sentence regex = '(\b\w+\b)' occ = i )
" Getting the count of unique characters
IN |Number of unique characters in the word: { word } -
{ count( val = word regex = `(\w)(?!.*\1)` ) } | ) ) ) ).

The usage of "Count" and "Match" replaced all that class-related code and now it became a lot cleaner.

 

Solution #3


So after that, I thought enough is enough with the "Regex" and tried to find a different solution that doesn't use it.

Highlights:

  • Not a One-Line Solution

  • No Regex

  • Finding Unique characters using "GROUPS" that auto sorts and gives unique records


  " Get the total no of words
SPLIT condense( sentence ) AT space INTO TABLE DATA(words).
" Output
out->write( data = VALUE string_table(
" Filling the base table with Total no of words
BASE VALUE string_table( ( |Number of Words: { lines( words ) }| ) )
" Looping words to find individual words unique character count
FOR word IN words ( |Number of unique characters in the word:
{ word } - { lines( VALUE string_table(
" Grouping characters -> group will auto sort and find the unique records
FOR GROUPS char_group OF char IN VALUE string_table(
" For filling character table to group it in the above statement,
" we need to loop string length times
FOR char_pos = 1 UNTIL char_pos > strlen( word )
" Now getting individual characters
( substring( val = word off = char_pos - 1 len = 1 ) ) )
" filling the character table for grouping
GROUP BY char ( char_group ) ) ) }| ) ) ).

As I thought, there is no other way to find the total no of words, I ended up using condense & Split to get the total no of words.

I used "GROUP BY" to find unique characters. AIthoug I used "GROUP BY" many times in my projects, but didn't realize till that time that I could use it that way.

 

Solution #4


After thomas.jung and few others were mentioning the importance of a clean solution and stuff, I thought I should do it in a simple readable approach. and here it is

Highlights:

  • Not a One-Line Solution

  • a simple readable approach


   DATA(sentence) = `ABАP  is excellent `.

SPLIT condense( sentence ) AT space INTO TABLE DATA(words).
out->write( data = |Number of Words: { lines( words ) }| ).
LOOP AT words REFERENCE INTO DATA(word).
DATA(characters) = VALUE string_table( FOR i = 1 UNTIL i > strlen( word->* )
( substring( val = word->* off = i - 1 len = 1 ) ) ).
SORT characters.
DELETE ADJACENT DUPLICATES FROM characters.
out->write( data = |Number of unique characters in the word: { word->* }
- { lines( characters ) }| ).
ENDLOOP.

 

Solution #5 (Final)


This one is the final solution that I submitted and the one that I liked the most. I found that I don't need to split the words outside anymore and can use the "Segment" string function to get the word & count space hack to find the total number of words.

Highlights:

  • One-Line Solution

  • My Favourite one (though it's still ugly 😄 )

  • No Regex


 out->write( data = VALUE string_table(
LET sentence = `ABАP is excellent `
" Condensed sentence
condensedSentance = condense( sentence )
" Total no of spaces + 1 equals to total no of words
totalNoOfWords = count( val = condensedSentance sub = ` ` ) + 1
" Filling the base table with Total no of words
IN BASE VALUE string_table( ( |Number of Words: { totalNoOfWords }| ) )
" Looping words to find individual words unique character count
FOR wordNo = 1 UNTIL wordNo > totalNoOfWords
LET word = segment( val = condensedSentance index = wordNo sep = ` ` )
uniqueChars = VALUE string_table(
" Grouping characters -> group will auto sort and find the unique records
FOR GROUPS charGrp OF char IN VALUE string_table(
" For filling character table to group it in the above statement
FOR charPos = 0 UNTIL charPos = strlen( word ) ( word+charPos(1) ) )
" filling the character table with unique chars resulted after grouping
GROUP BY char ( charGrp ) )
" Filling the string table for showing the ouput
IN ( |Number of unique characters in the word: { word } - { lines( uniqueChars ) }| ) ) ).

 

So at the end of this challenge, I learned a lot about the usage of Regex, string functions & many new ABAP syntaxes.

I felt very confident after doing this challenge and later I even answered some questions related to Regex, string functions & new ABAP syntax 🙂 . But still, there is so much to learn, for e.g., check this awesome solution from sandra.rossi, I was like (Mind = Blown), and took so much time to understand that 😄

https://answers.sap.com/questions/13058395/add-a-check-or-continue-in-a-for-loop-expression.html

 

Though I was using new ABAP in my projects from long back, this challenge made me explore more possibilities with the new ABAP syntax (especially because I tried to solve this challenge in one line). I would surely have not explored all these if I would have not tried a One-Liner Solution and most importantly the fun I had doing this n:)

I also had fun doing the coding challenge #2, maybe I will share it in another blog post 🙂

 

That's it folks and thanks for reading this 🙂

 

-Mahesh
2 Comments
Labels in this area