Skip to content

Instantly share code, notes, and snippets.

@kdeloach
Created July 19, 2020 20:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kdeloach/1d38913883fe355fa131a4757703ca43 to your computer and use it in GitHub Desktop.
Save kdeloach/1d38913883fe355fa131a4757703ca43 to your computer and use it in GitHub Desktop.
Calculate plate orderings for 531 workout
bar = 45
plates = [45, 35, 25, 10, 10, 5, 5, 2.5]
min_weight = bar
max_weight = bar + int(sum(plates) * 2)
def calculate_perms(plates):
result = set()
for i in range(len(plates)):
result.add(tuple([plates[i]]))
perms = calculate_perms(plates[:i] + plates[i + 1 :])
for tup in perms:
result.add(tuple([plates[i]]) + tup)
return result
# Calculate all possible plate orderings
perms = calculate_perms(plates)
# Sort each tuple by descending order and filter duplicates to reduce permutation space
perms = set([tuple(sorted(tup, key=lambda n: -n)) for tup in perms])
# Group plate orderings by weight (how many different ways can you arrange
# the plates to equal some weight) in 5 lbs increments
perms_by_weight = {}
for weight in range(min_weight, max_weight + 1, 5):
perms_by_weight[weight] = [tup for tup in perms if sum(tup) * 2 + bar == weight]
# Hack to support lifting empty bar
perms_by_weight[bar] = [("-",)]
def plate_change_score(a, b):
"""
Return score of changing from plates a to b based on number of
additions and removals.
"""
# Find largest common prefix
prefix = 0
size = min(len(a), len(b))
for i in range(size):
if a[i] == b[i]:
prefix += 1
else:
break
# Base score (from adding plates)
score = len(b) - prefix
# Penalize removing plates
score += (len(a) - prefix) * 2
return score
def generate_plans(weights, parent_plates=[], score=0):
"""
Return all possible plate combinations for a progression of weights
along with a score.
Ex.
generate_plans([45])
[
[(45,), 0]],
]
generate_plans([45, 55])
[
[(45,), (45, 10), 1],
[(45,), (45, 5, 5), 2],
]
"""
if not weights:
return [[score]]
perms = perms_by_weight[weights[0]]
result = []
for t1 in perms:
new_score = score + plate_change_score(parent_plates, t1)
sub_plans = generate_plans(weights[1:], parent_plates=t1, score=new_score)
for lst in sub_plans:
result.append([t1] + lst)
return result
def find_best_plan(weights):
"""
Return highest rank plan.
"""
plans = generate_plans(weights)
plans = sorted(plans, key=lambda lst: lst[-1])
best = plans[0]
best.pop(-1) # remove score
return best
def round_to_nearest(n, increment):
return increment * round(n / increment)
lifts = {
"Squat": {"repmax": 175},
"Bench": {"repmax": 130},
"Deadlift": {"repmax": 211},
"Press": {"repmax": 83},
}
for lift in lifts.values():
lift["training_max"] = round(lift["repmax"] * 0.9)
for week in range(3):
extra_perc = week * 0.05
week_percs = [
0.4,
0.5,
0.6,
0.65 + extra_perc,
0.75 + extra_perc,
0.85 + extra_perc,
0.65 + extra_perc,
]
for lift_name, lift in lifts.items():
tm = lift["training_max"]
weights = [max(bar, round_to_nearest(tm * w, 5)) for w in week_percs]
print(f"Week {week + 1} {lift_name}")
warmup_plan = find_best_plan(weights[:3])
rep_plan = find_best_plan(weights[3:])
plans = warmup_plan + rep_plan
for perc, weight, plates in zip(week_percs, weights, plans):
print(f"{perc:0.0%}\t{weight}\t{', '.join(str(n) for n in plates)}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment