Optimization for finding perfect-square algorithm

后端 未结 3 1365
醉酒成梦
醉酒成梦 2020-12-21 18:04

The question I\'m working on is:

Find which sum of squared factors are a perfect square given a specific range. So if the range was (1..10) you woul

3条回答
  •  南笙
    南笙 (楼主)
    2020-12-21 18:54

    One way to make it more efficient is to use Ruby's built-in method Prime::prime_division.

    For any number n, if prime_division returns an array containing a single element, that element will be [n,1] and n will have been shown to be prime. That prime number has factors n and 1, so must be treated differently than numbers that are not prime.

    require 'prime'
    
    def list_squared(range)
      range.each_with_object({}) do |i,h|
        facs = Prime.prime_division(i)
        ssq = 
        case facs.size
        when 1 then facs.first.first**2 + 1
        else facs.inject(0) { |tot,(a,b)| tot + b*(a**2) }
        end
        h[i] = facs if (Math.sqrt(ssq).to_i)**2 == ssq
      end
    end
    
    list_squared(1..10_000)
      #=> { 1=>[], 48=>[[2, 4], [3, 1]], 320=>[[2, 6], [5, 1]], 351=>[[3, 3], [13, 1]],
      #     486=>[[2, 1], [3, 5]], 1080=>[[2, 3], [3, 3], [5, 1]],
      #     1260=>[[2, 2], [3, 2], [5, 1], [7, 1]], 1350=>[[2, 1], [3, 3], [5, 2]],
      #     1375=>[[5, 3], [11, 1]], 1792=>[[2, 8], [7, 1]], 1836=>[[2, 2], [3, 3], [17, 1]],
      #     2070=>[[2, 1], [3, 2], [5, 1], [23, 1]], 2145=>[[3, 1], [5, 1], [11, 1], [13, 1]],
      #     2175=>[[3, 1], [5, 2], [29, 1]], 2730=>[[2, 1], [3, 1], [5, 1], [7, 1], [13, 1]],
      #     2772=>[[2, 2], [3, 2], [7, 1], [11, 1]], 3072=>[[2, 10], [3, 1]],
      #     3150=>[[2, 1], [3, 2], [5, 2], [7, 1]], 3510=>[[2, 1], [3, 3], [5, 1], [13, 1]],
      #     4104=>[[2, 3], [3, 3], [19, 1]], 4305=>[[3, 1], [5, 1], [7, 1], [41, 1]],
      #     4625=>[[5, 3], [37, 1]], 4650=>[[2, 1], [3, 1], [5, 2], [31, 1]],
      #     4655=>[[5, 1], [7, 2], [19, 1]], 4998=>[[2, 1], [3, 1], [7, 2], [17, 1]],
      #     5880=>[[2, 3], [3, 1], [5, 1], [7, 2]], 6000=>[[2, 4], [3, 1], [5, 3]],
      #     6174=>[[2, 1], [3, 2], [7, 3]], 6545=>[[5, 1], [7, 1], [11, 1], [17, 1]],
      #     7098=>[[2, 1], [3, 1], [7, 1], [13, 2]], 7128=>[[2, 3], [3, 4], [11, 1]],
      #     7182=>[[2, 1], [3, 3], [7, 1], [19, 1]], 7650=>[[2, 1], [3, 2], [5, 2], [17, 1]],
      #     7791=>[[3, 1], [7, 2], [53, 1]], 7889=>[[7, 3], [23, 1]],
      #     7956=>[[2, 2], [3, 2], [13, 1], [17, 1]],
      #     9030=>[[2, 1], [3, 1], [5, 1], [7, 1], [43, 1]],
      #     9108=>[[2, 2], [3, 2], [11, 1], [23, 1]], 9295=>[[5, 1], [11, 1], [13, 2]],
      #     9324=>[[2, 2], [3, 2], [7, 1], [37, 1]]} 
    

    This calculation took approximately 0.15 seconds.

    For i = 6174

     (2**1) * (3**2) * (7**3) #=> 6174
    

    and

     1*(2**2) + 2*(3**2) + 3*(7**2) #=> 169 == 13*13 
    

提交回复
热议问题