Move 178 passengers through one aisle. Tune the sequence, preserve groups, and compete against 1,000 canonical seeds.
Design the optimal boarding algorithm and compete on the global leaderboard
passengers (array), ROWS (30), and aircraft (seat info). Return the passengers in boarding order.Your goal is to minimize the total boarding time measured in ticks. A tick is the simulation's unit of time—each tick, passengers move one step forward in the aisle, make progress stowing luggage, or wait if blocked.
The challenge is that different boarding strategies have different tradeoffs. Boarding window seats first (WILMA method) reduces seat interference, but may cause more aisle congestion. Back-to-front boarding is intuitive but often performs poorly due to clustering. Your job is to find the optimal balance.
The simulation uses a Boeing 737-800 configuration with 30 rows in a 3-3 layout (seats A-B-C on the left, D-E-F on the right). Total capacity is 178 seats, with approximately 85% filled (~150 passengers per simulation).
Each passenger has a type that determines their walking speed and luggage stowing time. These values have some randomization (±20-30%) to reflect real-world variability.
Regular adult travelers. Speed: 1.0x, Stow time: ~3 ticks. The most common passenger type (~55% of solo travelers).
Frequent flyers with minimal, organized luggage. Speed: 1.2x, Stow time: ~2 ticks. They're efficient and quick to settle.
Senior travelers who need more time. Speed: 0.5x, Stow time: ~5 ticks. Often travel in pairs with a caregiver.
Young travelers who must be with a guardian. Speed: 0.8x, Stow time: ~1 tick. Always part of a family group.
Pre-boarded passengers already seated when boarding begins. They're in their seats from the start.
Light travelers with just a small carry-on bag. Speed: 1.0x, Stow time: ~1 tick. Quick to board and settle.
The single aisle is the main bottleneck. When a passenger is stowing luggage, they block the aisle at their row. Passengers behind them must wait until the aisle is clear before proceeding.
Pro tip: Spreading out passengers across different rows allows parallel stowing and reduces total time.
When a passenger needs to reach a window or middle seat, they may need to step over already-seated passengers:
When a passenger needs their seat but someone is already seated between them and the aisle, the seated passenger(s) must yield:
This is why WILMA (window first) strategies help: window passengers are already seated when middle/aisle passengers arrive, so no yielding is needed.
Families and travel groups must board within 10 positions of each other in the queue. If your algorithm separates group members too far apart, you'll see a GROUP_SEPARATION validation warning. This rule reflects real-world airline policies.
Groups are identified by groupId. The isGroupLeader flag indicates the primary traveler, and groupMemberIds lists other members.
Each row has overhead bin capacity for 6 pieces of luggage (both sides combined). When a passenger's row is full, they must walk to find available space.
Bin conflicts are tracked in the event log as bin_conflict events. Back-to-front boarding tends to cause more bin contention because rear passengers fill up rear bins, forcing later passengers to walk further.
Your algorithm has access to these global variables:
passengers (Passenger[]) — Array of passengers to sort and returnROWS (30) — Total number of rows on aircraftaircraft (object) — Aircraft layout and vacant seat info (see below)console.log() (function) — Outputs appear in Event Log for debuggingrand() (function) — Seeded RNG (same stream as Math.random)Each passenger object has these properties:
row (1-30) — Row numberseat ("A"-"F") — Seat letterseatIdx (0-5) — Seat index (A=0, F=5)isWindowSeat (bool) — Seats A and FisMiddleSeat (bool) — Seats B and EisAisleSeat (bool) — Seats C and DisExitRow (bool) — Rows 14-16isBulkhead (bool) — Row 1id (int) — Unique passenger identifiertype (string) — STD, BUS, ELD, CHD, WCHR, BAGtypeFull (string) — Full type name (e.g. "STANDARD")speed (0.24-1.44) — Walking speed multiplierluggageTime (1-10) — Base ticks to stow luggagecolor (string) — Hex color for passenger typegroupId (int|null) — Group identifiergroupSize (1-3) — Number in groupisGroupLeader (bool) — Primary travelergroupMemberIds (int[]) — Other member IDsMath.random() and rand() are seeded per simulation.Date.now() and performance.now() use a tick-based clock (tick * 1000ms).Function/eval, crypto randomness, and Node globals (process/require) are disabled.console.log()/warn()/error() appears in the Event Log as USR entries.Your algorithm has access to an aircraft variable with information about the full aircraft layout, including which seats are vacant:
aircraft.totalSeats (178) — Physical seats on planeaircraft.occupiedSeats (int) — Seats with passengersaircraft.vacantSeats (int) — Empty seat countaircraft.rows (30) — Number of rowsaircraft.seatsPerRow (6) — Seats per rowaircraft.seatLabels (string[]) — ["A", "B", "C", "D", "E", "F"]aircraft.exitRows (int[]) — [14, 15, 16]aircraft.bulkheadRow (1) — Row 1aircraft.seats (Seat[]) — All seatsaircraft.vacantSeatsList (Seat[]) — Empty seats onlyaircraft.occupiedSeatsList (Seat[]) — Occupied seats onlyaircraft.getSeat(row, seat) → Seat — Get seat infoaircraft.isVacant(row, seat) → bool — Check if emptyaircraft.isOccupied(row, seat) → bool — Check if takenseat.row, seat.seat, seat.seatIdxseat.isWindowSeat, seat.isMiddleSeat, seat.isAisleSeatseat.isExitRow, seat.isBulkheadseat.exists (bool) — False for 15A, 15Fseat.isOccupied (bool) — Has passengerseat.passengerId (int|null) — Passenger IDUse these as starting points or benchmarks. Select them from the dropdown to see their code:
Baseline random ordering. Surprisingly not terrible! Averages ~450-500 ticks.
Traditional airline method. Board row 30 first, then 29, etc. Actually performs poorly (~500+ ticks) due to aisle clustering.
The worst strategy. Front passengers block everyone behind them. Included for comparison.
Window seats first, then middle, then aisle. Reduces crossover penalties. Typically ~350-400 ticks.
Theoretically optimal: windows first, alternating rows (30, 28, 26... then 29, 27, 25...). Often ~300-350 ticks.
Back-to-front but keeps groups intact. A good starting point that passes validation.
The Event Log streams passenger actions and algorithm output in time order. Use it to debug bottlenecks and verify your strategy.
boarding — Passenger enters the aislestowing — Luggage stow beginsbin_conflict — Bin overflow requires extra walkingcrossover_start — Seat crossover beginsyielding — Aisle seat yields for crossovershuffling — Passengers settle into rowseated — Passenger sitswaiting_blocked — Passenger blocked in aisleconsole_log/console_warn/console_error — Algorithm outputT-MINUS — Total boarding time in ticksAVG_WAIT — Average per-passenger wait timeMANIFEST_LOAD — Seated passengers / totalGROUPS — Group count kept intactEXIT_ROW_PAX — Passengers assigned to exit rowsWhen you submit to the leaderboard, your algorithm is evaluated server-side across 1,000 canonical seeds. This ensures your algorithm is robust across different passenger configurations.
Mean ticks across all 1,000 simulations. Lower is better.
Percentage of simulations without group separation errors. 100% required for ranking.
Maximum ticks in any single simulation. Used as a tiebreaker.
You can submit multiple times and keep improving. Only your best score counts. Use the SAVE button to store your algorithms locally so you can iterate on them.
Built with TanStack Start, Cloudflare Workers, and D1. Algorithm execution is sandboxed and secure.
Inspired by real-world research into airline boarding optimization.