Compare commits

..

10 Commits

Author SHA1 Message Date
503e624b3f add 9 movers 2025-06-02 21:11:17 +03:00
6dd45363e7 buh 2025-05-31 21:14:03 +03:00
074878ee9f change settings 2024-09-12 17:05:53 +03:00
e3b065ff53 this never worked lol 2024-08-31 10:18:44 +03:00
acf43781b2 add custom regrip for F floating 2024-08-30 20:52:24 +03:00
0a1c25460e U2' feido 2024-08-25 20:29:19 +03:00
cebfd1a5bf rewrite the config format 2024-08-24 22:21:33 +03:00
473adc64b8 add blacklisting 2024-08-24 18:11:59 +03:00
f012c0536f add basic regrip times 2024-08-24 14:13:01 +03:00
50ceb636de add move approx 2024-08-24 13:48:36 +03:00
11 changed files with 913 additions and 226 deletions

View File

@ -13,17 +13,17 @@ from dataclasses import dataclass
from solver import EOLRBSolution, solve_eolrb, create_eolrb_prune_table
from scorer import (
FingerTrickWithRegrip,
load_config,
load_definitions,
generate_finger_tricks,
build_pretty_string_from_finger_tricks_with_regrips,
)
import heapq
from typing import List, Any, Generator, Dict
SOLUTIONS_TO_EVAL = 1000
SOLUTIONS_TO_EVAL = 100
SOLUTIONS_TO_SHOW = 3
PRUNE = 10
PRUNE = 9
SOLVE = 7
@ -38,7 +38,8 @@ def get_first_n_from_generator(gen: Generator[Any, None, Any], n: int) -> List[A
try:
while len(results) < n:
item = next(gen)
results.append(item)
if item not in results:
results.append(item)
except StopIteration:
pass
return results
@ -59,19 +60,19 @@ def load_or_generate_prune_table(file_path: str, prune_size: int) -> Dict:
def main():
config = load_config("./moves.yaml")
definitions = load_definitions("./moves.yaml")
prune_table = load_or_generate_prune_table("prune_table.pkl", PRUNE)
print("prune table size:", humanize.naturalsize(sys.getsizeof(prune_table)))
# TODO: make this function a method of an object that contains a list of finger tricks
score_func = lambda solution: sum(ft.score() for ft in solution.finger_tricks)
data = defaultdict(list)
# eolrb_states, n_states = eolrb_states_generator(
# list(EOLROrientation), EOLR_PERMUTATIONS
# )
eolrb_states, n_states = eolrb_states_generator(
list(EOLROrientation), EOLR_PERMUTATIONS
)
# eolrb_states, n_states = eolrb_states_generator(
# [EOLROrientation.Solved], [EOLRPermutation(UR="UR", UL="UL")]
# )
for i, (eolrb_cube, ori, perm, pre_auf) in enumerate(eolrb_states):
print(
f"generating algs for {ori.name} (UR in {perm.UR}, UL in {perm.UL}, pre AUF {pre_auf}) ({i}/{n_states})"
@ -80,7 +81,7 @@ def main():
solutions = get_first_n_from_generator(alg_generator, SOLUTIONS_TO_EVAL)
solutions_with_finger_tricks = [
EOLRBSolutionWithFingertricks(
solution, generate_finger_tricks(config, solution.alg)
solution, generate_finger_tricks(definitions, solution.alg)
)
for solution in solutions
]
@ -99,8 +100,8 @@ def main():
pretty_alg.extend(solution.alg)
if solution.post_auf:
pretty_alg.append(solution.post_auf)
if solution.mc:
pretty_alg.append("M")
if solution.post_ams:
pretty_alg.append(solution.post_ams)
pretty_finger_tricks = build_pretty_string_from_finger_tricks_with_regrips(
finger_tricks
)
@ -116,11 +117,12 @@ def main():
"raw_alg": " ".join(solution.alg),
"pre_auf": solution.pre_auf,
"post_auf": solution.post_auf,
"post_ams": solution.post_ams,
"finger_tricks": pretty_finger_tricks,
}
)
with open("output.json", "w") as f:
f.write(json.dumps(data))
f.write(json.dumps(data, indent=4))
if __name__ == "__main__":

25
alg_trainer.py Normal file
View File

@ -0,0 +1,25 @@
import json
def main():
with open("./output.json") as f:
data = json.loads(f.read())
covered_cases = set()
for case, scrambles in data.items():
if not scrambles:
continue
scramble = scrambles[0]
if scramble["raw_alg"] in covered_cases:
continue
if scramble["stm"] > 7:
continue
if case.startswith("Solved"):
continue
if "Arrow" in case:
continue
print(f'{case}: "{scramble['alg']}"')
covered_cases.add(scramble["raw_alg"])
if __name__ == "__main__":
main()

18
cube.py
View File

@ -119,6 +119,21 @@ class LSECube:
return "U"
return ""
def fix_m_slice(self) -> str:
match self.centers["U"]:
case "U":
return ""
case "B":
self.Mp()
return "M'"
case "D":
self.M2()
return "M2"
case "F":
self.M()
return "M"
return ""
def alg(self, alg: str):
move_functions = {
"U": self.U,
@ -196,9 +211,6 @@ def condense_algorithm(moves: List[str]) -> List[str]:
return result
reduced_moves = apply_reduction(moves)
# print(reduced_moves)
counted_moves = reduce_moves(reduced_moves)
# print(counted_moves)
reduced_alg = build_reduced_alg(counted_moves)
# print(reduced_alg)
return reduced_alg

72
move_score_approx.py Normal file
View File

@ -0,0 +1,72 @@
"""
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()

View File

@ -1,82 +1,164 @@
# TODO: do a lot of random MU algs and find out which moves are statistically faster
fingers:
- name: index
default_score: 1
home_grips:
- BL
- LB
# TODO: change to grip_set
grips:
side:
- B
- BL
- LB
- LF
- FL
- F
top:
- UF
regrips:
- start: UF
end: BL
score: 3
# TODO: this doesn't need to be here
finger: index
- start: UF
end: LB
score: 3
# TODO: this doesn't need to be here
finger: index
- name: ring
default_score: 1
home_grips:
- B
- DB
grips:
slice:
- B
- DB
- DF
- F
regrips: []
- name: pinky
default_score: 1
home_grips:
- DB
- DF
grips:
slice:
- B
- DB
- DF
- F
- F floating
regrips:
- start: F floating
end: F
score: 2
# F floating is hard
# TODO: this doesn't need to be here
finger: pinky
finger_tricks:
- name: "U push"
move: "U"
grip_pre:
index: BL
index: LB
grip_post:
index: B
score: 5
grip_pre_blacklist: {}
score: 1001
- name: "U flick"
move: "U"
grip_pre:
index: F
grip_post:
index: BL
score: 4
# TODO: rethink this parameter
index: LB
grip_pre_blacklist: {}
score: 1001
- name: "U' push"
move: "U'"
grip_pre:
index: FL
index: LF
grip_post:
index: F
score: 5
grip_pre_blacklist: {}
score: 1000
- name: "U' flick"
move: "U'"
grip_pre:
index: B
index: BL
grip_post:
index: FL
score: 3
- name: "U2 feido"
index: LF
grip_pre_blacklist: {}
score: 1000
- name: "U2' feido"
move: "U2"
grip_pre:
index: B
index: BL
grip_post:
index: F
score: 5
grip_pre_blacklist: {}
score: 1002
- name: "U2 double flick"
move: "U2"
grip_pre:
index: B
index: BL
grip_post:
index: FL
score: 6
index: LF
grip_pre_blacklist: {}
score: 1002
- name: "U2' double flick"
move: "U2"
grip_pre:
index: F
grip_post:
index: BL
score: 9
grip_pre_blacklist: {}
score: 1002
- name: "U2 beido"
move: "U2"
grip_pre:
index: F
grip_post:
index: B
score: 5
grip_pre_blacklist: {}
score: 1002
- name: "M' ring flick"
move: "M'"
grip_pre:
ring: B
grip_post:
ring: DF
score: 3
grip_pre_blacklist: {}
score: 1000
- name: "M' pinky flick"
move: "M'"
# I can't do M' after finishing beido
grip_pre:
pinky: B
grip_post:
pinky: F floating
score: 6
grip_pre_blacklist:
index:
- BL
- UF
score: 1000
- name: "M push"
move: "M"
grip_pre:
pinky: F
grip_post:
pinky: DB
score: 6
grip_pre_blacklist: {}
score: 1001
- name: "M index push"
move: "M"
grip_pre:
index: B
grip_post:
index: UF
grip_pre_blacklist: {}
score: 1001
- name: "M2 double flick"
move: "M2"
grip_pre:
@ -85,158 +167,5 @@ finger_tricks:
grip_post:
pinky: F floating
ring: DB
score: 7
regrips:
# TODO: rethink this format?
- finger: index
pre: B
post: BL
score: 1
- finger: index
pre: B
post: FL
score: 1
- finger: index
pre: B
post: F
score: 1
- finger: index
pre: BL
post: B
score: 1
- finger: index
pre: BL
post: FL
score: 1
- finger: index
pre: BL
post: F
score: 1
- finger: index
pre: FL
post: B
score: 1
- finger: index
pre: FL
post: BL
score: 1
- finger: index
pre: FL
post: F
score: 1
- finger: index
pre: F
post: B
score: 1
- finger: index
pre: F
post: BL
score: 1
- finger: index
pre: F
post: FL
score: 1
- finger: ring
pre: B
post: DB
score: 1
- finger: ring
pre: B
post: DF
score: 1
- finger: ring
pre: DB
post: B
score: 1
- finger: ring
pre: DB
post: DF
score: 1
- finger: ring
pre: DF
post: B
score: 1
- finger: ring
pre: DF
post: DB
score: 1
- finger: pinky
pre: B
post: DB
score: 1
- finger: pinky
pre: B
post: DF
score: 1
- finger: pinky
pre: B
post: F
score: 1
- finger: pinky
pre: B
post: F floating
score: 1
- finger: pinky
pre: DB
post: B
score: 1
- finger: pinky
pre: DB
post: DF
score: 1
- finger: pinky
pre: DB
post: F
score: 1
- finger: pinky
pre: DB
post: F floating
score: 1
- finger: pinky
pre: DF
post: B
score: 1
- finger: pinky
pre: DF
post: DB
score: 1
- finger: pinky
pre: DF
post: F
score: 1
- finger: pinky
pre: DF
post: F floating
score: 1
- finger: pinky
pre: F
post: B
score: 1
- finger: pinky
pre: F
post: DB
score: 1
- finger: pinky
pre: F
post: DF
score: 1
- finger: pinky
pre: F
post: F floating
score: 1
- finger: pinky
pre: F floating
post: B
score: 1
- finger: pinky
pre: F floating
post: DB
score: 1
- finger: pinky
pre: F floating
post: DF
score: 1
- finger: pinky
pre: F floating
post: F
score: 1
grip_pre_blacklist: {}
score: 1002

149
roux_7_movers.txt Normal file
View File

@ -0,0 +1,149 @@
U' M U' M' U' M' U' M' U' M2
M' U' M' U M U2 M U'
U M' U2 M U M' U M U'
M' U' M' U' M U2 M U'
U' M' U2 M U' M' U' M U'
M' U' M' U' M' U2 M U M2
M' U' M' U2 M' U2 M U M2
M' U' M U2 M' U2 M' U' M2
M' U' M' U' M U2 M' U' M2
M' U' M' U' M' U2 M' U
M' U' M' U2 M U2 M' U M2
U M U M' U M' U M U'
M' U' M' U2 M' U2 M' U'
U' M U' M' U' M' U' M U
M' U' M' U M' U2 M' U
M' U' M' U M U2 M' U' M2
M' U' M U' M' U2 M' U' M2
M' U' M U' M U2 M' U
M' U' M U M' U2 M U
U' M U' M' U' M' U M' U' M2
M' U' M U' M U2 M U' M2
M' U' M U' M' U2 M U
U' M' U2 M U' M' U M' U' M2
M' U' M U M U2 M' U
M' U' M U M' U2 M' U' M2
M' U M' U2 M' U2 M U' M2
U M' U M' U' M' U' M' U'
U2 M U' M U M' U2 M' U
U2 M U' M' U2 M' U2 M U'
U2 M U M' U2 M' U2 M U'
U M' U2 M' U M' U M U' M2
U2 M U' M U' M' U2 M' U
U' M' U2 M' U' M' U' M U' M2
U2 M U' M U' M U2 M' U' M2
U2 M U' M U' M' U2 M U M2
U' M' U2 M' U' M' U M'
U2 M U' M' U2 M U2 M' U'
U' M' U M U M U M' U
U2 M U M' U2 M' U2 M' U' M2
U M' U' M U' M U' M' U'
U M' U M' U' M' U' M U' M2
U2 M U M' U M U2 M' U'
U2 M U' M' U' M U2 M U M2
U2 M U' M' U' M' U2 M U'
U2 M U' M' U M U2 M' U'
U' M' U' M' U M' U M U' M2
U2 M U' M' U' M U2 M' U'
U M' U' M U' M U M'
U2 M U' M' U M U2 M U' M2
U2 M U' M' U M' U2 M U
U2 M U' M U M' U2 M U' M2
M' U2 M U2 M' U' M' M2
M' U2 M' U2 M' U' M' U2
U M' U2 M' U2 M' U' M U M2
U M' U2 M' U2 M' U M U' M2
M U' M U' M' U' M U' M2
M' U' M U' M' U M U
M U' M U' M' U M U' M2
M' U' M U' M' U' M' U' M2
M' U M U M' U M' U' M2
M' U M U M' U' M' U2 M2
M U' M U' M' U M' U'
U M U' M' U2 M' U M U
M' U' M U' M' U' M U
U M U' M U2 M' U M' U
M U M U M' U' M' U2
M' U' M U' M' U M' U' M2
M U M U M' U M' U
M U' M U' M' U' M' U
U M U' M' U2 M' U M' U2 M2
U M U' M' U2 M' U' M' U' M2
M' U M U M' U M U
U' M U M' U2 M' U M U'
U2 M' U' M' U' M U' M' U M2
U' M' U' M' U2 M U' M' U M2
U M' U M' U2 M U M' U M2
U2 M U' M' U' M U M' U'
U2 M' U' M' U' M U M' U M2
U2 M U M' U M U' M'
U2 M' U' M' U' M U M U
U' M' U' M U2 M U M' U'
U' M' U' M' U2 M U M U'
U2 M' U M' U M U' M' M2
U2 M U' M' U' M U M U M2
U2 M U' M' U' M U' M' U'
U2 M' U M' U M U M U'
U' M' U' M' U2 M U M' U2 M2
U2 M' U' M' U' M U' M U'
U2 M' U M' U M U' M U
U2 M U M' U M U' M U M2
U M' U M U2 M U M' U
U2 M U M' U M U M' U'
U' M2 U' M U' M2 U M' U2
U' M2 U' M U2 M2 U M' U2
M' U' M' U' M' U M'
U2 M' U2 M' U' M U M U
M' U M U' M U' M' U'
U M' U2 M' U M U M' M2
U2 M U M' U' M' U' M U
U' M' U M' U M' U' M' U
U' M' U2 M U' M U' M' U'
M' U' M' U' M' U' M' U'
U M' U2 M' U M U' M U'
U2 M' U2 M' U' M U M' M2
U' M' U' M U M U M' U'
U M U' M' U M' U M U
U2 M' U2 M' U' M U' M' U M2
M' U2 M U M U M' U
U M' U2 M' U M U' M' M2
M' U' M' U' M' U' M U' M2
U M U M U M U M' U' M2
U2 M U' M U' M U' M' U' M2
U' M' U M' U M' U M U' M2
U' M' U M' U2 M' U M' U
U M U M' U2 M U' M' U
M' U' M' U2 M' U M' U
U' M' U M U2 M' U M' U2 M2
M' U' M' U2 M' U' M' U
U2 M U' M' U2 M U M' U
U2 M U' M' U2 M U M U M2
M' U' M U2 M' U M' U' M2
U M U M U2 M U M' U' M2
U' M' U M' U2 M' U M U M2
U M U M' U2 M U M U' M2
M' U' M' U2 M' U M U M2
U2 M U' M U2 M U M' U M2
U' M U2 M' U2 M' U' M' U' M2
U' M' U2 M' U2 M U M U'
U M' U2 M' U2 M U' M' U M2
U2 M' U M U' M' U' M U'
M' U' M U M' U' M U
M' U M U' M' U M U
U2 M U' M' U M U M U M2
U2 M U M' U' M U' M U M2
M' U' M U M' U M' U' M2
M' U M U' M' U' M' U' M2
M' U' M U M' U M U
U2 M' U' M U M' U' M' U2 M2
M U M' U' M U M U M2
M U' M' U M U' M'
U2 M U M' U' M U' M'
U M' U' M' U M U' M' M2
U2 M' U M' U' M U' M' U2 M2
U M' U' M' U M U M
U2 M U' M U M' U M' U
U2 M U M U' M' U' M' U
U' M U M U' M' U' M U M2
M' U M' U' M U' M U'
U2

183
roux_9_movers.txt Normal file
View File

@ -0,0 +1,183 @@
U M' U' M2 U M' U' M U' M U M2
U M' U' M2 U' M' U M U M U M2
M U' M2 U' M' U2 M' U2 M' U
M' U' M' U2 M U2 M' U' M2 U'
U M' U M2 U' M U' M' U M' U'
U M2 U' M U M' U' M' U' M U' M2
U M2 U M' U' M' U' M' U M' U' M2
M' U' M U' M2 U' M' U2 M U' M2
U M' U' M2 U' M' U M U' M U' M2
M' U' M' U' M2 U M U2 M' U'
M' U' M' U' M2 U M' U2 M' U M2
M' U M U' M2 U' M' U2 M U' M2
M' U' M' U' M2 U' M' U2 M' U' M2
U M' U' M2 U M' U' M U' M' U
M' U' M U' M U2 M' U' M2 U' M2
U M' U' M U' M' U M2 U M U' M2
U M' U' M' U' M2 U M' U M U
U2 M' U' M2 U' M' U2 M' U2 M' U' M2
U2 M' U' M2 U' M U2 M' U2 M U M2
U M2 U' M U' M' U M' U M U' M2
U2 M' U' M2 U' M' U' M' U2 M U
U M' U M' U' M U' M2 U M' U'
U2 M' U' M2 U' M' U M U2 M U' M2
U2 M' U' M2 U' M' U M U2 M' U
U2 M' U' M2 U' M' U M' U2 M' U' M2
U M' U' M U' M' U M2 U' M' U
U M' U2 M' U M U M2 U' M' U2
U' M2 U' M' U' M' U' M' U M' U' M2
U' M' U' M U' M2 U' M' U M' U
M U2 M U2 M' U' M2 U' M' U2 M2
M U2 M' U2 M' U' M2 U' M'
U' M' U2 M' U2 M' U' M U' M2 U'
U M' U2 M' U2 M' U' M2 U2 M' U M2
U' M' U2 M' U2 M' U' M U M2 U'
U M' U2 M' U2 M' U' M' U' M2 U M2
U M' U2 M U2 M' U' M2 U2 M' U
U M' U2 M' U2 M' U' M' U M2 U M2
U M' U2 M' U2 M' U' M U2 M2 U'
U M' U2 M U2 M' U' M U M2 U' M2
U M' U2 M U2 M' U' M U' M2 U' M2
U M' U2 M U2 M' U' M U2 M2 U' M2
U' M' U' M2 U' M' U2 M U M U' M2
U' M' U2 M2 U M' U2 M U M' U
M' U' M2 U M' U M' U M U'
M' U' M2 U' M U M U' M' U M2
M' U' M U' M' U M' U M2 U
M' U' M' U' M2 U M U M' U'
M' U' M U' M U M2 U M' U M2
M U M2 U' M' U' M' U M'
M U' M' U' M2 U M U' M' U' M2
U' M' U' M2 U' M' U2 M U' M' U
U M' U2 M2 U' M' U2 M U M U M2
U M' U M2 U M' U2 M U M' U'
M' U' M U' M' U' M' U2 M2 U
M' U' M U' M U M2 U M U'
M' U' M' U' M2 U M U M U M2
M' U' M' U' M2 U M U' M' U'
M' U' M2 U' M U M U M' U' M2
U M' U2 M2 U' M' U2 M U' M' U'
U M U' M' U2 M U M2 U M' U M2
M' U' M U' M U' M2 U M' M2
M' U' M U' M U2 M2 U' M' U2 M2
M' U M' U' M2 U' M' U M' U' M2
M' U M' U2 M2 U M U' M' U'
M' U M' U M2 U' M U' M U M2
M' U2 M2 U' M' U M U' M'
U2 M' U' M U' M2 U M' U M' U
U2 M' U' M' U' M U M2 U2 M' U'
U2 M' U' M' U' M' U M2 U M' U' M2
M2 U' M U' M U2 M' U' M' M2
U2 M' U' M2 U' M' U M' U M' U' M2
U2 M' U' M' U' M U M U M2 U M2
U2 M' U' M U' M2 U M' U' M' U
U2 M' U' M' U' M U' M2 U2 M U' M2
U2 M' U' M' U' M' U M2 U' M' U M2
U M2 U' M' U' M U2 M' U' M' U'
U' M2 U2 M' U' M U2 M' U' M' U
U' M' U' M' U2 M' U M2 U M U'
U2 M U' M' U' M' U M2 U' M' U
U2 M U' M' U' M U M2 U2 M' U M2
U2 M U' M' U' M' U M2 U M' U
U2 M U' M U' M2 U M' U M' U' M2
U2 M U' M2 U' M' U M' U M U M2
U M2 U2 M' U M' U2 M' U M' U' M2
U2 M' U M U M2 U' M' U' M' U'
M2 U' M U' M' U2 M' U' M U' M2
U2 M U' M' U' M' U2 M2 U' M'
U2 M' U' M' U' M' U2 M2 U' M' M2
U2 M' U' M2 U' M' U M' U M U
U2 M U M U2 M2 U M' U' M U
U2 M U M U M2 U' M' U' M' U' M2
M' U' M' U' M U M2 U M'
U M' U' M2 U' M U M' U M' U
U M' U' M2 U' M U M' U' M' U
U' M2 U' M' U' M U M' U2 M U' M2
M2 U M' U' M U' M' U2 M U' M2
U' M2 U' M' U' M' U' M U2 M' U
U M2 U' M U' M U' M' U2 M' U' M2
U' M2 U' M' U' M' U' M' U2 M U'
U' M' U' M U M' U' M2 U' M' U
U' M2 U' M' U' M U' M' U2 M U' M2
M' U' M' U' M' U' M2 U2 M' U' M2
M' U' M' U' M' U M U M2 U
M' U' M' U' M U M2 U' M'
M2 U M' U' M' U' M U2 M U' M2
M2 U M' U' M' U' M' U2 M U
U M2 U' M U' M' U2 M' U2 M U M2
M2 U M' U' M U2 M' U2 M' U'
U' M2 U' M' U' M U2 M' U2 M' U
M2 U M' U' M' U2 M' U2 M U
M' U' M' U' M' U M U2 M2 U'
U M2 U M U' M' U' M U M' U' M2
U2 M2 U' M' U' M' U' M U M' U'
U M2 U M' U' M' U' M U M' U
M2 U' M' U' M U' M' U M U' M2
U2 M2 U' M U' M' U' M U' M' U M2
U' M' U M' U2 M' U' M2 U2 M' U' M2
M2 U' M' U M U M' U M U' M2
U M' U' M2 U' M' U2 M' U' M U'
U' M2 U2 M U' M' U2 M' U' M' U
U2 M2 U' M U M' U M U M' U M2
U M' U' M2 U' M' U2 M' U' M' M2
U M' U' M2 U' M U2 M' U' M' U2
U' M2 U M' U' M U' M' U' M U' M2
U2 M2 U' M' U' M' U' M U' M' U
M' U' M' U2 M U M2 U M' U'
U M2 U M U' M' U' M U' M' U M2
M2 U' M U' M U' M' U' M U'
U2 M U' M U2 M' U M2 U M U
M2 U' M U' M U' M' U M' U2 M2
U2 M' U2 M2 U' M U2 M' U' M' U'
U2 M' U M2 U M' U2 M' U M' U' M2
M2 U' M' U' M U' M' U M' U
M' U' M' U2 M U M2 U M U' M2
M' U' M' U2 M U M2 U' M'
U M' U2 M2 U M U2 M' U M' U'
U M2 U2 M' U' M U2 M U' M' U' M2
U' M2 U M U' M U' M' U M' U2 M2
U' M' U M' U2 M' U M U2 M2 U'
M2 U2 M U M' U2 M' U M' U'
U M' U2 M' U2 M' U' M2 U' M' U M2
U M U2 M U2 M' U' M2 U2 M' U M2
U M' U2 M U2 M' U' M2 U M' U
M2 U' M U2 M' U2 M' U' M' U2
U M2 U' M' U2 M U2 M' U' M'
M2 U' M U2 M U2 M' U' M' M2
U' M2 U' M' U2 M' U2 M' U' M' M2
U' M' U2 M U2 M' U' M2 U' M' U'
U M' U2 M' U2 M U M2 U2 M' U'
U M' U2 M' U2 M' U' M2 U M U
U2 M2 U' M U2 M' U2 M' U M U' M2
U' M2 U' M' U2 M U2 M' U' M U' M2
U2 M2 U' M U2 M' U2 M' U' M U' M2
U M2 U' M' U2 M' U2 M' U' M U'
M2 U M U2 M U2 M' U' M' U M2
U M' U2 M' U2 M U' M U2 M2 U' M2
U M' U2 M' U2 M' U' M2 U M' U' M2
U M U2 M' U2 M' U' M2 U2 M' U'
U M U2 M' U2 M' U' M U2 M2 U M2
U M' U2 M U2 M' U' M2 U M U M2
U M2 U M' U2 M U2 M' U' M' U'
U' M2 U M' U2 M' U2 M' U' M' U' M2
M' U' M2 U' M' U' M' U' M U'
U M2 U' M' U M U' M' U' M' U'
U2 M' U M U' M U' M2 U M' U' M2
M2 U' M' U' M' U M U' M' U
M' U' M2 U' M' U' M' U M U'
U2 M U M' U' M' U' M2 U M' U
M2 U' M' U' M' U M U M' U
M2 U' M' U M' U' M U' M' U
U2 M2 U' M U' M U M' U M U'
M' U' M' U2 M2 U M U' M' U'
M2 U' M' U' M' U M U M U' M2
M' U' M' U' M2 U' M' U M' U' M2
U2 M' U' M2 U' M' U' M' U M' M2
U M2 U' M' U' M U M' U' M' U'
M' U' M2 U' M U' M U M' M2
M' U2 M2 U M' U M U M M2
M' U2 M2 U M' U M U' M'
U2 M' U' M2 U M' U' M' U' M' U M2
M' U' M U M2 U' M' U' M U' M2
U M' U M' U' M' U' M2 U M' M2
U2

24
roux_trainer.py Normal file
View File

@ -0,0 +1,24 @@
import json
def main():
with open("./output.json") as f:
data = json.loads(f.read())
covered_cases = set()
for case, scrambles in data.items():
if not scrambles:
continue
scramble = scrambles[0]
if scramble["raw_alg"] in covered_cases:
continue
if scramble["stm"] != 9:
continue
if case.startswith("Solved"):
continue
print(scramble["alg"])
covered_cases.add(scramble["raw_alg"])
print("U2")
if __name__ == "__main__":
main()

174
scorer.py
View File

@ -1,4 +1,4 @@
from typing import Dict, List
from typing import Dict, List, Set, Tuple
import yaml
import dacite
from dataclasses import dataclass
@ -8,13 +8,14 @@ from dataclasses import dataclass
class FingerTrick:
name: str
move: str
grip_pre_blacklist: Dict[str, List[str]]
grip_pre: Dict[str, str]
grip_post: Dict[str, str]
score: float
@dataclass
class Regrip:
class Grip:
finger: str
pre: str
post: str
@ -22,23 +23,104 @@ class Regrip:
@dataclass
class Config:
finger_tricks: List[FingerTrick]
class Regrip:
finger: str
start: str
end: str
score: float
@dataclass
class Finger:
name: str
default_score: int
home_grips: List[str]
grips: Dict[str, List[str]]
regrips: List[Regrip]
def home_grip() -> Dict[str, str]:
return {
"index": "B", # this could also be BL
"ring": "B",
"pinky": "BD",
}
@dataclass
class Config:
fingers: List[Finger]
finger_tricks: List[FingerTrick]
def load_config(file_path: str) -> Config:
@dataclass
class Definitions:
fingers: List[Finger]
finger_tricks: List[FingerTrick]
finger_regrips: List[Regrip]
def build_missing_regrips(
finger_regrips: Dict[Tuple[str, str], Regrip], finger: Finger, grips: Set[str]
) -> Dict[Tuple[str, str], Regrip]:
# this might just be the worst piece of code I have ever written
# fill in missing regrips so every pair of grips has a regrip
for grip_start in grips:
for grip_end in grips:
if grip_start != grip_end:
if (grip_start, grip_end) not in finger_regrips:
# TODO: this only works for regrips which are 2 apart
possible_start_regrips = {
grips: regrip
for grips, regrip in finger_regrips.items()
if grip_start == regrip.start
}
possible_end_regrips = {
grips: regrip
for grips, regrip in finger_regrips.items()
if grip_end == regrip.end
}
for start_regrip in possible_start_regrips.values():
for end_regrip in possible_end_regrips.values():
# if start grips ends at the beginning of end grip
if start_regrip.end == end_regrip.start:
finger_regrips[(start_regrip.start, end_regrip.end)] = (
Regrip(
finger=finger.name,
start=start_regrip.start,
end=end_regrip.end,
score=start_regrip.score + end_regrip.score,
)
)
return finger_regrips
def build_regrips_from_fingers(fingers: List[Finger]) -> List[Regrip]:
regrips = []
for finger in fingers:
finger_regrips = {}
for grip_set in finger.grips.values():
# reate a dict with distances of every two elements in a list
for i, grip_start in enumerate(grip_set):
for j, grip_end in enumerate(grip_set):
if grip_start != grip_end:
finger_regrips[(grip_start, grip_end)] = Regrip(
start=grip_start,
end=grip_end,
score=abs(j - i) * finger.default_score,
finger=finger.name,
)
for regrip in finger.regrips:
finger_regrips[(regrip.start, regrip.end)] = regrip
grips = {grip for grip_set in finger.grips.values() for grip in grip_set}
finger_regrips = build_missing_regrips(finger_regrips, finger, grips)
regrips.extend(finger_regrips.values())
return regrips
def load_definitions(file_path: str) -> Definitions:
with open(file_path, "r") as f:
data_dict = yaml.safe_load(f.read())
return dacite.from_dict(data_class=Config, data=data_dict)
config = dacite.from_dict(data_class=Config, data=data_dict)
return Definitions(
fingers=config.fingers,
finger_tricks=config.finger_tricks,
finger_regrips=build_regrips_from_fingers(config.fingers),
)
def grip_correct(current_grip: Dict[str, str], required_grip: Dict[str, str]):
@ -59,47 +141,69 @@ class FingerTrickWithRegrip:
return score
def calculate_finger_trick_regrips(
config: Config, finger_trick: FingerTrick, grip: Dict[str, str]
@dataclass
class Algorithm:
score: float
finger_tricks_with_regrips: List[FingerTrickWithRegrip]
def find_finger_trick_regrips(
regrips: List[Regrip], finger_trick: FingerTrick, grip: Dict[str, str]
) -> List[Regrip]:
regrips = []
alg_regrips = []
for finger in finger_trick.grip_pre.keys():
current_location = grip[finger]
desired_location = finger_trick.grip_pre.get(finger)
blacklisted_locations = finger_trick.grip_pre_blacklist.get(finger, [])
if current_location != desired_location:
regrip = next(
# print("FINGA", finger)
# print("CURRENT", current_location)
# print("DESIRED", desired_location)
# print("BLACK", blacklisted_locations)
# __import__("pprint").pprint(regrips)
alg_regrip = next(
(
regrip
for regrip in config.regrips
for regrip in regrips
if regrip.finger == finger
and regrip.pre == current_location
and regrip.post == desired_location
and regrip.start == current_location
and regrip.end == desired_location
and regrip.start not in blacklisted_locations
),
None,
)
if regrip:
regrips.append(regrip)
return regrips
if alg_regrip:
alg_regrips.append(alg_regrip)
return alg_regrips
def generate_home_grip(fingers: List[Finger]) -> Dict[str, str]:
# TODO: make this smarter
home_grip = {}
for finger in fingers:
home_grip[finger.name] = finger.home_grips[0]
return home_grip
def generate_finger_tricks(
config: Config, moves: List[str]
definitions: Definitions, moves: List[str]
) -> List[FingerTrickWithRegrip]:
grip = home_grip()
alg = []
grip = generate_home_grip(definitions.fingers)
alg: List[FingerTrickWithRegrip] = []
for move in moves:
# print("current grip:", grip)
# prit("current move:", move)
possible_finger_tricks = [
finger_trick
for finger_trick in config.finger_tricks
for finger_trick in definitions.finger_tricks
if move == finger_trick.move
]
# print("possible finger tricks:", possible_finger_tricks)
finger_tricks_with_regrips = [
FingerTrickWithRegrip(
finger_trick=finger_trick,
regrips=calculate_finger_trick_regrips(config, finger_trick, grip),
regrips=find_finger_trick_regrips(
definitions.finger_regrips, finger_trick, grip
),
)
for finger_trick in possible_finger_tricks
]
@ -109,10 +213,14 @@ def generate_finger_tricks(
# print("best finger trick:", best_finger_trick)
# apply regrips
for regrip in best_finger_trick.regrips:
grip[regrip.finger] = regrip.post
grip[regrip.finger] = regrip.end
# apply move
grip.update(best_finger_trick.finger_trick.grip_post)
alg.append(best_finger_trick)
# TODO: think about this
# don't count the first regrip
# alg[0].finger_trick.score = 0
return alg
@ -123,7 +231,11 @@ def build_pretty_string_from_finger_tricks_with_regrips(
for finger_trick_with_regrips in finger_tricks_with_regrips:
for regrip in finger_trick_with_regrips.regrips:
elems.append(f"regrip {regrip.finger} from {regrip.pre} to {regrip.post}")
elems.append(finger_trick_with_regrips.finger_trick.name)
elems.append(
f"regrip {regrip.finger} from {regrip.start} to {regrip.end} ({regrip.score})"
)
elems.append(
f"{finger_trick_with_regrips.finger_trick.name} ({finger_trick_with_regrips.finger_trick.score})"
)
return elems

View File

@ -4,7 +4,6 @@ import copy
from dataclasses import dataclass
from cube import LSECube, condense_algorithm, reverse_algorithm
from eolr import eolrb_solved
from typing import Dict, List, Tuple
@ -13,7 +12,7 @@ class EOLRBSolution:
alg: List[str]
pre_auf: str
post_auf: str
mc: bool
post_ams: str
def lse_brute_force_generator(max_length: int):
@ -57,11 +56,16 @@ def create_eolrb_prune_table(prune_depth: int):
generator = lse_brute_force_generator(prune_depth)
pruned = 0
# TODO: for every solved state (pre auf), we can apply the generator's moves and save to prune table?
for alg in generator:
cube.reset()
cube.alg(" ".join(alg))
prune_table[cube.eolrb_hash()].append(reverse_algorithm(alg))
pruned += 1
if pruned % 1000 == 0:
print(pruned)
return prune_table
@ -80,19 +84,23 @@ def solve_eolrb(cube: LSECube, prune_table: Dict, solve: int):
c.alg(" ".join(moves))
if c.eolrb_hash() in prune_table:
for prune_solution in prune_table[c.eolrb_hash()]:
# TODO: split this function, very ugly copies and very long
prune_cube = copy.deepcopy(c)
prune_cube.alg(" ".join(prune_solution))
alg = condense_algorithm(moves + prune_solution)
# TODO: this is very weird
for _ in range(5):
alg = condense_algorithm(alg)
if len(alg) > 2:
# TODO: check if this is mc
pre_auf = ""
if alg[0].startswith("U"):
pre_auf = alg.pop(0)
post_auf = ""
if alg[-1].startswith("U"):
post_auf = alg.pop(-1)
yield EOLRBSolution(alg, pre_auf, post_auf, False)
post_ams = prune_cube.fix_m_slice()
yield EOLRBSolution(alg, pre_auf, post_auf, post_ams)
# for auf in ["U", "U2", "U'", ""]:
# c = copy.deepcopy(cube)
# auf_alg = f"{' '.join(alg)} {auf}"

171
weighted_moves.yaml Normal file
View File

@ -0,0 +1,171 @@
fingers:
- name: index
default_score: 1
home_grips:
- BL
- LB
# TODO: change to grip_set
grips:
side:
- B
- BL
- LB
- LF
- FL
- F
top:
- UF
regrips:
- start: UF
end: BL
score: 3
# TODO: this doesn't need to be here
finger: index
- start: UF
end: LB
score: 3
# TODO: this doesn't need to be here
finger: index
- name: ring
default_score: 1
home_grips:
- B
- DB
grips:
slice:
- B
- DB
- DF
- F
regrips: []
- name: pinky
default_score: 1
home_grips:
- DB
- DF
grips:
slice:
- B
- DB
- DF
- F
- F floating
regrips:
- start: F floating
end: F
score: 2
# F floating is hard
# TODO: this doesn't need to be here
finger: pinky
finger_tricks:
- name: "U push"
move: "U"
grip_pre:
index: LB
grip_post:
index: B
grip_pre_blacklist: {}
score: 5
- name: "U flick"
move: "U"
grip_pre:
index: F
grip_post:
# TODO: rethink this parameter
index: LB
grip_pre_blacklist: {}
score: 4
- name: "U' push"
move: "U'"
grip_pre:
index: LF
grip_post:
index: F
grip_pre_blacklist: {}
score: 5
- name: "U' flick"
move: "U'"
grip_pre:
index: BL
grip_post:
index: LF
grip_pre_blacklist: {}
score: 3
- name: "U2' feido"
move: "U2"
grip_pre:
index: BL
grip_post:
index: F
grip_pre_blacklist: {}
score: 5
- name: "U2 double flick"
move: "U2"
grip_pre:
index: BL
grip_post:
index: LF
grip_pre_blacklist: {}
score: 6
- name: "U2' double flick"
move: "U2"
grip_pre:
index: F
grip_post:
index: BL
grip_pre_blacklist: {}
score: 9
- name: "U2 beido"
move: "U2"
grip_pre:
index: F
grip_post:
index: B
grip_pre_blacklist: {}
score: 5
- name: "M' ring flick"
move: "M'"
grip_pre:
ring: B
grip_post:
ring: DF
grip_pre_blacklist: {}
score: 3
- name: "M' pinky flick"
move: "M'"
# I can't do M' after finishing beido
grip_pre:
pinky: B
grip_post:
pinky: F floating
grip_pre_blacklist:
index:
- BL
- UF
score: 6
- name: "M push"
move: "M"
grip_pre:
pinky: F
grip_post:
pinky: DB
grip_pre_blacklist: {}
score: 5
- name: "M index push"
move: "M"
grip_pre:
index: B
grip_post:
index: UF
grip_pre_blacklist: {}
score: 6
- name: "M2 double flick"
move: "M2"
grip_pre:
pinky: B
ring: B
grip_post:
pinky: F floating
ring: DB
grip_pre_blacklist: {}
score: 7