Skip to content

Instantly share code, notes, and snippets.

@ryunp
Last active March 15, 2024 14:19
Show Gist options
  • Save ryunp/3c34aa1bec447f9b0c65c55b915788b9 to your computer and use it in GitHub Desktop.
Save ryunp/3c34aa1bec447f9b0c65c55b915788b9 to your computer and use it in GitHub Desktop.
Alright, detective, one of our colleagues successfully observed our target person,
Robby the robber. We followed him to a secret warehouse, where we assume to find
all the stolen stuff. The door to this warehouse is secured by an electronic
combination lock. Unfortunately our spy isn't sure about the PIN he saw, when
Robby entered it.
The keypad has the following layout:
┌───┬───┬───┐
│ 1 │ 2 │ 3 │
├───┼───┼───┤
│ 4 │ 5 │ 6 │
├───┼───┼───┤
│ 7 │ 8 │ 9 │
└───┼───┼───┘
│ 0 │
└───┘
He noted the PIN 1357, but he also said, it is possible that each of the digits
he saw could actually be another adjacent digit (horizontally or vertically, but
not diagonally). E.g. instead of the 1 it could also be the 2 or 4. And instead
of the 5 it could also be the 2, 4, 6 or 8.
He also mentioned, he knows this kind of locks. You can enter an unlimited amount
of wrong PINs, they never finally lock the system or sound the alarm. That's why
we can try out all possible (*) variations.
* possible in sense of: the observed PIN itself and all variations considering the
adjacent digits
Can you help us to find all those variations? It would be nice to have a function,
that returns an array of all variations for an observed PIN with a length of 1 to 8
digits. We could name the function getPINs (get_pins in python). But please note that
all PINs, the observed one and also the results, must be strings, because of
potentially leading '0's. We already prepared some test cases for you.
Detective, we count on you!
// Requires >= ES6 (Set object)
function getPINs(observed) {
var combos = [];
var neighbors = {
"0": ["8"],
"1": ["2", "4"],
"2": ["1", "3", "5"],
"3": ["2", "6"],
"4": ["1", "5", "7"],
"5": ["2", "4", "6", "8"],
"6": ["3", "5", "9"],
"7": ["4", "8"],
"8": ["5", "7", "9", "0"],
"9": ["6", "8"]
};
var strDigits = observed.toString().split("");
getCombos(strDigits, 0, "");
return combos;
// Depth first combinatorial traversal
function getCombos(digits, idx, curCombo) {
// Get possible candidates
var curDigit = digits[idx];
var candidates = new Set(neighbors[curDigit]);
candidates.add(curDigit);
//console.log(digits, idx, curCombo, candidates); // Pretty cool
candidates.forEach(idx == digits.length - 1 ? reachedEnd : goDeeper);
// (Avoiding anon funcs)
function reachedEnd(candidate) { combos.push(curCombo + candidate); }
function goDeeper(candidate) {
getCombos(digits, idx + 1, curCombo + candidate)
}
}
}
/* Output of one test (with console.log lines)
[ '3', '6', '9' ] 0 '' Set { '2', '6', '3' }
[ '3', '6', '9' ] 1 '2' Set { '3', '5', '9', '6' }
[ '3', '6', '9' ] 2 '23' Set { '6', '8', '9' }
[ '3', '6', '9' ] 2 '25' Set { '6', '8', '9' }
[ '3', '6', '9' ] 2 '29' Set { '6', '8', '9' }
[ '3', '6', '9' ] 2 '26' Set { '6', '8', '9' }
[ '3', '6', '9' ] 1 '6' Set { '3', '5', '9', '6' }
[ '3', '6', '9' ] 2 '63' Set { '6', '8', '9' }
[ '3', '6', '9' ] 2 '65' Set { '6', '8', '9' }
[ '3', '6', '9' ] 2 '69' Set { '6', '8', '9' }
[ '3', '6', '9' ] 2 '66' Set { '6', '8', '9' }
[ '3', '6', '9' ] 1 '3' Set { '3', '5', '9', '6' }
[ '3', '6', '9' ] 2 '33' Set { '6', '8', '9' }
[ '3', '6', '9' ] 2 '35' Set { '6', '8', '9' }
[ '3', '6', '9' ] 2 '39' Set { '6', '8', '9' }
[ '3', '6', '9' ] 2 '36' Set { '6', '8', '9' }
✔ Test Passed: Value == '[\'236\', \'238\', \'239\', \'256\', \'258\', \'259\', \'266\', \'268\', \'269\', \'296\', \'298\', \'299\', \'336\', \'338\', \'339\', \'356\', \'358\', \'359\', \'366\', \'368\', \'369\', \'396\', \'398\', \'399\', \'636\', \'638\', \'639\', \'656\', \'658\', \'659\', \'666\', \'668\', \'669\', \'696\', \'698\', \'699\']'
*/
@ryunp
Copy link
Author

ryunp commented Oct 6, 2016

@frj2a
Copy link

frj2a commented Nov 10, 2023

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment