Skip to content

Instantly share code, notes, and snippets.

@Vlad-CSA
Forked from ryunp/The observed PIN
Created September 28, 2019 14:34
Show Gist options
  • Save Vlad-CSA/8d0c66ce1dc9bf8ea65d049a974f2e29 to your computer and use it in GitHub Desktop.
Save Vlad-CSA/8d0c66ce1dc9bf8ea65d049a974f2e29 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\']'
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment