the number of trailing zeros in a factorial of a given number - Ruby

后端 未结 12 1895
执念已碎
执念已碎 2020-12-11 03:37

Having a little trouble trying calculate the number of trailing zeros in a factorial of a given number. This is one of the challenges from Codewars- can\'t get mine to pass.

12条回答
  •  囚心锁ツ
    2020-12-11 04:29

    So, now that @Spunden has so artfully let the cat out of the bag, here's one way to implement it.

    Code

    def zeros(n)
      return 0 if n.zero?
      k = (Math.log(n)/Math.log(5)).to_i
      m = 5**k
      n*(m-1)/(4*m)
    end
    

    Examples

    zeros(3)   #=>  0
    zeros(5)   #=>  1
    zeros(12)  #=>  2
    zeros(15)  #=>  3
    zeros(20)  #=>  4
    zeros(25)  #=>  6
    zeros(70)  #=> 16
    zeros(75)  #=> 18
    zeros(120) #=> 28
    zeros(125) #=> 31
    

    Explanation

    Suppose n = 128.

    Then each number between one and 128 (inclusive) that is divisible by 5^1=>5 provides at least one factor, and there are 128/5 => 25 such numbers. Of these, the only ones that provide more than one factor are those divisible by 5^2=>25, of which there are 128/25 => 5 (25, 50, 75, 100, 125). Of those, there is but 128/125 => 1 that provides more than two factors, and since 125/(5^4) => 0, no numbers contribute more than three divisors. Hence, the total number of five divisors is:

    128/5 + 128/25 + 128/125 #=> 31
    

    (Note that, for 125, which has three divisors of 5, one is counted in each of these three terms; for 25, 50, etc., which each have two factors of 5, one is counted in each of the first terms.)

    For arbitrary n, we first compute the highest power k for which:

    5**k <= n
    

    which is:

    k <= Math.log(n)/Math.log(5)
    

    so the largest such value is:

    k = (Math.log(n)/Math.log(5)).to_i
    

    As @spundun noted, you could also calculate k by simply iterating, e.g.,

    last = 1
    (0..1.0/0).find { |i| (last *= 5) > n }
    

    The total number of factors of five is therefore

    (n/5) + (n/25) +...+ (n/5**k)
    

    Defining:

    r = 1/5,
    

    this sum is seen to be:

    n * s
    

    where

    s = r + r**2 +...+ r**k
    

    The value of s is the sum of the terms of a geometric series. I forget the formula for that, but recall how it's derived:

    s  = r + r**2 +...+ r**k
    sr =     r**2 +...+ r**(k+1)
    
    s-sr = r*(1-r**k)
    
    s = r*(1-r**k)/(1-r)
    

    I then did some rearrangement so that only only integer arithmetic would be used to calculate the result.

提交回复
热议问题