A band formation optimizer for Girls Rock! summer camp. Automatically assigns campers into balanced bands based on instrument preferences, age distribution, and bandmate compatibility.
- Preference-aware matching: Campers specify who they want to play with and who they'd prefer to avoid
- Scalable algorithm: Handles 100-200 campers in seconds using greedy construction + local search
- Age-balanced bands: Scores bands higher when members are close in age
- Valid band constraints: Each band requires exactly 1 drummer, 1-2 guitarists, 1-2 bassists, optional keyboard player
- Persistent storage: Save and load camper lists between sessions
Requires Clojure and Leiningen.
lein depsStart the interactive REPL:
lein run- Add a new camper — Enter name, age, instrument, and bandmate preferences (comma-separated)
- View current campers — Display all loaded campers
- Edit a camper — Remove and re-add a camper
- Suggest band formations — Generate the optimal formation
- Exit — Quit the program
- Load test data — Load 16 sample campers for testing
- Save campers to file — Persist camper list to disk (EDN format)
- Load campers from file — Restore camper list from disk
lein run
→ Menu appears
→ Select "6" to load test data
→ Select "4" to see suggested formations
→ Select "7" to save campers.edn
The band formation uses a two-phase optimization:
-
Greedy Construction:
- Start one band per drummer
- Assign each non-drummer to the band that maximizes their marginal score contribution
- Respects instrument capacity constraints (1-2 guitarists, 1-2 bassists, 0+ keyboardists per band)
-
Local Search:
- Repeatedly try swapping pairs of non-drummer campers between different bands
- Accept swaps that improve the total formation score
- Stop when no improvement is possible (local optimum)
Each band's score combines:
-
Age balance (0-10 points): Tighter age grouping scores higher
- stddev ≤ 1.0 → 10 points
- stddev ≤ 3.0 → 8 points
- stddev ≤ 5.0 → 4 points
- stddev ≤ 7.0 → 2 points
- else → 1 point
-
Preference matching (variable):
- Mutual want (both want each other) → +3 per pair
- One-way want → +1 per pair
- Either camper avoids the other → -5 per pair
Campers are stored as EDN (Clojure data format):
{:name "Alice"
:age 12
:instrument :drums
:wants ["Bob" "Charlie"]
:avoids ["Diana"]}Valid instruments: :drums, :guitar, :bass, :keys
lein test- Integration with Salesforce for camper import/export
- Web UI for band assignment visualization
- Multi-instrument support per camper
- Advanced constraint handling (skill levels, accessibility needs)
Copyright © 2017-2026
Distributed under the Eclipse Public License either version 1.0 or (at your option) any later version.