Talk:Weird numbers: Difference between revisions

From Rosetta Code
Content added Content deleted
Line 20: Line 20:
[[User:Hout|Hout]] ([[User talk:Hout|talk]]) 11:52, 24 March 2019 (UTC)
[[User:Hout|Hout]] ([[User talk:Hout|talk]]) 11:52, 24 March 2019 (UTC)


: PS I think we may be able to see and test the operation of '''hasSum''' more clearly if we enrich its type from Bool to [Int] (with a return value of the empty list for '''False''', and the integers of the first sum found for '''True'''. Let's call this richer-typed variant '''anySum''', and sketch it in Python 3.
: PS I think we may be able to see and test the operation of '''hasSum''' more clearly if we enrich its type from Bool to [Int] (with a return value of the empty list for '''False''', and the integers of the first sum found for '''True'''). Let's call this richer-typed variant '''anySum''', and sketch it in Python 3.


::<lang python># anySum :: Int -> [Int] -> [Int]
::<lang python># anySum :: Int -> [Int] -> [Int]

Revision as of 13:59, 24 March 2019

A faster and less ambitious algorithm ?

I noticed yesterday that entries here were sparse.

Perhaps some were abandoned after first-sketch exhaustive searches appeared interminably slow ? And possibly the references to number theory in the Perl 6 founding example could look a bit daunting to some ?

Here is a theoretically unambitious approach, which seems, for example, to compress the (functionally composed) Python version down to c. 300 ms for 50 weirds (about half that for 25 weirds), on a system which needs c. 24 seconds to find 25 weirds with the initial Perl 6 draft.

  1. Choose a smaller target for the sum-search.
  2. Use a recursive hasSum(target, divisorList) predicate which fails early.
  3. Generate the properDivisors in descending order of magnitude.


A smaller target should, I think, involve a smaller number of possible sums. The obvious candidate in an abundant number is the difference between the sum of the proper divisors and the number considered. If a sum to that difference exists, then removing the participants in the smaller sum will leave a set which sums to the abundant number itself.

For possible early-failing implementations of hasSum, see the Python, Haskell, JavaScript and even AppleScript drafts.

If hasSum considers large divisors first, it can soon exclude all those those too big to sum to a smaller target. Hout (talk) 11:52, 24 March 2019 (UTC)

PS I think we may be able to see and test the operation of hasSum more clearly if we enrich its type from Bool to [Int] (with a return value of the empty list for False, and the integers of the first sum found for True). Let's call this richer-typed variant anySum, and sketch it in Python 3.
<lang python># anySum :: Int -> [Int] -> [Int]

def anySum(n, xs):

   First subset of xs found to sum to n.
      (Probably more efficient where xs is sorted in descending
      order of magnitude)
   def go(n, xs):
       if xs:
           # Assumes Python 3 for list deconstruction
           # Otherwise: h, t = xs[0], xs[1:]
           h, *t = xs
           if n < h:
               return go(n, t)
           else:
               if n == h:
                   return [h]
               else:
                   ys = go(n - h, t)
                   return [h] + ys if ys else go(n, t)
       else:
           return []
   return go(n, xs)


print(anySum(7, [1,1,1,1,1,6]))

  1. -> [1, 6]

print(anySum(7, [6, 3]))

  1. -> []</lang>