Advertisement
Guest User

Untitled

a guest
Dec 16th, 2018
181
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.98 KB | None | 0 0
  1. package Advent2018;
  2.  
  3. import util.AdventOfCode;
  4. import util.FileIO;
  5.  
  6. import java.util.*;
  7. import java.util.function.IntBinaryOperator;
  8. import java.util.function.ToIntFunction;
  9.  
  10. public class Day16 extends AdventOfCode {
  11.  
  12.     public Day16(List<String> input) {
  13.         super(input);
  14.         title = "Chronal Classification";
  15.         part1Description = "Samples with 3 or more valid opcodes: ";
  16.         part2Description = "Value at register 0 after running test program: ";
  17.     }
  18.  
  19.     class Sample {
  20.         int[] before = new int[4];
  21.         int[] after = new int[4];
  22.         int[] codes = new int[4];
  23.     }
  24.  
  25.     List<Sample> samples;
  26.     List<int[]> program;
  27.     Command[] commandMap = new Command[16];
  28.  
  29.     class Operation {
  30.         int aReg;
  31.         int aVal;
  32.         int bReg;
  33.         int bVal;
  34.         int c;
  35.         Command cmd;
  36.  
  37.         public Operation(int aReg, int aVal, int bReg, int bVal, int c, Command cmd) {
  38.             this.aReg = aReg;
  39.             this.aVal = aVal;
  40.             this.bReg = bReg;
  41.             this.bVal = bVal;
  42.             this.c = c;
  43.             this.cmd = cmd;
  44.         }
  45.     }
  46.  
  47.  
  48.     enum Command {
  49.         ADDR((x, y) -> x + y, Command::rr),
  50.         ADDI((x, y) -> x + y, Command::ri),
  51.         BANR((x, y) -> x & y, Command::rr),
  52.         BANI((x, y) -> x & y, Command::ri),
  53.         BORR((x, y) -> x | y, Command::rr),
  54.         BORI((x, y) -> x | y, Command::ri),
  55.         MULR((x, y) -> x * y, Command::rr),
  56.         MULI((x, y) -> x * y, Command::ri),
  57.         SETR((x, y) -> x, Command::rr),
  58.         SETI((x, y) -> x, Command::ir),
  59.         EQRI(Command::eq, Command::ri),
  60.         EQIR(Command::eq, Command::ir),
  61.         EQRR(Command::eq, Command::rr),
  62.         GTIR(Command::gt, Command::ir),
  63.         GTRR(Command::gt, Command::rr),
  64.         GTRI(Command::gt, Command::ri);
  65.  
  66.  
  67.         IntBinaryOperator function;
  68.         ToIntFunction<Operation> opcode;
  69.         Command(IntBinaryOperator function, ToIntFunction<Operation> opcode) {
  70.             this.function = function;
  71.             this.opcode = opcode;
  72.         }
  73.  
  74.  
  75.         static int gt(int x, int y) {
  76.             return x > y ? 1 : 0;
  77.         }
  78.  
  79.         static int eq(int x, int y) {
  80.             return x == y ? 1 : 0;
  81.         }
  82.  
  83.         static int rr(Operation op) {
  84.             return op.cmd.function.applyAsInt(op.aReg, op.bReg);
  85.         }
  86.  
  87.         static int ri(Operation op) {
  88.             return op.cmd.function.applyAsInt(op.aReg, op.bVal);
  89.         }
  90.  
  91.         static int ir(Operation op) {
  92.             return op.cmd.function.applyAsInt(op.aVal, op.bReg);
  93.         }
  94.  
  95.     }
  96.  
  97.     void run(int[] reg, int[] codes, Command cmd) {
  98.         int a = codes[1];
  99.         int b = codes[2];
  100.         int c = codes[3];
  101.  
  102.         Operation op = new Operation(reg[a], a, reg[b], b, reg[c], cmd);
  103.         reg[c] = cmd.opcode.applyAsInt(op);
  104.     }
  105.  
  106.     @Override
  107.     public Object part1() {
  108.         int hasThree = 0;
  109.  
  110.         // use this to order enums for part 2
  111.         Map<Integer, Set<Command>> cmdFreq = new HashMap<>();
  112.  
  113.         for (Sample sample : samples) {
  114.             int count = 0;
  115.            
  116.             for (Command cmd : Command.values()) {
  117.                 int[] copy = new int[sample.before.length];
  118.                 System.arraycopy(sample.before, 0, copy, 0, sample.before.length);
  119.                 run(copy, sample.codes, cmd);;
  120.                 if (Arrays.equals(copy, sample.after)) {
  121.                     cmdFreq.putIfAbsent(sample.codes[0], new HashSet<>());
  122.                     cmdFreq.get(sample.codes[0]).add(cmd);
  123.                     count++;
  124.                 }
  125.             }
  126.             if (count > 2) hasThree++;
  127.         }
  128.  
  129.         // find command order
  130.         int done = 0;
  131.         while (done < 16) {
  132.             done = 0;
  133.             for (int i = 0; i < 16; i++) {
  134.                 if (cmdFreq.get(i).size() == 1) {
  135.                     Command cmd = cmdFreq.get(i).toArray(new Command[0])[0];
  136.                     done++;
  137.                     for (int j = 0; j < 16; j++) {
  138.                         if (j != i) {
  139.                             cmdFreq.get(j).remove(cmd);
  140.                         }
  141.                     }
  142.                 }
  143.             }
  144.         }
  145.  
  146.         // load into lookup table
  147.         for (int i = 0; i < 16; i++) {
  148.             commandMap[i] = cmdFreq.get(i).stream().findFirst().orElse(null);
  149.         }
  150.         return hasThree;
  151.     }
  152.  
  153.     @Override
  154.     public Object part2() {
  155.         int[] register = { 0, 0, 0, 0 };
  156.         for (int[] line : program) {
  157.             run(register, line, commandMap[line[0]]);
  158.         }
  159.         return register[0];
  160.     }
  161.  
  162.     @Override
  163.     public void parse() {
  164.         samples = new ArrayList<>();
  165.         program = new ArrayList<>();
  166.         boolean part2 = false;
  167.         Sample sample;
  168.         for (int i = 0; i < input.size(); i++) {
  169.             String line = input.get(i);
  170.             if (part2) {
  171.                 program.add(FileIO.StringArrayToInt(line.split(" ")));
  172.             } else {
  173.                 if (line.startsWith("Before")) {
  174.                     sample = new Sample();
  175.                     String[] split = line.substring(9, line.indexOf(']'))
  176.                             .split(", ");
  177.                     sample.before = FileIO.StringArrayToInt(split);
  178.                     String codes = input.get(++i);
  179.                     String after = input.get(++i);
  180.                     sample.codes = FileIO.StringArrayToInt(codes.split(" "));
  181.                     sample.after = FileIO.StringArrayToInt(after
  182.                             .substring(9, after.indexOf(']'))
  183.                             .split(", "));
  184.                     samples.add(sample);
  185.                 } else {
  186.                     if (line.isEmpty()) {
  187.                         if (input.get(i + 1).isEmpty() && input.get(i + 2).isEmpty()) {
  188.                             i += 2;
  189.                             part2 = true;
  190.                         }
  191.                     }
  192.                 }
  193.             }
  194.         }
  195.     }
  196. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement