A string is encoded by performing the following sequence of actions:
1. Replace each character with its ASCII value representation.
2. Reverse the string.
For example, the table below shows the conversion from the string "HelloWorld"
to the ASCII string "7210110810811187111114108100"
:
Character
H e l l o W o r l d
ASCII Value
72 101 108 108 111 87 111 114 108 100
The ASCII string is then reversed to get the encoded string "0018014111117811180180110127
".
The characters in encoded string are within the range 10 - 126 which include special characters.
I need to write a function that must decode the encoded string and return the list of ways in which it can be decoded.
I could not get a work around to solve this. Any help is appreciated.
solutions = []
currentSolution = ''
unprocessed = ''
def decode(s):
flipped = s[::-1]
global solutions
global unprocessed
global currentSolution
currentSolution = ''
unprocessed = flipped
_decode()
return solutions
def is_valid(split):
if split.startswith('0'):
return False
value = int(split)
if value < 10 or value > 126:
return False
return True
def _decode():
global unprocessed
global currentSolution
global solutions
if len(unprocessed) == 0:
solutions.append(currentSolution)
else:
possible_splits = list()
possible_splits.append(unprocessed[0:2])
possible_splits.append(unprocessed[0:3])
for split in possible_splits:
if is_valid(split):
decoded_character = chr(int(split))
currentSolution += decoded_character
unprocessed = unprocessed[len(split):]
_decode()
currentSolution = currentSolution[0: len(currentSolution) - 1]
unprocessed = split + unprocessed
def main():
final_solutions = decode('0018014111117811180180110127')
print(final_solutions)
if __name__ == '__main__':
main()
I'd like to point out that you're asking a very computer science question--one I'd see in an intro data structures/algorithms class. I'm assuming you know some of the terminology I'll be using here given that context.
I used backtracking to calculate every possible split and if the split was valid (eg used all numbers), then I added it to a list of solutions.
You'll notice that it isn't the most efficient algorithm but it still works on your input. I believe the time complexity is something like O(2^n)
(though I may be wrong about that) because, @Mulliganaceous pointed out, at each decision to split, you create another branch which has at most two options.
Furthermore, since you want all possible ways, you need to exhaust this search tree until you find all solutions. You might be able to get a faster algorithm using dynamic programming but I haven't thought about this problem enough to do so.
So here's the O(2^n)
solution:
The code below has these steps in the comments.
decode
function/method. in this method, flip the input and assign that to the unprocessed substring. You can additionally reset the other state parameters if you plan on running this function more than once. call the recursive _decode
function to kick off the backtracking. 123456
. For this string, there are only 2 possible splits for this branch: 12
and 123
. If the unprocessed string was just 78
, there would only be one possible split: 78
. _decode
method. this will keep going down the search tree until it doesn't have any options. And that's that!
But here's some javascript code (the only reason it's in javascript is so you can press the "Run code snippet" button in browser).
If you're on mac, hit Cmd + option I
and then click "Run code snippet" If you're on windows, his F12
and then click "Run code snippet"
You'll see your browser open up a debugger. Step through the code . See what it's doing.
// 1 let solutions = []; let currentSolution = ''; let unprocessed = ''; function range(n) { const list = []; for (let i = 0; i < n; i += 1) { list.push(i); } return list; } // 2 function decode(input) { const flipped = input .split('') .reverse() .join(''); solutions = []; currentSolution = ''; unprocessed = flipped; _decode(); return solutions.slice(); } function isValid(split) { if (split.startsWith('0')) return false; const value = parseInt(split, 10); if (value < 10) return false; if (value > 126) return false; return true; } function _decode() { // 3 if (unprocessed.length === 0) { solutions.push(currentSolution); } // 4 const possibleSplits = range(2) .map(i => i + 1) .filter(i => i < unprocessed.length) .map(i => unprocessed.substring(0, i + 1)); // 5 for (const split of possibleSplits) { if (isValid(split)) { const decodedCharacter = String.fromCharCode(parseInt(split, 10)); // 6 currentSolution += decodedCharacter; unprocessed = unprocessed.substring(split.length); // 7 _decode(); // 8 currentSolution = currentSolution.substring(0, currentSolution.length - 1); unprocessed = split + unprocessed; } } } debugger; console.time('calculation time'); const finalSolutions = decode('0018014111117811180180110127'); console.timeEnd('calculation time'); console.log(finalSolutions.length, 'solutions (all but one of them contain special characters)'); console.log(finalSolutions); console.log('final solutions in ascii code'); console.log(finalSolutions .map(solution => solution .split('') .map(c => c.charCodeAt(0)) .map(code => code.toString()) .join(', ') ) .map(line => `[${line}]`) .join('\\n') )
Can you also add an additional part to your code which prints out every char as an ASCII code, each encased in brackets? – Mulliganaceous 24 mins ago
sure thing, see the edited answer.
Edit: updated the isValid
function to check to see if the string starts with 0
, if it does, then it should not consider that split valid.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.