From fb730092b4295a1399d5dfc63d13fe37612aaeb6 Mon Sep 17 00:00:00 2001 From: Bas Dado Date: Fri, 7 Dec 2018 14:06:59 +0100 Subject: [PATCH] Day 7 --- pom.xml | 2 +- .../kotlin/com/basdado/adventofcode/Day4.kt | 2 +- .../com/basdado/adventofcode/Day6Extra.kt | 2 + .../kotlin/com/basdado/adventofcode/Day7.kt | 168 ++++++++++++++++++ src/main/resources/day/6/extra/input.txt | 0 src/main/resources/day/7/input.txt | 102 +++++++++++ 6 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 src/main/kotlin/com/basdado/adventofcode/Day6Extra.kt create mode 100644 src/main/kotlin/com/basdado/adventofcode/Day7.kt create mode 100644 src/main/resources/day/6/extra/input.txt create mode 100644 src/main/resources/day/7/input.txt diff --git a/pom.xml b/pom.xml index f48d24a..a661852 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ UTF-8 - 1.3.10 + 1.3.11 official 4.12 diff --git a/src/main/kotlin/com/basdado/adventofcode/Day4.kt b/src/main/kotlin/com/basdado/adventofcode/Day4.kt index db7fb2d..15f97e2 100644 --- a/src/main/kotlin/com/basdado/adventofcode/Day4.kt +++ b/src/main/kotlin/com/basdado/adventofcode/Day4.kt @@ -71,7 +71,7 @@ class Day4 { private fun parseGuardDays(sortedLines: MutableList): List { val guardDays = mutableListOf() - var currentDay = GuardDay(0, LocalDate.EPOCH, mutableListOf()) + var currentDay = GuardDay(0, LocalDate.MIN, mutableListOf()) var sleepStartMinute = 0 for (line in sortedLines) { if (line.event == GuardEventType.BEGIN_SHIFT) { diff --git a/src/main/kotlin/com/basdado/adventofcode/Day6Extra.kt b/src/main/kotlin/com/basdado/adventofcode/Day6Extra.kt new file mode 100644 index 0000000..7d2ae4e --- /dev/null +++ b/src/main/kotlin/com/basdado/adventofcode/Day6Extra.kt @@ -0,0 +1,2 @@ +package com.basdado.adventofcode + diff --git a/src/main/kotlin/com/basdado/adventofcode/Day7.kt b/src/main/kotlin/com/basdado/adventofcode/Day7.kt new file mode 100644 index 0000000..f0f0672 --- /dev/null +++ b/src/main/kotlin/com/basdado/adventofcode/Day7.kt @@ -0,0 +1,168 @@ +package com.basdado.adventofcode + +import java.lang.IllegalStateException +import java.lang.Integer.min +import java.util.Arrays.stream +import java.util.stream.Collectors +import java.util.stream.IntStream + +fun main() { + + val day = Day7() + day.puzzle1() + day.puzzle2() +} + +class Day7 { + + fun puzzle1() { + + val graph = loadGraph() + + val nodeOrder = mutableListOf() + val availableNodes = graph.nodes.filter { n -> n.previous.isEmpty() }.toMutableSet() + + while (!availableNodes.isEmpty()) { + val nextNode = availableNodes.sortedBy { n -> n.id }[0] + nodeOrder.add(nextNode) + availableNodes.remove(nextNode) + availableNodes.addAll(nextNode.next + .filter { !nodeOrder.contains(it) } + .filter { nodeOrder.containsAll(it.previous) }) + } + + println(nodeOrder.stream().map{ it.id }.collect(Collectors.joining())) + } + + fun puzzle2() { + + val graph = loadGraph() + + val timeline = TimeLine() + + // The first timeslot is available +// timeline.add(Array(workerCount) { null }) + var finished = emptySet() + var availableNodes = graph.nodes.filter { n -> n.previous.isEmpty() }.toMutableSet() + + var time = 0 + while (!finished.containsAll(graph.nodes)) { + + val orderedAvailableNodes = availableNodes.sortedBy { n -> n.id } + + val timeSlot = timeline.getSlot(time) + + // Divide the available workers + for (availableNode in orderedAvailableNodes) { + val availableWorkerIndex = timeSlot.indexOfFirst { it == null } + if (availableWorkerIndex == -1) { + break + } + timeline.addJob(time, availableWorkerIndex, availableNode) + } + + time++ + finished = timeline.finishedNodes(time) + availableNodes = graph.nodes + .filter { finished.containsAll(it.previous) } + // Not finished + .filter { !finished.contains(it) } + // Not in progress + .filter { !timeline.getSlot(time).contains(it) } + .toMutableSet() + + } + +// println(timeline) + println(timeline.timeline.size) + + } + + private fun loadGraph(): Graph { + val graph = Graph() + val lineMatcher = Regex("""Step ([A-Z]) must be finished before step ([A-Z]) can begin.""") + lines("/day/7/input.txt") + .forEach { + val match = lineMatcher.matchEntire(it)!! + graph.addConnection(match.groupValues[1], match.groupValues[2]) + } + return graph + } + + class TimeLine(val workerCount: Int = 5) { + val timeline = mutableListOf>() + + fun getSlot(time: Int): Array { + extendUntil(time) + return timeline[time] + } + + fun finishedNodes(time: Int): Set { + + // All jobs that were active before "time" and are no longer active on "time" are finished + val finished = mutableSetOf() + for (t in 0 until min(time, timeline.size)) { + finished.addAll(timeline[t].filterNotNull()) + } + if (timeline.size > time) { + finished.removeAll(timeline[time].filterNotNull()) + } + return finished + } + + fun addJob(startTime: Int, workerId: Int, node: Node) { + + extendUntil(startTime + node.processTime()) + for(time in startTime until startTime + node.processTime()) { + if (timeline[time][workerId] != null) { + throw IllegalStateException("Worker $workerId is already busy in timeslot $time") + } + timeline[time][workerId] = node + } + } + + fun extendUntil(time: Int) { + if (timeline.size > time) { + return + } + for(t in timeline.size..time) { + timeline.add(Array(workerCount) { null }) + } + } + + override fun toString(): String { + return IntStream.range(0, timeline.size) + .mapToObj { "" + it + " " + + stream(timeline[it]).map{ n -> n?.toString() ?: "." }.collect(Collectors.joining(" ")) + " " + + finishedNodes(it).map{n -> n.id}.joinToString ( ", " )} + .collect(Collectors.joining("\r\n")) + } + } + class Graph { + + val nodes: MutableSet = mutableSetOf() + + fun addConnection(id1: String, id2: String) { + val node1 = findOrCreateNode(id1) + val node2 = findOrCreateNode(id2) + + node1.next.add(node2) + node2.previous.add(node1) + } + + fun findOrCreateNode(id: String): Node { + return nodes.stream().filter{ it.id == id }.findAny() + .orElseGet { + val newNode = Node(id) + nodes.add(newNode) + newNode + } + } + } + + class Node(val id: String, val next: MutableSet = mutableSetOf(), val previous: MutableSet = mutableSetOf()) { + fun processTime() = 60 + (id[0] - 'A') + 1 + + override fun toString(): String = id + } +} \ No newline at end of file diff --git a/src/main/resources/day/6/extra/input.txt b/src/main/resources/day/6/extra/input.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/day/7/input.txt b/src/main/resources/day/7/input.txt new file mode 100644 index 0000000..7ae58e4 --- /dev/null +++ b/src/main/resources/day/7/input.txt @@ -0,0 +1,102 @@ +Step G must be finished before step S can begin. +Step T must be finished before step Q can begin. +Step A must be finished before step B can begin. +Step H must be finished before step X can begin. +Step V must be finished before step O can begin. +Step Z must be finished before step P can begin. +Step R must be finished before step J can begin. +Step L must be finished before step Y can begin. +Step Y must be finished before step E can begin. +Step W must be finished before step X can begin. +Step X must be finished before step B can begin. +Step K must be finished before step E can begin. +Step Q must be finished before step P can begin. +Step U must be finished before step B can begin. +Step M must be finished before step O can begin. +Step P must be finished before step N can begin. +Step I must be finished before step J can begin. +Step B must be finished before step C can begin. +Step C must be finished before step O can begin. +Step J must be finished before step F can begin. +Step F must be finished before step O can begin. +Step E must be finished before step D can begin. +Step D must be finished before step N can begin. +Step N must be finished before step S can begin. +Step S must be finished before step O can begin. +Step W must be finished before step O can begin. +Step L must be finished before step P can begin. +Step N must be finished before step O can begin. +Step T must be finished before step D can begin. +Step G must be finished before step I can begin. +Step V must be finished before step X can begin. +Step B must be finished before step N can begin. +Step R must be finished before step N can begin. +Step H must be finished before step J can begin. +Step B must be finished before step S can begin. +Step P must be finished before step I can begin. +Step A must be finished before step J can begin. +Step A must be finished before step U can begin. +Step B must be finished before step D can begin. +Step T must be finished before step A can begin. +Step U must be finished before step D can begin. +Step T must be finished before step L can begin. +Step I must be finished before step E can begin. +Step R must be finished before step U can begin. +Step H must be finished before step S can begin. +Step P must be finished before step F can begin. +Step Q must be finished before step C can begin. +Step A must be finished before step P can begin. +Step X must be finished before step E can begin. +Step Q must be finished before step N can begin. +Step E must be finished before step N can begin. +Step Q must be finished before step O can begin. +Step J must be finished before step S can begin. +Step X must be finished before step P can begin. +Step K must be finished before step U can begin. +Step F must be finished before step E can begin. +Step C must be finished before step E can begin. +Step H must be finished before step K can begin. +Step W must be finished before step B can begin. +Step G must be finished before step O can begin. +Step F must be finished before step N can begin. +Step I must be finished before step D can begin. +Step G must be finished before step V can begin. +Step E must be finished before step S can begin. +Step Y must be finished before step P can begin. +Step G must be finished before step E can begin. +Step P must be finished before step J can begin. +Step P must be finished before step J can begin. +Step U must be finished before step N can begin. +Step U must be finished before step F can begin. +Step X must be finished before step U can begin. +Step X must be finished before step C can begin. +Step R must be finished before step Q can begin. +Step Q must be finished before step E can begin. +Step Z must be finished before step E can begin. +Step X must be finished before step F can begin. +Step J must be finished before step D can begin. +Step X must be finished before step M can begin. +Step Y must be finished before step D can begin. +Step K must be finished before step J can begin. +Step Z must be finished before step J can begin. +Step M must be finished before step P can begin. +Step T must be finished before step M can begin. +Step F must be finished before step S can begin. +Step P must be finished before step S can begin. +Step X must be finished before step I can begin. +Step U must be finished before step J can begin. +Step M must be finished before step B can begin. +Step Q must be finished before step D can begin. +Step Z must be finished before step I can begin. +Step D must be finished before step S can begin. +Step J must be finished before step N can begin. +Step D must be finished before step O can begin. +Step T must be finished before step H can begin. +Step P must be finished before step D can begin. +Step M must be finished before step F can begin. +Step Y must be finished before step S can begin. +Step H must be finished before step I can begin. +Step Y must be finished before step W can begin. +Step X must be finished before step J can begin. +Step L must be finished before step W can begin. +Step G must be finished before step N can begin. \ No newline at end of file