Last active
January 24, 2018 15:04
-
-
Save sreeprasad/902863e6ebc0b8733136e4bfe7e2441f to your computer and use it in GitHub Desktop.
Decompress string interview problem from https://techdevguide.withgoogle.com/paths/advanced/compress-decompression?no-filter=true#code-challenge
This file contains hidden or 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
package com.sreeprasad.algorithms; | |
import java.util.Stack; | |
public class RecommendedSequence { | |
private static StringBuilder recommended(String S) { | |
StringBuilder result = new StringBuilder(); | |
if (S==null || S.length()==0) return result; | |
int N = S.length(); | |
// this stack is to keep track of all the numbers. | |
// eg. in input 2[3[a]b], the numbers 2,3 goes to this stack. | |
Stack<Integer> st = new Stack<>(); | |
// sb1 stores numbers or alphabets temporarily before processing | |
StringBuilder sb1 = new StringBuilder(); | |
// counterOfOpenBrac is used to store number of '['. | |
// each time we see '[' counterOfOpenBrac increments. | |
// each time we see ']' counterOfOpenBrac decrements. | |
// every time counterOfOpenBrac becomes 0, | |
// we append the subResult to final result string AND flush the subResult. | |
int counterOfOpenBrac=0, i=-1; | |
// to store intermediary result. | |
StringBuilder subResult = new StringBuilder(); | |
while (++i<N) { | |
sb1 = new StringBuilder(); | |
// sb1 stores numbers or alphabets. | |
// this while loop stops running until we see '[' or ']' or end of string length. | |
while (i<N && isNumOrChar(S.charAt(i))) { | |
sb1.append(S.charAt(i++)); | |
} | |
// if sb1 is a number, push number to stack. | |
if(isNotEmpty(sb1) && isNum(sb1)) { | |
st.push(Integer.parseInt(sb1.toString())); | |
} | |
// increment counterOfOpenBrac when we see '[' | |
if (i< N && S.charAt(i)=='[') counterOfOpenBrac++; | |
// this is main core | |
if (i< N && S.charAt(i)==']' && isNotEmpty(sb1)) { | |
// v represents the number of times we have to multiply inner string. | |
// eg. for input 3[a] , v=3 | |
int v = (!st.isEmpty()) ? st.pop() : 1; | |
counterOfOpenBrac--; | |
// sb2 is just to temporarily store results of multiplication | |
StringBuilder sb2 = new StringBuilder(); | |
// keep multiplying and store in temp variable. | |
while (v>0) { | |
sb2.append(subResult).append(sb1); | |
v--; | |
} | |
// if counterOfOpenBrac is zero then means we have decompressed | |
// one substring completely. Hence store the decompressed string to final result | |
// and flush the subResult. | |
if (counterOfOpenBrac==0) { | |
// eg. for input 3[abc]2[ab], here we have completed decompressing 3[abc] to abcabcabc | |
// so store this decompressed string to final result. | |
result.append(sb2); | |
// We just completed processing 3[abc] part of the input. | |
// The input string still contains 2[ab] that needs to be processed. | |
subResult = new StringBuilder(); | |
} else { | |
// reaching here means, this decompressed string needs to be | |
// stored in subResult and continue processing. | |
// eg. for input 3[2[a]b], after decompressing 2[a] to 'aa' | |
// do not write to final result. Instead store the decompressed string in | |
// subResult and continue processing. | |
subResult = new StringBuilder(sb2); | |
} | |
// flush the temporary store | |
// not sure if this is required. | |
sb1 = new StringBuilder(); | |
} else if (i<N && st.isEmpty() && isNotEmpty(sb1)) { | |
// this is for edge case a[]b where there is no number and only chars | |
result.append(sb1); | |
sb1 = new StringBuilder(); | |
} | |
} | |
// finally there may be chars at the end of the input string without any numbers | |
// eg. in input 3[abc]2[bc]c, 'c' is not associated with any number. | |
// so just append that to final result. | |
if (sb1.length()>0) result.append(sb1); | |
return result; | |
} | |
private static boolean isNotEmpty(StringBuilder sb1) { | |
return sb1!=null && sb1.length()>0; | |
} | |
public static void main(String[] args) { | |
//String S = "2[3[a]b]"; // tested. | |
String S = "3[abc]2[ab]c"; // tested. | |
//String S = "a[]b"; // tested. | |
//String S = "0[abc]"; // tested. | |
//String S = "10[a]"; // tested. | |
System.out.printf("input: %s\n",S); | |
System.out.printf("output: %s\n",recommended(S).toString()); | |
} | |
// returns true if sb is a number else false | |
private static boolean isNum(StringBuilder sb) { | |
try { | |
Integer.parseInt(sb.toString()); | |
} catch (NumberFormatException e){ | |
return false; | |
} | |
return true; | |
} | |
private static boolean isNum(char c) { | |
return c>='0' && c<='9'; | |
} | |
private static boolean isChar(char c) { | |
return c>='a' && c<='z'; | |
} | |
private static boolean isNumOrChar(char c) { | |
//System.out.println("c "+c+" isNum(c) "+(isNum(c))+" isChar(c) "+(isChar(c))); | |
return isNum(c) || isChar(c); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment