Skip to content

Instantly share code, notes, and snippets.

@FedericoPonzi
Last active January 21, 2021 06:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FedericoPonzi/c14eec20829a3a641b0279c4f21b3402 to your computer and use it in GitHub Desktop.
Save FedericoPonzi/c14eec20829a3a641b0279c4f21b3402 to your computer and use it in GitHub Desktop.
Google's compression and decompression challange

From: https://techdevguide.withgoogle.com/paths/advanced/compress-decompression/#code-challenge

The Challenge

In this exercise, you're going to decompress a compressed string.

Your input is a compressed string of the format number[string] and the decompressed output form should be the string written number times. For example:

The input

3[abc]4[ab]c

Would be output as

abcabcabcababababc

Other rules

  • Number can have more than one digit. For example, 10[a] is allowed, and just means aaaaaaaaaa
  • One repetition can occur inside another. For example, 2[3[a]b] decompresses into aaabaaab
  • Characters allowed as input include digits, small English letters and brackets [ ].
  • Digits are only to represent amount of repetitions.
  • Letters are just letters.
  • Brackets are only part of syntax of writing repeated substring.
  • Input is always valid, so no need to check its validity.

Learning objectives

This question gives you the chance to practice with strings, recursion, algorithm, compilers, automata, and loops. It’s also an opportunity to work on coding with better efficiency

package me.fponzi;
class Main {
static class Pair{
// Result string
String ret;
// Position of the consumed portion of the string.
int val;
public Pair( String ret, int val) {
this.ret = ret;
this.val = val;
}
}
static Pair innerCompDecomp(String input) {
StringBuilder toRet = new StringBuilder();
int i;
for(i = 0; i < input.length(); i++){
char ch = input.charAt(i);
if(Character.isDigit(ch)){
int numStart = i;
while(input.charAt(i) != '[') i++;
int repeats = Integer.parseInt(input.substring(numStart, i));
i++; //consume [
Pair toAppend = innerCompDecomp(input.substring(i));
i += toAppend.val;
//automatically consume ] with the for loop.
while(repeats > 0) {
toRet.append(toAppend.ret);
repeats--;
}
}else if(Character.isAlphabetic(ch)) {
toRet.append(input.charAt(i));
}else{
break;
}
}
return new Pair(toRet.toString(), i);
}
static String compressionDecompression(String input){
return innerCompDecomp(input).ret;
}
}
package me.fponzi;
import org.junit.Assert;
public class MainTest {
@org.junit.Test
public void compressionDecompression() {
Assert.assertEquals(Main.compressionDecompression("3[abc]4[ab]c"), "abcabcabcababababc");
Assert.assertEquals(Main.compressionDecompression("10[a]"), "aaaaaaaaaa");
Assert.assertEquals(Main.compressionDecompression("2[3[a]b]"),"aaabaaab" );
Assert.assertEquals(Main.compressionDecompression("3[a]"),"aaa");
Assert.assertEquals(Main.compressionDecompression("2[aa]3[b]"), "aaaabbb");
Assert.assertEquals(Main.compressionDecompression("3[a2[b2[c]d]e]"), "abccdbccdeabccdbccdeabccdbccde");
}
}
@rnkjoshi
Copy link

rnkjoshi commented Apr 7, 2020

it doesn't work for strings like 3[a2[b2[c]d]e].
can you please help me out for that?

@FedericoPonzi
Copy link
Author

it doesn't work for strings like 3[a2[b2[c]d]e].
can you please help me out for that?

I've updated the solution, though you should probably do homework on your own.

@wiknwo
Copy link

wiknwo commented Jan 21, 2021

When I try this: repetitions = repetitions + int(valuestring)
I get the following error: ValueError: invalid literal for int() with base 10: ''

I am not sure what the problem is. Would you be able to help me out or can you spot the error.

@wiknwo
Copy link

wiknwo commented Jan 21, 2021

def main():
stringtodecompress = input("Enter compressed string: ")
print(stringtodecompress) # Check input read correctly
valuestring = "" # String to hold digit representing number of times to repeat following string in decompressed string
decompressedstring = "" # Decompressed string
tokens = []
repetitions = 0
word = "" # String to hold current word

# Parse the input string
for character in stringtodecompress:
    print(character)
    if character.isdigit():
        valuestring = valuestring + character

    elif character.isalpha():
        word = word + character
        print(word)

    # Start of new string
    elif character == "[":
        repetitions = repetitions + int(valuestring)
        
    # End of new string
    elif character == "]":
        for i in range(0, repetitions):
            decompressedstring = decompressedstring + word
    valuestring = ""
    word = ""
    repetitions = 0

@FedericoPonzi
Copy link
Author

You should provide a failing input example (you should probably write your solution via tests) and maybe the full output of a run with the provided input example.

As the errore suggests, it look like "valuestring" doesn't only old digits but also other characters. Before doing the conversion, I would print out the repr(valuestring).

As last tip, before submitting comments, use the preview tab and style accordingly. Copy pasting python code can be hard if not properly formatted.

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