Inspiration
House Edge asked for each machine's exact probabilities for its next spin (0×, 1×, 2×, 5× or 20×). Scoring compared our predictions to the simulator's true probabilities, not to the random outcome. That meant the winning move was to figure out how the simulator actually works, not to throw a generic model at it.
What it does
For every test query, it outputs five calibrated probabilities. On the public validation set it scores 57.64 / 60 with the official checker, against 30 for the organizers' baseline. It runs on plain Python with no extra libraries and finishes in about 15 seconds.
How we built it
We explored the data first and modeled second. That uncovered the simulator's structure:
- Win chance follows a lag-pair rule. Each machine's win chance depends on whether its win/loss outcomes at two earlier spins match. The pairs were (1,3), (2,5) and (4,7), with a "high" and a "low" win level per machine type.
- Payout size has two modes. Given a win, each machine type pays from one of exactly two fixed distributions. Which one applies depends on whether the payout at the rule's first lag was a big win (2× or more).
- Rules can change. In drifting and shared-change episodes the rule flips, and in shared-change episodes all machines flip at the same tick.
- Small episode-wide effects exist: the other machines' recent luck, and their wins 3 ticks back.
The model is a joint Bayesian model. It weighs every hypothesis (which lag pair, which direction, which size mode) using closed-form Beta-Binomial likelihoods, and averages over possible change points, including change points shared across an episode. The rules are discovered automatically from each round's training data, so the same code adapts to round two's changed patterns. Validation answers were used only to read off type-level constants, never to fit individual machines.
Challenges we ran into
- Avoiding overfitting. Scores very close to 60 on validation usually mean a model memorized the validation answers, which doesn't carry over to the hidden test set. We split validation into halves and re-checked every improvement on both.
- Reproducibility. The organizers re-run our code offline with no extra packages, so everything uses only the Python standard library. The code also checks that the submitted CSV can be recreated exactly from the zip.
Accomplishments that we're proud of
- Cutting the baseline's error by about 95% on stable machines
- Discovering the hidden two-mode payout structure
- A one-command pipeline that rebuilds a full entry for new data in minutes
- Round two (adaptation): the same code re-learned the changed rules on its own, finding new lag pairs (1,4), (3,8), (2,6); scored 19.42 / 20 on the official validation checker.
What we learned
Understanding how the data was generated beats generic machine learning. We also learned to stay skeptical of our own validation scores.
What's next
Better handling of short histories and changing machines, which is where most of our remaining error is.