From: Bryan on
I wrote:
> > I came up with a recursive memo-izing algorithm that
> > handles 100-digit n's.

Oops. I missed Richard Thomas's post. He posted the same algorithm a
couple days before.


--
--Bryan
From: Albert van der Horst on
In article <4bf442cd$0$31377$4fafbaef(a)reader1.news.tin.it>,
superpollo <utente(a)esempio.net> wrote:
>... how many positive integers less than n have digits that sum up to m:
>
>In [197]: def prttn(m, n):
> tot = 0
> for i in range(n):
> s = str(i)
> sum = 0
> for j in range(len(s)):
> sum += int(s[j])
> if sum == m:
> tot += 1
> return tot
> .....:
>
>In [207]: prttn(25, 10000)
>Out[207]: 348
>
>any suggestion for pythonizin' it?

I don't like the excursion to string and back.

def x(i) : return x(i/10)+i%10 if i else 0

or if you can't stand recursion:

def x(i):
s= 0
while i:
s += i%10
i /= 10
return s

(All untested but you get the idea.)

>
>bye


--
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert(a)spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

From: Lie Ryan on
On 05/26/10 11:04, Bryan wrote:
> Jean-Michel Pichavant wrote:
>> I still don't see "how many positive integers less than n have digits
>> that sum up to m" makes it a "partition" though if that what prttn
>> means. Surely because I miss the context.
>
> A partition of a positive integer m is an unordered collection of
> positive integers that sum to m. [1, 1, 2, 5] is a partition of 9. The
> problem at issue here is not that of counting partitions.
>
> My algorithm for our prttn separated out the 'ndsums' sub-problem:
> Count d-digit ints with digits summing to m. I found a generalization
> of that problem stated in the /CRC Handbook of Discrete and
> Combinatorial Mathematics/ (2000 edition, section 2.1) among "counting
> problems" as:
>
> Solutions to x_1 + ... x_n = k
> 0 <= x_i <= a_i for one or more i
>
> Alas, the handbook does not provide a formula or algorithm. It refers
> to the inclusion/exclusion principle, which I did not see how to turn
> into an efficient algorithm.

superpollo posted this question in comp.programming
(http://groups.google.com/group/comp.programming/browse_thread/thread/e3b10346db8ebd0a/579ca67f8b9b5a8c;
http://groups.google.com/group/comp.programming/msg/f7323d6e6942e883;
http://groups.google.com/group/comp.programming/browse_thread/thread/e3b10346db8ebd0a/dc4cd1e2feb89500
)

I went through the mathematical foundation of using
partition/distribution and inclusion-exclusion, and have written some
code that solves a subset of the problem, feel free if you or superpollo
are interested in continuing my answer (I won't be able to continue it
until next week, have been a little bit busy here)


copying the code here for convenience:

# memoization would be very useful here
def fact(n):
""" factorial function (i.e. n! = n * (n-1) * ... * 2 * 1) """
return n * fact(n - 1) if n != 0 else 1

def C(n, r):
""" regular Combination (nCr) """
return fact(n) / (fact(n - r) * fact(r))

def D(M, N):
""" Distribution aka Partitioning """
return C(M + N - 1, M)

def partition10(M, i):
""" Count how many integer < N sums to M where N = 10**int(i) """
s = 0
sign = 1
for j in range(i + 1):
s += sign * D(M, i) * C(i, j)

# flip the sign for inclusion-exclusion
sign *= -1

# if M = 32, then 32, 22, 12, 2, -8
M -= 10
return s

# still need to write:
# def partitionN10(...): -- applies a "restriction"/"boundary" to
# the most significant digit
# then make it recurse.

# assuming factorials calculation is constant time (hint: memoization)
# the resulting code should work in O(n**2)
# an improvement over the naive method which is O(10**n)
# where n is the number of digits in N
# DISCLAIMER: the big-O is a quick guess, not really calculated
From: Albert van der Horst on
In article <l3172q.b4n(a)spenarnc.xs4all.nl>,
Albert van der Horst <albert(a)spenarnc.xs4all.nl> wrote:
>In article <4bf442cd$0$31377$4fafbaef(a)reader1.news.tin.it>,
>superpollo <utente(a)esempio.net> wrote:
>>... how many positive integers less than n have digits that sum up to m:
>>
>>In [197]: def prttn(m, n):
>> tot = 0
>> for i in range(n):
>> s = str(i)
>> sum = 0
>> for j in range(len(s)):
>> sum += int(s[j])
>> if sum == m:
>> tot += 1
>> return tot
>> .....:
>>
>>In [207]: prttn(25, 10000)
>>Out[207]: 348
>>
>>any suggestion for pythonizin' it?
>
>I don't like the excursion to string and back.
>
>def x(i) : return x(i/10)+i%10 if i else 0

Can't be made to work easily.

>
>or if you can't stand recursion:
>
>def x(i):
> s= 0
> while i:
> s += i%10
> i /= 10
> return s

The above doesn't work.

This one has been tested:

"
def x(i):
s= 0
while i:
s *= 10
s += i%10
i /= 10
return s
"
(With as loop-invariant the concatenation of i and reversed-s
and as loop-variant i)

Groetjes Albert

--
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert(a)spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

From: Bryan on
Lie Ryan wrote:
> I went through the mathematical foundation of using
> partition/distribution and inclusion-exclusion, and have written some
> code that solves a subset of the problem, feel free if you or superpollo
> are interested in continuing my answer (I won't be able to continue it
> until next week, have been a little bit busy here)
>
> copying the code here for convenience:
>
> # memoization would be very useful here
> def fact(n):
>     """ factorial function (i.e. n! = n * (n-1) * ... * 2 * 1) """
>     return n * fact(n - 1) if n != 0 else 1
>
> def C(n, r):
>     """ regular Combination (nCr) """
>     return fact(n) / (fact(n - r) * fact(r))
>
> def D(M, N):
>     """ Distribution aka Partitioning """
>     return C(M + N - 1, M)
>
> def partition10(M, i):
>     """ Count how many integer < N sums to M where N = 10**int(i) """
>     s = 0
>     sign = 1
>     for j in range(i + 1):
>         s += sign * D(M, i) * C(i, j)
>
>         # flip the sign for inclusion-exclusion
>         sign *= -1
>
>         # if M = 32, then 32, 22, 12, 2, -8
>         M -= 10
>     return s

It doesn't seem to work. I get no answer at all, because it recursion-
loops out when it calls fact() with a negative integer.

--
--Bryan