A More Interesting Hello World
Everyone knows the classic "hello world" program. When picking up a new programming language it's the first program you write because it's small and lets you know if you installed the toolchain correctly. When you want to test your knowledge on a real program (with loops, branches, flags, etc) it's helpful to have one in mind that you can easily verify. My favorite is generating Starting Strength lifting schedules. I've trained many friends and family over the years using Starting Strength, so I can usually spot errors in the output right away.
The Starting Strength lifting program is two alternating workouts (workout A, workout B), three days a week, with steadily increasing weight. It's simple but very effective at quickly building strength.
Here is a version in golang:
package main
import (
"flag"
"fmt"
)
type Lift string
const (
LiftSquat Lift = "SQUAT"
LiftOHP Lift = "OHP"
LiftDL Lift = "DL"
LiftRow Lift = "ROW"
LiftBench Lift = "BENCH"
)
// getNextWeight returns the weight that should be used for the current workout.
//
// For the first few weeks of training, the weight can go up quickly (10lb a workout),
// but after the first few weeks progress slows down.
// Also these threshold values are geared to an untrained, but otherwise healthy young-ish man.
// I would lower these if training a woman or anyone with past injury issues.
func getNextWeight(lift Lift, prev int) int {
threshold := 0
switch lift {
case LiftSquat:
threshold = 185
case LiftDL:
threshold = 315
case LiftOHP:
threshold = 95
case LiftBench, LiftRow:
threshold = 185
default:
panic(fmt.Sprintf("unknown lift: %q", lift))
}
if prev < threshold {
return prev + 10
} else {
return prev + 5
}
}
func main() {
startSquatPtr := flag.Int("squat", 65, "Starting squat weight")
startOHPPtr := flag.Int("ohp", 45, "Starting ohp weight")
startBenchPtr := flag.Int("bench", 95, "Starting bench weight")
startDLPtr := flag.Int("deadlift", 135, "Starting deadlift weight")
startRowPtr := flag.Int("row", 65, "Starting row weight")
weeksPtr := flag.Int("weeks", 12, "Number of weeks to generate")
flag.Parse()
fmt.Printf("# LIFTING SCHEDULE\n\n")
squat := *startSquatPtr
ohp := *startOHPPtr
bench := *startBenchPtr
dl := *startDLPtr
row := *startRowPtr
workout := 0
for i := range *weeksPtr {
fmt.Printf("## WEEK %v\n\n", i+1)
for range 3 {
if workout % 2 == 0 {
fmt.Println("### WORKOUT A")
fmt.Printf("- [ ] %-5s 3x5 @ %d\n", LiftSquat, squat)
fmt.Printf("- [ ] %-5s 3x5 @ %d\n", LiftOHP, ohp)
fmt.Printf("- [ ] %-5s 3x5 @ %d\n", LiftDL, dl)
ohp = getNextWeight(LiftOHP, ohp)
dl = getNextWeight(LiftDL, dl)
} else {
fmt.Println("### WORKOUT B")
fmt.Printf("- [ ] %-5s 3x5 @ %d\n", LiftSquat, squat)
fmt.Printf("- [ ] %-5s 3x5 @ %d\n", LiftBench, bench)
fmt.Printf("- [ ] %-5s 3x5 @ %d\n", LiftRow, row)
bench = getNextWeight(LiftBench, bench)
row = getNextWeight(LiftRow, row)
}
fmt.Println()
squat = getNextWeight(LiftSquat, squat)
workout++
}
}
}
And the output of that program:
# LIFTING SCHEDULE
## WEEK 1
### WORKOUT A
- [ ] SQUAT 3x5 @ 65
- [ ] OHP 3x5 @ 45
- [ ] DL 3x5 @ 135
### WORKOUT B
- [ ] SQUAT 3x5 @ 75
- [ ] BENCH 3x5 @ 95
- [ ] ROW 3x5 @ 65
### WORKOUT A
- [ ] SQUAT 3x5 @ 85
- [ ] OHP 3x5 @ 55
- [ ] DL 3x5 @ 145
## WEEK 2
### WORKOUT B
- [ ] SQUAT 3x5 @ 95
- [ ] BENCH 3x5 @ 105
- [ ] ROW 3x5 @ 75
### WORKOUT A
- [ ] SQUAT 3x5 @ 105
- [ ] OHP 3x5 @ 65
- [ ] DL 3x5 @ 155
### WORKOUT B
- [ ] SQUAT 3x5 @ 115
- [ ] BENCH 3x5 @ 115
- [ ] ROW 3x5 @ 85
...
## WEEK 12
### WORKOUT B
- [ ] SQUAT 3x5 @ 290
- [ ] BENCH 3x5 @ 220
- [ ] ROW 3x5 @ 205
### WORKOUT A
- [ ] SQUAT 3x5 @ 295
- [ ] OHP 3x5 @ 155
- [ ] DL 3x5 @ 305
### WORKOUT B
- [ ] SQUAT 3x5 @ 300
- [ ] BENCH 3x5 @ 225
- [ ] ROW 3x5 @ 210