- Thu 07 November 2019
- analysis
- Christophe
- #Python
Question: How many stickers do you need to buy to complete a Panini album ?¶
Panini stickers album are famous ( especially during soccer world cup ) in many school yard, where multiple exchange of duplicate are taking place in order to achieve the evasive completion of an album. I am not sure I have ever been able to complete fully an album when I was a kid. This bring the question, what does it takes to be able to complete an album. First we will look at it without the possibility of exchange between collectors. Off course now as a parent the number of packet needed to purchase reveals the sad reality of cost.
# N total number of stickers in the album
N = 662
import math
import matplotlib.pyplot as plt
class album:
def __init__(self, Nstickers):
# Album start empty. making it private
self.__album = {i:0 for i in range(1,Nstickers+1)}
self.__Nstickers = Nstickers
def addSticker(self,sticker_number):
if sticker_number <= self.__Nstickers:
self.__album[sticker_number] += 1
else:
print("Not a valid number.")
def isAlbumFull(self):
return all([v >= 1 for v in self.__album.values()])
def countGot(self):
return sum([v >= 1 for v in self.__album.values()])
def duplicates(self):
return sum([v > 1 for v in self.__album.values()])
def display(self):
plt.plot([self.__album[n] for n in self.__album.keys()])
plt.ylabel('Sticker Count')
plt.xlabel('Sticker Number')
plt.show()
import random
def packet(Sticker_in_packet = 5, Nalbum=N):
return random.sample(range(1,Nalbum+1), k=Sticker_in_packet)
a = album(N)
print(a.isAlbumFull(),a.countGot(),a.duplicates())
False 0 0
def fill_album(album,limit=50):
packet_bought = 0
tracker = []
while not album.isAlbumFull():
packet_bought += 1
for card in packet():
album.addSticker(card)
tracker.append([album.countGot(),album.duplicates(),album.isAlbumFull()])
if album.countGot() - N < limit:
#print('INFO can buy the remaining',packet_bought)
if packet_bought > N*10:
return tracker
return tracker
t = fill_album(a)
t[-1]
[662, 647, True]
def plot_tracker(tracker):
plt.figure()
plt.subplot(211)
plt.plot([y[0] for y in tracker])
plt.axhline(y=N-50,linewidth=4, color='r')
plt.ylabel('Sticker filled')
plt.xlabel('number of packet bought')
plt.subplot(212)
plt.plot([y[1] for y in tracker])
plt.ylabel('Duplicates')
plt.xlabel('number of packet bought')
plt.show()
def plot_filled(tracker):
plt.plot([y[0] for y in tracker])
plt.axhline(y=N-50,linewidth=4, color='r')
plt.ylabel('Sticker filled')
plt.xlabel('number of packet bought')
plt.show()
def plot_duplicate(tracker):
plt.plot([y[1] for y in tracker])
plt.ylabel('Duplicates')
plt.xlabel('number of packet bought')
plt.show()
plot_filled(t)
The red line indicate the thresold you need to reach to be able to buy directly from Panini the missing cards. The company only allow you to purchase a limited number of individually chosen cards (usually 50). That is about 320 packets in our example !!! It is true that after that the completion become really hard.
plot_duplicate(t)
plot_tracker(t)
a.display()
#Monte Carlo
n_monte_carlo = 500
y1 = []
y2 = []
for i in range(n_monte_carlo):
am = album(N)
t = fill_album(am)
y1.append(len(t))
y2.append(t[-1])
plt.plot(y1)
plt.ylabel('how many bought')
plt.xlabel('MONTE Carlo runs')
plt.show()
print("Average",sum(y1)/len(y1),"Max",max(y1),"Min",min(y1))
Average 949.922 Max 1565 Min 628
y_dup = [yy[1] for yy in y2]
print("Mean",sum(y_dup)/len(y_dup))
Mean 655.518
print("Max duplicates",max(y_dup),"Min duplicates",min(y_dup))
Max duplicates 661 Min duplicates 633
See below in the links few article which examined the problem.