From fca03a5d46808a700e5808070ea574e118456e09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89amonn=20McManus?= Date: Wed, 18 Dec 2024 16:10:58 +0000 Subject: [PATCH] Solutions for Days 16 and 17 of 2024. --- README.md | 4 +- src/advent2024/Puzzle16.java | 297 +++++++++++++++++++++++++ src/advent2024/Puzzle17.java | 256 +++++++++++++++++++++ src/advent2024/puzzle16.txt | 141 ++++++++++++ src/advent2024/puzzle17.txt | 5 + src/adventlib/Dir.java | 13 ++ test/advent2024/PuzzleResultsTest.java | 29 ++- 7 files changed, 742 insertions(+), 3 deletions(-) create mode 100644 src/advent2024/Puzzle16.java create mode 100644 src/advent2024/Puzzle17.java create mode 100644 src/advent2024/puzzle16.txt create mode 100644 src/advent2024/puzzle17.txt diff --git a/README.md b/README.md index 1ca2528..4c16f5d 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,9 @@ years 2022, 2023, 2024 (ongoing). They are all coded in Java, needing Java 21 at * [2024-12-11](https://adventofcode.com/2024/day/11): [solution](src/advent2024/Puzzle11.java) (exponential evolution of a list of numbers). * [2024-12-12](https://adventofcode.com/2024/day/12): [solution](src/advent2024/Puzzle12.java) (perimeters and side counts of regions in a grid). * [2024-12-13](https://adventofcode.com/2024/day/13): [solution](src/advent2024/Puzzle13.java) (simultaneous Diophantine equations). -* [2024-12-14](https://adventofcode.com/2024/day/13): [solution](src/advent2024/Puzzle13.java) (vector-moving robots forming a Christmas tree). +* [2024-12-14](https://adventofcode.com/2024/day/14): [solution](src/advent2024/Puzzle14.java) (vector-moving robots forming a Christmas tree). +* [2024-12-16](https://adventofcode.com/2024/day/16): [solution](src/advent2024/Puzzle16.java) (shortest path through a maze with penalty for turns). +* [2024-12-17](https://adventofcode.com/2024/day/17): [solution](src/advent2024/Puzzle17.java) (quining a program on a 3-bit CPU). # Acknowledgements diff --git a/src/advent2024/Puzzle16.java b/src/advent2024/Puzzle16.java new file mode 100644 index 0000000..8f75a0b --- /dev/null +++ b/src/advent2024/Puzzle16.java @@ -0,0 +1,297 @@ +package advent2024; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static java.lang.Integer.max; +import static java.lang.Integer.min; +import static java.lang.Math.abs; +import static java.util.stream.Collectors.toSet; + +import adventlib.CharGrid; +import adventlib.CharGrid.Coord; +import adventlib.Dir; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Table; +import com.google.common.graph.GraphBuilder; +import com.google.common.graph.ImmutableGraph; +import com.google.common.io.CharStreams; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.Collections; +import java.util.EnumSet; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Callable; + +/** + * @author Éamonn McManus + */ +public class Puzzle16 { + private static final String SAMPLE1 = + """ + ############### + #.......#....E# + #.#.###.#.###.# + #.....#.#...#.# + #.###.#####.#.# + #.#.#.......#.# + #.#.#####.###.# + #...........#.# + ###.#.#####.#.# + #...#.....#.#.# + #.#.#.###.#.#.# + #.....#...#.#.# + #.###.#.#.#.#.# + #S..#.....#...# + ############### + """; + + private static final String SAMPLE2 = + """ + ################# + #...#...#...#..E# + #.#.#.#.#.#.#.#.# + #.#.#.#...#...#.# + #.#.#.#.###.#.#.# + #...#.#.#.....#.# + #.#.#.#.#.#####.# + #.#...#.#.#.....# + #.#.#####.#.###.# + #.#.#.......#...# + #.#.###.#####.### + #.#.#...#.....#.# + #.#.#.#####.###.# + #.#.#.........#.# + #.#.#.#########.# + #S#.............# + ################# + """; + + private static final Map> INPUT_PRODUCERS = + ImmutableMap.of( + "sample 1", + () -> new StringReader(SAMPLE1), + "sample 2", + () -> new StringReader(SAMPLE2), + "problem", + () -> new InputStreamReader(Puzzle16.class.getResourceAsStream("puzzle16.txt"))); + + public static void main(String[] args) throws Exception { + for (var entry : INPUT_PRODUCERS.entrySet()) { + String name = entry.getKey(); + try (Reader r = entry.getValue().call()) { + List lines = CharStreams.readLines(r); + var maze = parseMaze(lines); + var costs = computeCosts(maze); + int leastCost = Collections.min(costs.row(maze.end).values()); + System.out.printf("For %s, least cost is %d\n", name, leastCost); + Set bestEdges = new LinkedHashSet<>(); + reverseVisit(maze, costs, bestEdges, maze.end, leastCost); + Set bestCoords = new LinkedHashSet<>(); + for (var pair : bestEdges) { + // TODO: clean up + Coord start = pair.first; + Coord end = pair.second; + bestCoords.add(start); + bestCoords.add(end); + if (start.col() == end.col()) { + for (int line = min(start.line(), end.line()); + line < max(start.line(), end.line()); + line++) { + bestCoords.add(new Coord(line, start.col())); + } + } else { + checkState(start.line() == end.line()); + for (int col = min(start.col(), end.col()); col < max(start.col(), end.col()); col++) { + bestCoords.add(new Coord(start.line(), col)); + } + } + } + System.out.printf("For %s, tiles on path: %d\n", name, bestCoords.size()); + } + } + } + + private static Dir direction(Coord a, Coord b) { + if (a.line() == b.line()) { + return a.col() < b.col() ? Dir.E : Dir.W; + } else { + checkState(a.col() == b.col()); + return a.line() < b.line() ? Dir.N : Dir.S; + } + } + + private static int distance(Coord a, Coord b) { + return abs(a.line() - b.line() + abs(a.col() - b.col())); + } + + private static Table computeCosts(Maze maze) { + Table costs = HashBasedTable.create(); + visit(maze, costs, maze.start, Dir.E, 0); + return costs; + } + + // Each node in the graph has a map from direction entered to lowest cost. If we reach a node + // in a certain direction and it already has a cost for that direction, then if that cost is lower + // than the current cost we can stop along this path, and otherwise we can update the cost and + // keep going. + private static void visit( + Maze maze, + Table costs, + Coord current, + Dir enteringFrom, + int costOnCurrentPath) { + Integer existingCost = costs.get(current, enteringFrom); + if (existingCost != null && existingCost <= costOnCurrentPath) { + return; + } + costs.put(current, enteringFrom, costOnCurrentPath); + for (Coord next : maze.graph.successors(current)) { + int nextCost = costOnCurrentPath + distance(current, next); + Dir direction = direction(current, next); + if (direction != enteringFrom) { + nextCost += 1000; + } + visit(maze, costs, next, direction, nextCost); + } + } + + record CoordPair(Coord first, Coord second) { + @Override + public String toString() { + return first + "-" + second; + } + } + + // Work backwards from the end, starting with the final cost. At each point, we have a target cost + // which we know correspnods to the best path, and we can trace along every edge where the + // difference between this target cost and the cost of the other end of the edge is indeed the + // cost that the edge would have added. + private static void reverseVisit( + Maze maze, + Table costs, + Set bestEdges, + Coord current, + int targetCost) { + for (Coord prev : maze.graph.predecessors(current)) { + int distance = distance(prev, current); + Dir dir = direction(prev, current); + costs + .row(prev) + .forEach( + (prevDir, cost) -> { + int edgeCost = (dir == prevDir) ? distance : distance + 1000; + if (cost + edgeCost == targetCost) { + bestEdges.add(new CoordPair(prev, current)); + reverseVisit(maze, costs, bestEdges, prev, cost); + } + }); + } + } + + record Maze(CharGrid grid, ImmutableGraph graph, Coord start, Coord end) {} + + private static Maze parseMaze(List lines) { + CharGrid grid = new CharGrid(lines); + Coord start = new Coord(grid.height() - 2, 1); + checkArgument(grid.get(start) == 'S'); + Coord end = new Coord(1, grid.width() - 2); + checkArgument(grid.get(end) == 'E'); + ImmutableGraph.Builder builder = GraphBuilder.undirected().immutable(); + parseMaze(builder, grid); + ImmutableGraph graph = builder.build(); + if (false) { + System.out.println(graph); + for (Coord coord : grid.coords()) { + if (coord.col() == 0) { + System.out.println(); + } + if (graph.nodes().contains(coord)) { + System.out.print('+'); + } else { + System.out.print(grid.get(coord)); + } + } + System.out.println(); + } + return new Maze(grid, graph, start, end); + } + + /** + * Constructs a graph from the maze grid. This is a little clunky and it might be better just to + * do a DFS through the grid. Instead, we look at the neighbours of every empty cell. If it has + * more than 2 neighbours, or if it has exactly 2 and they are not opposite each other, then we + * have a node in the graph. + */ + private static void parseMaze(ImmutableGraph.Builder builder, CharGrid grid) { + // Determine the nodes of the graph. A position is a node if it is S (start) or E (end), or if + // it has non-walls on two non-opposite sides. + Set nodes = new LinkedHashSet<>(); + for (Coord coord : grid.coords()) { + switch (grid.get(coord)) { + case 'S', 'E' -> nodes.add(coord); + case '.' -> { + if (isCorner(grid, coord)) { + nodes.add(coord); + } + } + case '#' -> {} + default -> throw new AssertionError(grid.get(coord)); + } + } + + // Trace each row, making an edge between two consecutive nodes unless there is a wall between. + for (int line = 1; line < grid.height() - 1; line++) { + Coord prev = null; + for (int col = 1; col < grid.width() - 1; col++) { + Coord here = new Coord(line, col); + if (grid.get(here) == '#') { + prev = null; + } + if (nodes.contains(here)) { + if (prev != null) { + builder.putEdge(prev, here); + } + prev = here; + } + } + } + + // Same thing for the columns. + for (int col = 1; col < grid.width() - 1; col++) { + Coord prev = null; + for (int line = 1; line < grid.height() - 1; line++) { + Coord here = new Coord(line, col); + if (grid.get(here) == '#') { + prev = null; + } + if (nodes.contains(here)) { + if (prev != null) { + builder.putEdge(prev, here); + } + prev = here; + } + } + } + } + + private static final Set NS = EnumSet.of(Dir.N, Dir.S); + private static final Set EW = EnumSet.of(Dir.E, Dir.W); + private static final Set> NS_OR_EW = ImmutableSet.of(NS, EW); + + private static boolean isCorner(CharGrid grid, Coord coord) { + Set adjacent = + Dir.NEWS.stream().filter(dir -> grid.get(dir.move(coord)) != '#').collect(toSet()); + return switch (adjacent.size()) { + case 0, 1 -> false; + case 3, 4 -> true; + case 2 -> !NS_OR_EW.contains(adjacent); + default -> throw new AssertionError(adjacent.size()); + }; + } +} \ No newline at end of file diff --git a/src/advent2024/Puzzle17.java b/src/advent2024/Puzzle17.java new file mode 100644 index 0000000..370ca07 --- /dev/null +++ b/src/advent2024/Puzzle17.java @@ -0,0 +1,256 @@ +package advent2024; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static com.google.common.collect.ImmutableMap.toImmutableMap; +import static java.lang.Math.toIntExact; + +import com.google.common.base.Joiner; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; +import com.google.common.io.CharStreams; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.List; +import java.util.OptionalLong; +import java.util.concurrent.Callable; +import java.util.regex.Pattern; +import java.util.stream.IntStream; + +/** + * @author Éamonn McManus + */ +public class Puzzle17 { + private static final ImmutableList SAMPLES = + ImmutableList.of( + // Tests + """ + Register C: 9 + + Program: 2,6 + """, + """ + Register A: 10 + + Program: 5,0,5,1,5,4 + """, + """ + Register A: 2024 + + Program: 0,1,5,4,3,0 + """, + """ + Register B: 29 + + Program: 1,7 + """, + """ + Register B: 2024 + Register C: 43690 + + Program: 4,0 + """, + // Part 1 Sample + """ + Register A: 729 + Register B: 0 + Register C: 0 + + Program: 0,1,5,4,3,0 + """, + // Part 2 Sample + """ + Register A: 117440 + Register B: 0 + Register C: 0 + + Program: 0,3,5,4,3,0 + """); + + private static final ImmutableMap> SAMPLE_INPUT_PRODUCERS = + IntStream.range(0, SAMPLES.size()) + .boxed() + .collect(toImmutableMap(i -> "Sample " + i, i -> () -> new StringReader(SAMPLES.get(i)))); + + private static final ImmutableMap> INPUT_PRODUCERS = + ImmutableMap.>builder() + .putAll(SAMPLE_INPUT_PRODUCERS) + .put( + "problem", + () -> new InputStreamReader(Puzzle17.class.getResourceAsStream("puzzle17.txt"))) + .build(); + + public static void main(String[] args) throws Exception { + for (var entry : INPUT_PRODUCERS.entrySet()) { + String name = entry.getKey(); + try (Reader r = entry.getValue().call()) { + List lines = CharStreams.readLines(r); + checkArgument(lines.size() >= 3); + int blank = lines.indexOf(""); + checkArgument(blank == lines.size() - 2); + Pattern registerPattern = Pattern.compile("Register ([ABC]): (\\d+)"); + long[] reg = new long[3]; + for (int i = 0; i < blank; i++) { + var matcher = registerPattern.matcher(lines.get(i)); + checkState(matcher.matches()); + int regI = matcher.group(1).charAt(0) - 'A'; + checkState(regI >= 0 && regI < 3); + reg[regI] = Integer.parseInt(matcher.group(2)); + } + String programString = Splitter.on(' ').splitToList(lines.get(blank + 1)).get(1); + List program = + Splitter.on(',').splitToStream(programString).map(Integer::valueOf).toList(); + + // Part 1 + List output = run(program, reg.clone()); + System.out.printf( + "For %s, program output is %s\n", + name, output.isEmpty() ? "empty" : Joiner.on(',').join(output)); + + // Part 2 + if (name.equals("problem")) { + if (false) { + disassemble(program).forEach(System.out::println); + } + int len = program.size(); + // The last instruction should be jnz 0, encoded as [3, 0]. + checkState(program.get(len - 2) == 3 && program.get(len - 1) == 0); + List subprogram = program.subList(0, len - 2); + OptionalLong quineA = search(0, program, subprogram); + if (quineA.isPresent()) { + System.out.printf("Quine A is %d\n", quineA.getAsLong()); + } + } + } + } + } + + /* + + I found Part 2 much more difficult than previous days. + + This was my problem input: + 2,4,1,5,7,5,0,3,4,1,1,6,5,5,3,0 + + Disassembled to this (with explanatory comments): + bst A: b = a & 7 + bxl 5: b ^= 5 + cdv B: c = a >> b + adv 3: a >>= 3 + bxc 1: b ^= c + bxl 6: b ^= 6 + out B: b & 7 + jnz 0: back to top unless a is 0 + + So each loop produces an output value, then shifts register A 3 bits right and loops, + until A is 0. The value to output depends on the bottom 3 bits of A, which form a shift amount + from which the 3 output bits will be selected. (I presume everybody's problem looked like this, + with the xor values, the unused operand to the bxc instruction, and probably instruction order + differing.) + + We can work backwards from the end of the list. At each point, we have a target A value that we + want to end up with. At the end of the list it must be 0 so that the loop will exit. Before then, + it must be some value that will produce the remaining output digits. The two key insights, which + I needed forum help to get, were (1) at each step we are only looking at the possible values for + the bottom 3 bits, since the target A value is fixed; and (2) several such possible values will + produce the correct output digit. Not every 3-bit combination will work as we proceed backwards + through the desired output, so we must be prepared to backtrack. + + */ + + private static OptionalLong search( + long targetA, List targetOutput, List subprogram) { + if (targetOutput.isEmpty()) { + return OptionalLong.of(targetA); + } + int target = targetOutput.getLast(); + List shorterOutput = targetOutput.subList(0, targetOutput.size() - 1); + for (int bottom = 0; bottom < 8; bottom++) { + long a = (targetA << 3) | bottom; + List out = run(subprogram, new long[] {a, 0, 0}); + checkState(out.size() == 1); + if (out.get(0) == target) { + OptionalLong newA = search(a, shorterOutput, subprogram); + if (newA.isPresent()) { + return newA; + } + } + } + return OptionalLong.empty(); + } + + private static final int A = 0; + private static final int B = 1; + private static final int C = 2; + + /** Runs the given program with the given register array. */ + private static List run(List program, long[] reg) { + checkArgument(reg.length == 3); + List out = new ArrayList<>(); + for (int pc = 0; pc < program.size(); pc += 2) { + int opcode = program.get(pc); + int opd = program.get(pc + 1); + switch (opcode) { + case 0, 6, 7 -> { + long opd2 = combo(opd, reg); + int r = + switch (opcode) { + case 0 -> A; + case 6 -> B; + case 7 -> C; + default -> throw new AssertionError(opcode); + }; + reg[r] = (opd2 >= 64) ? 0 : (reg[A] >> (int) opd2); + } + case 1 -> reg[B] ^= opd; + case 2 -> reg[B] = combo(opd, reg) & 7; + case 3 -> { + if (reg[A] != 0) { + pc = opd - 2; + } + } + case 4 -> reg[B] ^= reg[C]; + case 5 -> out.add(toIntExact(combo(opd, reg) & 7)); + } + } + return out; + } + + private static long combo(int opd, long[] reg) { + return switch (opd) { + case 0, 1, 2, 3 -> opd; + case 4, 5, 6 -> reg[opd - 4]; + default -> throw new AssertionError(opd); + }; + } + + private static final ImmutableList OPCODES = + ImmutableList.of("adv", "bxl", "bst", "jnz", "bxc", "out", "bdv", "cdv"); + private static final ImmutableSet COMBO_OPCODES = + ImmutableSet.of("adv", "bdv", "cdv", "bst", "out"); + + private static List disassemble(List program) { + List out = new ArrayList<>(); + for (int i = 0; i < program.size(); i += 2) { + int op = program.get(i); + String opcode = OPCODES.get(op); + int opd = program.get(i + 1); + String opdString = + COMBO_OPCODES.contains(opcode) ? disassembleCombo(opd) : String.valueOf(opd); + out.add(op + " " + opd + ": " + opcode + " " + opdString); + } + return out; + } + + private static String disassembleCombo(int opd) { + return switch (opd) { + case 0, 1, 2, 3 -> String.valueOf(opd); + case 4, 5, 6 -> String.valueOf((char) ('A' + opd - 4)); + default -> throw new AssertionError(opd); + }; + } +} \ No newline at end of file diff --git a/src/advent2024/puzzle16.txt b/src/advent2024/puzzle16.txt new file mode 100644 index 0000000..54f04c8 --- /dev/null +++ b/src/advent2024/puzzle16.txt @@ -0,0 +1,141 @@ +############################################################################################################################################# +#.................#.....#.#...#...............#.......#.......#.......#.....#.........#.............#...#.......#.#.......#.........#...#..E# +#.#.#.#.###.#####.###.#.#.#.#.#.#####.#######.#.###.###.#.###.###.#.#.###.#.###.#.###.#######.#.###.#.#.###.###.#.#.#.#####.#.#####.#.#.###.# +#...#.#...................#.#...#.....#...#...#...#...............#.#.....#...#.#.#...#.....#.#...#.#.#...#.#...#.#.#.....#.#.....#...#.....# +#.###.#######.#####.###.###.#####.#####.#.#.###.#.#.#.#####.###.###.#########.###.#.###.###.#####.#.#.###.#.###.#.#.#####.#.###.#.#########.# +#.#.#.......#.#.............#...#.....#.#.....#.#.#.#.#...#.#.......#.......#.....#.#...#.#.#.....#.#.#...#...#.#.....#.....#...#.#.......#.# +#.#.#######.#.#.#######.#.###.#######.#####.#.###.###.#.#.#.###########.###.#######.###.#.#.#.#####.#.#.#####.#.#######.###.#.#.#.###.###.#.# +#.....................#...#.........#.......#.#...#.............................#...#...#.#...#.......#.#.....#.#.....#.......#.#...#...#.#.# +#.#########.#####.###.#.#.#####.###.#####.#.#.#.#.#.###.#.#.#.#.#.#.#.#.#.#####.#.###.###.#####.#######.###.###.#.###.#########.###.#####.#.# +#.#.......#...#...#.#...#.................#...................#.#...#.................#.......#.#...#.......#.#...#.#.....#.....#...#.....#.# +#.#.#####.#.#.#.#.#.###.#.#.#####.#.#.#.###.#####.###.###.#.#.#.###.#########.#.#.#.#####.#.###.#.#.#########.#####.#####.#######.###.###.#.# +#.#.#.....#.#.#.#.....#...#.#.#.........................#.#.#.#...#.............#.#...............................#.#...#...#.....#...#...#.# +###.#####.###.#.#.#.###.###.#.#.#.#.#.###.#.#.#.#.#####.#.#.#.#.#.###.#.#.#.#####.#####.###.#.###.###.#.###.#.#.#.#.#.#.###.#.#######.#####.# +#...#...#.....#.#...#.....#.#...#.#.#...#.#.#.#...#.....#.....#.#.....#.#...#.................#...#.#...#...#.#.#.#.#.#...#.#.#.......#.....# +#.###.#.###.###.#.###.#.###.#.###.#.###.#.#.#.#####.#####.#.#######.###.#.###.#.#####.#.#.###.#.###.#####.#####.#.#.#.###.#.#.#.#.###.#.##### +#...................#.#.#...#.#.#.....#.#.#.#.#.....#.....#...#...#.#...#.#...#.......#.#...#.#.#.......#...#...#...#.#.#...#.#.#...#.#...#.# +#.#####.###.#.###.#.#.#.#.###.#.#####.#.#.#.#.#.#######.#.###.#.#.###.#####.#########.###.#.###.#.###.#####.#.#####.#.#.#####.###.#.#####.#.# +#.#...#...#.#.....#...#.....#.#.....#.#.#...#.#...#.....#...#...#...#.....#.#.#.....#...#.#.#...#...#.....#.#.#.....#.....#.#...#.#.........# +#.#.#####.#.#####.###.#.###.#.#.###.#.#.#####.###.#.#####.#######.#.#.###.#.#.#.###.###.###.#.#####.#####.#.#.#.#########.#.#.#.#.#######.#.# +#.#.....#.#.#...#...#...#...#.#.#.#...#.....#.......#.......#...#.#.#...#...#.#.#.#.#.......#...#.#...#...#.#.#.#.....#.......#.#...#...#...# +#.#.#.###.#.#.#.###.###.#.###.#.#.#.#######.#.#.#####.#####.#.#.###.#.#####.#.#.#.#.###########.#.###.#.#.#.#.###.###.#.###.###.#####.#.#.#.# +#.#.#...#.#.#.#...#.#...#.......#...#.......#.#.#.....#.......#.#...#.#...#...#...#.....#.......#.....#.#.#.#.....#...#...#.#.#.#.........#.# +#.#####.#.#.#.###.#.###.#.###########.#########.#.#####.#######.#.#####.#.#######.#####.#.#############.###.#.#####.#.###.#.#.#.#.#######.#.# +#.#.....#.#.#.#...#...#.#.#.....#.....#.........#.......#...#.....#.....#.......#.#...#.#.............#.#...#.....#.#.#...#...#.....#.....#.# +#.#.#####.#.#.#.#####.#.#.#.###.#.###.#.###########.#.###.#.#####.#.###########.#.###.#.#.#.###.#.###.#.#.#######.#.#.#.###########.#.#.#.### +#.#.....#.......#.#...#.#.....#.#.#...#.#.........#.#...#.#.......#...#.......#.#...#.#...#.....#.#.#.#.#.....#.#.#.#...#.......#.#.#.#.#...# +#.#####.#.#####.#.#.#.#########.#.#####.#.#.#####.#.#####.###.#.#####.###.###.#.###.#.###########.#.#.#.#####.#.#.#.#####.#.###.#.#.#.###.#.# +#.....#.#...#.....#.......#...#.#.#...#.#.#.#...#.#.......#.#.............#...#.....#...........#.#...#.....#.#.#.#.....#...#...#...#.....#.# +#####.#.###.#####.#######.#.#.#.#.#.#.#.#.#.#.#.###########.#######.###############.#####.#####.#.#.###.###.#.#.#.###.#.###.###.#########.#.# +#...............#.......#.#.#...#...#.#.#.#...#.....#.......#...#...#.....#.......#...........#...#...#...#.#.#.......#...#...#...#.....#.#.# +###.#.#.#.#.#.#.#######.#.#.#.#######.#.#########.#.#.#####.###.#.#.#.###.#.#####.#########.#.#######.#.#.#.#.###########.###.###.#.###.#.#.# +#...#...#.#.#.#.....#.#.#.#.#.#.....#...........#.#...#...#.#...#.#...#.#...#...#...#...#...#.#.......#.#.#.#.......#...#...#...#...#.#.#...# +#.#######.#.#.#####.#.#.#.#.#.#.###.#.###.#.###.#.#####.#.#.#.###.#####.#####.#####.#.#.#.###.###.#######.#.#######.#.#####.#.#.#####.#.#.#.# +#.....#...#.....#...#...#.#.#.#.#...#.#.......#.#.....#.#.#.#.#...#.....#.........#...#.#.#.#...#...#.....#...#.....#...#...#.#...#.......#.# +#.###.#.#####.###.#######.#.#.#.#.###.#.#####.#.#.###.#.#.#.#.#.#####.###.#######.#####.#.#.###.###.#.###.#####.#####.#.#.###.###.#.#####.### +#...#.#.#.#...#...#.........#.#.#.#...#.....#...#...#.#.#.....#.....#...#.#...#.......#...#...#.#.....#...#.....#.....#...#.....#.#...#.....# +#####.#.#.#.#.#.###.###########.#.###.#####.#####.#.#.###########.#.###.#.#.#.#.#############.#.###########.#####.###########.#.#.#####.#.#.# +#...#.#.#...#.#...#.#...........#...#.......#.......#.....#.....#.#.....#...#.#...............#.#...#.......#.#...#.........#.#...#.....#...# +#.#.#.#.#####.###.#.#.#############.#######.#####.#######.#.###.###.#.#######.#######.#######.#.#.#.#.#######.#.###.#######.#.###.#.#####.#.# +#.#...#.#.....#.#...#...#.#.......#.......#.....#.....#...#...#.....#.......#.#...#...#.....#.#...#...........#.....#...#...#...#...#.....#.# +#.###.#.#.###.#.#######.#.#.###.#########.#####.#.#####.#.###.#######.###.#.#.#.#.#.###.#####.###########.#.#.#######.#.#.###.#.#.###.###.#.# +#...#.#.#...#.....#...#.#.#.#.#.......#...#.....#.#...#.#.....#...#...#...#.#.#.#.#.#.........#.........#.#.#.#...#...#.#...#.#...#...#.....# +###.#.#.###.#####.###.#.#.#.#.###.#####.###.#####.#.#.#.###.#.###.#.###.###.#.###.#.#######.###.#######.#.#.#.#.###.###.###.#.###.#.#####.### +#...#.#.....#...#...#.#.#.......#.#.....#.......#.#.#...#...#...#.....#.....#.....#.......#...#.#...#...#.#.#...#...#.....#.#...............# +#.#####.#####.#.###.#.#.#####.###.#.###########.###.#######.###.#.###.#####.#####.#######.###.#.#.#.#.#####.###.#.###.#.#.#.#.#.#.#######.#.# +#.........#...#...#...#.....#.#...#.........#.#...#.#.....#.#...#...#...#.#.....#...#...#.#.#.#.#.#.#.......#...#...#.#...#.#...#.#.........# +#.#.###.#.#.###.#####.#####.###.#####.###.#.#.###.#.#.###.#.#.###.#.###.#.#.#######.#.#.#.#.#.#.#.#.#.#######.#####.#.#.#.#.#####.#.#.#.#.#.# +#...#...#...#.#.....#.#...#.....#...#.....#.#...#.#.....#.#.#.#...#...#.#.#.......#...#.#.........#.#...#.......#...#.#.#.#.#.......#.#...#.# +#.###.#.#####.#####.#.#.#######.#.#.#####.#.###.#.#######.#.#.#.#####.#.#.#######.#####.#.#######.#.#.#.###.#####.###.#.#.#.#.###.#######.### +#...#.......#.....#...#.....#...#.......#.#...#.#.....#...#.#...#...#...#.#.......#.....#.#.....#.#...#...#...#.....#.#...#.#.#.........#...# +###.###.#####.###.#####.#.###.###.#####.#####.#.#####.#.#####.#.###.#.#.#.#.#######.#####.#.###.#.#######.###.#.#####.#.###.#.#.#.#####.#.#.# +#.#...#.......#.#.....#.#...#.#...#...#.......#.#.....#.....#.#.....#.....#.........#.#...#.......#.....#.#...#...#...#.#...#.#.#.....#.....# +#.###.#.#######.###.###.###.#.#.###.#.#########.#.#########.#.#####.###########.#####.#.#####.#######.#.#.###.###.#.###.#.#####.#.#.#.###.#.# +#.#...#...........#.....#...#.#.#...#...........#...#.....#.#.#.#...#...#.....#.....#.#...#...........#.#...#.#...#.#...#.#.....#...#.#.....# +#.#.#.#.###########.#####.#.#.#.#############.#.###.#.###.#.#.#.#.###.###.###.#####.#.###.#.###.#.#####.###.#.#.###.#.###.###.###.###.#.#.### +#.................#.#.....#.#.#.........#...#.#...#.#.#.#...#.#...#...#...#.#.#...#...#...#.....#.#...#.#.#.#.#...#.#.#...#...#...#...#.....# +#.###.###.#.#####.###.#####.#.#########.#.#.#.#####.#.#.###.#.###.###.#.###.#.#.#####.#.#.###.###.#.#.#.#.#.#####.#.###.###.###.#.#.#######.# +#.....#.#...#...#.#.....#...#.#...#...#.....#.#...#...#.#...#...#.#...#...#.#.#.....#...#.....#.....#.#.....#.....#.....#...#...#...#.....#.# +#####.#.#######.#.#.###.#.###.#.###.#.#####.#.#.#.#####.#.#####.#.#.#####.#.#.###.#####.###.###.#####.###.#.#.#.###########.#.###.#####.###.# +#...............#...#.....#.#.#.#...#.....#.#...#...........#.#.#...#...#.#.#...#.#.....#...#...#.......#.#.#...............#...#.......#...# +#####.#.###.###.#####.#.###.#.#.#.#####.#.#.#.#.###########.#.#.###.#.#.#.#.###.#.#.#####.#.#.###.#######.#.#################.#.#######.#.### +#.......#.....#.#...#.#...#.#.#.......#.#.#.#...#.........#.#.#...#.#.#.#.#.#...#.#.....#.#.#.#.#.........#.........#.........#.#.......#...# +#.###.#.#.#.#.#.#.#.#.###.#.#.###.#####.#.#.#####.#######.#.#.###.###.#.#.#.#.###.###.###.#.#.#.#############.#####.#.###.#####.###########.# +#.....#.#.#.#.#...#...#...#.#...#.#.....#.#.#...#...#...#.#.....#.....#...#.#...#.#...#...#.#.....#.....#...#.#...#.#...#.....#...........#.# +#.###.###.#.#.#########.###.###.#.#.#####.#.#.#.###.#.###.###########.#####.###.#.#.###.###.#####.#####.#.#.#.#.#.###.#.#.###############.#.# +#.#.#.....#.#...............#...#.#...#...#...#.....#...#...#...#...#.......#...#.#...#...#...#.........#.#...#.#.......#...........#.....#.# +#.#.#.#####.#################.#######.#.###############.#.#.#.#.#.#.#######.#.#.#.###.###.#####.#########.#####.#######.#####.#####.#.#.###.# +#.#...#.........#...#.........#.......#.#.................#...#.#.#.#...#.....#.#.......#.......#...#.....#.....#...........#.#...#.#.#.....# +#.#.#.#.###.#.###.#.#.#########.#.#######.#########.#####.#####.#.#.#.#.###.###.#####.#######.###.#.#.#####.#####.#####.###.###.#.#.#.#.##### +#.#.....#...#.....#.#...#.......#.#...#...#...#...#...........#.#.#...#...#.#...#...#.#.....#...#.#...#.....#...#.....#...#...#.#.#.#...#...# +#.#.#.#####.#######.###.#######.#.#.#.#.#####.#.#.#######.###.#.#.#######.#.#.#.#.#.###.###.###.#.###.#.#####.#.#########.###.#.#.#.#####.#.# +#.#...#...#.......#...#.#.....#.#...#.........#.#...#...#.#...#.......#.#.#.#.#.#.#.#.....#.#...#...#.#...#...#...........#.#.#.#.......#.#.# +#.###.#.#.#.#.###.###.#.#.###.#.###.#########.#.###.#.#.###.#.#########.#.###.###.#.#.#####.#######.#####.#.###############.#.#.#######.###.# +#.#.....#.....#.#...#.#.#.#.......#...#.....#.#...#...#.....#...#.......#.#...#...#...#.....#.......#...#.#...#.......#.....#...#.....#...#.# +#.#.#.#########.###.#.#.#.###.###.#.#.#.###.#####.#############.#.#######.#.###.#######.#####.#######.#.#.###.#.#.###.#.###.###.#.#.#.###.#.# +#.#.#.......#.....#.#.#.#...#...#.#.#...#.........#...........#.#.#.......#.....#...#...#.......#.....#...#...#.#...#.#...#.........#.#...#.# +#.#.#.#####.#.#####.#.#.#.#.###.#.#.#####.#####.#############.#.#.#.#######.#######.#.#########.#.#########.###.###.#.###.#####.#.###.#.###.# +#.#...................#.#.#...#.#.#.#.....#...#...............#.#...#.....#.#.......#.....#.....#.#.........#.#...#.#.....#.........#.#.....# +#.###.#.#####.#.#####.#.#####.#.#.#.#######.#.###.###.#######.#.#####.#.#.#.#.#.###.#.###.#.#####.###.#######.###.#.###.#.#.###.#.#.#.###.#.# +#.....#.....#...#.....#.......#.#.#.........#.......#.#...#...#...#...#...#.#.#...#.....#.#...........#...#.....#.#.#.......#.......#.#...#.# +###########.#.###.#############.#.#############.#.#.###.#.#######.###.#.#.#.###.#.#####.#.#.#######.###.#.###.#.#.#.###.#.#####.#.###.###.#.# +#.......#...#.#.#.#.........#...#...#.........#.#.#.....#...#...#.......#.#...#.#...#.#.#.#...#.....#...#...#.#...#.#...#.....#.#.........#.# +#.###.###.###.#.#.#.###.###.#.###.###.#######.#.#.#########.#.#.#########.###.#.###.#.#.#.#####.###.#.#####.#.#####.#.#####.#.###.#########.# +#...#.#...#.....#.....#.#...#...#.#...#.....#...#...#.....#.#.#.....#...#.#.#.#.#...#...#...#.........#.....#...#...#.......#.......#.......# +#.#.#.#.#############.#.#.#####.#.#.###.#.#########.#####.#.#.#.###.###.#.#.#.#.#.###.#####.#.###.###.#.#########.#####.#########.#.#.####### +#.#.#.#.#.........#...#.#.....#...#...#.#.........#.#.....#...#.#.....#.#.#.#.#.#...#...#...#.#...#...#.#.......#.....#.#.....#...#.#.......# +#.#.###.#.#######.#####.#####.#.#.###.###.#####.###.#.###.#####.#####.#.#.#.#.#.###.#####.###.#.###.###.###.#.#.#####.#.###.#.#.#.#.#######.# +#.#.....#.....#.#.......#.#...#.#.#.#...#.....#...#.#...#.#...#.#.......#...#.#.#...#...#.....#.......#...#...#.......#...#.#...#.#.......#.# +#.#######.###.#.###.#####.#.###.#.#.###.#.#.#.#.#.#.#.#.#.#.#.#.#.#.###.###.#.###.###.#.#######.#########.#.#############.#.#.###.#########.# +#.#...#...#...#.....#...#.....#.#.#...#.#.#.#...#.#.#.#.#...#.#...#...#...#.#.....#...#.......#...#...#...#.........#.......#.#...#.....#...# +#.###.#.###.###.###.#.#.###.#.#.#.#.#.#.###.###.#.#.#.#.#############.#####.#.#####.#########.#####.#.#.#####.#.###.#######.#.#.#.#.###.#.### +#...#.#.#.#.#...#.....#...#.#...#...#.#.....#...#.#.#.#.............#.......#.......#...#...#.......#...#...#.#.............#...............# +###.#.#.#.#.#####.#####.#.#.#.###.#######.#.#.###.#.#########.#####.#######.#.#.#####.###.#.#######.#####.#.#.###.#########.#.###.#.#.#.#.#.# +#...#.....#.........#...#.#.#...#.........#.......#.#.......#.#...#.....#.....#...#.......#.........#.....#.....#.#.......#.#...#.....#.#...# +#.###.#.#.#.#######.#.#.#.#####.#.#########.#.#####.#.#####.#.#.#.#####.#.#######.###.#####.#######.###.#########.#.#.#####.#.#####.###.###.# +#.....#...#.......#.#.#...#.....#.#.........#.#...#.#.#.....#...#.....#.#.......#...#.#.....#.....#.....#.......#.#.#.....#...#...#.#...#...# +#####.#.###.#.###.#.#.#.###.#####.###.###.#.###.#.#.#.#.#####.#########.#####.#####.###.#####.#####.#.###.#####.#.#######.#####.#.###.###.### +#...#.....#.#.....#.#.#.#...#...........#.#.....#.....#.....#.#...#...#.....#.......#...#...#.......#.#...#.................#...#.#...#...#.# +#.###.#.#.#.#.#####.#.###.###.###.#####.###.###########.###.###.#.#.#.#.#.###.#.#####.###.###.#.###.#.#.#####.#####.###.#####.###.#.###.###.# +#.......#...#...#...#...#.#.......#...#...#.#.........#...#.....#...#...#.#...#.#.....#.......#...#...#...........#...#.#.....#.#.#...#...#.# +#.#.#.#######.#.#######.#.#####.###.#####.#.#.#######.#.#.#####.###.#######.###.###.###########.#.#####.#########.###.###.#.###.#.###.###.#.# +#.#.....#.....#.#.......#.....#.#.........#.#.#.....#.#.#...#.....#.#.....#...#...#.............#...........#.....#...#...#.............#...# +#.###.#.#.#.#.#.#.#.#########.#.#.#.#.#######.#.###.#.#.###.#####.#.#.###.###.###.#########.#########.#####.#.#.#.#.#.#.###.#.#######.#####.# +#.#.#...#.#.#.#.#.#.........#.#.#.#.#.#.......#.#.....#...#.....#...#.#.#.......#.#.......#.......#...#.#.....#.#.....#.....#.#...#...#...#.# +#.#.#.###.#.#.#.#.#.#####.###.#.#.###.#.#######.#########.#####.#####.#.#########.#.#####.###.#####.###.#.###########.#####.#.#.#.#####.#.#.# +#...#...#.#.....#.#.#...#.#...#.#...#...#.....#.........#.#...#...#...#.....#...#.#.....#...#.#...#...#.....#.......#.#...#.#.#.#...#...#.#.# +###.#.#.#.###.###.#.###.#.#.###.###.#########.#####.###.#.#.#.###.#.###.#.###.#.#.#.###.###.###.#.###.#.#####.###.#.#.###.#.###.###.#.###.#.# +#...#...#.....#.....#...#.#.#.......#...........#.....#.#...#...#.#.....#.#...#...#...#.#.......#...#.#...#...#.#...#.....#.....#.#...#.#...# +#.###.#.###.#.###.###.#.#.#.#.#####.#.#########.#.###.#.#.#######.###.#####.###########.###########.#.###.#.###.#.#######.#######.#####.##### +#...#.#.....#...#.....#.#.#.....#...#...#.........#.#.#...#.....#.....#.....#...........#.........#.#...#.#.#...#.......#.#.......#...#.....# +###.#.#####.#.#.#######.#.#####.#.###.#.#.###.#####.#.#####.###.###.###.#######.#.#######.#######.#.###.#.#.###.#######.#.#.#####.#.#.#.##### +#.#.#.....#.....#...#...#.#.....#.#...#.....#.#.....#.....#...#...#.#...#.......#.....#...#.#.....#...#.#.#.......#...#.#.......#...#.#.....# +#.#.#.###.#.#.###.#.#####.#.#.###.###########.#####.###.#.#.#.###.#.#.###.###.###.###.#.###.#.#######.#.#.#######.#.#.#.#####.#.#####.###.#.# +#...#.#...#.#.....#.#.....#...#.........#.....#...#.......#.#...#.#.#.#.#.#.#...#.#.#...#...#...#...#...#.....#...#.#...#...#.#.....#.......# +#.###.#.###.#.#####.#.###.###.#########.#.#####.#.#########.###.#.###.#.#.#.###.#.#.#####.#.###.#.#.#.#######.#.###.###.#.#.#.###.#######.#.# +#...#.#.......#.......#.....#.......#.#.#.#.....#.........#...#.#.....#.#.....#...#.........#.#.#.#...#.....#.#.#.#...#.#.#.....#.....#.....# +###.#.#####.#.#####################.#.#.#.#.#############.#.#.#.#######.#####.###.###.#.###.#.#.###.###.###.#.#.#.###.#.#####.#.#.#.#.#.#.### +#.#.#.#...#.#.....#.....#.........#.#...#.#.#.......#...#.....#.#.........#.#...#...#.#.#.#...#.......#...#.#.#.#...#.#.....#...#...#.#.#...# +#.#.#.#.#.#.#.###.#.###.#.#####.###.#.#.#.#.#.###.#.#.#.#######.#.###.###.#.###.#.#.###.#.###.#######.###.#.###.###.#.#####.#.###.#.###.#.#.# +#.#...#.#.....#...#.#.#.#...#.#.....#.......#...#.#.....#...........#...#.....#...#.....#...#.#.....#.....#.....#.......#...#.....#.#...#.#.# +#.###.#.###.###.###.#.#.###.#.#########.###.###.#.#####.#.###.#.###.###.#####.#####.#####.###.#####.#############.#####.#.###.###.#.#.###.### +#.#...#.#.....#...#...#...#...#...#...#.....#...#.......#...#.....#.#.#.#.....#.....#.....#...#.....#...............#...#.#...#.....#.#.....# +#.#.###.#.#.#.###.###.#.#####.#.#.#.#.#.#####.#.#.###.###.###.#####.#.#.###.###.###.#.###.#.###.###.#.#.###########.#.###.#.#.###.#.#.###.#.# +#.#.#.#...#...#.#...#.#.......#.#...#.#.#.....#.#...#.#...#...#...#...#...#.......#.#...#.#...#.#...#.#.#...#...#...#...#...................# +#.#.#.#####.###.#.#.#.#########.#####.#.#.#####.###.#.#.#.#.###.#.#.#####.#.#.###.#.###.#.###.#.#.###.#.#.#.###.#.#####.#######.#.#.#####.#.# +#.#.#...#...#...#.#.#.#.........#.....#.#.#...#.#...#...#.#.....#.#.#.....#.#...#.#.#...#...#...#.#...#.#.#.....#.....#...#.....#.#.....#.#.# +#.#.###.#.###.#.#.###.#######.###.#.#.#.#.#.#.#.#.#.#.#.#.#######.#.#.#####.###.#.#.#######.#####.#.###.#.###.#.#####.###.#.#####.#.#.###.#.# +#.#.....#.#...#.....................#.#.....#.#.....................#.#.....#...#.#.............#.#...#...#.....#...#...#...#...#...#.....#.# +#.#####.#.#####.#######.###.#.#.###.#.###.#######.###.###.#.#.#.#####.###.###.#.#.###########.###.#.#.###.#.#.#.#.#.###.#####.#.#.#########.# +#.#.....#...#.........#.#.....#.#.#...#...#.....#...#.#.#...#.#.....#...#.#...#...#.....#.....#...#.#.....#...#.#.............#.....#.......# +#.#.#######.#.#######.#.#######.#.#####.#.#.###.###.#.#.#####.#####.###.#.#.###.###.#.###.#####.###.#####.###.#.#.###.#####.#####.#.#.#####.# +#...#.................#.......#.....#...#...#...#...#.#...#...#...#...#.#.#...#...#.#.......#.#.#...#...#.#...#...#.#.......#...#.#.#...#.#.# +#.#.#.###.###.#.#######.#####.#####.#.###.###.###.###.#.#.#.###.#.#.#.#.#.###.#.#.#########.#.#.#.###.#.#.#.#.#####.#####.###.#.#.#.###.#.#.# +#...#...#.#...#.......#...#.#.#.....#.#.....#.#...#...#.#...#...#.#...#.#...#.#.#.......#.....#.#...#.#.#.#.......#.......#...#...#.....#...# +###.###.#.###.#######.###.#.#.#.#####.#.#.#.#.#.###.###.#######.#.#.#.#.###.#.#.#######.#######.#####.#.#####.###.#####.###.#############.### +#.#...#.#...#.....#.#...#.#.#.#...#...#.#.#.#.#...#.#.#.....#...#.#...#.#.#.#.....#.....#.....#.#.....#.#...#...#.....#.#.......#.#...#...#.# +#.#.#.#.###.#####.#.###.#.#.#.###.#.###.#.#.#.#.#.#.#.#####.#.###.#.###.#.#.###.###.#####.###.#.#.#####.#.#.#.###.###.#.#.#####.#.#.#.#.###.# +#.#...#...#.....#.#.#...#...#.#...#.#.#...#...#.#...#.....#...#.#.#...#.#...........#...#...#.#.#.#.#...#.#.#...................#.#.#.#.#...# +#.#.###.#.#####.#.#.#.#######.#.###.#.###.#######.###.#.#######.#.#.#.#.#######.#####.#.###.#.#.#.#.#.###.#.#.#####.#.#.###.#.#.#.#.#.#.#.#.# +#S......#.....#...#...........#.....#.............#...#...............#...............#.....#.....#.......#...#.......#.....#...#...#.....#.# +############################################################################################################################################# diff --git a/src/advent2024/puzzle17.txt b/src/advent2024/puzzle17.txt new file mode 100644 index 0000000..aec07c8 --- /dev/null +++ b/src/advent2024/puzzle17.txt @@ -0,0 +1,5 @@ +Register A: 47719761 +Register B: 0 +Register C: 0 + +Program: 2,4,1,5,7,5,0,3,4,1,1,6,5,5,3,0 diff --git a/src/adventlib/Dir.java b/src/adventlib/Dir.java index 702721b..b83d6b5 100644 --- a/src/adventlib/Dir.java +++ b/src/adventlib/Dir.java @@ -84,4 +84,17 @@ public Dir right90() { case W -> N; }; } + + public Dir left90() { + return switch (this) { + case NW -> SW; + case N -> W; + case NE -> NW; + case E -> N; + case SE -> NE; + case S -> E; + case SW -> SE; + case W -> S; + }; + } } diff --git a/test/advent2024/PuzzleResultsTest.java b/test/advent2024/PuzzleResultsTest.java index 3ea9207..0e2098d 100644 --- a/test/advent2024/PuzzleResultsTest.java +++ b/test/advent2024/PuzzleResultsTest.java @@ -120,18 +120,43 @@ public class PuzzleResultsTest { For problem, total fence price for part 1 is 1456082 For problem, total fence price for part 2 is 872382 """), - entry(Puzzle13.class, + entry( + Puzzle13.class, """ For Part 1 sample, total 480 For Part 2 sample, total 875318608908 For Part 1 problem, total 37297 For Part 2 problem, total 83197086729371 """), - entry(Puzzle14.class, + entry( + Puzzle14.class, """ For sample, safety factor 12 For problem, safety factor 225943500 Pattern after 6377 steps + """), + entry( + Puzzle16.class, + """ + For sample 1, least cost is 7036 + For sample 1, tiles on path: 45 + For sample 2, least cost is 11048 + For sample 2, tiles on path: 64 + For problem, least cost is 73432 + For problem, tiles on path: 496 + """), + entry( + Puzzle17.class, + """ + For Sample 0, program output is empty + For Sample 1, program output is 0,1,2 + For Sample 2, program output is 4,2,5,6,7,7,7,7,3,1,0 + For Sample 3, program output is empty + For Sample 4, program output is empty + For Sample 5, program output is 4,6,3,5,6,3,5,2,1,0 + For Sample 6, program output is 0,3,5,4,3,0 + For problem, program output is 7,0,3,1,2,6,3,7,1 + Quine A is 109020013201563 """)); @Test