Skip to content

Instantly share code, notes, and snippets.

@TheArcherST
Last active December 14, 2021 20:33
Show Gist options
  • Save TheArcherST/84eca0ac91a889fb3d3c86dc2eb1faa5 to your computer and use it in GitHub Desktop.
Save TheArcherST/84eca0ac91a889fb3d3c86dc2eb1faa5 to your computer and use it in GitHub Desktop.
Code to estimate your test results
"""
This program helps you to evaluate you test results
```input.md
1. .
2. ?
3.
4.
5. ?
```
Here i said that i totally know answer on first question,
don't know answers on 2 and 5, and know possible answer
on 3 and 4.
You can change constatnts in following vars and classes
Without script, you can approximately estimate it:
`Count of unknown` / `Answers in question` / `Total questions`
"""
import abc
import typing
from dataclasses import dataclass
from tabulate import tabulate
# ====== CONSTATNTS ========
FILE_NAME = 'input.md'
ANSWERS_IN_QUESTION = 4
class StatusEstimates:
MAYBE = 0.6
RIGHT = 0.9
RANDOM = 1 / ANSWERS_IN_QUESTION
class TokenType:
NUMBER = 'NUMBER'
DOT = 'DOT'
EOF = 'EOF'
STATUS = 'STATUS'
# ==========================
@dataclass
class Token:
type: str
value: str
class Lexer:
def __init__(self, text: str):
self.text = text
def iterator(self):
text = self.normalize_text(self.text)
for i in text.split(' '):
yield self._token_factory(i)
@staticmethod
def normalize_text(text: str):
def unplug(literals: list[str], text_: str):
for literal in literals:
text_ = text_.replace(literal, f' {literal} ')
return text_
# if operators concatenated to id, will be unplugged
# but can be generated double spaces
text = unplug(['.', '?'], text)
# rm all double spaces
while text.find(' ') != -1:
text = text.replace(' ', ' ')
return text
@staticmethod
def _token_factory(literal: str):
if literal == '.':
type_ = TokenType.DOT
elif literal.isnumeric():
type_ = TokenType.NUMBER
elif literal in ('?',):
type_ = TokenType.STATUS
elif literal == '':
type_ = TokenType.EOF
else:
raise KeyError(f"Unknown token: `{literal}`")
return Token(type_, literal)
class BaseInterpreter:
def __init__(self, text: str):
self.tokens_iterator = Lexer(text).iterator()
self.current_token = Token(TokenType.EOF, '')
self.previous_token = Token(TokenType.EOF, '')
self._next_token()
def _next_token(self):
self.previous_token = self.current_token
try:
self.current_token = self.tokens_iterator.__next__()
except StopIteration:
self.current_token = Token(TokenType.EOF, '')
return self.current_token
def eat(self, *token_types: str):
if self.check(*token_types):
self._next_token()
return self.previous_token
else:
raise SyntaxError(f'excepted token(-s): {token_types}, but `{self.current_token}` got')
def check(self, *token_types: str) -> bool:
return self.current_token.type in token_types
@abc.abstractmethod
def expr(self):
pass
@dataclass
class ExprResult:
question_number: int
literal: str
value: float
class Interpreter(BaseInterpreter):
def expr(self) -> ExprResult:
if self.current_token.type == TokenType.NUMBER:
question_number = int(self.eat(TokenType.NUMBER).value)
self.eat(TokenType.DOT)
status = self.current_token.value
self.eat(TokenType.EOF, TokenType.DOT, TokenType.STATUS)
lib = {
'': StatusEstimates.MAYBE,
'.': StatusEstimates.RIGHT,
'?': StatusEstimates.RANDOM
}
try:
result = lib[status]
except KeyError:
raise RuntimeError('Interpreter: unknown status, please, check lexer.')
return ExprResult(question_number, status, result)
def run(text: str) -> list[ExprResult]:
results = []
lines = text.split('\n')
for i in lines:
interpreter = Interpreter(i)
res = interpreter.expr()
results.append(res)
return results
def get_comment(assumed_value: float):
if assumed_value < 40:
result = "You will don't pass it. Try to resolve most bad-answered questions"
elif assumed_value < 50:
result = 'Bad. Try to resolve most bad-answered questions'
elif assumed_value < 60:
result = 'I think you pass it, but try resolve more questions'
elif assumed_value < 70:
result = 'Good! But not great. Try resolve more questions'
elif assumed_value < 90:
result = 'Great! You can finish work. Really good.'
elif assumed_value < 96:
result = 'Just awesome!'
else:
raise ValueError(f"Can't estimate assumed_value `{assumed_value}`")
return result
def main():
with open(FILE_NAME) as fs:
text = fs.read()
results = run(text)
percentage = sum([i.value for i in results]) / len(results) * 100
random_answers = filter(lambda x: x.literal == '?', results)
maybe_answers = filter(lambda x: x.literal == '', results)
def to_q_numbers(results__: typing.Iterable[ExprResult]) -> list[int]:
result = []
for i in results__:
result.append(i.question_number)
return result
random_answers = to_q_numbers(random_answers)
maybe_answers = to_q_numbers(maybe_answers)
print(f'Assumed value: {round(percentage, 2)}%\n')
print(get_comment(percentage))
print()
print(tabulate(zip(random_answers, maybe_answers),
('random', 'maybe')))
print()
print('That answers on what you can think')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment