mirror of
https://github.com/InternLM/InternBootcamp.git
synced 2026-04-24 17:05:00 +00:00
init-commit
This commit is contained in:
commit
18a552597a
3461 changed files with 1150579 additions and 0 deletions
163
internbootcamp/libs/wordladder/interactive.py
Executable file
163
internbootcamp/libs/wordladder/interactive.py
Executable file
|
|
@ -0,0 +1,163 @@
|
|||
from libs.wordladder.solving.puzzle import Puzzle
|
||||
from libs.wordladder.solving.solver import Solver
|
||||
from libs.wordladder.words.dictionary import Dictionary
|
||||
from libs.wordladder.words.word import Word
|
||||
from time import perf_counter
|
||||
|
||||
|
||||
APP_NAME = "WordLadder"
|
||||
PROMPT_PREFIX = APP_NAME + "> "
|
||||
MINIMUM_WORD_LENGTH = 2
|
||||
MAXIMUM_WORD_LENGTH = 15
|
||||
MINIMUM_LADDER_LENGTH = 1
|
||||
MAXIMUM_LADDER_LENGTH = 20
|
||||
|
||||
STEPS = [
|
||||
"Enter start word: ",
|
||||
"Enter final word: ",
|
||||
'Maximum ladder length? [%d-%d, or return]: ' % (MINIMUM_LADDER_LENGTH, MAXIMUM_LADDER_LENGTH)
|
||||
]
|
||||
|
||||
|
||||
class Interactive(object):
|
||||
def __init__(self, args):
|
||||
# not using these yet
|
||||
self.args = args
|
||||
self.on_step: int = 0
|
||||
self.dictionary: Dictionary = None
|
||||
self.dictionary_load_time: int = 0
|
||||
self.start_word: Word = None
|
||||
self.end_word: Word = None
|
||||
self.maximum_ladder_length: int = -1
|
||||
|
||||
|
||||
|
||||
def run(self):
|
||||
again = True
|
||||
while again:
|
||||
while self.on_step < len(STEPS):
|
||||
self._process_input()
|
||||
self.on_step = 0
|
||||
self._solve()
|
||||
print()
|
||||
|
||||
# 无须手动again
|
||||
# inp = input('%sRun again? [y/n]: ' % PROMPT_PREFIX)
|
||||
# again = inp == "y" or inp == "Y"
|
||||
# print()
|
||||
|
||||
def _process_input(self):
|
||||
inp = input('%s%s' % (PROMPT_PREFIX, STEPS[self.on_step]))
|
||||
ok = False
|
||||
if self.on_step == 0:
|
||||
ok = self._set_start_word(inp)
|
||||
elif self.on_step == 1:
|
||||
ok = self._set_end_word(inp)
|
||||
elif self.on_step == 2:
|
||||
ok = self._set_maximum_ladder_length(inp)
|
||||
if ok:
|
||||
self.on_step += 1
|
||||
|
||||
def _set_start_word(self, inp: str) -> bool:
|
||||
if len(inp) < MINIMUM_WORD_LENGTH or len(inp) > MAXIMUM_WORD_LENGTH:
|
||||
print(red(' Please enter a word with between %d and %d characters' % (MINIMUM_WORD_LENGTH, MAXIMUM_WORD_LENGTH)))
|
||||
return False
|
||||
self._load_dictionary(len(inp))
|
||||
self.start_word = self._validate_word(inp)
|
||||
return self.start_word is not None
|
||||
|
||||
def _set_end_word(self, inp: str) -> bool:
|
||||
if len(inp) != self.dictionary.word_length:
|
||||
print(red(" Final word length must match start word length!"))
|
||||
return False
|
||||
self.end_word = self._validate_word(inp)
|
||||
return self.end_word is not None
|
||||
|
||||
def _validate_word(self, inp: str) -> Word or None: # type: ignore
|
||||
word: Word = self.dictionary[inp]
|
||||
if word is None:
|
||||
print(red(' Word \'%s\' does not exist!' % inp))
|
||||
return
|
||||
elif word.is_island:
|
||||
print(red(' Word \'%s\' is an island word (cannot change single letter to form another word)' % inp))
|
||||
return
|
||||
return word
|
||||
|
||||
def _set_maximum_ladder_length(self, inp: str) -> bool:
|
||||
if len(inp) == 0:
|
||||
print(green(" No answer - assuming auto calc of minimum ladder length"))
|
||||
self.maximum_ladder_length = -1
|
||||
return True
|
||||
try:
|
||||
inp_int = int(inp)
|
||||
if inp_int < MINIMUM_LADDER_LENGTH or inp_int > MAXIMUM_LADDER_LENGTH:
|
||||
raise TypeError
|
||||
self.maximum_ladder_length = inp_int
|
||||
return True
|
||||
except TypeError:
|
||||
print(red(' Invalid input (please enter a integer between %d and %d)' % (MINIMUM_LADDER_LENGTH, MAXIMUM_LADDER_LENGTH)))
|
||||
return False
|
||||
|
||||
def _load_dictionary(self, word_length: int):
|
||||
start = perf_counter()
|
||||
self.dictionary = Dictionary(word_length)
|
||||
self.dictionary_load_time = (perf_counter() - start) * 1000
|
||||
|
||||
def _solve(self):
|
||||
print('Took %s to load dictionary' % green('%.2fms' % self.dictionary_load_time))
|
||||
puzzle = Puzzle(self.start_word, self.end_word)
|
||||
if self.maximum_ladder_length == -1:
|
||||
start = perf_counter()
|
||||
min_ladder = puzzle.calculate_minimum_ladder_length()
|
||||
took = (perf_counter() - start) * 1000
|
||||
if min_ladder is None:
|
||||
print(red('Cannot solve \'%s\' to \'%s\' (took %.2fms to determine that)' % (self.start_word, self.end_word, took)))
|
||||
return
|
||||
self.maximum_ladder_length = min_ladder
|
||||
print('Took %s to determine minimum ladder length of %s' % (green('%.2fms' % took), green('%d' % min_ladder)))
|
||||
solver = Solver(puzzle)
|
||||
start = perf_counter()
|
||||
solutions = solver.solve(self.maximum_ladder_length)
|
||||
took = (perf_counter() - start) * 1000
|
||||
if len(solutions) == 0:
|
||||
print(red('Took %.2fms to find no solutions (explored %d solutions)' % (took, solver.explored_count)))
|
||||
return
|
||||
print('Took %s to find %s solutions (explored %s solutions)'
|
||||
% (green('%.2fms' % took), green(len(solutions)), green(solver.explored_count)))
|
||||
self._display_solutions(solutions)
|
||||
|
||||
def _display_solutions(self, solutions):
|
||||
solutions.sort()
|
||||
page_start: int = 0
|
||||
length: int = len(solutions)
|
||||
while page_start < (length - 1):
|
||||
inp = input(
|
||||
'%sList%s solutions? (Enter \'n\' for no, \'y\' or return for next 10, \'all\' for all or how many): '
|
||||
% (PROMPT_PREFIX, " more" if page_start > 0 else ""))
|
||||
limit = 10
|
||||
if inp == "n" or inp == "N":
|
||||
return
|
||||
elif inp == "all":
|
||||
limit = length
|
||||
elif len(inp) > 0 and inp != "y" and inp != "Y":
|
||||
try:
|
||||
inp_int = int(inp)
|
||||
if inp_int > 0:
|
||||
limit = inp_int
|
||||
except TypeError:
|
||||
limit = 10
|
||||
for page_start in range(page_start, min(page_start + limit, length)):
|
||||
print('%d/%d %s' % (page_start + 1, length, green(solutions[page_start])))
|
||||
|
||||
|
||||
TERMINAL_COLOUR_RED = "\u001b[31m"
|
||||
TERMINAL_COLOUR_GREEN = "\u001b[32m"
|
||||
TERMINAL_COLOUR_BLACK = "\u001b[0m"
|
||||
|
||||
|
||||
def green(msg):
|
||||
return TERMINAL_COLOUR_GREEN + str(msg) + TERMINAL_COLOUR_BLACK
|
||||
|
||||
|
||||
def red(msg):
|
||||
return TERMINAL_COLOUR_RED + str(msg) + TERMINAL_COLOUR_BLACK
|
||||
Loading…
Add table
Add a link
Reference in a new issue