Combination Lock Breaking
So there's a web site, www.combinationlock.com, which I'm quite addicted to. It's a little online game that presents the player with a multi-reel combination lock. Each reel contains a number from 0-9, and a single combination of all the reels will open the lock -- just like a standard combination lock.
A typical game will present the player with a three-reel lock and a set of clues:
- The largest and smallest digits have a difference of 6
- Reel B has the highest digit
- Reel B is triple the last reel
- The answer is divisible by 2
In every case, the clues provided are enough to come up with one - and only one - correct answer. In this case, the answer is 062.
Just because I know it can be done, and I know it would be fun, I've set out to create an app which can parse the rules and crack the code.
Sorting Out the Rules
First step would be to sort out the different kinds of rules there are. So I started several games and copied/pasted the rules into notepad, to look for similarities. After cleaning up the rules a bit, I found that there are several different ways of wording identical rules. More importantly, I discovered that there are two different types of rules I need concern myself with.
Type 1: Rules that address the value of a single reel, such as:
- Reel 3 has the highest digit
- The third reel is less than 4
- Reel 2 is a square number
Type 2: Rules that determine the overall value of the entire combination.
- The largest and smallest digits have a difference of 4
- The answer is above 532
- The digits total 16
It could be argued that a third type exists which derives values from two or more reels, but I'll lump those into the second type for now. So the next step would be to categorize each rule into a Type 1 rule, or a Type 2 rule. Since Type 1 rules address a particular reel, they're much more specific. The key to breaking the code is eliminating possibilities, so running through all the Type 1 rules first would be optimal.
Initially,
Reel A has the following possibilities: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
If I come across the rule: Reel A is an even number
Reel A now has only the following possibilites: 0, 2, 4, 6, 8
Now if I come acress the rule: Reel A is less than 4
Reel A now only has two possibilities: 0, 2
... and so on.
So lets break the process down:
- Use regular expressions to determine if a rule is a first-round or second-round rule.
- Parse first set of rules, removing possibilites from each reel.
- Loop through each remaining possibility, testing it against all second-round rules.
Here's some more notes and observations, I'll organize this later:
// TODO:
If time were the main goal, I could attach events to every time a reel possibility changes to test the rules against interdependent rules.
i.e.: The first reel times the last reel = 30
If the last rule changes, it needs to check that that's consistent.
On the second thought, that would get too complex and create circular references etc.. It might be counter-productive as far as execution time goes.
Round 1 Rules:
Reel *R* has the highest digit
Reel *R* is less than *D*
Reel *R* is a square number
Reel *R* is an odd number
Reel *R* is *D* or *D*
The *W* reel is *D* or *D*
The *W* reel is an even number
The *W* reel has the lowest digit
The *W* reel has the highest digit
Round 2 Rules:
The answer is above *D*
The digits total *D*
The largest and smallest digits have a difference of *D*
Reel *R* plus reel *R* = *D*
The answer is divisible by *D*
The *W* reel times reel *R* = *D*
enum ReelWord {
first = 1,
second = 2,
third = 3,
fourth = 4,
fifth = 5,
sixth = 6,
seventh = 7,
eighth = 8,
ninth = 9,
tenth = 10,
eleventh = 11
}
- 6560 reads