1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 from random import randrange, shuffle, choice
17
18
20
22 self.config = config
23 self.numpieces = numpieces
24 self.interests = [range(numpieces)]
25 self.pos_in_interests = range(numpieces)
26 self.numinterests = [0] * numpieces
27 self.have = [False] * numpieces
28 self.crosscount = [numpieces]
29 self.started = []
30 self.seedstarted = []
31 self.numgot = 0
32 self.scrambled = range(numpieces)
33 shuffle(self.scrambled)
34
36 numint = self.numinterests[piece]
37 self.crosscount[numint + self.have[piece]] -= 1
38 self.numinterests[piece] += 1
39 try:
40 self.crosscount[numint + 1 + self.have[piece]] += 1
41 except IndexError:
42 self.crosscount.append(1)
43 if self.have[piece]:
44 return
45 if numint == len(self.interests) - 1:
46 self.interests.append([])
47 self._shift_over(piece, self.interests[numint], self.interests[numint + 1])
48
50 numint = self.numinterests[piece]
51 self.crosscount[numint + self.have[piece]] -= 1
52 self.numinterests[piece] -= 1
53 self.crosscount[numint - 1 + self.have[piece]] += 1
54 if self.have[piece]:
55 return
56 self._shift_over(piece, self.interests[numint], self.interests[numint - 1])
57
59 p = self.pos_in_interests[piece]
60 l1[p] = l1[-1]
61 self.pos_in_interests[l1[-1]] = p
62 del l1[-1]
63 newp = randrange(len(l2) + 1)
64 if newp == len(l2):
65 self.pos_in_interests[piece] = len(l2)
66 l2.append(piece)
67 else:
68 old = l2[newp]
69 self.pos_in_interests[old] = len(l2)
70 l2.append(old)
71 l2[newp] = piece
72 self.pos_in_interests[piece] = newp
73
75 if piece not in self.started:
76 self.started.append(piece)
77 if seed and piece not in self.seedstarted:
78 self.seedstarted.append(piece)
79
81 assert not self.have[piece]
82 self.have[piece] = True
83 self.crosscount[self.numinterests[piece]] -= 1
84 try:
85 self.crosscount[self.numinterests[piece] + 1] += 1
86 except IndexError:
87 self.crosscount.append(1)
88 self.numgot += 1
89 l = self.interests[self.numinterests[piece]]
90 p = self.pos_in_interests[piece]
91 l[p] = l[-1]
92 self.pos_in_interests[l[-1]] = p
93 del l[-1]
94 try:
95 self.started.remove(piece)
96 self.seedstarted.remove(piece)
97 except ValueError:
98 pass
99
100 - def next(self, havefunc, seed = False):
101 bests = None
102 bestnum = 2 ** 30
103 if seed:
104 s = self.seedstarted
105 else:
106 s = self.started
107 for i in s:
108 if havefunc(i):
109 if self.numinterests[i] < bestnum:
110 bests = [i]
111 bestnum = self.numinterests[i]
112 elif self.numinterests[i] == bestnum:
113 bests.append(i)
114 if bests:
115 return choice(bests)
116 if self.numgot < self.config['rarest_first_cutoff']:
117 for i in self.scrambled:
118 if havefunc(i):
119 return i
120 return None
121 for i in xrange(1, min(bestnum, len(self.interests))):
122 for j in self.interests[i]:
123 if havefunc(j):
124 return j
125 return None
126
128 return self.numgot == self.numpieces
129
130 - def bump(self, piece):
131 l = self.interests[self.numinterests[piece]]
132 pos = self.pos_in_interests[piece]
133 del l[pos]
134 l.append(piece)
135 for i in range(pos,len(l)):
136 self.pos_in_interests[l[i]] = i
137 try:
138 self.started.remove(piece)
139 self.seedstarted.remove(piece)
140 except ValueError:
141 pass
142