-
Notifications
You must be signed in to change notification settings - Fork 2
/
fingeo.py
executable file
·124 lines (90 loc) · 2.77 KB
/
fingeo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# Finite geometry routines for dealing with the spaces:
# F_3^4 (standard tau)
# P_5 F_2 (projective tau)
# F_2^6 (boolean quadruple tau)
import itertools
def get_space(game_type):
if game_type == '3ptau':
return ProjectiveSpace()
elif game_type in ['bqtau', 'sbqtau']:
return BooleanSpace()
else:
return AffineSpace()
def all_vectors(p, n):
return list(itertools.product(*[range(p) for i in range(n)]))
class Space(object):
def sum_cards(self, cards):
return tuple([sum(zipped) % self.p for zipped in zip(*cards)])
def negate(self, card):
# Note that in Python, the % operator always returns a non-negative number.
return tuple(map(lambda x: (-x) % self.p, card))
def negasum(self, a, b):
return self.negate(self.sum_cards([a,b]))
# The space F_3^4.
class AffineSpace(Space):
COORDS = 4
def __init__(self):
self.p = 3
def all_points(self):
return all_vectors(3, 4)
def to_client_card(self, point):
if point is not None and len(point) != 4:
raise ValueError('Point length is %d (expected 4)' % len(point))
return point
def from_client_card(self, card):
if card is not None and len(card) != 4:
raise ValueError('Card length is %d (should be 4)' % len(card))
return card
# Methods and fields specific to AffineSpace.
SIZE = 3**4
def to_int(self, point):
ret = 0
for x in point:
ret = self.p * ret + x
return ret
def from_int(self, x):
ret = []
for i in range(self.COORDS):
ret.append(x % self.p)
x /= self.p
ret.reverse()
return tuple(ret)
# Routines for converting between boolean 6-tuples and 4-valued 3-tuples.
def binary_point_to_card(point):
if point is not None and len(point) != 6:
raise ValueError('Point length is %d (should be 6)' % len(point))
if point is None:
return None
return tuple([(2*point[2*i] + point[2*i+1]) for i in range(3)])
def card_to_binary_point(card):
if card is not None and len(card) != 3:
raise ValueError('Card length is %d (should be 3)' % len(card))
if card is None:
return None
point = []
for v in card:
point.append(v // 2)
point.append(v % 2)
return tuple(point)
# The space P_5 F_2.
class ProjectiveSpace(Space):
COORDS = 6
def __init__(self):
self.p = 2
def all_points(self):
return filter(any, all_vectors(2, 6))
def to_client_card(self, point):
return binary_point_to_card(point)
def from_client_card(self, card):
return card_to_binary_point(card)
# The space F_2^6.
class BooleanSpace(Space):
COORDS = 6
def __init__(self):
self.p = 2
def all_points(self):
return all_vectors(2, 6)
def to_client_card(self, point):
return binary_point_to_card(point)
def from_client_card(self, card):
return card_to_binary_point(card)