Last active
August 29, 2015 14:01
-
-
Save Kyuuhachi/a8a23ba19e32bfb1c6a9 to your computer and use it in GitHub Desktop.
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
import java.io.*; | |
import java.util.LinkedList; | |
import java.util.List; | |
public class Hard162 { | |
public static void main(String[] args) { | |
if(args.length < 3) err("<Error: too few arguments>"); | |
if(args.length > 3) err("<Error: too many arguments>"); | |
if(!args[0].equals("-d") && !args[0].equals("-c")) err("<Error: unknown operation>"); | |
File in = new File(args[1]).getAbsoluteFile(); | |
File out = new File(args[2]).getAbsoluteFile(); | |
out.getParentFile().mkdirs(); | |
try(FileReader rdr = new FileReader(in); FileWriter wr = new FileWriter(out)) { | |
String input = read(rdr); | |
String output = args[0].equals("-d") ? decompress(input) : compress(input); | |
if(output.startsWith("<")) err(output); | |
wr.write(output); | |
} catch(IOException e) { | |
err("<Error: IO error '" + e.getLocalizedMessage() + "'>"); | |
} | |
} | |
public static String compress(String s) { //Honestly, apostrophes should be allowed too. As should "What?!" and "AAAAAAAAaaaaaaaaaaaaa!!!" | |
final int LOWER = 1, UPPER = 2; | |
StringBuilder out = new StringBuilder(); | |
int wordType = 0; | |
StringBuilder currentWord = new StringBuilder(); | |
List<String> dict = new LinkedList(); | |
for(int i = 0; i < s.length(); i++) { | |
char ch = s.charAt(i); | |
if(ch >= 'a' && ch <= 'z') { | |
currentWord.append(ch); | |
wordType |= LOWER; | |
} else if(ch >= 'A' && ch <= 'Z') { | |
currentWord.append(ch); | |
wordType |= UPPER; | |
if((wordType & LOWER) != 0) return "<Error: invalid capitalization>"; | |
} else if("- .,?!;:\n".indexOf(ch) != -1) { | |
if(wordType != 0) { | |
String word = currentWord.toString().toLowerCase(); | |
int index = dict.indexOf(word); | |
if(index == -1) { | |
index = dict.size(); | |
dict.add(word); | |
} | |
out.append(index); | |
} | |
if(wordType == UPPER) out.append('!'); | |
if(wordType == (UPPER | LOWER)) out.append('^'); | |
if(ch == ' ' || ch == '-' || ch == '\n') currentWord.setLength(0); | |
else if(wordType == 0) return "<error: multiple punctuation in a row>"; | |
if(ch != '-') out.append(' '); | |
if(ch == '\n') out.append("R"); | |
if(ch != ' ') out.append(ch); | |
wordType = 0; | |
} else return "<error: invalid character " + ch + ">"; | |
} | |
out.append(" E"); | |
StringBuilder outDict = new StringBuilder(); | |
outDict.append(dict.size()).append("\n"); | |
for(String word:dict) | |
outDict.append(word).append("\n"); | |
return outDict.toString() + out.toString().replaceAll("[ ]*\n[ ]*", "\n").trim(); | |
} | |
public static String decompress(String s) { | |
StringBuilder out = new StringBuilder(); | |
int dictLen = -1; | |
List<String> dict = new LinkedList(); | |
StringBuilder currentWord = new StringBuilder(); | |
int currentNumber = -1; | |
char nextChar = 0; | |
for(int i = 0; i < s.length(); i++) { | |
char ch = s.charAt(i); | |
if(dict.size() != dictLen) { //Fill dict | |
if('0' <= ch && ch <= '9') { | |
if(currentNumber == -1) currentNumber = 0; | |
currentNumber = currentNumber * 10 + ch - '0'; | |
} else if(ch == '\n') { | |
if(currentNumber != -1) dictLen = currentNumber; | |
else dict.add(currentWord.toString()); | |
currentWord.setLength(0); | |
currentNumber = -1; | |
} else currentWord.append(ch); | |
continue; | |
} | |
//Decompress | |
if('0' <= ch && ch <= '9') { | |
if(currentNumber == -1) currentNumber = 0; | |
currentNumber = currentNumber * 10 + ch - '0'; | |
} else if(currentNumber != -1) { | |
if(nextChar != 0) out.append(nextChar); | |
if(ch == '!') out.append(dict.get(currentNumber).toUpperCase()); | |
else if(ch == '^') out.append(toFirstUpper(dict.get(currentNumber))); | |
else out.append(dict.get(currentNumber)); | |
currentNumber = -1; | |
nextChar = ' '; | |
} else if(ch == '-') nextChar = '-'; | |
else if(".,?!;:".indexOf(ch) != -1) out.append(ch); | |
else if(ch == 'R') { | |
nextChar = 0; | |
out.append('\n'); | |
} else if(ch == 'E') break; | |
else if(ch != ' ' && ch != '\n') return "<Error: unknown character>"; | |
} | |
return out.toString(); | |
} | |
// Misc helper functions | |
private static String read(Reader rdr) throws IOException { | |
StringBuilder sb = new StringBuilder(); | |
int ch; | |
while((ch = rdr.read()) != -1) | |
sb.append((char)ch); | |
return sb.toString(); | |
} | |
private static String toFirstUpper(String s) { | |
return s.substring(0, 1).toUpperCase() + s.substring(1); | |
} | |
private static void err(String string) { | |
System.err.println(string); | |
System.exit(1); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment