getProblemStatus() {
+ return problemStatus;
+ }
+
+ /**
+ * Primary Method for Day 7, Part 1.
+ *
+ * Determines the order, in which the instructions should be completed. For this purpose {@link #stepsMap} is copied
+ * into a list. The new HashMap is scanned for all {@link Step}s that have no previous steps in them. These are
+ * added to an ArrayList which then gets sorted alphabetically. The first item is the current step, which gets added
+ * to the output. Subsequently, this step gets removed from all previous steps and from the HashMap, as well as from
+ * the available Steps. This process gets repeated until the HashMap is empty.
+ *
+ * @return the ordered String of instructions
+ */
+ private String determineOrder() {
+ final List availableStepsIds = new ArrayList<>();
+ final List steps = getLocalCopyOfStepsMapAsArrayList();
+ final StringBuilder order = new StringBuilder();
+
+ while (!steps.isEmpty()) {
+ steps.forEach((step) -> {
+ if (!step.hasPrevious() && !availableStepsIds.contains(step.id)) {
+ availableStepsIds.add(step.id);
+ }
+ });
+
+ Collections.sort(availableStepsIds);
+ final Character currentStepId = availableStepsIds.get(0);
+ order.append(currentStepId);
+
+ removeStepFromListAndPreviousSteps(steps, currentStepId);
+ availableStepsIds.remove(currentStepId);
+ }
+
+ return order.toString();
+ }
+
+ /**
+ * Primary method for Day 7, Part 2.
+ *
+ * Determines the time it takes to complete all tasks with the number of workers given in {@link #workers}. For this
+ * purpose, {@link #stepsMap} is copied into a list. In a while loop, first the available steps are determined.
+ * Secondly, each available step is given to a worker, if one is available. The time it takes for the step to be
+ * completed is calculated in this step and stored with the respective ID. In the third step, the time left is
+ * reduced. If there is just one second left, the step is removed from the map of Steps, from the list of previous
+ * steps in each other step and from the list of steps in progress. Lastly the time taken is increased by 1. If
+ * there are no more steps left, the while loop ends and the total time taken is returned.
+ *
+ * @return time it takes to complete all the tasks
+ */
+ private int determineTime() {
+ final List steps = getLocalCopyOfStepsMapAsArrayList();
+ int availableWorkers = workers;
+
+ final List availableSteps = new ArrayList<>();
+ final Map stepsInProgress = new HashMap<>();
+
+ int timeTaken = 0;
+
+ while (!steps.isEmpty()) {
+ steps.forEach((step) -> {
+ if (!(step.hasPrevious() || availableSteps.contains(step.id) || stepsInProgress.containsKey(step.id))) {
+ availableSteps.add(step.id);
+ }
+ });
+
+ final List stepsToRemoveFromAvailable = new ArrayList<>();
+ for (final Character id : availableSteps) {
+ if (availableWorkers > 0) {
+ final int timeForThisId = id - DIFFERENCE_BETWEEN_CHAR_AND_SECONDS;
+ final int timeToFinish = minTimePerTask + timeForThisId;
+
+ stepsInProgress.put(id, timeToFinish);
+ availableWorkers--;
+
+ stepsToRemoveFromAvailable.add(id);
+ }
+ }
+ availableSteps.removeAll(stepsToRemoveFromAvailable);
+
+ final List stepsToRemoveFromInProgress = new ArrayList<>();
+ for (final Map.Entry stepInProgress : stepsInProgress.entrySet()) {
+ int timeLeft = stepInProgress.getValue();
+ final char currentStepId = stepInProgress.getKey();
+
+ if (timeLeft > 1) {
+ --timeLeft;
+ stepInProgress.setValue(timeLeft);
+ } else {
+ removeStepFromListAndPreviousSteps(steps, currentStepId);
+ stepsToRemoveFromInProgress.add(currentStepId);
+ availableWorkers++;
+ }
+ }
+ stepsToRemoveFromInProgress.forEach(stepsInProgress.keySet()::remove);
+
+ timeTaken++;
+ }
+
+ return timeTaken;
+ }
+
+ /**
+ * Parses the {@link #instructions} to create {@link Step}s and add previous IDs.
+ */
+ private void parseSteps() {
+ for (final String instruction : instructions) {
+ final Matcher matcher = Pattern.compile("Step (\\w) must be finished before step (\\w) can begin\\.").matcher(instruction);
+
+ if (matcher.find()) {
+ final char firstId = matcher.group(1).charAt(0);
+ final char secondId = matcher.group(2).charAt(0);
+
+ stepsMap.putIfAbsent(firstId, new Step(firstId));
+ stepsMap.putIfAbsent(secondId, new Step(secondId));
+ stepsMap.get(secondId).addPrevious(firstId);
+ }
+ }
+ }
+
+ /**
+ * Creates a deep copy of the {@link #stepsMap} and returns it as an ArrayList.
+ *
+ * @return a copy of the {@link #stepsMap} as an ArrayList.
+ */
+ private List getLocalCopyOfStepsMapAsArrayList() {
+ final List copyOfStepHashMap = new ArrayList<>();
+
+ stepsMap.forEach((id, step) -> copyOfStepHashMap.add(new Step(step)));
+
+ return copyOfStepHashMap;
+ }
+
+ /**
+ * Removes the given step ID from the given List and the previous steps of its elements.
+ *
+ * @param stepsList list of Steps to remove from
+ * @param currentStepId ID of step to remove
+ */
+ private void removeStepFromListAndPreviousSteps(final List stepsList, final char currentStepId) {
+ for (final Iterator steps = stepsList.iterator(); steps.hasNext(); ) {
+ final Step step = steps.next();
+ step.removePrevious(currentStepId);
+ if (step.id == currentStepId) {
+ steps.remove();
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/basseur/adventofcode/advent2018/days/day07/Step.java b/src/main/java/org/basseur/adventofcode/advent2018/days/day07/Step.java
new file mode 100644
index 0000000..645c911
--- /dev/null
+++ b/src/main/java/org/basseur/adventofcode/advent2018/days/day07/Step.java
@@ -0,0 +1,66 @@
+package org.basseur.adventofcode.advent2018.days.day07;
+
+import java.util.ArrayList;
+
+public class Step {
+ /** Letter of this step */
+ public final char id;
+ /** List of previous steps */
+ private final ArrayList previousSteps = new ArrayList<>();
+
+ /**
+ * Constructs Step with id.
+ *
+ * @param id the id of this Step
+ */
+ public Step(Character id) {
+ this.id = id;
+ }
+
+ /**
+ * Constructs Step with id and previousSteps.
+ *
+ * @param id the id for this Step
+ * @param previousSteps the previous Steps for this Step
+ */
+ public Step(Character id, ArrayList previousSteps) {
+ this.id = id;
+ this.previousSteps.addAll(previousSteps);
+ }
+
+ /**
+ * Constructs Step as copy of another Step
+ *
+ * @param other the other Step to be copied
+ */
+ public Step(Step other) {
+ this(other.id, other.previousSteps);
+ }
+
+ /**
+ * Returns {@code true} if this step has previous steps
+ *
+ * @return {@code true} if this Step has previous steps, {@code false} otherwise.
+ */
+ public boolean hasPrevious() {
+ return previousSteps.size() > 0;
+ }
+
+ /**
+ * Adds an id to the {@link Step#previousSteps} ArrayList.
+ *
+ * @param prevId id of the previous step to be added
+ */
+ public void addPrevious(Character prevId) {
+ previousSteps.add(prevId);
+ }
+
+ /**
+ * Removes an id to the {@link Step#previousSteps} ArrayList.
+ *
+ * @param prevId id of the previous step to be removed
+ */
+ public void removePrevious(Character prevId) {
+ previousSteps.remove(prevId);
+ }
+}
diff --git a/src/main/java/org/basseur/adventofcode/advent2018/days/day07/package-info.java b/src/main/java/org/basseur/adventofcode/advent2018/days/day07/package-info.java
new file mode 100644
index 0000000..93e40f8
--- /dev/null
+++ b/src/main/java/org/basseur/adventofcode/advent2018/days/day07/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * Contains Day 7: The Sum of Its Parts.
+ *
+ * @author Jan Philipp Gölz
+ */
+package org.basseur.adventofcode.advent2018.days.day07;
\ No newline at end of file
diff --git a/src/main/resources/puzzleInputs/Input07.txt b/src/main/resources/puzzleInputs/Input07.txt
new file mode 100644
index 0000000..f309b05
--- /dev/null
+++ b/src/main/resources/puzzleInputs/Input07.txt
@@ -0,0 +1,101 @@
+Step X must be finished before step C can begin.
+Step C must be finished before step G can begin.
+Step F must be finished before step G can begin.
+Step U must be finished before step Y can begin.
+Step O must be finished before step S can begin.
+Step D must be finished before step N can begin.
+Step M must be finished before step H can begin.
+Step J must be finished before step Q can begin.
+Step G must be finished before step R can begin.
+Step I must be finished before step N can begin.
+Step R must be finished before step K can begin.
+Step A must be finished before step Z can begin.
+Step Y must be finished before step L can begin.
+Step H must be finished before step P can begin.
+Step K must be finished before step S can begin.
+Step Z must be finished before step P can begin.
+Step T must be finished before step S can begin.
+Step N must be finished before step P can begin.
+Step E must be finished before step S can begin.
+Step S must be finished before step W can begin.
+Step W must be finished before step V can begin.
+Step L must be finished before step V can begin.
+Step P must be finished before step B can begin.
+Step Q must be finished before step V can begin.
+Step B must be finished before step V can begin.
+Step P must be finished before step Q can begin.
+Step S must be finished before step V can begin.
+Step C must be finished before step Q can begin.
+Step I must be finished before step H can begin.
+Step A must be finished before step E can begin.
+Step H must be finished before step Q can begin.
+Step G must be finished before step V can begin.
+Step N must be finished before step L can begin.
+Step R must be finished before step Q can begin.
+Step W must be finished before step L can begin.
+Step X must be finished before step L can begin.
+Step X must be finished before step J can begin.
+Step W must be finished before step P can begin.
+Step U must be finished before step B can begin.
+Step P must be finished before step V can begin.
+Step O must be finished before step P can begin.
+Step W must be finished before step Q can begin.
+Step S must be finished before step Q can begin.
+Step U must be finished before step Z can begin.
+Step Z must be finished before step T can begin.
+Step M must be finished before step T can begin.
+Step A must be finished before step P can begin.
+Step Z must be finished before step B can begin.
+Step N must be finished before step S can begin.
+Step H must be finished before step N can begin.
+Step J must be finished before step E can begin.
+Step M must be finished before step J can begin.
+Step R must be finished before step A can begin.
+Step A must be finished before step Y can begin.
+Step F must be finished before step V can begin.
+Step L must be finished before step P can begin.
+Step K must be finished before step L can begin.
+Step F must be finished before step P can begin.
+Step G must be finished before step L can begin.
+Step I must be finished before step Q can begin.
+Step C must be finished before step L can begin.
+Step I must be finished before step Y can begin.
+Step G must be finished before step B can begin.
+Step H must be finished before step L can begin.
+Step X must be finished before step U can begin.
+Step I must be finished before step K can begin.
+Step R must be finished before step N can begin.
+Step I must be finished before step L can begin.
+Step M must be finished before step I can begin.
+Step K must be finished before step V can begin.
+Step G must be finished before step E can begin.
+Step F must be finished before step B can begin.
+Step O must be finished before step Y can begin.
+Step Y must be finished before step Q can begin.
+Step F must be finished before step K can begin.
+Step N must be finished before step W can begin.
+Step O must be finished before step R can begin.
+Step N must be finished before step E can begin.
+Step M must be finished before step V can begin.
+Step H must be finished before step T can begin.
+Step Y must be finished before step T can begin.
+Step F must be finished before step J can begin.
+Step F must be finished before step O can begin.
+Step W must be finished before step B can begin.
+Step T must be finished before step E can begin.
+Step T must be finished before step P can begin.
+Step F must be finished before step M can begin.
+Step U must be finished before step I can begin.
+Step H must be finished before step S can begin.
+Step S must be finished before step P can begin.
+Step T must be finished before step W can begin.
+Step A must be finished before step N can begin.
+Step O must be finished before step N can begin.
+Step L must be finished before step B can begin.
+Step U must be finished before step K can begin.
+Step Z must be finished before step W can begin.
+Step X must be finished before step D can begin.
+Step Z must be finished before step L can begin.
+Step I must be finished before step T can begin.
+Step O must be finished before step W can begin.
+Step I must be finished before step B can begin.
\ No newline at end of file
diff --git a/src/test/java/org/basseur/adventofcode/advent2018/days/day07/Day07Test.java b/src/test/java/org/basseur/adventofcode/advent2018/days/day07/Day07Test.java
new file mode 100644
index 0000000..b43bf48
--- /dev/null
+++ b/src/test/java/org/basseur/adventofcode/advent2018/days/day07/Day07Test.java
@@ -0,0 +1,67 @@
+package org.basseur.adventofcode.advent2018.days.day07;
+
+import org.basseur.adventofcode.advent2018.days.Days;
+import org.basseur.adventofcode.advent2018.utils.FileReaders;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.util.ReflectionTestUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@RunWith(SpringRunner.class)
+public class Day07Test {
+
+ @MockBean
+ private FileReaders fileReaders;
+ private List instructions = new ArrayList<>();
+ private Days day07;
+
+ @Before
+ public void setUp() {
+ instructions.add("Step C must be finished before step A can begin.");
+ instructions.add("Step C must be finished before step F can begin.");
+ instructions.add("Step A must be finished before step B can begin.");
+ instructions.add("Step A must be finished before step D can begin.");
+ instructions.add("Step B must be finished before step E can begin.");
+ instructions.add("Step D must be finished before step E can begin.");
+ instructions.add("Step F must be finished before step E can begin.");
+
+ Mockito.when(fileReaders.readFileIntoStringList(Mockito.anyString())).thenReturn(instructions);
+ day07 = new Day07(fileReaders);
+ }
+
+ @Test
+ public void getDay() {
+ int expectedResult = 7;
+ int actualResult = day07.getDay();
+
+ Assert.assertEquals(expectedResult, actualResult);
+ }
+
+ @Test
+ public void firstPart() {
+ String expectedResult = "Part 1 - Order in which the steps in the instructions should be completed: CABDFE";
+ String actualResult = day07.firstPart();
+ String actualResult2 = day07.firstPart();
+
+ Assert.assertEquals(expectedResult, actualResult);
+ Assert.assertEquals(expectedResult, actualResult2);
+ }
+
+ @Test
+ public void secondPart() {
+ ReflectionTestUtils.setField(day07, "workers", 2);
+ ReflectionTestUtils.setField(day07, "minTimePerTask", 0);
+
+ String expectedResult = "Part 2 - Time required to complete all of the steps: 15 seconds";
+ String actualResult = day07.secondPart();
+
+ Assert.assertEquals(expectedResult, actualResult);
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/basseur/adventofcode/advent2018/days/day07/StepTest.java b/src/test/java/org/basseur/adventofcode/advent2018/days/day07/StepTest.java
new file mode 100644
index 0000000..0511d9f
--- /dev/null
+++ b/src/test/java/org/basseur/adventofcode/advent2018/days/day07/StepTest.java
@@ -0,0 +1,45 @@
+package org.basseur.adventofcode.advent2018.days.day07;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.junit4.SpringRunner;
+
+
+@RunWith(SpringRunner.class)
+public class StepTest {
+
+ private Step step;
+
+ @Before
+ public void setUp() {
+ step = new Step('A');
+ }
+
+ @Test
+ public void testAddRemoveAndHasPrevious() {
+ step.addPrevious('B');
+ Assert.assertTrue(step.hasPrevious());
+
+ step.removePrevious('B');
+ Assert.assertFalse(step.hasPrevious());
+ }
+
+ @Test
+ public void testRemoveFromEmptyPreviousSteps() {
+ step.removePrevious('Z');
+ Assert.assertFalse(step.hasPrevious());
+ }
+
+ @Test
+ public void testCopiedStepIsNotJustReference() {
+ Step copiedStep = new Step(step);
+
+ step.addPrevious('B');
+
+ Assert.assertTrue(step.hasPrevious());
+ Assert.assertFalse(copiedStep.hasPrevious());
+
+ }
+}
\ No newline at end of file