In the Python library SymPy I try to understand the function partitions()
in sympy.utilities.iterables
:
It starts like this:
def partitions(n, m=None, k=None, size=False):
"""Generate all partitions of integer n (>= 0).
I am confused about the following while loop, because it looks pointless. If I remove the while 1:
and the break
it should make no difference. However, I expect that the people who develop SymPy know what they are doing, and don't make very simple mistakes. So does this make some sense that I fail to see?
while 1:
# Let i be the smallest key larger than 1. Reuse one instance of i.
i = keys[-1]
newcount = ms[i] = ms[i] - 1
reuse += i
if newcount == 0:
del keys[-1], ms[i]
room += 1
# Break the remainder into pieces of size i-1.
i -= 1
q, r = divmod(reuse, i)
need = q + bool(r)
if need > room:
if not keys:
return
continue
ms[i] = q
keys.append(i)
if r:
ms[r] = 1
keys.append(r)
break
For learning purposes I have simplified the whole function, and my_partitions(n)
gives the same results as partitions(n)
.
def my_partitions(n):
ms = {n: 1}
keys = [n]
yield ms
while keys != [1]:
# Reuse any 1's.
if keys[-1] == 1:
del keys[-1]
reuse = ms.pop(1)
else:
reuse = 0
# Let i be the smallest key larger than 1. Reuse one instance of i.
i = keys[-1]
ms[i] -= 1
reuse += i
if ms[i] == 0:
del keys[-1], ms[i]
# Break the remainder into pieces of size i-1.
i -= 1
q, r = divmod(reuse, i)
ms[i] = q
keys.append(i)
if r:
ms[r] = 1
keys.append(r)
yield ms
This is a dirty hack to bring goto to Python. The while 1:
line is the label and the continue
statement is the goto.
Please do not write code like that if you can avoid it. If you must do this, at least make it while True:
since the argument to while
is ordinarily a boolean value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With