Created
December 13, 2022 17:42
-
-
Save maksverver/822f6bf71ef5e60e97e9dbeefe4458a9 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
package com.janoz.aoc.y2022.day13; | |
import java.util.ArrayList; | |
import java.util.Collections; | |
import java.util.Iterator; | |
import java.util.List; | |
public class Package implements Comparable<Package> { | |
private final AList contents; | |
public Package(String data) { | |
contents = new AList(parseList(new CharIterator(data))); | |
} | |
public String asString() { | |
return asString(contents.asList()); | |
} | |
private String asString(List<ListOrInt> l) { | |
StringBuilder sb = new StringBuilder(); | |
sb.append('['); | |
for (int i=0; i<l.size(); i++) { | |
if (i!=0) { | |
sb.append(','); | |
} | |
if (!l.get(i).isList()) { | |
sb.append(l.get(i).getInt()); | |
} else { | |
sb.append(asString(l.get(i).asList())); | |
} | |
} | |
sb.append(']'); | |
return sb.toString(); | |
} | |
private List<ListOrInt> parseList(CharIterator it) { | |
List<ListOrInt> currentList = new ArrayList<>(); | |
it.pop(); // pop [ | |
while (it.peek()!=']') { | |
if (it.peek() == '[') { | |
currentList.add(new AList(parseList(it))); | |
} else { | |
currentList.add(new AnInt(it.popInt())); | |
} | |
if (it.peek() == ',') it.pop(); | |
} | |
it.pop(); | |
return currentList; | |
} | |
@Override | |
public int compareTo(Package o) { | |
return compare(contents, o.contents); | |
} | |
private static int compare(ListOrInt a, ListOrInt b) { | |
if (a.isList() || b.isList()) { | |
Iterator<ListOrInt> i1 = a.asList().iterator(); | |
Iterator<ListOrInt> i2 = b.asList().iterator(); | |
while (i1.hasNext() && i2.hasNext()) { | |
int c = compare(i1.next(), i2.next()); | |
if (c != 0) return c; | |
} | |
if (i1.hasNext()) return +1; | |
if (i2.hasNext()) return -1; | |
return 0; | |
} else { | |
return Integer.compare(a.getInt(), b.getInt()); | |
} | |
} | |
private static class CharIterator { | |
int curpos; | |
String data; | |
CharIterator(String data) { | |
this.data = data; | |
curpos = 0; | |
} | |
char peek() { | |
return data.charAt(curpos); | |
} | |
char pop() { | |
return data.charAt(curpos++); | |
} | |
int popInt() { | |
int i=0; | |
while (peek() >= '0' && peek() <= '9') { | |
i = i * 10; | |
i = i + (pop() - '0'); | |
} | |
return i; | |
} | |
} | |
private static abstract class ListOrInt { | |
abstract boolean isList(); | |
abstract int getInt(); | |
abstract List<ListOrInt> asList(); | |
} | |
private static class AList extends ListOrInt { | |
private final List<ListOrInt> l; | |
AList(List<ListOrInt> l) { | |
this.l = l; | |
} | |
boolean isList() { | |
return true; | |
} | |
int getInt() { | |
throw new UnsupportedOperationException("Cannot convert a list to an int"); | |
} | |
List<ListOrInt> asList() { | |
return l; | |
} | |
} | |
private static class AnInt extends ListOrInt { | |
private final int i; | |
private List<ListOrInt> l; | |
AnInt(int i) { | |
this.i = i; | |
} | |
boolean isList() { | |
return false; | |
} | |
int getInt() { | |
return i; | |
} | |
List<ListOrInt> asList() { | |
if (l == null) { | |
// Cache it for later. | |
l = Collections.singletonList(this); | |
} | |
return l; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment