-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinsert.py
More file actions
executable file
·112 lines (86 loc) · 3.72 KB
/
insert.py
File metadata and controls
executable file
·112 lines (86 loc) · 3.72 KB
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
from inspect import isfunction
class InsertMixin(object):
def insert_keys(self, *chars):
"""Insert am args iterable of items (chars).
Return new "hots", "matches", and "drops"
"""
drops, matches, new_hots = set(), set(), set()
update = lambda x,y:x.update(set(y))
as_tuples = lambda *v: tuple(tuple(x) for x in v)
for c in chars:
hots, _matches, _drops = self.insert_key(c)
update(new_hots, hots)
update(matches, _matches)
update(drops, _drops)
return as_tuples(new_hots, matches, drops)
# def tick_sleeping(self):
# """Increment all sleeping positions by 1 until the value reaches -1"""
# table = self.table
# for table_id, pos in table.items():
# if pos >= -1: continue
# print('Tick', table_id, pos +1)
# table[table_id] = pos + 1
def insert_key(self, char, reset_on_fail=True):
matches = ()
resets = ()
table = self.table
_hots = self.set_next_hots(char)
# self.tick_sleeping()
for table_id, pos in table.items():
## Testing for -1 assumes the hot starts have stepped any active
# sequence to 0.
if pos <= -1: continue
success, res = self._test_insert_key(char, table_id, pos, table)
if not success:
if reset_on_fail:
# seq = self.get_sequence(table_id)
# pos = table[table_id]
table[table_id] = -1 # -(len(seq[pos:])-1)
resets += res
continue
_matches, t_values = res
table.update(t_values)
# for _table_id, t_value in _matches:
# # table[_table_id] = t_value
# matches += (_table_id,)
matches += tuple(x[0] for x in _matches)
return _hots, matches, resets
def _test_insert_key(self, char, table_id, pos, table):
seq = self.get_sequence(table_id)
index_match = self._test_index_match(seq, pos, char, table_id)
if index_match == 0:
return False, (table_id, )
return True, self._position_match(table, table_id, index_match, seq, char)
def _test_index_match(self, seq, pos, char, table_id):
"""assert if the seq[pos] == char. Return the integer of the match as
0 or 1
"""
try:
table_position = seq[pos]
except IndexError:
# The position is past the edge of the given sequence
# This occurs when a key completes (has matched)
# print('IndexError for', pos, 'on', table_id)
index_match = seq[0] == char
return int(index_match)
index_match = table_position == char
if isfunction(table_position):
index_match = table_position(char)
return int(index_match)
def _position_match(self, table, table_id, index_match, seq, char):
# The given char does match the current sequence position,
# advance the index (usually by 1) and test for a completion
# match.
matches = ()
t_value = table[table_id] + int(index_match)
len_match = t_value >= len(seq)
item = (table_id, t_value)
if len_match:
# table[table_id] = int(seq[0] == char)
t_value = int(seq[0] == char)
item = (table_id, t_value)
# A sequence is complete, present a match,
matches = (item,)
# becomes `table[table_id] = t_value`
table_updates = (item,)
return matches, table_updates