loading...

Daily Challenge #214 - Persistent Bugger

thepracticaldev profile image dev.to staff ・1 min read

Write a function, persistence, that takes in a positive parameter num and returns its multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit.

Examples

 persistence(39) === 3 // because 3*9 = 27, 2*7 = 14, 1*4=4
                       // and 4 has only one digit

 persistence(999) === 4 // because 9*9*9 = 729, 7*2*9 = 126,
                        // 1*2*6 = 12, and finally 1*2 = 2

 persistence(4) === 0 // because 4 is already a one-digit number

Tests

persistence(5)
persistence(52)
persistence(377)

Good luck!


This challenge comes from joh_pot on CodeWars. Thank you to CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

Posted on by:

thepracticaldev profile

dev.to staff

@thepracticaldev

The hardworking team behind dev.to ❤️

Discussion

pic
Editor guide
 

Haskell solution:

import Numeric (floatToDigits)

persistence :: Int -> Int
persistence = recurse 0
  where
    recurse d x
      | x > 9 = recurse (d+1) . foldr (*) 1 . digits $ x
      | otherwise = d
    digits = fst . floatToDigits 10 . fromIntegral

Edit:
Inspired by other solutions I realized that I don't need to track recursion depth

import Numeric (floatToDigits)

persistence :: Int -> Int
persistence x
  | x > 9 = 1 + (persistence . foldr (*) 1 . digits $ x)
  | otherwise = 0
  where digits = fst . floatToDigits 10 . fromIntegral
 

Nice use of pointfree style!

 

My Swift solution :

extension BinaryInteger {
    var digits: [Int] {
        String(describing: self).compactMap { Int(String($0)) }
    }

    var persistence: Int {
        self.digits.reduce(into: 1) { $0 = $0 * $1 }
    }
}

func persistence(number: Int) -> Int {
    number > 9 ? 1 + persistence(number: number.persistence) : 0
}


persistence(number: 4) // Output: 0
persistence(number: 39) // Output: 3
persistence(number: 999) // Output: 4
persistence(number: 5) // Output: 0
persistence(number: 52) // Output: 2
persistence(number: 377) // Output: 4
 

Python solution

from functools import reduce
persistence = lambda num: 0 if num < 10 else 1 + persistence(reduce(int.__mul__,map(int, str(num))))

print(persistence(39)) # output 3
print(persistence(999)) # output 4
print(persistence(4)) # output 0
print(persistence(5)) # output 0
print(persistence(52)) # output 2
print(persistence(377)) # output 4
 

TypeScript

"use strict";

/**
 * Compute the multiplicative persistence of a number.
 * 
 * @param {number} number The number to compute the persistence from.
 * 
 * @throws {Error}      If the function is called with not exactly one argument.
 * @throws {TypeError}  If the first argument is not an integer.
 * @throws {RangeError} If the first argument is not greater than or equal to zero.
 * 
 * @return {number} The persistence of the number.
 * 
 * @example
 * persistence(39);     // 3
 * persistence(999);    // 4
 * persistence(4);      // 0
 */
const persistence = (number: number, ...extraParameters: unknown[]): number => {
    if (0 !== extraParameters.length) {
        throw new RangeError("The function has not been called with exactly one argument.");
    }

    if (!Number.isInteger(number)) {
        throw new TypeError("First argument is not an integer.");
    }

    if (0 > number) {
        throw new RangeError("First argument is not greater than or equal to zero");
    }

    const characters = number.toString();

    if (1 === characters.length) {
        return 0;
    }

    return 1 + persistence([...characters].reduce((total, character) => total * parseInt(character), 1));
};
 
 

Recursive JavaScript solution:

function persistence(num) {
    const digits = `${num}`.split("");
    if (digits.length === 1) {
        return 0;
    }

    const product = digits.reduce((product, digit) => {
        return product * digit;
    }, 1);

    return 1 + persistence(product);
}
 

Elixir

defmodule Challenge do
  def persistence(n) do
    n
      |> Integer.digits
      |> _persistence(0)
  end
  defp _persistence([ _ | [] ], x), do: x
  defp _persistence(list, x) do
    list
      |> List.foldl(1, &(&1 * &2))
      |> Integer.digits
      |> _persistence(x + 1)
  end
end
 

Python solution with test cases.

from functools import reduce


def persistence(n):
    count = 0
    while True:
        if len(str(n)) == 1:
            return count
        n = reduce(lambda x, y: x*y, [int(i) for i in str(n)], 1)
        count += 1

if __name__ == "__main__":
    test_cases = [39, 999, 4, 5, 52, 377]  
    expected_results = [3, 4, 0, 0, 2, 4]
    total_test_cases = len(test_cases)
    for i in range(total_test_cases):
        test_case = test_cases[i]
        expected_result = expected_results[i]
        result = persistence(test_case)
        assert_message = "persistence({}) returns {}. Expected {}".format(
            test_case, result, expected_result
        )
        assert result == expected_result, assert_message
    print("Passed all {} test cases".format(total_test_cases))
 

JS

const persistence = (num, result =0) => {
    const str = `${num}`
    if(str.length === 1) return result;
    const mult = str.split("").reduce((a,b) => a * b)
    return persistence(mult , result + 1)
}
 

C++ solution

/*
Recursion :
persistence(num) = 0 if num < 10
                 = [1 + persistence(multiplication of digits of num)] if num >= 10
*/

int persistence(int num){
    // Given number is positive, so no need to check for negative numbers

    // if number is already single digit return 0
    if(num < 10)
        return 0;

    // get the multiplication of digits
    int mul = 1;
    while(num > 0){
        mul *= (num%10);
        num /= 10;
    }

    // return 1 + persistence(mul)
    return 1 + persistence(mul);
}
 

JS solution

function persistance(num){
  let n = num;
  let count = 0;
  while(n > 9){
    count++;
    n = [...String(n)].map(Number).reduce((a,v)=> a*v,1)
  }
  return count
}
 
 

Ruby

def persistence(n)
    cnt = 0
    loop do 
    return cnt  if  n < 10 
    n = n.digits.reduce(&:*)
    cnt +=1      
    end
end