DataWeave programming challenge #6: Using tail-recursion to get the factorial of a number
Create a tail-recursive function to get the factorial of each positive number from the payload.
DataWeave Programming Challenges· Part 6 of 8
- 1.DataWeave programming challenge #1: Add numbers separated by paragraphs and get the max number
- 2.DataWeave programming challenge #2: Rock Paper Scissors game score system
- 3.DataWeave programming challenge #3: Count palindrome phrases using the Strings module
- 4.DataWeave programming challenge #4: Solve the Tower of Hanoi mathematical puzzle
- 5.DataWeave programming challenge #5: Reverse a phrase's words, but keep the punctuation
- 6.DataWeave programming challenge #6: Using tail-recursion to get the factorial of a number
- 7.DataWeave programming challenge #7: Modify certain values from a JSON structure
- 8.DataWeave programming challenge #8: Sum all digits to get a 1-digit number
Try to solve this challenge on your own to maximize learning. We recommend you refer to the DataWeave documentation only. Try to avoid using Google or asking others so you can learn on your own and become a DataWeave expert!
Solve on the PlaygroundInput
Consider the following input payload (can be of txt format):
3
5
-6
300
Explanation of the problem
- Create a tail-recursive function to get the factorial of each positive number from the payload.
- Sum the results.
- Retrieve the digits/characters located at positions 20-25.
- Make sure to return a number and not a string.
- Numbers 0 or less won’t be calculated.
For example:
- The factorial of 3 is 6 (3 x 2 x 1)
- The factorial of 5 is 120 (5 x 4 x 3 x 2 x 1)
- The factorial of -6 won’t be calculated so the result will be 0
- And so on
- Once the results are summed (6 + 120 + 0…), extract the digits at indexes 20 to 25.
- Return this last 6-digit number.
Expected output
In this case, the expected output would be:
537046
Clues
If you’re stuck with your solution, feel free to check out some of these clues to give you ideas on how to solve it!
Clue #1
Use lines() from the Strings module or splitBy() to process every line.
Clue #2
Make sure to use tail-recursiveness and not regular recursiveness. Otherwise, your script might not work.
Clue #3
Make sure to create an if statement before calling the function in recursion. Otherwise, you might get stuck in an infinite loop!
Clue #4
You can use the keyword as to transform to/from strings and numbers.
Clue #5
You can extract characters from a string with the range selector [ x to y ]
Answer
If you haven’t solved this challenge yet, we encourage you to keep trying! It’s ok if it’s taking longer than you thought. We all have to start somewhere ✨ Check out the clues and read the docs before giving up. You got this!! 💙
There are many ways to solve this challenge, but you can find here one of my solutions!
Solution #1
%dw 2.0
import lines from dw::core::Strings
output application/json
fun factorial(num:Number, result:Number=1):Number = do {
if (num == 0) result
else if (num < 0) 0
else factorial(num - 1, result * num)
}
---
lines(payload) map factorial($)
then sum($) as String
then $[20 to 25] as Number
Subscribe to receive notifications as soon as new content is published ✨
Reader notes
Helpful comments preserved from the original post.
- Nicky van Steensel van der Aa · Jul 18, 2023
For those using
dw::core::Arraysslice it excludes the last index, so select 20-26 - Nicky van Steensel van der Aa · Jul 18, 2023
%dw 2.0 output application/json fun solve(x)= x reduce (item, acc) -> ( (if(item > 0) acc + factorial(item) else acc)) fun factorial(x)= 2 to x reduce (item, acc) -> (acc*item) --- (solve(payload splitBy('\n')) splitBy(''))[20 to 25] joinBy("") - Nirmala Vairaganthan · May 10, 2023
%dw 2.0 fun factorial(num)= num to 1 reduce ((item, accumulator) -> accumulator * item) fun pos(val) = val[20 to 25] --- pos(sum((payload splitBy "\n" ) map factorial($))) as Number - Disha Bhar · May 10, 2023
Tried this out. :)
%dw 2.0 import * from dw::core::Strings fun tailFactorial(n:Number, p:Number = 1) = (if(n == 1 or n == 0) p else tailFactorial(n-1, (p * n))) output application/json --- (sum((payload splitBy "\n") filter($>0) map tailFactorial($ as Number) )as String)[20 to 25] as Number - Felix Schnabel · May 9, 2023
%dw 2.0 output application/json import * from dw::core::Strings @TailRec fun solve(i: Number, acc: Number = 1): Number = i match { case 0 -> acc case i if(i < 0) -> 0 else -> solve(i - 1, acc * i) } --- lines(payload) map solve($ as Number) then sum($) then $[20 to 25] as Number - Sudiptaa · May 9, 2023
%dw 2.0 output application/json import lines from dw::core::Strings fun factorial(n:Number,res:Number=1):Number = if (n == 1 or n ==0) res else if (n < 0) 0 else factorial(n - 1,res * n) --- sum(lines(payload) map factorial($))[20 to 25] as Number - Shyam Raj Prasad · May 9, 2023
Solved using reduce.
%dw 2.0 import lines from dw::core::Strings output application/json fun factorial(x) = 1 to x reduce ((item, accumulator) -> accumulator * item ) --- ((lines(payload) filter ($>0) reduce ((item, accumulator) -> factorial(item) + accumulator )) as String)[20 to 25] as Number
FAQs
Frequently asked questions about this post.
-
What is this DataWeave challenge asking me to do?
The challenge asks you to create a tail-recursive function that gets the factorial of each positive number in the payload, sum the results, then retrieve the digits located at positions 20 to 25, returning a number and not a string. Numbers that are 0 or less aren't calculated, so for the sample input the factorial of 3 is 6, the factorial of 5 is 120, the factorial of -6 isn't calculated (treated as 0), and the expected output is
537046. -
How do I process every line of the input payload?
As the clues suggest, you can use
lines()from the Strings module orsplitBy()to process every line of the payload, which can be in txt format. -
Why does the post insist on tail-recursion instead of regular recursion?
The clues warn that you must use tail-recursiveness and not regular recursiveness, otherwise your script might not work.
-
How do I avoid an infinite loop in the recursive factorial function?
Make sure to create an if statement before calling the function in recursion; otherwise you might get stuck in an infinite loop, as noted in the clues.
-
How do I return a number instead of a string for the final result?
You can use the keyword
asto transform to and from strings and numbers, and you extract the characters at positions 20 to 25 from a string using the range selector[ x to y ]before converting the result back to a number. -
Where should I look for help while solving this challenge?
The post recommends referring only to the DataWeave documentation at https://docs.mulesoft.com/dataweave/latest/ and avoiding Google or asking others, so you can learn on your own; you can also solve it directly on the linked DataWeave Playground.
More from this series
DataWeave Programming Challenges· Part 6 of 8
- 1.DataWeave programming challenge #1: Add numbers separated by paragraphs and get the max number
- 2.DataWeave programming challenge #2: Rock Paper Scissors game score system
- 3.DataWeave programming challenge #3: Count palindrome phrases using the Strings module
- 4.DataWeave programming challenge #4: Solve the Tower of Hanoi mathematical puzzle
- 5.DataWeave programming challenge #5: Reverse a phrase's words, but keep the punctuation
- 6.DataWeave programming challenge #6: Using tail-recursion to get the factorial of a number
- 7.DataWeave programming challenge #7: Modify certain values from a JSON structure
- 8.DataWeave programming challenge #8: Sum all digits to get a 1-digit number
