Skip to content

Instantly share code, notes, and snippets.

@plammens
Created May 20, 2023 09:22
Show Gist options
  • Save plammens/da85ee64d47cba9f8e39eb82894ed437 to your computer and use it in GitHub Desktop.
Save plammens/da85ee64d47cba9f8e39eb82894ed437 to your computer and use it in GitHub Desktop.
Number of ways to cut pizza into identical-shaped pieces such that some do not touch the centre.
import itertools
import math
import typing
from collections import Counter
from sympy import factorint
def submultisets(multiset: Counter) -> typing.Iterable[Counter]:
for counts in itertools.product(*[range(count + 1) for count in multiset.values()]):
yield Counter({element: count for element, count in zip(multiset, counts)})
def factors_to_number(factors: Counter) -> int:
return math.prod(factors.elements())
def parker_ways_to_cut_pizza(pieces: int):
assert pieces % 2 == 0, "The number of pieces must be even."
factors = Counter(factorint(pieces))
del factors[2] # We can only make odd-sized grins.
for submultiset in submultisets(factors):
grin_size = factors_to_number(submultiset)
number_of_grins = 2 * grin_size
pieces_per_grin = pieces // number_of_grins
# A 1-grin doesn't exist (or is a circle), and we need to cut each grin in more
# than one piece so that some of them do not touch the centre (Parker cut).
if grin_size == 1 or pieces_per_grin == 1:
continue
print(
f"{number_of_grins} {grin_size}-grins cut into {pieces_per_grin} pieces each"
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment