Created
June 7, 2021 09:28
-
-
Save joshparkerj/b334c0ba95981859d070568f70f49d7f to your computer and use it in GitHub Desktop.
decode variations puzzle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* this is the first puzzle I've ever received from pramp. | |
I admit, I didn't know how to approach the problem until after I'd slept on it. | |
Here's how the challenge works: | |
Each letter of the alphabet is encoded as a number | |
A -> 1 | |
B -> 2 | |
C -> 3 | |
... | |
Z -> 26 | |
The numbers are mashed together, so they can't be decoded unambiguously. | |
For example, the string '11' can be decoded as AA or K | |
How many possible variations can be decoded from the given string? | |
Input: string S of length at least 1 and no more than 12 | |
Each character in S is a digit. | |
*/ | |
function decodeVariations(S) { | |
let first = 0; | |
let second = 0; | |
for (let i = S.length - 1; i >= 0; i--) { | |
if (S[i] === '0') { | |
first = 0; | |
} else if (S[i] === '1') { | |
first = 2 * second; | |
} else if (S[i] === '2') { | |
} else { | |
first = second; | |
} | |
second = first; | |
} | |
return first; | |
} | |
function decodeVariations(S) { | |
return decodeToLetters(S).length; | |
} | |
function decodeToLetters(s) { | |
if (s.length === 1) { | |
return [String.fromCodePoint(64 + Number(s))]; | |
} | |
const mid = Math.floor(s.length / 2); | |
const leftOutputs = decodeToLetters(s.slice(0, mid)); | |
const rightOutputs = decodeToLetters(s.slice(mid)); | |
return combineDecodedStrings(leftOutputs, rightOutputs); | |
} | |
function combineDecodedStrings(leftStrings, rightStrings) { | |
return leftStrings.reduce((acc, e) => { | |
acc = acc.concat(rightStrings.map(s => e + s)); | |
const rights = rightStrings.filter(s => s[0] < 'J'); | |
return acc.concat(rights.map(r => combineAffixes(e, r)).filter(e => e)); | |
}, []).filter(w => !w.includes('@')); | |
} | |
function combineAffixes(left, right) { | |
const suffix = 10 * (left.codePointAt(left.length - 1) - 64); | |
const prefix = right.codePointAt(0) - 64; | |
const middle = suffix + (prefix === '@' ? 0 : prefix) | |
if (middle > 26) { | |
return null; | |
} | |
return left.slice(0, left.length - 1) + String.fromCodePoint(64 + middle) + right.slice(1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment