-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtestlib.py
134 lines (108 loc) · 3.59 KB
/
testlib.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
125
126
127
128
129
130
131
132
133
134
import sys
import re
import string
LF = '\n'
CR = '\r'
SPACE = ' '
TAB = '\t'
EOLNS = "\n\r"
WHITESPACES = " \t" + EOLNS
intregex = r"^-?[1-9]\d*|0$"
intpattern = re.compile(intregex)
def strictInt(x: str, lo=None, hi=None) -> int:
res = int(x)
if not intpattern.match(x):
raise Exception("Invalid integer")
if lo is not None and res < lo:
raise Exception("Integer less than lo bound")
if hi is not None and res > hi:
raise Exception("Integer greater than hi bound")
return res
def isBlank(c):
return c in WHITESPACES
def isEoln(c):
return c in EOLNS
class validator:
def __init__(self, string=None, strict=True):
self.idx = 0
if string is None:
string = sys.stdin.read()
self.string = string
self.strict = strict
def peekChar(self):
if self.idx == len(self.string):
raise Exception("Unexpected EOF")
return self.string[self.idx]
def readChar(self, c=None):
ch = self.peekChar()
if c is not None and ch!=c:
raise Exception("Unexpected character")
self.idx += 1
return ch
def readOptional(self, c):
try:self.readChar(c)
except:pass
def readSpace(self):
return self.readChar(' ')
def unreadChar(self):
self.idx -= 1
def skipBlanks(self):
while not self.isEOF() and isBlank(self.peekChar()):
self.idx += 1
def readUntil(self, endF, regex=None):
chars = []
c = self.peekChar()
if endF(c):
raise Exception("Unexpected read termination - expected something")
while not endF(c):
chars.append(c)
self.idx += 1
if self.idx >= len(self.string):
break
c = self.peekChar()
res = ''.join(chars)
if regex is not None:
pattern = re.compile(regex)
if not pattern.match(res):
raise Exception("Result does not match pattern")
return res
def readToken(self, regex=None):
if not self.strict:
self.skipBlanks()
return self.readUntil(isBlank, regex)
def readLine(self, regex=None):
return self.readUntil(isEoln, regex)
def readString(self, regex=None):
return self.readLine(regex)
def readWord(self, regex=None):
return self.readToken(regex)
def readInt(self, L=None, R=None):
return strictInt(self.readToken(), L, R)
def readLong(self, L=None, R=None):
return self.readInt(L=None, R=None)
def readInteger(self, L=None, R=None):
return self.readInt(L=None, R=None)
def readInts(self, n, L=None, R=None):
res = []
if n > 0:res.append(self.readInt(L,R))
for i in range(1,n):
self.readSpace()
res.append(self.readInt(L,R))
return res
def readIntegers(self, *args, **kwargs):
return self.readInts(*args, **kwargs)
def readLongs(self, *args, **kwargs):
return self.readInts(*args, **kwargs)
def readEoln(self):
if self.string[self.idx]=='\r':
self.idx += 1
if self.string[self.idx]!='\n':
raise Exception("Expected Eoln")
self.idx += 1
def isEOF(self):
return self.idx == len(self.string)
def readEOF(self):
if not self.strict:
self.skipBlanks()
if not self.isEOF():
raise Exception("Expected EOF")