import java.util.ArrayList;
public class Workflow
{
private ArrayList<String[]> steps;
private String otherwise;
public Workflow(String s)
{
steps = new ArrayList<String[]>();
String[] sections = s.split(",");
for (int i = 0; i < sections.length- 1; i++) {
String[] section = new String[4];
String ch = sections[i].split("[<>]")[0];
if (ch.equals("x")) {
section[0] = "0";
} else if (ch.equals("m")) {
section[0] = "1";
} else if (ch.equals("a")) {
section[0] = "2";
} else {
section[0] = "3";
}
if (sections[i].contains("<")) {
section[1] = "<";
} else {
section[1] = ">";
}
section[2] = sections[i].split("[<>]")[1].split(":")[0];
section[3] = sections[i].split(":")[1];
steps.add(section);
}
otherwise = sections[sections.length-1];
}
public String calculate(int[] in) {
for (String[] step: steps) {
if (step[1].equals("<") && in[Integer.parseInt(step[0])] < Integer.parseInt(step[2])) {
return step[3];
} else if (step[1].equals(">") && in[Integer.parseInt(step[0])] > Integer.parseInt(step[2])) {
return step[3];
}
}
return otherwise;
}
}
private HashMap<String, Workflow> workflow;
private ArrayList<int[]> parts;
public int partOne() {
workflow = new HashMap<String, Workflow>();
parts = new ArrayList<int[]>();
for (String line: inputLines) {
if (line.length() == 0) {
continue;
} else if (!line.startsWith("{")) {
workflow.put(line.split("\\{")[0], new Workflow(line.split("\\{")[1].split("\\}")[0]));
} else {
int[] part = new int[4];
String[] xmas = line.split("\\{")[1].split("\\}")[0].split(",");
for (int i = 0; i < 4; i++) {
part[i] = Integer.parseInt(xmas[i].split("=")[1]);
}
parts.add(part);
}
}
int summe = 0;
for (int[] part: parts) {
String nextKey = "in";
while(true) {
nextKey = workflow.get(nextKey).calculate(part);
if (nextKey.equals("R")) {
break;
} else if (nextKey.equals("A")) {
for (int p: part) {
summe += p;
}
break;
}
}
}
return summe;
}
private ArrayList<ArrayList<String[]>> allPaths;
public long partTwo() {
workflow = new HashMap<String, Workflow>();
// lies nur die workflows ein
for (String line: inputLines) {
if (line.length() == 0) {
continue;
} else if (!line.startsWith("{")) {
workflow.put(line.split("\\{")[0], new Workflow(line.split("\\{")[1].split("\\}")[0]));
}
}
Workflow start = workflow.get("in");
allPaths = new ArrayList();
ArrayList<String[]> path = new ArrayList<String[]>();
getPathsToA(start, 0, path);
long ergebnis = 0;
for (ArrayList<String[]> p: allPaths) {
int[][] range = new int[4][2];
for (int i = 0; i < 4; i++) {
range[i][0] = 1;
range[i][1] = 4000;
}
for (String[] r: p) {
int comp;
if (r[1].equals(">") && Integer.parseInt(r[2]) > range[Integer.parseInt(r[0])][0]) {
range[Integer.parseInt(r[0])][0] = Integer.parseInt(r[2]);
} else if (r[1].equals("<") && Integer.parseInt(r[2]) < range[Integer.parseInt(r[0])][1]) {
range[Integer.parseInt(r[0])][1] = Integer.parseInt(r[2]);
}
}
long teilergebnis = 1;
for (int i = 0; i < 4; i++) {
teilergebnis *= range[i][1] - range[i][0] + 1;
}
ergebnis += teilergebnis;
}
return ergebnis;
}
private void getPathsToA(Workflow w, int step, ArrayList<String[]> path) {
if (step >= w.getSteps().size()) {
String nachfolger = w.getOtherwise();
if (nachfolger.equals("A")) {
allPaths.add(path);
} else if (nachfolger.equals("R")) {
// do nothing
} else {
getPathsToA(workflow.get(nachfolger), 0, (ArrayList<String[]>)path.clone());
}
return;
}
String[] stepX = w.getSteps().get(step);
// annahme, es sei false -> gehe zum nächsten step
ArrayList<String[]> p1 = (ArrayList<String[]>)path.clone();
//invertieren
if (stepX[1].equals("<")) {
p1.add(new String[]{stepX[0], ">", stepX[2]});
} else if (stepX[1].equals(">")) {
p1.add(new String[]{stepX[0], "<", stepX[2]});
}
getPathsToA(w, step + 1, p1);
// annahme, es sei true -> gehe zum neuen workflow
if (stepX[1].equals("<")) {
path.add(new String[]{stepX[0], "<", String.valueOf(Integer.parseInt(stepX[2])-1)});
} else if (stepX[1].equals(">")) {
path.add(new String[]{stepX[0], ">", String.valueOf(Integer.parseInt(stepX[2])+1)});
}
if (stepX[3].equals("A")) {
allPaths.add(path);
return;
} else if (stepX[3].equals("R")) {
return;
}
getPathsToA(workflow.get(stepX[3]), 0, path);
}