Created
December 20, 2018 13:23
-
-
Save msx80/8cb7315d097194472b1a22f764d5296d 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 aoc; | |
import java.io.IOException; | |
import java.nio.file.Files; | |
import java.nio.file.Paths; | |
import java.time.Duration; | |
import java.time.Instant; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.HashMap; | |
import java.util.HashSet; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Set; | |
import java.util.stream.Collectors; | |
import java.util.stream.Stream; | |
public class Aoc16 { | |
interface Op{ | |
int exec(int[] s, int a, int b); | |
} | |
enum OpCode { | |
ADDR( (s, a, b) -> s[a] + s[b]), | |
ADDI( (s, a, b) -> s[a] + b), | |
MULR( (s, a, b) -> s[a] * s[b]), | |
MULI( (s, a, b) -> s[a] * b), | |
BANR( (s, a, b) -> s[a] & s[b]), | |
BANI( (s, a, b) -> s[a] & b), | |
BORR( (s, a, b) -> s[a] | s[b]), | |
BORI( (s, a, b) -> s[a] | b), | |
SETR( (s, a, b) -> s[a]), | |
SETI( (s, a, b) -> a), | |
GTIR( (s, a, b) -> a > s[b] ? 1 : 0), | |
GTRI( (s, a, b) -> s[a] > b ? 1 : 0), | |
GTRR( (s, a, b) -> s[a] > s[b] ? 1 : 0), | |
EQIR( (s, a, b) -> a == s[b] ? 1 : 0), | |
EQRI( (s, a, b) -> s[a] == b ? 1 : 0), | |
EQRR( (s, a, b) -> s[a] == s[b] ? 1 : 0); | |
Op operation; | |
OpCode(Op operation) | |
{ | |
this.operation = operation; | |
} | |
public boolean match(TestCase testCase) { | |
int[] state = testCase.before.clone(); | |
exec( state, testCase.input[1], testCase.input[2], testCase.input[3]); | |
return Arrays.equals(state, testCase.after); | |
} | |
public void exec( int[] state, int a, int b, int c) { | |
int res = operation.exec(state, a, b); | |
state[c] = res; | |
} | |
} | |
static class TestCase{ | |
int[] before; | |
int[] input; | |
int[] after; | |
public TestCase(String b, String i, String a) | |
{ | |
b = b.substring(b.indexOf("[")+1, b.lastIndexOf("]")).replace(',', ' '); | |
a = a.substring(a.indexOf("[")+1, a.lastIndexOf("]")).replace(',', ' '); | |
before = parse4(b); | |
input = parse4(i); | |
after = parse4(a); | |
} | |
} | |
public static void main(String[] args) throws IOException { | |
Instant start = Instant.now(); | |
List<String> lines = Files | |
.readAllLines(Paths.get("c:\\aoc16a.txt")) | |
.stream() | |
.collect(Collectors.toList()); | |
List<TestCase> tests = new ArrayList<>(); | |
for (int i = 0; i < lines.size(); i+=4) { | |
tests.add(new TestCase(lines.get(i), lines.get(i+1), lines.get(i+2) )); | |
} | |
findMatch3OrMore(tests); | |
Map<Integer, OpCode> opcodes = findOpcodes(tests); | |
execTestProgram(opcodes); | |
System.out.println(Duration.between(start, Instant.now())); | |
} | |
public static void execTestProgram(Map<Integer, OpCode> opcodes) throws IOException { | |
List<int[]> program = Files | |
.readAllLines(Paths.get("c:\\aoc16b.txt")) | |
.stream() | |
.map(Aoc16::parse4) | |
.collect(Collectors.toList()); | |
int[] state = new int[4]; | |
for (int[] instruction : program) { | |
opcodes.get(instruction[0]).exec(state, instruction[1], instruction[2], instruction[3]); | |
} | |
System.out.println("Final state: "+Arrays.toString(state)); | |
} | |
private static Map<Integer, OpCode> findOpcodes(List<TestCase> tests) { | |
Map<Integer, OpCode> res = new HashMap<>(); | |
Set<OpCode> toFind = new HashSet<>(Arrays.asList(OpCode.values())); | |
while(!toFind.isEmpty()) | |
{ | |
for (TestCase t : tests) { | |
Set<OpCode> matched = toFind.stream().filter(a -> a.match(t)).collect(Collectors.toSet()); | |
if(matched.size() == 1 && !res.containsKey(t.input[0])) | |
{ | |
OpCode o = matched.iterator().next(); | |
res.put(t.input[0], o); | |
toFind.remove(o); | |
break; | |
} | |
} | |
} | |
return res; | |
} | |
public static void findMatch3OrMore(List<TestCase> tests) { | |
long match3 = tests.stream() | |
.filter(t -> countByTest(t) >= 3) | |
.count(); | |
System.out.println("TestCases matching 3 or more ops: "+match3); | |
} | |
private static int countByTest(TestCase testCase) { | |
return (int) Stream.of(OpCode.values()).filter(o -> o.match(testCase)).count(); | |
} | |
public static int[] parse4(String i) { | |
return Stream.of(i.split(" +")).mapToInt(Integer::parseInt).toArray(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment