""" use least squares to estimate the time it takes for each move. to use this, you can start a cstimer session of M and U moves (3x3x3 substes -> roux generator) and time how much time it takes you to scramble each scramble. you can then export the session and paste the times to this script. this is experimenal and deosn't work very well """ from typing import List from dataclasses import dataclass from collections import Counter from typing import List, Dict import numpy as np from scipy.linalg import lstsq POSSIBLE_MOVES = {"M", "M2", "M'", "U", "U'", "U2"} @dataclass class Solve: scramble: List[str] time: float def multiline_input() -> List[str]: print("Enter/Paste your content. Ctrl-D or Ctrl-Z ( windows ) to save it.") contents = [] while True: try: line = input() except EOFError: break contents.append(line) return contents def parse_cstimer_session_solves(lines: List[str]) -> List[Solve]: solves = [] for line in lines: if line: parts = line.split() time = float(parts[1]) scramble = parts[2:] solves.append(Solve(time=time, scramble=scramble)) return solves def approximate_move_times(solves: List[Solve]) -> Dict[str, float]: times = [] move_counters = [] for solve in solves: times.append(solve.time) move_counter = Counter(solve.scramble) for move in POSSIBLE_MOVES: move_counter[move] = move_counter.get(move, 0) print(move_counter, solve.time) move_counters.append(list(move_counter.values())) x, _, _, _ = lstsq(move_counters, times) move_times = {} for i, move in enumerate(POSSIBLE_MOVES): move_times[move] = x[i] return move_times def main(): session_times_raw = multiline_input() solves = parse_cstimer_session_solves(session_times_raw) print(approximate_move_times(solves)) if __name__ == "__main__": main()