DEV Community

Cover image for Dig at Berghain Coding Challenge
Saksham Solanki
Saksham Solanki

Posted on • Edited on

Dig at Berghain Coding Challenge

Ever wondered what it's like to be the bouncer at the world's most exclusive nightclub? Listen Labs has created a fascinating algorithmic challenge that lets you experience just that! Minus the music and questionable fashion choices. The Berghain Challenge is a brilliant constraint satisfaction problem disguised as a nightclub simulation, and I've got to hand it to the creators, this is one addictive optimization puzzle.

The Challenge: More Than Just a Velvet Rope

The Berghain Challenge presents you with a simple task: fill a venue with exactly 1000 people while meeting specific demographic quotas. People arrive sequentially with binary attributes (young/old, well-dressed/casual, techno-lover/not, etc.), and you must make immediate accept/reject decisions. No take-backs.

You're scored on how many people you reject before filling the venue. Less rejections = better score.

First Impressions: The Naive Approach

When I first encountered this challenge, my instinct was to be that friendly bouncer who lets everyone in. Spoiler alert: that doesn't work when you need 600 young people out of 1000 spots as well as 600 well dressed, but only 32.25% of the crowd is actually young. The math doesn't lie - you need to be selective.
My initial attempts were... educational. Accept everyone who meets any constraint? Venue fills up with the wrong mix. Be too picky? Hit 2000-3000 rejections before filling the venue. There's a sweet spot, and finding it requires strategy.

The Strategy: Proportional Filling with a Safety Buffer
After several iterations, I developed what I call the "Proportional Filling with Buffer" strategy.
Here's the core insight:

pythonvenue_filled_percent = admitted_count / 1000
target_progress = min(venue_filled_percent + 0.10, 1.0)

The idea is elegant: maintain each attribute at your current venue fill percentage plus a 10% buffer. If you're 40% full, you want each constraint to be at least 50% complete. This buffer is crucial - it prevents the desperate scramble when you're at 950 admissions and still need 50 more young people.

The Implementation: Three-Phase Execution

My bot operates in three distinct phases:
Phase 1: Early Aggression (0-300 admissions)
# Aggressively accept valuable individuals
if person_has_multiple_attributes:
return ACCEPT # These people are gold

Early on, we can afford to be somewhat liberal with acceptances, especially for people with multiple desired attributes. They're rare (only ~6.8% have both young AND well-dressed in Scenario 1) and incredibly valuable.

Phase 2: Strategic Balance (300-800 admissions)
# Check if person helps maintain proportions
for attribute in constraints:
current_progress = attribute_counts[attribute] / constraints[attribute]
if person_has_attribute and current_progress < target_progress:
return ACCEPT

This is where the magic happens. We're constantly recalculating whether accepting someone keeps us on track. The 10% buffer means we're never in crisis mode - we're always slightly ahead of where we need to be.

Phase 3: Endgame Flexibility (900+ admissions)
# Constraints met? Fill remaining spots
if all_constraints_satisfied:
return ACCEPT # Take anyone at this point

Once we've hit our quotas, it's party time - everyone gets in until we hit capacity.

The Secret Sauce: Strategic Rejection
Here's what separates good strategies from great ones: knowing who to reject and when. In Scenario 1, about 41.7% of people have neither desired attribute. These are your strategic rejection candidates:
# Strategic rejection of "neither" category
if has_no_attributes and min_progress > venue_filled + threshold:
return REJECT

But here's the kicker - you can't reject them all immediately. You need some flexibility for the endgame. My strategy uses a dynamic threshold that adjusts based on rejection count and progress differential.

Results

With this approach, I consistently achieve:

Scenario 1: 900-950 rejections (compared to the optimal ~770-800)
Acceptance Rate: 51-53%
Success Rate: 100% constraint satisfaction
Total Decisions: ~1950

Is it the absolute best? No. I've since developed strategies that can go below 750 rejections. But this initial approach taught me valuable lessons about online decision-making, constraint satisfaction, and the importance of safety buffers in optimization problems.

Technical Insights

What makes this challenge particularly interesting from an algorithmic perspective is that it's an online constraint satisfaction problem with:

No lookahead: You can't see the queue, making this a true online algorithm challenge
Stochastic input: The attribute distribution is random but follows known probabilities
Multiple constraints: Balancing multiple quotas simultaneously requires careful tracking
Hard capacity limit: Exactly 1000 spots, no more, no less

The optimal solution likely involves more sophisticated techniques like:

Dynamic programming for threshold calculation
Bayesian updating of attribute probabilities
Linear programming-inspired dual variable pricing

Final Thoughts

The Berghain Challenge is a masterclass in gamified algorithm design. It's accessible enough that you can get started with basic if-then logic, but deep enough that optimizing your solution requires genuine algorithmic thinking. Huge props to the Listen Labs team for creating this engaging challenge - it's problems like these that make algorithm design feel less like homework and more like solving a really satisfying puzzle.

Whether you're aiming for the leaderboard top spot or just trying to beat your personal best, this challenge offers a perfect playground for exploring optimization strategies.

Challenge link: https://berghain.challenges.listenlabs.ai/

Have you tackled the Berghain Challenge? What strategies worked for you? Drop a comment below - I'd love to compare notes on optimization approaches!

Top comments (5)

Collapse
 
pedro_osrio_0dfcb5c78b5b profile image
Pedro Osório • Edited

They're rare (only ~6.8% have both young AND well-dressed in Scenario 1) and incredibly valuable.

Is this a typo? Assuming we all have the same scenario inputs, the probability of this event is not close to 6.8%

Collapse
 
sardanios profile image
Saksham Solanki

Can you explain a bit more? Considering the values, it does come out to that percentage only.

Collapse
 
pedro_osrio_0dfcb5c78b5b profile image
Pedro Osório • Edited

What are the frequencies and correlation between variables in your input for scenario 1?

EDIT: And how are you using those to compute p(well_dressed AND young)?

Collapse
 
sarah_h_42b0504624d5572c profile image
Sarah H.

I found it via a random post on reddit - someone posting the original billboard and asking what it means. Although I am absolutely not a data scientist (I am working on a managerial level in eCommerce), the challenge looked quite fascinating.

My early approach was to build a quota-aware online greedy selector that converts remaining-need vs. capacity and base rates into per-attribute scarcity weights, sprinkles in a correlation-based bonus/penalty, and accepts whenever a candidate’s score clears a dynamic, auto-tuned threshold. Under the hood I used a lightweight frequentist engine (empirical frequencies + pairwise correlations) with a proportional feedback controller for acceptance-rate pacing—picky early, balanced mid-game, and laser-focused (or just fills) at the end. My score reached 912 for scenario 1, which is okay after just a few runs, but not really satisfactory if you look at the current leaderboard. On the other hand, it makes you appreciate the genius of the other participants that have found more optimal solutions.
What was a bit cumbersome though was the sluggishness of the API. I had to rebuild my script multiple times just to be able to deal with the server not responding, 500 server errors, and garbled answers that stopped mid data being transferred.

I am also working on a better solution, but am currently time constrained by other projects, although I have no interest in a) Berlin (I am from Germany) and b) that night-club (I am 50, my night-club days are well behind me), even though it seems to be somewhat of a well-known one with a hard door bouncer for whatever reason. Meeting the team of listenlabs.ai would be fun though, just to meet those that caused me to spend working on a challenge that actually has no real-life value for me till the early morning hours ;)

Do you do this for fun, or also because of the "prize" that you can win? -- looking at the participants, I think there are quite a lot that just participate for the sake of solving the challenge and are not even considering to be flown out.

I hope you don't stop where you are currently. Would love to see you climbing up the leaderboard!

Collapse
 
sardanios profile image
Saksham Solanki

Definitely the APIs slowness was a bit too much, a better architecture could have done a better job. 912 rejections is very god result for the first try though! I had achieved around 911 max with the strategy I had stated, although I was able to optimize with pretty simple logical factors and conditions that helped me achieve less than 800 rejections. It did took me a lot of time, around 1 full day to achieve them, still working on optimizing it more though it's pretty darn difficult.

Indeed meeting listenlabs.ai would be fuin and is my primary goal, I'm also not that much of a club person, never had alcohol as well lol. But yeah prize is not much of value to me as compared to other things, I'm well interested in solving these complex yet entertaining puzzels, far far better than DSA based problems.

Thankyou for your support! I'm currently in the top 50 but trying my best to beat others, if you're gonna try just one advice, try to build a simple solution with very bare basic rules and start optimizing from there, that will give you a better idea.