From b0ed1a7017fdfdf0bf137be39dbe8ebedd142301 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Tue, 28 Nov 2023 18:42:34 +0000 Subject: [PATCH] Practice some Kotlin by doing 2018 problems --- README.md | 90 +- advents/build.gradle.kts | 1 + .../net/fish/collections/IntRangeExt.kt | 8 + .../main/kotlin/net/fish/geometry/Point.kt | 34 +- .../kotlin/net/fish/maths/Permutations.kt | 13 + .../kotlin/net/fish/y2018/AdventOfCode.kt | 14 + .../src/main/kotlin/net/fish/y2018/Day01.kt | 38 + .../src/main/kotlin/net/fish/y2018/Day02.kt | 48 + .../src/main/kotlin/net/fish/y2018/Day03.kt | 64 + .../src/main/kotlin/net/fish/y2018/Day04.kt | 74 + .../src/main/kotlin/net/fish/y2018/Day05.kt | 42 + .../src/main/kotlin/net/fish/y2018/Day06.kt | 105 ++ .../main/kotlin/net/fish/y2018/DayTemplate.kt | 21 + .../src/main/kotlin/net/fish/y2022/Day04.kt | 9 +- .../src/main/kotlin/net/fish/y2022/Day05.kt | 7 +- .../src/main/kotlin/net/fish/y2022/Day07.kt | 2 + .../src/main/kotlin/net/fish/y2022/Day08.kt | 16 +- advents/src/main/resources/2018/day01.txt | 1040 ++++++++++++++ advents/src/main/resources/2018/day02.txt | 250 ++++ advents/src/main/resources/2018/day03.txt | 1227 +++++++++++++++++ advents/src/main/resources/2018/day04.txt | 986 +++++++++++++ advents/src/main/resources/2018/day05.txt | 1 + advents/src/main/resources/2018/day06.txt | 50 + .../test/kotlin/net/fish/PermutationsTest.kt | 14 + .../kotlin/net/fish/geometry/PointTest.kt | 32 + .../test/kotlin/net/fish/y2018/Day03Test.kt | 37 + .../test/kotlin/net/fish/y2018/Day04Test.kt | 38 + .../test/kotlin/net/fish/y2018/Day05Test.kt | 17 + .../test/kotlin/net/fish/y2018/Day06Test.kt | 48 + .../test/kotlin/net/fish/y2022/Day08Test.kt | 34 + .../src/test/resources/2018/day03-test.txt | 3 + .../src/test/resources/2018/day04-test.txt | 17 + .../src/test/resources/2018/day06-test.txt | 6 + build.gradle.kts | 1 + 34 files changed, 4368 insertions(+), 19 deletions(-) create mode 100644 advents/src/main/kotlin/net/fish/collections/IntRangeExt.kt create mode 100644 advents/src/main/kotlin/net/fish/y2018/AdventOfCode.kt create mode 100644 advents/src/main/kotlin/net/fish/y2018/Day01.kt create mode 100644 advents/src/main/kotlin/net/fish/y2018/Day02.kt create mode 100644 advents/src/main/kotlin/net/fish/y2018/Day03.kt create mode 100644 advents/src/main/kotlin/net/fish/y2018/Day04.kt create mode 100644 advents/src/main/kotlin/net/fish/y2018/Day05.kt create mode 100644 advents/src/main/kotlin/net/fish/y2018/Day06.kt create mode 100644 advents/src/main/kotlin/net/fish/y2018/DayTemplate.kt create mode 100644 advents/src/main/resources/2018/day01.txt create mode 100644 advents/src/main/resources/2018/day02.txt create mode 100644 advents/src/main/resources/2018/day03.txt create mode 100644 advents/src/main/resources/2018/day04.txt create mode 100644 advents/src/main/resources/2018/day05.txt create mode 100644 advents/src/main/resources/2018/day06.txt create mode 100644 advents/src/test/kotlin/net/fish/y2018/Day03Test.kt create mode 100644 advents/src/test/kotlin/net/fish/y2018/Day04Test.kt create mode 100644 advents/src/test/kotlin/net/fish/y2018/Day05Test.kt create mode 100644 advents/src/test/kotlin/net/fish/y2018/Day06Test.kt create mode 100644 advents/src/test/resources/2018/day03-test.txt create mode 100644 advents/src/test/resources/2018/day04-test.txt create mode 100644 advents/src/test/resources/2018/day06-test.txt diff --git a/README.md b/README.md index cfe6392..9ec601a 100644 --- a/README.md +++ b/README.md @@ -17,4 +17,92 @@ git config --global core.autocrlf input # if you had checked it out without setting above first, you need to fix files with CRLF into LF: git rm -rf --cached . git reset --hard HEAD -``` \ No newline at end of file +``` + +## coding notes + +### Reading resources + +1. column of data, separator is EOL + +Example 2022 02 + +```kotlin +// simply split into List +resourceLines(2022, 2) + +// then can deal with each line +data.fold(0) { acc, l -> + val (a,b) = l.split(" ", limit = 2) + // ... etc +``` + +1. column data with blank line separator + +Example, 2022 01 + +```text +5538 +6760 + +5212 +2842 +``` + +```kotlin +// first a list of strings for each block (which still have \n in them) +private val data by lazy { totals(resourceStrings(2022, 1)) } + +// Then split by \n +data.map { block -> + block.split("\n").sumOf { f -> f.toInt() } +} +``` + +### Parsing data with regex + +Example where each line contains information we want to extract parts out of +```text +12-80,12-81 +13-94,14-93 +... +``` +Use `resourceLines` to pull each line, and then map that through a regex "Extractor" +```kotlin +private val assignmentExtractor by lazy { Regex("""(\d+)-(\d+),(\d+)-(\d+)""") } +private val data by lazy { toAssignments(resourceLines(2022, 4)) } + +fun toAssignments(data: List): List = data.map { line -> + assignmentExtractor.find(line)?.destructured!!.let { (a, b, c, d) -> + Assignments(IntRange(a.toInt(), b.toInt()), IntRange(c.toInt(), d.toInt())) + } +} +``` +Example 2022 04 + +### Grid data + +See GridDataUtils for parsing grid information from lines where each point represents 1 datum, either as numbers: + +```text + 1234 + 2256 + 1978 +``` + +or as characters: + +```text + .x. + yz. +``` + +#### Grid viewing + +There are some good examples of looking from a point to a boundary in 2022 Day 08, using `generateSequence` on points in a direction until they hit the boundary. + +```kotlin +private fun pointsToBoundaryInDir(p: Point, dir: Direction): Sequence { + return generateSequence(p + dir) { it + dir }.takeWhileInclusive { !onBoundary(it) } +} +``` diff --git a/advents/build.gradle.kts b/advents/build.gradle.kts index d3b5c2b..5c72555 100644 --- a/advents/build.gradle.kts +++ b/advents/build.gradle.kts @@ -56,6 +56,7 @@ dependencies { testImplementation("org.junit.jupiter:junit-jupiter-engine:$junitJupiterEngineVersion") testImplementation("org.assertj:assertj-core:$assertJVersion") testImplementation("io.mockk:mockk:$mockkVersion") + testImplementation("org.junit.jupiter:junit-jupiter:5.8.1") } tasks { diff --git a/advents/src/main/kotlin/net/fish/collections/IntRangeExt.kt b/advents/src/main/kotlin/net/fish/collections/IntRangeExt.kt new file mode 100644 index 0000000..7da707c --- /dev/null +++ b/advents/src/main/kotlin/net/fish/collections/IntRangeExt.kt @@ -0,0 +1,8 @@ +package net.fish.collections + +fun IntRange.fullyContains(t: IntRange): Boolean = this.first <= t.first && this.last >= t.last + +fun IntRange.overlaps(t: IntRange): Boolean { + return (this.first in t.first..t.last) || (this.last in t.first..t.last) || + (t.first in this.first..this.last) || (t.last in this.first..this.last) +} \ No newline at end of file diff --git a/advents/src/main/kotlin/net/fish/geometry/Point.kt b/advents/src/main/kotlin/net/fish/geometry/Point.kt index 55088cc..ee980c4 100644 --- a/advents/src/main/kotlin/net/fish/geometry/Point.kt +++ b/advents/src/main/kotlin/net/fish/geometry/Point.kt @@ -73,4 +73,36 @@ fun Collection.bounds() = fun Point.abs() = Point(kotlin.math.abs(x), kotlin.math.abs(y)) fun Point.max(): Int = maxOf(x, y) -fun Point.sign(): Point = Point(x.sign, y.sign) \ No newline at end of file +fun Point.sign(): Point = Point(x.sign, y.sign) + +fun Pair.edgePoints(): Sequence { + val upperLeft = first + val lowerRight = second + + return sequence { + // Top edge + yieldAll((upperLeft.x..lowerRight.x).map { x -> Point(x, upperLeft.y) }) + + // Right edge + yieldAll((upperLeft.y + 1 until lowerRight.y).map { y -> Point(lowerRight.x, y) }) + + // Bottom edge + yieldAll((lowerRight.x downTo upperLeft.x).map { x -> Point(x, lowerRight.y) }) + + // Left edge + yieldAll((lowerRight.y - 1 downTo upperLeft.y + 1).map { y -> Point(upperLeft.x, y) }) + } +} + +fun Pair.points(): Sequence { + val upperLeft = first + val lowerRight = second + + return sequence { + for (y in upperLeft.y..lowerRight.y) { + for (x in upperLeft.x..lowerRight.x) { + yield(Point(x, y)) + } + } + } +} \ No newline at end of file diff --git a/advents/src/main/kotlin/net/fish/maths/Permutations.kt b/advents/src/main/kotlin/net/fish/maths/Permutations.kt index 87b00fa..cd44807 100644 --- a/advents/src/main/kotlin/net/fish/maths/Permutations.kt +++ b/advents/src/main/kotlin/net/fish/maths/Permutations.kt @@ -89,6 +89,19 @@ class Permutations(N: Int) : IntCombinations(N) { } } +// Creates a list of pairs (list) of integers, e.g. PairCombinations(4) gives: +// listOf( +// listOf(0, 0), listOf(0, 1), listOf(0, 2), listOf(0, 3), +// listOf(1, 0), listOf(1, 1), listOf(1, 2), listOf(1, 3), +// listOf(2, 0), listOf(2, 1), listOf(2, 2), listOf(2, 3), +// listOf(3, 0), listOf(3, 1), listOf(3, 2), listOf(3, 3) +// ) + +class PairCombinations(size: Int): IntCombinations(2) { + override val state = Array(2) { Ring(size) }.toList() + override fun state() = state.map { it.state() }.reversed() +} + fun main() { val n = 100 val sumNumbers = Ring(n).sum() diff --git a/advents/src/main/kotlin/net/fish/y2018/AdventOfCode.kt b/advents/src/main/kotlin/net/fish/y2018/AdventOfCode.kt new file mode 100644 index 0000000..d8402b6 --- /dev/null +++ b/advents/src/main/kotlin/net/fish/y2018/AdventOfCode.kt @@ -0,0 +1,14 @@ +@file:JvmName("AdventOfCode2023") +package net.fish.y2018 + +import net.fish.Reflect +import net.fish.Runner + +object AdventOfCode { + val days = Reflect.getDays(2018) +} + +fun main(args: Array) { + val day = if(args.isEmpty()) 0 else args[0].toInt() + Runner.run(2018, AdventOfCode.days, day) +} \ No newline at end of file diff --git a/advents/src/main/kotlin/net/fish/y2018/Day01.kt b/advents/src/main/kotlin/net/fish/y2018/Day01.kt new file mode 100644 index 0000000..018fac0 --- /dev/null +++ b/advents/src/main/kotlin/net/fish/y2018/Day01.kt @@ -0,0 +1,38 @@ +package net.fish.y2018 + +import net.fish.Day +import net.fish.resourceLines + +object Day01 : Day { + private val data by lazy { resourceLines(2018, 1).map { it.toInt() } } + private val previousTotals: MutableSet = mutableSetOf() + + override fun part1() = doPart1(data) + override fun part2() = doPart2(data) + + fun doPart1(data: List): Int = data.sum() + fun doPart2(data: List): Int { + var currentIndex = 0 + var foundDuplicate = false + var currentTotal = 0 + previousTotals += 0 + // find when the total repeats itself by checking when we've seen it previously in the set, or adding to it and repeating + while (!foundDuplicate) { + currentTotal += data[currentIndex] + if (previousTotals.contains(currentTotal)) { + foundDuplicate = true + } else { + previousTotals += currentTotal + currentIndex = (currentIndex + 1) % data.size + } + } + return currentTotal + } + + @JvmStatic + fun main(args: Array) { + println(part1()) + println(part2()) + } + +} \ No newline at end of file diff --git a/advents/src/main/kotlin/net/fish/y2018/Day02.kt b/advents/src/main/kotlin/net/fish/y2018/Day02.kt new file mode 100644 index 0000000..54b4175 --- /dev/null +++ b/advents/src/main/kotlin/net/fish/y2018/Day02.kt @@ -0,0 +1,48 @@ +package net.fish.y2018 + +import net.fish.Day +import net.fish.maths.combinations +import net.fish.maths.permutations +import net.fish.resourceLines + +object Day02 : Day { + private val data by lazy { toBoxes(resourceLines(2018, 2)) } + + override fun part1() = doPart1(data) + override fun part2() = doPart2(data) + + fun hasDuplicateOfCount(code: String, count: Int): Boolean { + val byCharCount = code.toCharArray().toList().groupBy { it } + // do any of the groups have the right size? + return byCharCount.any { it.value.size == count } + } + + data class Box(val code: String) { + val size = code.length + val hasPairs: Boolean = hasDuplicateOfCount(code, 2) + val hasTriples: Boolean = hasDuplicateOfCount(code, 3) + + fun numDiffs(other: Box): Int = size - code.zip(other.code).count { it.first == it.second } + fun removeDiffs(other: Box): String { + return code.zip(other.code).filter { it.first == it.second }.map { it.first }.joinToString("") + } + } + + private fun toBoxes(data: List): List { + return data.map { Box(it) } + } + + fun doPart1(data: List): Int = data.count { it.hasPairs } * data.count { it.hasTriples } + fun doPart2(data: List): String { + val x = data.combinations(2) + val pairWith1Diff = x.first { it[0].numDiffs(it[1]) == 1 } + return pairWith1Diff[0].removeDiffs(pairWith1Diff[1]) + } + + @JvmStatic + fun main(args: Array) { + println(part1()) + println(part2()) + } + +} \ No newline at end of file diff --git a/advents/src/main/kotlin/net/fish/y2018/Day03.kt b/advents/src/main/kotlin/net/fish/y2018/Day03.kt new file mode 100644 index 0000000..f4aef20 --- /dev/null +++ b/advents/src/main/kotlin/net/fish/y2018/Day03.kt @@ -0,0 +1,64 @@ +package net.fish.y2018 + +import net.fish.Day +import net.fish.geometry.Point +import net.fish.resourceLines +import java.lang.Exception + +object Day03 : Day { + private val claimExtractor by lazy { Regex("""#(\d+) @ (\d+),(\d+): (\d+)x(\d+)""") } + private val data by lazy { toClaims(resourceLines(2018, 3)) } + + override fun part1() = doPart1(data) + override fun part2() = doPart2(data) + + data class Claim(val id:Int, val x: Int, val y: Int, val sx: Int, val sy: Int) { + fun allPoints(): List { + val combinations: MutableList = mutableListOf() + for (a in (x until (x+sx))) { + for (b in (y until (y+sy))) { + combinations.add(Point(a, b)) + } + } + return combinations.toList() + } + } + + fun toClaims(data: List): List = data.map { line -> + claimExtractor.find(line)?.destructured!!.let { (id, x, y, sx, sy) -> + // println("Adding claim for $id, $x, $y, $sx, $sy") + Claim(id.toInt(), x.toInt(), y.toInt(), sx.toInt(), sy.toInt()) + } + } + + fun doPart1(claims: List): Int = createPointToClaims(claims).values.count { it.size > 1 } + + private fun createPointToClaims(claims: List): MutableMap> { + val mapPointToClaims: MutableMap> = mutableMapOf() + claims.forEach { claim -> + claim.allPoints().forEach { p -> + mapPointToClaims.getOrPut(p) { mutableSetOf() } += claim + } + } + return mapPointToClaims + } + + fun doPart2(claims: List): Int { + // find all claims that have a point in more than one claim, and remove them from all claims. should be left with 1 claim that + // doesn't overlap anything. + val p2c = createPointToClaims(claims) + val claimsThatOverlap = p2c.values.filter { it.size > 1 }.flatten().toSet() + val unique = claims - claimsThatOverlap + if (unique.size != 1) { + throw Exception("Found more than 1 that doesn't overlap: $unique") + } + return unique.first().id + } + + @JvmStatic + fun main(args: Array) { + println(part1()) + println(part2()) + } + +} \ No newline at end of file diff --git a/advents/src/main/kotlin/net/fish/y2018/Day04.kt b/advents/src/main/kotlin/net/fish/y2018/Day04.kt new file mode 100644 index 0000000..6e056d5 --- /dev/null +++ b/advents/src/main/kotlin/net/fish/y2018/Day04.kt @@ -0,0 +1,74 @@ +package net.fish.y2018 + +import net.fish.Day +import net.fish.resourceLines +import java.lang.Exception + +object Day04 : Day { + private val bs by lazy { Regex("""\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}] Guard #(\d+) begins shift""") } + private val fa by lazy { Regex("""\[\d{4}-\d{2}-\d{2} \d{2}:(\d{2})] falls asleep""") } + private val wu by lazy { Regex("""\[\d{4}-\d{2}-\d{2} \d{2}:(\d{2})] wakes up""") } + private val data by lazy { parseInstructions(resourceLines(2018, 4)) } + + override fun part1() = doPart1(data) + override fun part2() = doPart2(data) + + fun doPart1(guardMap: Map): Int { + val longestSleepingGuard = guardMap.maxBy { it.value.totalSleep() }.value + return longestSleepingGuard.id * longestSleepingGuard.mostAsleepAt() + } + + fun doPart2(guardMap: Map): Int { + // look at all the guards, find the one with the largest asleep time in a particular minute + val longestSleepingGuardOnSingleMinute = guardMap.maxBy { entry -> entry.value.sleeps.entries.maxOf { sleepsEntry -> sleepsEntry.value } }.value + return longestSleepingGuardOnSingleMinute.id * longestSleepingGuardOnSingleMinute.mostAsleepAt() + } + + data class Guard(val id: Int, val sleeps: MutableMap) { + fun totalSleep(): Int = sleeps.values.sum() + fun mostAsleepAt(): Int = sleeps.entries.maxBy { it.value }.key + } + + fun parseInstructions(data: List): Map { + val dataMap: MutableMap = mutableMapOf() + // sort the data so we get correct processing order. it's already in good format by date to simply sort by natural text order + val sortedData = data.sorted() + var isSleeping = false + var asleepStart = -1 + var currentGuard = 0 + // Data is strictly in the order of: + // - Guard + // - N x pairs of Sleep/Awake + sortedData.forEach { line -> + // println("parsing: $line") + if (line.contains("Guard")) { + val match = bs.find(line) ?: throw Exception("Failed to parse line for guard data: $line") + match.destructured.let { (gId) -> currentGuard = gId.toInt() } + } else if (!isSleeping) { + val match = fa.find(line) ?: throw Exception("Failed to parse line for sleep data: $line") + match.destructured.let { (t) -> asleepStart = t.toInt() } + isSleeping = true + } else { + val match = wu.find(line) ?: throw Exception("Failed to parse line for waking up: $line") + match.destructured.let {(awakeMinute) -> + isSleeping = false + // now save this guard's sleep times + val guard = dataMap.getOrPut(currentGuard) { Guard(currentGuard, mutableMapOf()) } + (asleepStart until awakeMinute.toInt()).forEach { minute -> + val currentSleepCountForMinute = guard.sleeps.getOrPut(minute) { 0 } + guard.sleeps[minute] = currentSleepCountForMinute + 1 + } + } + + } + } + return dataMap + } + + @JvmStatic + fun main(args: Array) { + println(part1()) + println(part2()) + } + +} \ No newline at end of file diff --git a/advents/src/main/kotlin/net/fish/y2018/Day05.kt b/advents/src/main/kotlin/net/fish/y2018/Day05.kt new file mode 100644 index 0000000..abe38e3 --- /dev/null +++ b/advents/src/main/kotlin/net/fish/y2018/Day05.kt @@ -0,0 +1,42 @@ +package net.fish.y2018 + +import net.fish.Day +import net.fish.resourceString + +object Day05 : Day { + private val data by lazy { resourceString(2018, 5) } + + override fun part1() = doPart1(data) + override fun part2() = doPart2(data) + + fun doPart1(data: String): Int = reduce(data).length + fun doPart2(data: String): Int { + val uniqueLowercaseLetters = data.map { it.lowercase() }.toSet() + return uniqueLowercaseLetters.minOf { c -> + val newData = data.replace(c, "").replace(c.uppercase(), "") + reduce(newData).length + } + } + + private fun isOpposite(a: Char, b: Char): Boolean = (a.lowercaseChar() == b.lowercaseChar()) && ((a.isUpperCase() && b.isLowerCase()) || (a.isLowerCase() && b.isUpperCase())) + + fun reduce(data: String): String { + val cumulative: MutableList = mutableListOf() + + data.forEach { c -> + if (cumulative.isEmpty() || !isOpposite(c, cumulative.last())) { + cumulative += c + } else { + cumulative.removeLast() + } + } + return cumulative.joinToString("") + } + + @JvmStatic + fun main(args: Array) { + println(part1()) + println(part2()) + } + +} \ No newline at end of file diff --git a/advents/src/main/kotlin/net/fish/y2018/Day06.kt b/advents/src/main/kotlin/net/fish/y2018/Day06.kt new file mode 100644 index 0000000..d6cdfea --- /dev/null +++ b/advents/src/main/kotlin/net/fish/y2018/Day06.kt @@ -0,0 +1,105 @@ +package net.fish.y2018 + +import net.fish.Day +import net.fish.geometry.Point +import net.fish.geometry.bounds +import net.fish.geometry.edgePoints +import net.fish.geometry.points +import net.fish.resourceLines + +object Day06 : Day { + private val data by lazy { toLocations(resourceLines(2018, 6)) } + + override fun part1() = doPart1(data) + override fun part2() = doPart2(data) + + fun doPart1(locations: List): Int { + // locations.forEach { println(it) } + val allLocationsOwners: MutableMap> = mutableMapOf() + val boundLocations = locations.filter { it.isBounded } + val boundLocationOwnedPoints: MutableMap = mutableMapOf() + // We only need to consider points in the bounds of edge locations + val bounds = locations.map { it.position }.bounds() + for(y in bounds.first.y .. bounds.second.y) { + for (x in bounds.first.x..bounds.second.x) { + val p = Point(x, y) + val b2 = belongsTo(p, locations) + allLocationsOwners[p] = b2 + if (b2.size == 1 && boundLocations.contains(b2.first())) { + val l = b2.first() + val count = boundLocationOwnedPoints.getOrPut(l) { 0 } + boundLocationOwnedPoints[l] = count + 1 + } + } + } + println(boundLocationOwnedPoints) + val boundLocationWithLargestOwnedPoints = boundLocationOwnedPoints.maxBy { it.value } + println("max: ${boundLocationWithLargestOwnedPoints.key} = ${boundLocationWithLargestOwnedPoints.value}") + return boundLocationWithLargestOwnedPoints.value + } + + fun doPart2(locations: List): Int { + // very easy. just find all locations where the sum of MD's to every point is under 10000 + return safeLocations(locations, 10000) + } + + fun safeLocations(locations: List, limit: Int) = + locations.map { it.position }.bounds().points() + .map { p -> locations.sumOf { p.manhattenDistance(it.position) } }.filter { it < limit }.count() + + data class Location(val position: Point, var isBounded: Boolean) + + private fun belongsTo(p: Point, locations: List): List { + // for this point, find the locations with the lowest manhatten distance + // gets a map entry of format {2, [Location1, Location2]} for this point + val lowestMDtoLocations = locations.groupBy { location -> + location.position.manhattenDistance(p) + }.minBy { it.key } + return lowestMDtoLocations.value + } + + fun toLocations(data: List): List { + val locations = data.map { line -> + val p = line.split(",", limit = 2).map { it.trim().toInt() }.let { Point(it[0], it[1]) } + Location(position = p, isBounded = true) + } + + // go around the bounding edge, and find the closest location to us. that will be an infinite location and thus unbounded + // Only consider those points not shared, as this could just be the edge of the data + // My original implementation of considering points that had nothing Up/Down/Left/Right of them didn't work on real data, but did on test :( + val bounds = locations.map { it.position }.bounds() + bounds.edgePoints().forEach { edge -> + val b2 = belongsTo(edge, locations) + if (b2.size == 1) b2[0].isBounded = false + } + + return locations + } + + fun ownershipString(locations: List): String { + var output = "" + val namedLocations = locations.mapIndexed { index, location -> + location to ('a' + index) + }.toMap() + val bounds = locations.map { it.position }.bounds() + for(y in bounds.first.y - 1 .. bounds.second.y + 1) { + for (x in bounds.first.x - 1 .. bounds.second.x + 1) { + val p = Point(x, y) + val b2 = belongsTo(p, locations) + output += if (b2.size > 1) "." else { + val n = namedLocations[b2.first()]!! + if (locations.any { it.position == p }) n.uppercase() else n + } + } + output += "\n" + } + return output + } + + @JvmStatic + fun main(args: Array) { + println(part1()) + println(part2()) + } + +} \ No newline at end of file diff --git a/advents/src/main/kotlin/net/fish/y2018/DayTemplate.kt b/advents/src/main/kotlin/net/fish/y2018/DayTemplate.kt new file mode 100644 index 0000000..609e545 --- /dev/null +++ b/advents/src/main/kotlin/net/fish/y2018/DayTemplate.kt @@ -0,0 +1,21 @@ +package net.fish.y2018 + +import net.fish.Day +import net.fish.resourceLines + +object DayTemplate : Day { + private val data by lazy { resourceLines(2018, 0) } + + override fun part1() = doPart1(data) + override fun part2() = doPart2(data) + + fun doPart1(data: List): Int = data.size + fun doPart2(data: List): Int = data.size + + @JvmStatic + fun main(args: Array) { + println(part1()) + println(part2()) + } + +} \ No newline at end of file diff --git a/advents/src/main/kotlin/net/fish/y2022/Day04.kt b/advents/src/main/kotlin/net/fish/y2022/Day04.kt index acff98d..b50f5e0 100644 --- a/advents/src/main/kotlin/net/fish/y2022/Day04.kt +++ b/advents/src/main/kotlin/net/fish/y2022/Day04.kt @@ -1,6 +1,8 @@ package net.fish.y2022 import net.fish.Day +import net.fish.collections.fullyContains +import net.fish.collections.overlaps import net.fish.resourceLines object Day04 : Day { @@ -30,10 +32,3 @@ object Day04 : Day { println(part2()) } } - -fun IntRange.fullyContains(t: IntRange): Boolean = this.first <= t.first && this.last >= t.last - -fun IntRange.overlaps(t: IntRange): Boolean { - return (this.first in t.first..t.last) || (this.last in t.first..t.last) || - (t.first in this.first..this.last) || (t.last in this.first..this.last) -} \ No newline at end of file diff --git a/advents/src/main/kotlin/net/fish/y2022/Day05.kt b/advents/src/main/kotlin/net/fish/y2022/Day05.kt index e1ff1e3..244cfc1 100644 --- a/advents/src/main/kotlin/net/fish/y2022/Day05.kt +++ b/advents/src/main/kotlin/net/fish/y2022/Day05.kt @@ -24,11 +24,13 @@ object Day05 : Day { do { val instruction = move(model) } while (instruction != NoMoreInstructions) } + // Could use a boolean instead of MoverInstruction, we just need to know if it processed anything fun move(model: MoverModel): MoverInstruction { return if (currentInstruction < instructions.size) { val instruction = instructions[currentInstruction++] val taken = (0 until instruction.count).map { _ -> columns[instruction.from - 1]!!.removeLast() } (if (model == M9000) taken else taken.reversed()).forEach { c -> columns[instruction.to - 1]!!.addLast(c) } + // only returned to indicate it wasn't end instruction } else NoMoreInstructions } @@ -41,8 +43,11 @@ object Day05 : Day { val moves = data[1] val columns = layout.split("\n").reversed().drop(1).fold(mutableMapOf>()) { ac, row -> + // position of letters on the line is 1, 5, 9, ... from "[Z] [M] [P]..." row.filterIndexed { i, _ -> (i - 1) % 4 == 0 }.mapIndexed { i, c -> - if (c != ' ') { ac.getOrDefault(i, ArrayDeque()).let { it.addLast(c); ac[i]= it } } + // get or create the map entry for the index, then add the character to the end of the (double ended) queue + // the char will be a space where there's nothing in that column, e.g. " [D]" + if (c != ' ') { ac.getOrDefault(i, ArrayDeque()).let { it.addLast(c); ac[i] = it } } } ac } diff --git a/advents/src/main/kotlin/net/fish/y2022/Day07.kt b/advents/src/main/kotlin/net/fish/y2022/Day07.kt index 7181d8a..18d80a1 100644 --- a/advents/src/main/kotlin/net/fish/y2022/Day07.kt +++ b/advents/src/main/kotlin/net/fish/y2022/Day07.kt @@ -39,6 +39,8 @@ object Day07 : Day { } fun readDisk(data: List): AOCDir { + // The instructions always "ls" a directory once going into it, which then gives us the definitions for that dir. + // The ls instruction itself is ignored val root = AOCDir("/", mutableListOf(), mutableListOf(), null) var currentDir = root val fileRE = Regex("^\\d+ ") diff --git a/advents/src/main/kotlin/net/fish/y2022/Day08.kt b/advents/src/main/kotlin/net/fish/y2022/Day08.kt index b5f488c..fcf3144 100644 --- a/advents/src/main/kotlin/net/fish/y2022/Day08.kt +++ b/advents/src/main/kotlin/net/fish/y2022/Day08.kt @@ -5,8 +5,7 @@ import net.fish.collections.takeWhileInclusive import net.fish.geometry.Direction import net.fish.geometry.Point import net.fish.geometry.bounds -import net.fish.maths.IntCombinations -import net.fish.maths.Ring +import net.fish.maths.PairCombinations import net.fish.resourceLines import net.fish.y2021.GridDataUtils @@ -23,16 +22,15 @@ object Day08 : Day { return TreeGrid(GridDataUtils.mapIntPointsFromLines(data)) } - class PairCombinations(size: Int): IntCombinations(2) { - override val state = Array(2) { Ring(size) }.toList() - override fun state() = state.map { it.state() }.reversed() - } - data class TreeGrid(private val gridData: Map) { private val compassDirs = listOf(Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST) private val boundary: Pair = gridData.keys.bounds() - private val treeColumns = PairCombinations(boundary.second.x + 1).groupBy { it[0] }.values.map { it.map { x -> Point(x[0], x[1]) } } - private val treeRows = PairCombinations(boundary.second.y + 1).groupBy { it[1] }.values.map { it.map { y -> Point(y[0], y[1]) } } + // PairCombinations are lists of "lists of pairs". see tests. + // This orders the combinations of (0,0), (0,1), ... into by column or row. See tests + // list of N lists of the columns point locations, {(0,0), (0,1), (0,2), (0,3), ...}, {(1,0), (1,1), (1,2), (1,3), ...}, ... + private val treeColumns = PairCombinations(boundary.second.x + 1).groupBy { it[0] }.values.map { it.map { p -> Point(p[0], p[1]) } } + // list of N lists of the rows point locations, {(0,0), (1,0), (2,0), (3,0), ...}, {(0,1), (1,1), (2,1), (3,1), ...}, ... + private val treeRows = PairCombinations(boundary.second.y + 1).groupBy { it[1] }.values.map { it.map { p -> Point(p[0], p[1]) } } private fun allPoints(): Set = gridData.keys private fun onBoundary(p: Point): Boolean = diff --git a/advents/src/main/resources/2018/day01.txt b/advents/src/main/resources/2018/day01.txt new file mode 100644 index 0000000..f954534 --- /dev/null +++ b/advents/src/main/resources/2018/day01.txt @@ -0,0 +1,1040 @@ ++2 ++11 ++4 +-16 +-4 ++15 ++19 +-8 +-17 ++12 ++8 ++8 ++18 +-10 +-17 +-6 ++10 ++10 ++19 ++11 ++12 +-17 ++4 +-1 ++12 ++6 ++13 ++14 ++6 ++19 ++2 ++19 +-7 +-15 ++6 +-12 +-15 +-18 ++17 ++8 ++4 ++14 ++1 ++15 +-6 +-6 ++13 ++9 +-2 ++1 ++15 +-12 ++18 ++7 +-14 ++15 +-16 ++6 +-12 +-11 +-12 +-1 +-15 +-8 +-18 +-15 ++11 ++13 +-7 ++15 ++19 ++2 ++17 +-9 +-15 +-11 +-8 ++16 ++17 +-6 ++13 ++16 +-20 ++19 ++8 ++14 ++5 ++11 +-5 ++6 ++10 ++3 +-7 +-5 +-14 ++9 ++6 ++13 ++4 +-3 +-13 +-6 +-18 +-23 +-2 ++16 ++12 +-4 ++12 ++3 +-4 ++9 +-14 ++1 +-17 +-21 ++11 +-8 ++7 +-16 +-20 +-3 +-10 +-17 +-11 ++6 +-15 +-11 ++17 ++12 +-13 +-11 +-12 +-18 +-1 ++10 +-16 +-1 +-8 ++18 ++4 ++2 +-11 +-18 ++8 ++18 +-17 ++7 ++3 ++17 ++7 ++1 +-16 ++10 +-6 +-10 ++31 +-5 +-14 ++15 ++19 ++6 +-1 ++17 +-4 ++16 +-6 ++9 +-26 +-18 ++17 +-9 +-5 +-19 ++2 ++13 ++41 +-18 ++10 +-26 +-12 ++4 +-3 +-23 +-9 +-29 +-13 ++15 ++4 +-21 ++14 ++23 +-24 +-4 +-12 +-8 +-18 +-16 +-14 ++17 +-8 +-16 ++13 +-15 ++7 ++9 +-17 +-4 +-7 +-12 ++4 ++10 +-13 +-6 +-8 ++10 ++1 ++9 +-15 ++14 +-15 ++11 +-18 +-18 ++2 ++10 +-8 +-10 ++5 +-4 ++12 +-4 +-2 ++15 ++17 ++16 ++19 ++17 ++13 ++8 +-10 ++13 ++8 +-13 +-14 ++5 +-3 +-15 +-16 +-9 +-5 +-10 ++8 +-2 ++1 +-14 +-7 +-3 +-12 +-3 ++10 +-18 ++22 ++8 +-13 +-3 +-18 +-12 +-9 ++1 +-10 ++8 +-13 +-12 +-9 +-2 ++12 +-14 ++8 +-19 +-6 +-11 ++12 ++15 ++17 ++7 +-14 ++11 ++9 +-10 +-21 ++3 +-19 +-6 +-6 ++7 ++15 +-13 +-8 ++10 +-18 ++15 +-9 +-19 ++5 ++11 +-7 +-14 ++7 ++9 ++6 ++6 ++13 ++8 ++13 ++19 +-8 +-3 +-4 +-18 ++12 +-2 ++18 ++13 +-1 ++17 +-7 ++12 ++8 ++2 ++19 +-11 ++22 ++14 ++9 +-12 ++24 ++1 ++5 ++20 +-18 ++17 +-9 ++12 +-4 +-15 +-10 ++4 +-7 ++11 ++13 ++10 ++21 +-14 +-1 +-13 +-6 ++14 ++7 ++7 ++10 ++11 +-22 ++6 ++17 ++26 +-7 ++8 +-5 ++29 +-54 +-16 ++13 ++10 +-1 +-23 ++12 +-20 +-20 +-27 ++1 +-2 +-4 +-26 +-2 +-36 +-18 ++14 +-3 +-18 +-1 ++17 ++15 +-12 ++9 ++1 ++23 +-22 +-6 +-20 ++19 ++3 +-17 +-6 +-41 +-5 +-5 +-5 +-19 +-9 +-13 ++3 ++2 ++10 ++5 +-6 +-18 +-19 ++10 ++17 ++6 +-17 ++5 +-7 ++10 ++6 +-5 +-14 ++1 +-17 +-19 ++7 ++14 +-19 ++6 ++12 +-16 ++13 +-1 ++16 ++14 +-13 +-4 ++2 +-17 +-1 +-7 +-5 +-3 +-14 +-3 ++5 ++11 +-12 +-5 +-14 ++2 ++2 +-15 ++12 +-3 ++15 +-2 ++10 ++7 +-16 ++12 +-15 ++1 +-3 +-4 +-19 ++7 +-5 ++22 ++8 ++17 ++16 ++15 ++11 ++3 +-16 +-10 ++7 ++12 ++16 ++13 +-10 ++15 +-1 +-15 ++22 ++1 ++3 ++20 ++24 ++12 ++17 +-19 +-12 ++7 +-11 +-19 ++4 ++4 +-21 ++22 ++1 ++45 ++3 +-9 ++41 +-1 ++94 ++2 ++7 +-37 ++3 ++217 ++13 ++10 +-14 ++5 +-3 +-14 +-26 +-39 ++80 ++33 ++9 +-13 ++7 ++7 +-13 +-14 ++1 ++37 ++33 ++7 ++14 ++1 +-5 +-11 +-8 +-12 ++4 ++14 +-17 ++1 +-10 +-20 +-25 ++27 ++31 +-8 ++1 ++53 ++22 ++9 +-14 +-49 ++13 +-52 +-64 +-100 ++34 ++198 ++605 ++76787 +-8 ++13 ++4 +-8 ++5 ++9 +-7 +-13 +-6 +-4 +-20 ++6 ++12 +-4 ++7 ++5 +-14 ++10 ++17 ++18 ++18 ++5 ++6 +-12 +-6 +-8 +-13 +-5 +-8 +-17 ++6 ++2 ++3 ++18 +-1 ++20 ++14 +-18 ++21 +-12 ++3 ++8 ++6 ++21 +-3 ++1 ++9 ++16 ++15 +-7 ++1 +-16 ++17 +-5 +-15 +-14 ++3 ++3 +-4 ++2 ++1 ++16 ++19 ++12 +-4 ++14 +-8 ++17 +-7 +-1 +-3 +-11 +-12 ++7 ++9 +-10 +-13 ++1 +-8 ++4 +-12 ++13 +-10 +-8 +-3 +-19 +-12 ++7 ++9 +-1 +-9 +-4 +-19 +-12 ++17 +-12 ++19 ++18 +-12 +-7 +-10 ++5 +-21 ++4 +-6 ++4 +-15 +-9 ++19 +-17 ++21 ++12 ++24 ++13 ++18 +-16 +-11 ++10 ++18 ++7 ++16 +-10 +-4 +-13 ++29 +-13 +-9 ++3 +-22 +-13 ++67 +-10 ++9 ++6 ++2 ++8 ++6 ++18 +-16 +-15 ++9 ++2 ++3 +-4 ++7 ++18 ++12 +-10 +-15 ++1 ++11 +-9 +-19 ++15 ++8 ++11 ++2 ++3 ++9 ++14 +-19 ++16 +-5 +-12 ++8 ++17 ++4 ++10 +-13 ++19 ++9 +-19 +-11 ++8 ++6 ++3 ++5 +-16 ++3 ++7 ++11 +-1 ++5 +-7 +-12 ++13 +-6 ++1 ++18 ++6 ++1 ++14 +-7 +-2 +-13 ++18 +-1 ++18 +-5 ++3 +-14 +-17 ++1 ++13 ++16 ++14 ++4 +-13 +-12 +-1 ++2 ++3 ++14 +-1 +-6 ++12 ++8 +-11 ++6 +-7 ++19 +-16 ++5 ++18 ++11 +-16 +-8 +-3 ++13 ++6 ++7 +-14 ++9 ++14 +-7 ++9 +-14 ++1 +-6 ++16 +-2 +-12 +-5 +-8 ++7 +-19 ++13 ++2 ++7 ++13 +-8 ++7 ++15 ++9 ++10 +-5 ++4 ++7 +-1 ++12 ++13 ++13 ++10 ++13 ++13 +-6 ++12 ++10 +-5 ++9 ++11 +-16 ++8 +-11 +-15 +-15 ++10 +-17 ++2 +-6 +-11 +-14 +-13 +-14 +-5 +-8 +-1 +-7 +-7 ++21 +-11 +-5 ++3 ++5 +-15 ++20 ++8 +-17 ++7 +-13 ++35 ++6 +-3 +-1 +-16 ++8 +-5 +-10 ++14 ++20 ++13 ++10 +-20 +-17 ++13 +-2 ++9 ++19 +-8 ++4 +-2 ++12 +-15 ++12 +-4 ++20 +-7 ++2 +-5 +-19 +-3 +-1 ++3 ++6 ++7 +-20 ++19 ++15 ++10 ++3 +-7 ++1 ++13 ++4 ++6 ++5 ++4 ++4 ++7 +-19 ++16 ++2 ++4 +-8 +-7 ++18 ++15 ++6 ++1 +-13 ++14 ++18 +-7 ++8 +-16 +-10 ++13 +-12 ++13 ++14 ++14 +-8 +-19 ++4 +-15 +-16 +-16 +-8 ++10 ++17 +-12 ++10 ++8 ++19 +-13 ++14 ++12 ++3 +-10 ++2 ++14 ++1 +-2 ++3 ++16 +-3 +-12 ++5 ++4 +-19 ++17 +-4 +-8 ++15 +-6 ++14 ++21 +-4 +-18 ++4 +-8 ++21 +-28 ++5 +-25 +-4 +-2 ++14 +-2 +-22 +-9 +-7 +-5 +-20 +-17 +-6 ++8 +-5 +-4 +-2 +-15 +-6 ++13 ++13 ++13 +-29 +-16 ++13 +-38 ++5 +-16 ++4 +-15 ++19 +-31 ++24 ++6 +-13 ++20 +-47 +-6 ++13 ++14 +-79 +-14 ++11 +-4 ++24 +-18 +-1 ++20 +-4 ++24 +-26 +-25 +-16 +-6 +-8 +-7 ++8 +-77371 \ No newline at end of file diff --git a/advents/src/main/resources/2018/day02.txt b/advents/src/main/resources/2018/day02.txt new file mode 100644 index 0000000..0227cfd --- /dev/null +++ b/advents/src/main/resources/2018/day02.txt @@ -0,0 +1,250 @@ +ymdrcyapvwfloiuktanxzjsieb +ymdrwhgznwfloiuktanxzjsqeb +ymdrchguvwfloiuktanxmjsleb +pmdrchgmvwfdoiuktanxzjsqeb +ymdrfegpvwfloiukjanxzjsqeb +ymdrchgpvwfloiukmanazjsdeb +ymdsnhgpvwflciuktanxzjsqeb +lmdrbhrpvwfloiuktanxzjsqeb +ymdrwhgpvwfloiukeanxzjsjeb +ymdrchgpvpfloihktanszjsqeb +omdrchgpvwflokuktanazjsqeb +kmsrchgpvwfloiuktanxqjsqeb +ymdrchopvwzloiustanxzjsqeb +omdrchgpvwfloiuktawxtjsqeb +ymdrchgpvwfroiukhanozjsqeb +ymdrchgpvwfloikktanyzosqeb +ymdrchgpvwfioiuktaexzjsqea +ymdrcngpvwfloiuktanxzjsamb +ymdrchgpqwfaoiuktanxxjsqeb +ymdrcmgpvwflziuktakxzjsqeb +ymdrchguvwsloiuktanxzjsqen +ymdrchppowfloiuvtanxzjsqeb +ymdrcngpvwflyiukkanxzjsqeb +ymdrcbgpvwfloiukjanxzjspeb +ymdrchgpvwflopuktanxzosseb +ygdrchgpvwfloiukxanxcjsqeb +ymdrchgpvwfloauktanuzjsqei +ymerchgpvwfloiumtanxzjsqet +ymdlcegpvwfloiuktbnxzjsqeb +ymdrclgpvwfloiukyanxzjlqeb +ymdrchgpvwhmoiuktanxijsqeb +ymdrchgpwrfloiuktanxdjsqeb +ymdbcwgpvwfloiuktanxzusqeb +ymgrchgphwfloiuktanxzjspeb +imdrchgpvwflmiuktanxzjsqib +ymdrihgpvwfloiiktanxzjsteb +ywdrchgpvwfloibkvanxzjsqeb +ymdrchgpxwfloiuktanezjsqes +ymdrchgpiwfloiukxanxzhsqeb +ymdrchgpveflokuktdnxzjsqeb +kmdrchgpvwfloviktanxzjsqeb +ymdrchgpvgfmoiuytanxzjsqeb +ymyrchgpvzfluiuktanxzjsqeb +ymdrchguvwfloiuktanxpjsqlb +ymerchgpvwfloiukthnxsjsqeb +hmdrchgpvwglfiuktanxzjsqeb +ymdrchgpvwfdoiuktanxzjsqaf +yudrchgdvwfloiuktaexzjsqeb +ymdbchgxvwfloiuktanxzjsqem +ymdrchgpvwfloiumjanxzjsqpb +ymdrchgpqwfloiuqtanxrjsqeb +ymdqchhpvwfloiuktanxzzsqeb +ymdryhgpfwfloiuktanxzjsyeb +xmdrchgpvwfloioitanxzjsqeb +ykdrchgpvwfloiuktcnxzisqeb +ymdrcpgprwfloiuktanqzjsqeb +yidrchgpvwfloiuktanxzjgleb +ymdrchgpxwfloiuktanxzjsxfb +ymdrchgfvwfloiuktanxzjiteb +ymdrchgvvwflqifktanxzjsqeb +ymdrchgplwfloiuktanizjnqeb +ymdrchgpvwfyfiuktafxzjsqeb +ymddchgpvwcloiuktanxzjsqeq +ymdrchgkvwflaiuktanxzjsqfb +yudrchgpvwfzoiuktanxzjsreb +ymdrdhgpvwfloiuktnnxqjsqeb +ymdrnhgpvwfloiuktauxzjdqeb +ymdrchgpvwflsiddtanxzjsqeb +ymdrchgpvwhloeuktanxzjsqek +ymdrchgpvjfioiuktawxzjsqeb +ycdrohgpvwfgoiuktanxzjsqeb +ymdrchgpvwflmifktanxzjsqel +yfdrchrpvwfloruktanxzjsqeb +ymdrchgjvwfloiuktanxzrsqeg +ymarchgpxwfloiukkanxzjsqeb +ymdrchgppwflghuktanxzjsqeb +ymdrchvpvwfloiuktanxpjrqeb +ymdlchgpqjfloiuktanxzjsqeb +ymdrchgpvwfofiuktandzjsqeb +ymdrcngpqwfloiuktanlzjsqeb +ymdrchgpvwfloiuiocnxzjsqeb +ymdrcogpvwfloizktanxzjcqeb +ymdrchgpvlfvoiuksanxzjsqeb +ymdrchgpvwflocpctanxzjsqeb +ymdrchgpvwfloiuktanlzjsejb +yndrchgpvwflzifktanxzjsqeb +ymdrcrgpvkfloiuktanxrjsqeb +ymdrchhpvwslocuktanxzjsqeb +ymdrxhgpvwfloiuwtazxzjsqeb +ymdrchgpvafloiuutanxzjsqxb +ymdrchppvhfloquktanxzjsqeb +ymprcugpvwtloiuktanxzjsqeb +ymdrchgpvvflyiuktanxzjsqvb +ymdrchgovwfloiuftanxzjwqeb +ymdrchrpvwflotyktanxzjsqeb +gmdrchgpvwfloauttanxzjsqeb +ymdrchmpvofloiukmanxzjsqeb +ymdrchgpvwflsiuktanxzjspkb +ymdrchgpvwfloluktajxijsqmb +ymdrcngpvwfloiukbanxzdsqeb +ymdrchgpvwploiuktnnxzmsqeb +ymdrcwgpvwfloiuktbnxhjsqeb +ymdrcngpvwfloiuktaaxbjsqeb +ykdrchgpvwfloiuktanxzgsqej +yuhrchgpvwfdoiuktanxzjsqeb +ymdrchgpvsfloiukbanxujsqeb +ymqrchgpvwfliiuktanxzjsteb +ysdqchgpvwfloiuktanxzjtqeb +ymdjchgpcwfloiuktanxzrsqeb +ymdkchgpvwfloiukfanlzjsqeb +ymdrchgpvxfloikktanxzjiqeb +smdrchgwewfloiuktanxzjsqeb +ymdrchgpvwfljiuktanxajsqer +ymdrchgpowflifuktanxzjsqeb +ymdrchgpvpzloiukoanxzjsqeb +yydrchgwvwfvoiuktanxzjsqeb +ymdgcdgpvwflobuktanxzjsqeb +ymdechgpvkfloiuktanxzjsjeb +ymdnchnpvwfloixktanxzjsqeb +ymdrchgpiefloiuktqnxzjsqeb +ymprchgpvwfloiuktjnxzjsxeb +ymdrjdgpzwfloiuktanxzjsqeb +ymsrchgpywfloiuktanxzjsueb +ymdrchgpvgoloiuktanxzcsqeb +ymdrphgpswflbiuktanxzjsqeb +ymqrchgpvnfloiumtanxzjsqeb +ymjrchgpvwyloiuktacxzjsqeb +ymdrchepvwmlqiuktanxzjsqeb +kmirchgpvwfloiuktanxzjsreb +ymdncygpvwfloiuktanuzjsqeb +ymdrzhgpvwploiuktanxzxsqeb +ymdrchkpvwfloiwkmanxzjsqeb +ywdrchgovwfloiuktanxzjsceb +amdrchgpvwfloiuktanrzjqqeb +ymdpshgpvwfloiuktanxzjyqeb +ymdrcegpvwfloijktcnxzjsqeb +ymdrcygpvwfloiuktanxztsqwb +ymdrchgpvufloiuvtabxzjsqeb +ymdrchgpvwflkiuktrnxzjsqmb +ymdrchgpvqfloiuktanxpjfqeb +ymdrclgpvkfloiyktanxzjsqeb +ybdxchgpvwfloiuktanxzjskeb +pmdrchgpvwfzoirktanxzjsqeb +ycdfchgpvwfloiuktanxzjtqeb +ymdrchgpdwfloiumtbnxzjsqeb +ymdrchgpqmfloiuktanxzjsqer +ymgrchgpvwfroiuktanxzjsqey +ymdrnhgpvwfloiuktanjzjsqlb +dmdrchgpvgfloiuktqnxzjsqeb +yudrchgnvwfloiukranxzjsqeb +ymdrxhgpvafloiuktanxzjsqeq +ymdrchgpvwfyofuktanxzjsueb +ymdrrhgpvwfloiuktavxzjsqpb +yvdrchgpvwfloiuktalxzhsqeb +ymdrchgpbwfloiuktanxzfnqeb +ymdrqhgpvwfloiuvtznxzjsqeb +ymdrchgpvbfloiuetanxzjsqeo +ymdrchjpvwfloiuktanxzjnqrb +ymdrchgpmwfqoiuknanxzjsqeb +ymdrchgpvwfuoiuktaqxzjtqeb +ymdrchgpvwfloiuktamxaosqeb +fmdrchgpvffloiuktanxzjsaeb +ymdrrhglvwfwoiuktanxzjsqeb +ymdrchgpvwflohuktanxzjcqei +ymdrcsgpvwfloiuktaexzjsqek +ymlrchfpvwfloiuktpnxzjsqeb +yxdrchgpvwfdoiuvtanxzjsqeb +ymdrchgrvwfloiuktadxzjsqew +ymdrchgpvwbloiyktandzjsqeb +ymdrchgpvsfloiyktanozjsqeb +ymdrchgpjwfloiuktanxibsqeb +ymdrchgjvyfloiuktanxzjsqeh +ymdrchgvvwfloiuktanzrjsqeb +ymdrchgpvwaloiuktynxzjsqev +ymdrccgpvwflonvktanxzjsqeb +ymdrchgqvffloiuktanxfjsqeb +ymdbchgpvwsloiudtanxzjsqeb +ymdachgpvwfloiuktanlzjsqwb +ymdrclgpvwwloiuktanxzjsjeb +ybdpchgpvwdloiuktanxzjsqeb +ymdtchgpvwfleijktanxzjsqeb +ymdrchgpvwfloiustanxzjsxep +ymdrcjypvwfloiuktanxnjsqeb +ymdrcdgpvwfloiuutanxkjsqeb +yhirchgpvufloiuktanxzjsqeb +ymdrlhgpvwfluigktanxzjsqeb +ywdrhhgpvwftoiuktanxzjsqeb +ymdrchgpvwflyiuktanozjsqtb +cmdrchgpuwfloiukmanxzjsqeb +ymdochgpvrfloiuktanvzjsqeb +ymdrcvgpvwfgoiuktfnxzjsqeb +ymdrchgpmufloiuktanxzssqeb +ymurchgrvwfloiuktanxzjsqep +bmdrchgpvwfloiukpanxzjsqmb +ymdrchgphwvloiuktanszjsqeb +ymdpkhgpvwfloiuktanxzjsqtb +ymdrchgpvwfloiuwtanxzjfqev +ymdrchgpvwfloguktqlxzjsqeb +ymkrshgpvwflgiuktanxzjsqeb +ymdrchgpzwfloizktanxznsqeb +ymdrchgpvxfloiuktegxzjsqeb +yydrchgpwwfloiuktanxzjsqqb +ymdrcngwvwfltiuktanxzjsqeb +ymdszhgwvwfloiuktanxzjsqeb +ymdrchguvwfjoiuktanxzxsqeb +ymdomhgpvwfloiuktanxgjsqeb +ymdrcvgpvwfloiuktanwzzsqeb +yydrchgpvwfloiuktanxzjmqtb +rmdrchgpvwfloiuktmnszjsqeb +ykdrchgpvwfloyuktmnxzjsqeb +ymcrchkpvwfloiuktanxzjsoeb +ymdrcrgpvwfloiukpanxzjsceb +yrdrchgpvwfloiukwanxzjsqhb +ymdrcfgpvwfloiurtanxojsqeb +ymdrchgpuwstoiuktanxzjsqeb +ymdrchgpvwflpxuktanxzjsqer +ymdrehgpvwfloiuktabxdjsqeb +yedrchgpvwfloiukqanxzjiqeb +ymdrthgpvyfloiuktanxzjsqen +cmdlchgpvwfloiuvtanxzjsqeb +ymdrchgpvwtloiuktanlpjsqeb +ymdrchgpvwfloiuktanyvjsqea +gmdrcogpvwfloiuktanxzjsqqb +ymmrchgpvwflosuktauxzjsqeb +ymgrchgjvwfloiuktavxzjsqeb +ymdbclgpvwfloeuktanxzjsqeb +ymdrchgpvwfloiuktaixzcsqfb +ymdrchgpvwflmiuktanxttsqeb +ymxrchgpvwfloiuktanxzfsqec +yqzrchgpcwfloiuktanxzjsqeb +yvdrchgpvwfloiukgvnxzjsqeb +ymdrchepvwfloiuktahxzosqeb +ymdlchgpvwfloiuktamizjsqeb +ymdrchgpcwflovuktanxzjsqzb +yvduchgpvwfloiukaanxzjsqeb +ymdrchgpvwfloiuktxmxzjsgeb +ymdrcrgpvwfloizktanbzjsqeb +amdrchgpvwfloiukhanxzjsqbb +ymdrchgpvwfloluktajxijsqeb +ymdrcfgpvwfloiubtanxznsqeb +ymdrchgpvwfleiuwtanxzjsweb +ymdrchgpvwfzdguktanxzjsqeb +ymdrchgwvwflosyktanxzjsqeb +ymrrchgpvwfloiultanxzjsqez +ymdpchgkvwfleiuktanxzjsqeb +ymdrchgpvwfloijktalxfjsqeb +ymdrchgpmwfloiuktanzzjsqfb +ymdrcsgpvwfljiukyanxzjsqeb +ymdrcarpvwfloiuktapxzjsqeb +ymdrchgpvwfloiuktanxzjcqvs \ No newline at end of file diff --git a/advents/src/main/resources/2018/day03.txt b/advents/src/main/resources/2018/day03.txt new file mode 100644 index 0000000..628902c --- /dev/null +++ b/advents/src/main/resources/2018/day03.txt @@ -0,0 +1,1227 @@ +#1 @ 265,241: 16x26 +#2 @ 584,382: 12x8 +#3 @ 584,823: 22x10 +#4 @ 336,138: 26x22 +#5 @ 527,903: 26x18 +#6 @ 596,224: 23x20 +#7 @ 770,344: 15x12 +#8 @ 191,889: 17x11 +#9 @ 493,316: 12x19 +#10 @ 648,614: 26x28 +#11 @ 217,27: 25x20 +#12 @ 819,550: 16x12 +#13 @ 314,74: 18x25 +#14 @ 844,633: 22x16 +#15 @ 793,382: 11x18 +#16 @ 899,263: 16x14 +#17 @ 713,844: 11x21 +#18 @ 502,903: 19x12 +#19 @ 434,163: 29x24 +#20 @ 307,339: 23x15 +#21 @ 683,931: 10x22 +#22 @ 950,568: 23x15 +#23 @ 514,250: 11x19 +#24 @ 383,822: 28x20 +#25 @ 558,319: 13x22 +#26 @ 461,984: 25x11 +#27 @ 594,218: 18x14 +#28 @ 852,877: 18x29 +#29 @ 683,369: 22x29 +#30 @ 538,120: 20x24 +#31 @ 961,406: 26x27 +#32 @ 124,832: 11x15 +#33 @ 500,215: 16x22 +#34 @ 166,104: 12x23 +#35 @ 912,502: 22x16 +#36 @ 752,577: 18x10 +#37 @ 456,111: 11x20 +#38 @ 238,927: 18x14 +#39 @ 530,477: 20x13 +#40 @ 70,180: 26x22 +#41 @ 522,686: 17x20 +#42 @ 270,785: 17x23 +#43 @ 545,455: 24x15 +#44 @ 11,291: 10x18 +#45 @ 809,550: 21x12 +#46 @ 714,57: 19x12 +#47 @ 291,699: 29x17 +#48 @ 156,539: 25x26 +#49 @ 435,189: 13x16 +#50 @ 746,608: 26x16 +#51 @ 509,397: 15x4 +#52 @ 152,875: 22x29 +#53 @ 929,895: 22x18 +#54 @ 18,458: 19x26 +#55 @ 22,773: 28x14 +#56 @ 438,487: 17x11 +#57 @ 430,863: 27x13 +#58 @ 642,287: 19x25 +#59 @ 407,951: 13x4 +#60 @ 163,271: 18x19 +#61 @ 648,746: 11x27 +#62 @ 712,509: 21x23 +#63 @ 905,910: 29x25 +#64 @ 56,328: 25x24 +#65 @ 761,688: 11x18 +#66 @ 897,165: 29x25 +#67 @ 892,899: 19x28 +#68 @ 407,722: 12x25 +#69 @ 521,885: 20x26 +#70 @ 505,737: 24x10 +#71 @ 181,333: 24x16 +#72 @ 960,55: 11x24 +#73 @ 539,850: 23x28 +#74 @ 880,166: 13x13 +#75 @ 218,500: 18x18 +#76 @ 451,553: 25x22 +#77 @ 786,107: 20x13 +#78 @ 615,282: 22x15 +#79 @ 147,430: 25x29 +#80 @ 629,98: 18x25 +#81 @ 231,830: 17x13 +#82 @ 873,104: 18x11 +#83 @ 674,811: 21x13 +#84 @ 58,287: 13x29 +#85 @ 802,211: 18x11 +#86 @ 843,467: 21x23 +#87 @ 187,576: 24x21 +#88 @ 762,618: 10x20 +#89 @ 490,550: 12x13 +#90 @ 575,305: 12x25 +#91 @ 32,89: 16x20 +#92 @ 10,243: 23x14 +#93 @ 50,847: 15x28 +#94 @ 817,539: 17x29 +#95 @ 622,540: 12x20 +#96 @ 574,829: 23x10 +#97 @ 224,638: 18x23 +#98 @ 367,753: 29x14 +#99 @ 134,694: 17x11 +#100 @ 165,757: 14x29 +#101 @ 41,811: 13x22 +#102 @ 621,906: 25x16 +#103 @ 728,745: 14x26 +#104 @ 723,65: 24x16 +#105 @ 536,93: 10x22 +#106 @ 871,204: 22x25 +#107 @ 372,276: 19x21 +#108 @ 24,77: 29x16 +#109 @ 292,585: 26x16 +#110 @ 621,346: 11x15 +#111 @ 463,726: 20x22 +#112 @ 802,100: 19x11 +#113 @ 626,726: 23x16 +#114 @ 405,944: 21x20 +#115 @ 954,410: 13x22 +#116 @ 244,839: 11x26 +#117 @ 65,272: 29x10 +#118 @ 476,382: 28x10 +#119 @ 794,319: 18x19 +#120 @ 115,682: 24x14 +#121 @ 818,612: 16x28 +#122 @ 7,755: 21x24 +#123 @ 365,404: 14x21 +#124 @ 584,218: 29x20 +#125 @ 41,608: 20x21 +#126 @ 4,217: 16x16 +#127 @ 894,723: 21x24 +#128 @ 125,716: 24x22 +#129 @ 392,211: 23x27 +#130 @ 429,16: 27x16 +#131 @ 350,530: 26x28 +#132 @ 767,626: 12x20 +#133 @ 916,120: 24x27 +#134 @ 287,878: 20x10 +#135 @ 434,445: 21x21 +#136 @ 115,683: 22x13 +#137 @ 583,875: 25x28 +#138 @ 87,171: 12x23 +#139 @ 328,136: 29x17 +#140 @ 860,485: 10x10 +#141 @ 787,287: 15x11 +#142 @ 500,845: 12x24 +#143 @ 147,252: 10x13 +#144 @ 399,78: 16x14 +#145 @ 780,412: 25x13 +#146 @ 193,792: 19x29 +#147 @ 195,718: 20x10 +#148 @ 811,550: 21x19 +#149 @ 906,69: 14x21 +#150 @ 542,964: 18x19 +#151 @ 225,412: 25x22 +#152 @ 763,42: 19x11 +#153 @ 299,607: 28x13 +#154 @ 781,283: 29x19 +#155 @ 110,46: 23x10 +#156 @ 769,108: 20x10 +#157 @ 916,713: 20x22 +#158 @ 686,875: 28x17 +#159 @ 749,698: 13x22 +#160 @ 958,203: 11x11 +#161 @ 771,97: 28x18 +#162 @ 46,147: 11x20 +#163 @ 340,346: 26x25 +#164 @ 332,340: 14x22 +#165 @ 217,878: 14x24 +#166 @ 377,80: 29x16 +#167 @ 135,164: 14x18 +#168 @ 578,235: 23x27 +#169 @ 938,68: 11x12 +#170 @ 315,397: 19x26 +#171 @ 218,425: 19x27 +#172 @ 125,688: 10x27 +#173 @ 337,696: 29x14 +#174 @ 851,834: 10x23 +#175 @ 265,901: 18x21 +#176 @ 369,796: 23x24 +#177 @ 207,884: 28x16 +#178 @ 387,607: 18x22 +#179 @ 518,182: 18x25 +#180 @ 512,775: 13x11 +#181 @ 21,572: 15x27 +#182 @ 526,848: 14x18 +#183 @ 636,973: 19x24 +#184 @ 468,469: 10x23 +#185 @ 371,102: 15x27 +#186 @ 56,270: 26x22 +#187 @ 487,329: 25x17 +#188 @ 212,964: 16x15 +#189 @ 602,538: 19x18 +#190 @ 610,116: 26x28 +#191 @ 163,419: 22x11 +#192 @ 787,310: 18x25 +#193 @ 396,781: 13x17 +#194 @ 582,379: 22x18 +#195 @ 385,764: 10x18 +#196 @ 15,222: 11x10 +#197 @ 185,824: 14x11 +#198 @ 365,465: 21x13 +#199 @ 278,534: 20x19 +#200 @ 945,545: 20x28 +#201 @ 831,304: 20x25 +#202 @ 94,630: 15x26 +#203 @ 352,792: 25x14 +#204 @ 404,817: 15x18 +#205 @ 521,895: 26x12 +#206 @ 398,426: 17x20 +#207 @ 462,118: 21x18 +#208 @ 780,316: 19x13 +#209 @ 837,29: 16x25 +#210 @ 491,536: 20x19 +#211 @ 463,389: 25x26 +#212 @ 704,547: 17x21 +#213 @ 737,464: 14x23 +#214 @ 852,681: 19x14 +#215 @ 754,321: 20x16 +#216 @ 821,495: 11x24 +#217 @ 909,961: 20x21 +#218 @ 924,403: 19x12 +#219 @ 915,136: 12x21 +#220 @ 177,384: 12x20 +#221 @ 859,216: 19x14 +#222 @ 772,705: 25x12 +#223 @ 266,76: 22x14 +#224 @ 398,206: 22x22 +#225 @ 526,905: 23x26 +#226 @ 311,593: 22x23 +#227 @ 456,566: 20x24 +#228 @ 808,294: 11x10 +#229 @ 831,43: 24x24 +#230 @ 43,764: 20x29 +#231 @ 529,25: 13x29 +#232 @ 285,698: 10x16 +#233 @ 233,848: 26x21 +#234 @ 65,185: 13x22 +#235 @ 959,74: 18x20 +#236 @ 849,398: 26x19 +#237 @ 88,492: 26x11 +#238 @ 680,389: 17x29 +#239 @ 802,81: 24x19 +#240 @ 454,573: 15x25 +#241 @ 149,757: 16x27 +#242 @ 965,680: 24x24 +#243 @ 82,589: 16x16 +#244 @ 656,528: 23x23 +#245 @ 427,647: 24x29 +#246 @ 5,452: 26x21 +#247 @ 701,527: 17x13 +#248 @ 656,527: 14x27 +#249 @ 6,493: 14x29 +#250 @ 143,505: 21x17 +#251 @ 257,736: 15x29 +#252 @ 499,188: 28x20 +#253 @ 748,568: 24x20 +#254 @ 567,222: 23x12 +#255 @ 308,571: 12x14 +#256 @ 512,232: 11x22 +#257 @ 123,57: 27x25 +#258 @ 185,948: 15x28 +#259 @ 844,747: 21x26 +#260 @ 249,934: 25x23 +#261 @ 232,440: 15x14 +#262 @ 393,403: 15x27 +#263 @ 390,716: 21x17 +#264 @ 227,856: 15x10 +#265 @ 175,877: 12x16 +#266 @ 857,535: 11x25 +#267 @ 838,393: 12x14 +#268 @ 624,331: 12x21 +#269 @ 195,150: 24x14 +#270 @ 887,538: 23x27 +#271 @ 201,496: 24x20 +#272 @ 322,122: 25x25 +#273 @ 14,96: 28x10 +#274 @ 240,430: 19x25 +#275 @ 199,536: 26x24 +#276 @ 691,472: 26x22 +#277 @ 252,580: 25x13 +#278 @ 124,609: 26x28 +#279 @ 927,559: 14x11 +#280 @ 173,858: 21x14 +#281 @ 679,810: 10x15 +#282 @ 794,669: 15x27 +#283 @ 509,292: 23x26 +#284 @ 449,205: 11x23 +#285 @ 263,329: 24x23 +#286 @ 667,571: 29x25 +#287 @ 127,307: 21x14 +#288 @ 630,112: 23x23 +#289 @ 456,254: 11x13 +#290 @ 601,945: 20x19 +#291 @ 622,239: 18x15 +#292 @ 496,884: 20x14 +#293 @ 7,758: 27x27 +#294 @ 528,676: 12x21 +#295 @ 691,550: 15x17 +#296 @ 332,635: 26x26 +#297 @ 536,363: 27x29 +#298 @ 791,656: 16x23 +#299 @ 892,839: 6x11 +#300 @ 449,32: 22x24 +#301 @ 450,315: 11x23 +#302 @ 229,943: 26x15 +#303 @ 796,785: 11x18 +#304 @ 816,338: 24x12 +#305 @ 245,944: 10x29 +#306 @ 43,757: 20x26 +#307 @ 938,59: 12x14 +#308 @ 182,615: 27x16 +#309 @ 614,429: 25x21 +#310 @ 819,925: 23x23 +#311 @ 209,769: 20x24 +#312 @ 786,978: 25x15 +#313 @ 951,846: 25x27 +#314 @ 695,26: 12x11 +#315 @ 843,891: 23x10 +#316 @ 139,627: 21x28 +#317 @ 716,303: 23x24 +#318 @ 612,377: 22x12 +#319 @ 853,663: 11x25 +#320 @ 838,639: 14x24 +#321 @ 629,934: 24x16 +#322 @ 866,809: 12x27 +#323 @ 44,801: 21x18 +#324 @ 949,417: 22x17 +#325 @ 967,573: 15x19 +#326 @ 64,258: 19x22 +#327 @ 449,717: 21x17 +#328 @ 191,866: 15x27 +#329 @ 423,11: 24x18 +#330 @ 190,702: 21x24 +#331 @ 908,570: 15x28 +#332 @ 197,148: 27x14 +#333 @ 587,220: 28x17 +#334 @ 713,232: 25x16 +#335 @ 337,427: 21x20 +#336 @ 170,485: 17x14 +#337 @ 506,898: 25x19 +#338 @ 720,200: 14x12 +#339 @ 13,694: 28x24 +#340 @ 9,485: 16x15 +#341 @ 383,126: 22x14 +#342 @ 852,667: 3x10 +#343 @ 367,932: 11x25 +#344 @ 87,753: 26x26 +#345 @ 160,608: 29x24 +#346 @ 370,944: 10x22 +#347 @ 904,900: 18x19 +#348 @ 401,114: 28x22 +#349 @ 498,745: 24x17 +#350 @ 214,748: 22x23 +#351 @ 161,6: 11x20 +#352 @ 980,165: 12x18 +#353 @ 397,818: 10x10 +#354 @ 481,886: 28x12 +#355 @ 400,82: 13x13 +#356 @ 298,593: 24x28 +#357 @ 500,79: 10x27 +#358 @ 639,512: 20x27 +#359 @ 508,100: 26x22 +#360 @ 780,237: 23x21 +#361 @ 356,454: 11x10 +#362 @ 39,413: 19x19 +#363 @ 820,626: 20x17 +#364 @ 442,477: 11x12 +#365 @ 898,906: 28x14 +#366 @ 154,423: 29x14 +#367 @ 540,409: 28x17 +#368 @ 507,395: 22x10 +#369 @ 361,602: 21x20 +#370 @ 14,105: 14x12 +#371 @ 515,904: 14x18 +#372 @ 204,880: 18x24 +#373 @ 333,584: 29x22 +#374 @ 511,309: 11x27 +#375 @ 260,240: 14x12 +#376 @ 629,368: 16x24 +#377 @ 128,43: 13x22 +#378 @ 59,186: 13x27 +#379 @ 731,186: 23x15 +#380 @ 382,837: 17x4 +#381 @ 508,536: 15x11 +#382 @ 690,145: 18x17 +#383 @ 381,496: 25x25 +#384 @ 812,107: 8x11 +#385 @ 736,411: 27x19 +#386 @ 610,926: 29x23 +#387 @ 469,561: 10x27 +#388 @ 480,540: 10x25 +#389 @ 824,850: 29x20 +#390 @ 780,534: 29x17 +#391 @ 562,25: 23x19 +#392 @ 543,7: 21x11 +#393 @ 316,343: 29x12 +#394 @ 196,851: 20x24 +#395 @ 436,674: 14x15 +#396 @ 714,329: 21x11 +#397 @ 400,923: 28x27 +#398 @ 372,469: 10x17 +#399 @ 15,261: 15x12 +#400 @ 791,837: 22x24 +#401 @ 153,941: 21x25 +#402 @ 129,146: 20x28 +#403 @ 501,369: 23x23 +#404 @ 899,238: 28x29 +#405 @ 523,781: 29x16 +#406 @ 651,918: 21x13 +#407 @ 580,12: 25x28 +#408 @ 560,81: 19x29 +#409 @ 243,202: 19x19 +#410 @ 59,919: 28x20 +#411 @ 377,473: 20x17 +#412 @ 713,732: 18x18 +#413 @ 160,598: 16x11 +#414 @ 440,663: 26x10 +#415 @ 114,588: 12x14 +#416 @ 282,797: 24x22 +#417 @ 623,729: 28x20 +#418 @ 372,393: 13x19 +#419 @ 385,663: 28x13 +#420 @ 923,77: 12x16 +#421 @ 302,795: 13x19 +#422 @ 13,728: 23x16 +#423 @ 206,885: 19x24 +#424 @ 166,281: 16x13 +#425 @ 837,645: 27x13 +#426 @ 528,901: 19x15 +#427 @ 213,613: 23x26 +#428 @ 190,727: 29x17 +#429 @ 801,108: 12x21 +#430 @ 846,791: 19x25 +#431 @ 630,683: 27x12 +#432 @ 641,639: 15x19 +#433 @ 806,102: 22x20 +#434 @ 621,477: 26x16 +#435 @ 186,815: 22x12 +#436 @ 55,189: 11x11 +#437 @ 657,912: 12x18 +#438 @ 924,246: 19x16 +#439 @ 423,424: 14x28 +#440 @ 392,80: 14x12 +#441 @ 23,790: 22x27 +#442 @ 192,952: 25x16 +#443 @ 24,254: 10x14 +#444 @ 967,578: 26x27 +#445 @ 747,348: 7x4 +#446 @ 104,626: 10x21 +#447 @ 799,16: 10x13 +#448 @ 795,315: 29x26 +#449 @ 958,199: 19x20 +#450 @ 183,720: 23x26 +#451 @ 513,457: 29x21 +#452 @ 966,674: 16x13 +#453 @ 669,657: 24x12 +#454 @ 508,126: 18x29 +#455 @ 749,192: 24x25 +#456 @ 463,106: 24x12 +#457 @ 387,789: 17x20 +#458 @ 683,835: 16x24 +#459 @ 70,570: 24x26 +#460 @ 178,841: 10x11 +#461 @ 492,812: 27x29 +#462 @ 98,172: 15x15 +#463 @ 871,738: 21x17 +#464 @ 942,334: 18x27 +#465 @ 511,892: 17x16 +#466 @ 502,728: 26x25 +#467 @ 527,783: 11x17 +#468 @ 971,679: 15x17 +#469 @ 685,518: 27x27 +#470 @ 385,686: 13x26 +#471 @ 148,567: 25x25 +#472 @ 413,243: 20x28 +#473 @ 518,389: 4x15 +#474 @ 188,456: 20x12 +#475 @ 442,605: 15x11 +#476 @ 285,815: 18x22 +#477 @ 655,433: 13x12 +#478 @ 612,888: 21x28 +#479 @ 632,760: 20x25 +#480 @ 946,417: 25x10 +#481 @ 275,176: 24x14 +#482 @ 972,514: 21x28 +#483 @ 81,646: 17x14 +#484 @ 77,349: 12x26 +#485 @ 457,612: 10x25 +#486 @ 877,678: 24x19 +#487 @ 232,0: 11x26 +#488 @ 828,562: 20x10 +#489 @ 425,63: 12x22 +#490 @ 822,325: 25x15 +#491 @ 646,934: 24x20 +#492 @ 414,873: 27x29 +#493 @ 503,494: 27x19 +#494 @ 954,679: 26x13 +#495 @ 818,547: 20x11 +#496 @ 807,654: 12x24 +#497 @ 182,422: 27x27 +#498 @ 379,248: 13x29 +#499 @ 335,312: 27x12 +#500 @ 854,729: 21x21 +#501 @ 912,253: 23x22 +#502 @ 86,60: 11x12 +#503 @ 172,822: 21x16 +#504 @ 142,564: 13x26 +#505 @ 515,639: 16x12 +#506 @ 468,60: 12x24 +#507 @ 217,850: 21x20 +#508 @ 844,635: 23x13 +#509 @ 494,325: 22x22 +#510 @ 757,313: 11x17 +#511 @ 504,594: 28x17 +#512 @ 771,94: 11x29 +#513 @ 703,826: 11x16 +#514 @ 364,351: 21x11 +#515 @ 80,372: 21x10 +#516 @ 509,291: 27x14 +#517 @ 785,671: 23x23 +#518 @ 39,141: 19x25 +#519 @ 680,523: 26x18 +#520 @ 479,724: 24x25 +#521 @ 374,446: 15x17 +#522 @ 187,953: 13x13 +#523 @ 324,430: 26x25 +#524 @ 774,85: 18x14 +#525 @ 811,275: 20x18 +#526 @ 587,598: 29x22 +#527 @ 960,68: 16x27 +#528 @ 635,288: 14x14 +#529 @ 337,576: 27x10 +#530 @ 478,710: 14x26 +#531 @ 59,310: 19x24 +#532 @ 493,882: 26x20 +#533 @ 688,455: 17x28 +#534 @ 509,779: 16x13 +#535 @ 352,457: 16x16 +#536 @ 556,134: 29x13 +#537 @ 615,728: 10x20 +#538 @ 860,434: 24x15 +#539 @ 636,226: 29x16 +#540 @ 864,904: 11x16 +#541 @ 50,273: 11x15 +#542 @ 616,717: 10x26 +#543 @ 617,428: 26x21 +#544 @ 880,820: 14x22 +#545 @ 650,77: 12x16 +#546 @ 881,690: 11x21 +#547 @ 584,209: 28x14 +#548 @ 485,553: 20x18 +#549 @ 156,4: 26x29 +#550 @ 199,403: 17x17 +#551 @ 680,485: 29x25 +#552 @ 925,264: 22x29 +#553 @ 780,90: 27x21 +#554 @ 137,167: 28x26 +#555 @ 929,228: 19x12 +#556 @ 240,436: 22x20 +#557 @ 798,511: 17x21 +#558 @ 892,787: 27x10 +#559 @ 822,598: 25x29 +#560 @ 520,148: 13x24 +#561 @ 839,721: 17x24 +#562 @ 569,888: 26x13 +#563 @ 246,914: 29x27 +#564 @ 162,910: 19x10 +#565 @ 457,539: 27x17 +#566 @ 22,111: 28x24 +#567 @ 455,967: 18x22 +#568 @ 63,175: 16x17 +#569 @ 91,53: 12x18 +#570 @ 911,873: 23x14 +#571 @ 887,666: 21x18 +#572 @ 213,511: 28x18 +#573 @ 186,713: 24x11 +#574 @ 459,286: 20x20 +#575 @ 716,576: 17x24 +#576 @ 129,552: 15x29 +#577 @ 551,223: 27x22 +#578 @ 890,177: 28x27 +#579 @ 559,954: 11x23 +#580 @ 97,496: 17x11 +#581 @ 146,587: 13x11 +#582 @ 310,544: 14x11 +#583 @ 282,163: 16x14 +#584 @ 634,444: 27x20 +#585 @ 689,409: 18x26 +#586 @ 344,604: 22x14 +#587 @ 155,820: 10x21 +#588 @ 259,952: 13x26 +#589 @ 654,761: 19x19 +#590 @ 287,810: 27x23 +#591 @ 760,596: 11x29 +#592 @ 368,539: 21x27 +#593 @ 792,298: 28x23 +#594 @ 251,392: 18x13 +#595 @ 149,455: 16x24 +#596 @ 873,900: 22x10 +#597 @ 93,655: 20x15 +#598 @ 431,656: 20x21 +#599 @ 416,393: 23x11 +#600 @ 841,637: 11x27 +#601 @ 628,93: 21x22 +#602 @ 227,970: 22x26 +#603 @ 967,665: 11x22 +#604 @ 370,958: 10x15 +#605 @ 550,59: 26x28 +#606 @ 673,222: 22x13 +#607 @ 461,551: 21x14 +#608 @ 290,594: 19x12 +#609 @ 584,284: 29x26 +#610 @ 117,600: 23x11 +#611 @ 70,452: 21x12 +#612 @ 508,261: 10x10 +#613 @ 330,926: 25x13 +#614 @ 939,660: 20x27 +#615 @ 467,628: 29x21 +#616 @ 238,417: 22x23 +#617 @ 297,728: 28x18 +#618 @ 385,825: 27x23 +#619 @ 360,457: 24x11 +#620 @ 975,157: 19x17 +#621 @ 453,319: 4x14 +#622 @ 243,690: 22x13 +#623 @ 389,31: 23x23 +#624 @ 208,971: 19x21 +#625 @ 145,633: 12x23 +#626 @ 736,480: 25x17 +#627 @ 343,166: 20x17 +#628 @ 511,323: 14x26 +#629 @ 62,304: 20x21 +#630 @ 957,303: 23x29 +#631 @ 130,739: 29x28 +#632 @ 977,574: 18x13 +#633 @ 675,553: 10x22 +#634 @ 52,146: 13x10 +#635 @ 938,659: 16x17 +#636 @ 318,61: 26x19 +#637 @ 731,245: 24x15 +#638 @ 673,537: 11x11 +#639 @ 780,527: 11x21 +#640 @ 103,970: 22x19 +#641 @ 943,669: 17x20 +#642 @ 280,888: 10x28 +#643 @ 381,351: 16x28 +#644 @ 214,145: 10x20 +#645 @ 243,376: 27x28 +#646 @ 866,783: 11x14 +#647 @ 705,432: 18x11 +#648 @ 523,678: 16x24 +#649 @ 171,824: 17x19 +#650 @ 476,86: 7x10 +#651 @ 661,645: 16x27 +#652 @ 388,930: 24x15 +#653 @ 675,863: 24x16 +#654 @ 525,37: 26x26 +#655 @ 427,54: 16x27 +#656 @ 708,804: 13x29 +#657 @ 61,236: 25x15 +#658 @ 56,797: 25x29 +#659 @ 773,714: 23x16 +#660 @ 801,397: 11x10 +#661 @ 633,637: 28x21 +#662 @ 869,673: 12x13 +#663 @ 258,582: 10x13 +#664 @ 546,448: 18x23 +#665 @ 962,59: 6x16 +#666 @ 922,84: 13x23 +#667 @ 761,588: 25x29 +#668 @ 730,436: 13x11 +#669 @ 43,303: 27x28 +#670 @ 896,902: 29x29 +#671 @ 604,126: 25x24 +#672 @ 377,465: 13x23 +#673 @ 146,654: 13x25 +#674 @ 425,202: 22x12 +#675 @ 718,847: 16x23 +#676 @ 589,219: 14x12 +#677 @ 168,855: 29x23 +#678 @ 797,10: 10x27 +#679 @ 704,29: 18x26 +#680 @ 297,549: 24x20 +#681 @ 51,835: 16x17 +#682 @ 598,536: 25x26 +#683 @ 786,703: 15x26 +#684 @ 171,267: 15x21 +#685 @ 129,450: 24x22 +#686 @ 894,58: 23x12 +#687 @ 7,558: 27x19 +#688 @ 804,775: 16x12 +#689 @ 629,9: 26x19 +#690 @ 503,311: 28x13 +#691 @ 975,224: 13x13 +#692 @ 135,11: 20x16 +#693 @ 184,472: 25x23 +#694 @ 380,579: 17x22 +#695 @ 328,600: 21x25 +#696 @ 803,518: 13x15 +#697 @ 143,300: 29x23 +#698 @ 46,845: 29x18 +#699 @ 71,459: 26x16 +#700 @ 405,423: 18x16 +#701 @ 302,127: 29x16 +#702 @ 761,624: 15x26 +#703 @ 795,111: 22x26 +#704 @ 909,717: 11x26 +#705 @ 75,914: 25x21 +#706 @ 786,914: 19x12 +#707 @ 247,662: 28x20 +#708 @ 222,504: 22x20 +#709 @ 631,981: 24x15 +#710 @ 633,436: 28x11 +#711 @ 413,717: 21x14 +#712 @ 58,241: 26x23 +#713 @ 48,217: 18x18 +#714 @ 393,823: 26x20 +#715 @ 928,530: 24x18 +#716 @ 712,642: 19x14 +#717 @ 231,534: 21x13 +#718 @ 314,811: 15x21 +#719 @ 780,856: 29x23 +#720 @ 161,121: 10x14 +#721 @ 687,807: 17x19 +#722 @ 360,680: 13x24 +#723 @ 177,873: 23x25 +#724 @ 840,917: 15x20 +#725 @ 863,809: 12x21 +#726 @ 868,154: 19x24 +#727 @ 719,24: 25x16 +#728 @ 20,97: 11x21 +#729 @ 937,332: 27x24 +#730 @ 383,41: 24x17 +#731 @ 845,664: 14x17 +#732 @ 386,581: 16x11 +#733 @ 835,618: 21x29 +#734 @ 29,697: 20x18 +#735 @ 514,743: 16x12 +#736 @ 69,729: 27x29 +#737 @ 537,133: 26x21 +#738 @ 243,74: 26x19 +#739 @ 964,220: 28x19 +#740 @ 146,944: 11x25 +#741 @ 157,621: 29x22 +#742 @ 199,558: 26x13 +#743 @ 472,934: 6x11 +#744 @ 473,726: 11x21 +#745 @ 899,19: 16x11 +#746 @ 434,381: 21x28 +#747 @ 368,483: 16x20 +#748 @ 750,793: 18x17 +#749 @ 905,174: 16x28 +#750 @ 648,16: 13x20 +#751 @ 387,678: 21x12 +#752 @ 662,561: 19x17 +#753 @ 457,175: 22x28 +#754 @ 456,447: 17x20 +#755 @ 692,152: 22x21 +#756 @ 62,733: 13x24 +#757 @ 29,480: 14x20 +#758 @ 849,367: 28x16 +#759 @ 457,221: 19x22 +#760 @ 155,548: 23x24 +#761 @ 794,922: 28x16 +#762 @ 152,579: 19x10 +#763 @ 176,887: 24x13 +#764 @ 920,68: 23x17 +#765 @ 769,333: 12x26 +#766 @ 256,356: 15x17 +#767 @ 843,812: 29x15 +#768 @ 48,838: 13x18 +#769 @ 626,296: 18x11 +#770 @ 196,441: 12x23 +#771 @ 757,464: 11x20 +#772 @ 527,694: 24x21 +#773 @ 513,45: 22x19 +#774 @ 377,386: 29x21 +#775 @ 61,842: 16x14 +#776 @ 814,859: 18x11 +#777 @ 845,282: 27x23 +#778 @ 148,551: 29x19 +#779 @ 491,187: 18x25 +#780 @ 288,141: 28x25 +#781 @ 385,745: 11x27 +#782 @ 363,9: 23x29 +#783 @ 119,149: 19x27 +#784 @ 336,301: 26x15 +#785 @ 31,122: 28x28 +#786 @ 563,0: 23x15 +#787 @ 967,144: 21x26 +#788 @ 164,745: 15x15 +#789 @ 967,574: 29x22 +#790 @ 411,266: 13x21 +#791 @ 189,374: 26x12 +#792 @ 847,537: 20x21 +#793 @ 440,560: 15x10 +#794 @ 75,734: 14x28 +#795 @ 805,863: 19x23 +#796 @ 46,422: 20x18 +#797 @ 363,691: 27x23 +#798 @ 681,574: 16x24 +#799 @ 975,353: 16x11 +#800 @ 764,874: 25x29 +#801 @ 421,109: 21x29 +#802 @ 251,284: 10x18 +#803 @ 512,40: 25x25 +#804 @ 942,409: 29x25 +#805 @ 296,348: 25x20 +#806 @ 738,311: 29x28 +#807 @ 341,854: 22x25 +#808 @ 443,670: 20x29 +#809 @ 111,912: 25x13 +#810 @ 542,106: 14x17 +#811 @ 538,317: 21x25 +#812 @ 954,912: 25x23 +#813 @ 30,190: 18x27 +#814 @ 655,228: 25x12 +#815 @ 775,406: 29x20 +#816 @ 95,104: 11x14 +#817 @ 821,278: 18x23 +#818 @ 268,338: 14x6 +#819 @ 402,595: 26x25 +#820 @ 485,3: 27x22 +#821 @ 516,741: 18x22 +#822 @ 575,320: 24x14 +#823 @ 722,611: 15x15 +#824 @ 171,954: 26x10 +#825 @ 631,933: 24x21 +#826 @ 45,714: 21x20 +#827 @ 441,103: 23x21 +#828 @ 334,754: 17x22 +#829 @ 230,17: 20x15 +#830 @ 348,543: 14x12 +#831 @ 978,561: 16x16 +#832 @ 927,407: 8x4 +#833 @ 886,513: 26x29 +#834 @ 640,927: 23x26 +#835 @ 558,838: 20x13 +#836 @ 63,132: 10x21 +#837 @ 801,253: 21x10 +#838 @ 739,341: 19x20 +#839 @ 888,59: 24x14 +#840 @ 444,607: 15x24 +#841 @ 327,584: 25x25 +#842 @ 598,224: 3x7 +#843 @ 407,827: 18x11 +#844 @ 630,622: 25x26 +#845 @ 129,302: 29x26 +#846 @ 491,768: 24x22 +#847 @ 154,255: 11x22 +#848 @ 256,184: 18x19 +#849 @ 336,173: 12x15 +#850 @ 174,950: 26x16 +#851 @ 873,681: 19x17 +#852 @ 119,63: 20x16 +#853 @ 834,831: 18x13 +#854 @ 566,427: 18x22 +#855 @ 640,27: 12x15 +#856 @ 163,907: 27x16 +#857 @ 894,783: 14x25 +#858 @ 915,283: 12x21 +#859 @ 660,290: 20x25 +#860 @ 286,510: 27x22 +#861 @ 627,682: 26x10 +#862 @ 724,613: 10x8 +#863 @ 817,502: 17x18 +#864 @ 888,562: 26x19 +#865 @ 825,896: 12x15 +#866 @ 9,286: 26x21 +#867 @ 95,973: 19x14 +#868 @ 476,460: 19x19 +#869 @ 300,515: 22x21 +#870 @ 29,597: 17x12 +#871 @ 586,218: 17x19 +#872 @ 32,733: 24x23 +#873 @ 297,882: 19x25 +#874 @ 316,596: 27x17 +#875 @ 975,536: 16x29 +#876 @ 650,509: 29x20 +#877 @ 802,908: 26x13 +#878 @ 122,294: 18x27 +#879 @ 511,498: 26x16 +#880 @ 16,516: 15x19 +#881 @ 498,381: 29x29 +#882 @ 133,165: 14x11 +#883 @ 700,481: 11x25 +#884 @ 402,513: 23x23 +#885 @ 902,55: 23x25 +#886 @ 247,186: 16x10 +#887 @ 760,117: 16x19 +#888 @ 215,973: 7x16 +#889 @ 788,957: 25x22 +#890 @ 544,482: 24x12 +#891 @ 202,596: 16x15 +#892 @ 979,133: 12x23 +#893 @ 217,138: 17x10 +#894 @ 902,43: 20x27 +#895 @ 25,428: 22x26 +#896 @ 485,360: 17x18 +#897 @ 594,950: 28x28 +#898 @ 90,947: 14x29 +#899 @ 528,817: 21x24 +#900 @ 46,787: 25x19 +#901 @ 255,338: 20x21 +#902 @ 245,466: 14x17 +#903 @ 361,663: 18x20 +#904 @ 682,495: 16x13 +#905 @ 534,477: 19x19 +#906 @ 459,722: 18x20 +#907 @ 600,224: 26x29 +#908 @ 762,341: 14x23 +#909 @ 593,172: 15x25 +#910 @ 449,295: 25x26 +#911 @ 908,716: 12x23 +#912 @ 140,871: 24x11 +#913 @ 106,508: 16x11 +#914 @ 250,674: 24x28 +#915 @ 880,680: 10x19 +#916 @ 285,696: 22x26 +#917 @ 462,486: 25x13 +#918 @ 838,969: 24x27 +#919 @ 636,88: 18x26 +#920 @ 852,723: 24x18 +#921 @ 361,838: 23x27 +#922 @ 686,666: 23x24 +#923 @ 737,724: 8x9 +#924 @ 957,582: 17x27 +#925 @ 466,928: 22x23 +#926 @ 526,189: 15x21 +#927 @ 331,342: 15x13 +#928 @ 30,827: 22x16 +#929 @ 841,813: 6x12 +#930 @ 865,808: 27x14 +#931 @ 687,408: 23x29 +#932 @ 546,357: 10x23 +#933 @ 965,424: 22x24 +#934 @ 373,182: 26x27 +#935 @ 507,24: 25x20 +#936 @ 327,391: 24x18 +#937 @ 520,700: 13x25 +#938 @ 828,379: 12x27 +#939 @ 460,585: 29x15 +#940 @ 0,862: 27x27 +#941 @ 140,952: 22x19 +#942 @ 509,675: 14x12 +#943 @ 922,649: 19x18 +#944 @ 255,204: 14x15 +#945 @ 446,889: 11x20 +#946 @ 427,687: 28x20 +#947 @ 964,925: 16x13 +#948 @ 393,869: 19x24 +#949 @ 442,455: 29x23 +#950 @ 120,518: 25x21 +#951 @ 474,83: 13x19 +#952 @ 31,233: 22x25 +#953 @ 911,51: 25x20 +#954 @ 242,408: 10x27 +#955 @ 695,14: 18x14 +#956 @ 839,458: 21x14 +#957 @ 934,894: 27x19 +#958 @ 854,781: 20x11 +#959 @ 757,48: 13x11 +#960 @ 4,259: 29x19 +#961 @ 463,829: 15x16 +#962 @ 369,934: 6x14 +#963 @ 782,714: 15x23 +#964 @ 355,783: 24x22 +#965 @ 206,374: 25x24 +#966 @ 389,768: 11x28 +#967 @ 149,286: 22x16 +#968 @ 746,461: 16x14 +#969 @ 763,626: 28x13 +#970 @ 874,908: 23x12 +#971 @ 481,935: 26x26 +#972 @ 802,239: 27x17 +#973 @ 936,401: 14x19 +#974 @ 909,648: 16x13 +#975 @ 567,425: 25x13 +#976 @ 129,315: 11x15 +#977 @ 858,406: 20x16 +#978 @ 912,703: 23x26 +#979 @ 104,488: 10x22 +#980 @ 185,831: 28x29 +#981 @ 765,985: 20x9 +#982 @ 923,275: 12x28 +#983 @ 533,182: 11x27 +#984 @ 451,549: 13x14 +#985 @ 715,304: 28x21 +#986 @ 171,244: 12x22 +#987 @ 10,74: 20x20 +#988 @ 448,570: 10x19 +#989 @ 634,532: 16x23 +#990 @ 614,974: 22x10 +#991 @ 840,754: 16x10 +#992 @ 216,159: 22x10 +#993 @ 455,234: 16x25 +#994 @ 164,597: 27x18 +#995 @ 806,201: 10x29 +#996 @ 585,235: 25x29 +#997 @ 615,424: 17x27 +#998 @ 124,835: 28x14 +#999 @ 531,599: 23x29 +#1000 @ 941,189: 14x23 +#1001 @ 94,970: 12x16 +#1002 @ 930,402: 10x17 +#1003 @ 640,531: 16x26 +#1004 @ 379,833: 26x14 +#1005 @ 465,488: 11x8 +#1006 @ 136,72: 12x13 +#1007 @ 511,828: 20x22 +#1008 @ 457,72: 17x10 +#1009 @ 207,153: 13x19 +#1010 @ 225,700: 23x22 +#1011 @ 159,838: 18x14 +#1012 @ 340,783: 28x15 +#1013 @ 276,535: 13x11 +#1014 @ 483,76: 20x11 +#1015 @ 639,805: 26x16 +#1016 @ 106,533: 25x27 +#1017 @ 173,713: 27x16 +#1018 @ 196,770: 21x28 +#1019 @ 833,872: 28x27 +#1020 @ 870,811: 12x26 +#1021 @ 323,911: 22x23 +#1022 @ 399,721: 18x11 +#1023 @ 763,980: 26x18 +#1024 @ 16,760: 24x16 +#1025 @ 194,748: 25x29 +#1026 @ 26,595: 16x24 +#1027 @ 724,227: 11x26 +#1028 @ 686,505: 23x22 +#1029 @ 266,737: 11x27 +#1030 @ 810,106: 27x24 +#1031 @ 744,242: 17x19 +#1032 @ 688,220: 16x17 +#1033 @ 701,468: 19x11 +#1034 @ 180,383: 11x22 +#1035 @ 23,468: 14x28 +#1036 @ 615,402: 28x15 +#1037 @ 172,325: 10x29 +#1038 @ 35,204: 16x13 +#1039 @ 96,885: 27x29 +#1040 @ 391,850: 18x24 +#1041 @ 699,222: 10x21 +#1042 @ 852,346: 13x22 +#1043 @ 4,534: 16x21 +#1044 @ 482,706: 13x20 +#1045 @ 311,162: 27x24 +#1046 @ 686,948: 10x16 +#1047 @ 825,810: 29x21 +#1048 @ 258,470: 24x13 +#1049 @ 139,310: 27x29 +#1050 @ 959,326: 19x23 +#1051 @ 250,175: 13x17 +#1052 @ 306,554: 10x20 +#1053 @ 499,748: 25x19 +#1054 @ 690,521: 17x13 +#1055 @ 831,634: 13x21 +#1056 @ 245,539: 24x10 +#1057 @ 72,651: 16x12 +#1058 @ 520,99: 29x23 +#1059 @ 778,154: 21x23 +#1060 @ 913,881: 26x14 +#1061 @ 719,570: 25x18 +#1062 @ 419,516: 27x13 +#1063 @ 748,116: 15x13 +#1064 @ 701,655: 27x23 +#1065 @ 673,272: 21x27 +#1066 @ 273,693: 17x13 +#1067 @ 0,98: 18x17 +#1068 @ 810,842: 12x14 +#1069 @ 6,119: 26x15 +#1070 @ 891,587: 12x11 +#1071 @ 947,19: 10x26 +#1072 @ 367,591: 15x16 +#1073 @ 210,779: 28x26 +#1074 @ 337,47: 18x21 +#1075 @ 248,933: 29x18 +#1076 @ 467,819: 13x19 +#1077 @ 31,412: 10x17 +#1078 @ 245,609: 18x17 +#1079 @ 477,553: 26x11 +#1080 @ 501,211: 13x23 +#1081 @ 256,262: 10x23 +#1082 @ 974,702: 17x11 +#1083 @ 237,21: 16x13 +#1084 @ 797,86: 20x26 +#1085 @ 754,398: 12x26 +#1086 @ 615,527: 10x22 +#1087 @ 343,24: 26x16 +#1088 @ 348,535: 26x10 +#1089 @ 516,728: 15x14 +#1090 @ 528,100: 17x15 +#1091 @ 922,69: 12x22 +#1092 @ 410,118: 13x23 +#1093 @ 497,161: 29x28 +#1094 @ 100,951: 10x26 +#1095 @ 170,235: 15x14 +#1096 @ 127,956: 24x25 +#1097 @ 864,829: 14x17 +#1098 @ 236,425: 18x12 +#1099 @ 266,122: 14x11 +#1100 @ 505,526: 23x14 +#1101 @ 670,831: 26x13 +#1102 @ 772,171: 15x28 +#1103 @ 437,131: 18x10 +#1104 @ 496,863: 20x24 +#1105 @ 168,408: 15x14 +#1106 @ 526,425: 24x22 +#1107 @ 890,904: 23x10 +#1108 @ 460,24: 12x19 +#1109 @ 497,81: 26x25 +#1110 @ 694,507: 4x17 +#1111 @ 170,594: 22x21 +#1112 @ 415,625: 19x12 +#1113 @ 638,804: 26x23 +#1114 @ 113,637: 13x14 +#1115 @ 158,441: 25x21 +#1116 @ 635,11: 10x24 +#1117 @ 239,375: 26x22 +#1118 @ 784,166: 18x11 +#1119 @ 649,762: 23x21 +#1120 @ 235,831: 13x23 +#1121 @ 452,879: 12x27 +#1122 @ 105,629: 15x12 +#1123 @ 133,153: 19x18 +#1124 @ 869,103: 28x12 +#1125 @ 370,670: 20x29 +#1126 @ 610,108: 27x29 +#1127 @ 467,158: 20x10 +#1128 @ 866,194: 11x24 +#1129 @ 319,250: 16x10 +#1130 @ 543,141: 22x13 +#1131 @ 25,742: 16x26 +#1132 @ 781,716: 9x5 +#1133 @ 885,568: 10x27 +#1134 @ 297,174: 19x13 +#1135 @ 696,325: 21x16 +#1136 @ 127,715: 24x15 +#1137 @ 247,374: 24x28 +#1138 @ 934,561: 18x11 +#1139 @ 523,827: 12x23 +#1140 @ 938,41: 26x25 +#1141 @ 841,960: 28x18 +#1142 @ 959,837: 14x15 +#1143 @ 456,614: 29x10 +#1144 @ 184,764: 22x24 +#1145 @ 667,804: 25x24 +#1146 @ 22,92: 29x20 +#1147 @ 27,604: 10x21 +#1148 @ 970,594: 28x23 +#1149 @ 469,647: 18x11 +#1150 @ 469,169: 13x18 +#1151 @ 904,504: 22x14 +#1152 @ 346,757: 12x13 +#1153 @ 455,578: 26x16 +#1154 @ 271,319: 13x10 +#1155 @ 90,969: 16x15 +#1156 @ 938,187: 15x25 +#1157 @ 86,642: 15x16 +#1158 @ 531,887: 23x26 +#1159 @ 525,86: 21x24 +#1160 @ 922,939: 14x23 +#1161 @ 473,143: 21x27 +#1162 @ 308,628: 29x11 +#1163 @ 508,788: 25x18 +#1164 @ 678,368: 25x10 +#1165 @ 445,456: 13x12 +#1166 @ 530,244: 24x23 +#1167 @ 39,194: 28x27 +#1168 @ 282,165: 23x21 +#1169 @ 297,98: 25x17 +#1170 @ 415,636: 29x10 +#1171 @ 611,577: 16x22 +#1172 @ 628,480: 25x20 +#1173 @ 338,575: 18x28 +#1174 @ 963,672: 23x23 +#1175 @ 912,10: 23x18 +#1176 @ 392,763: 26x11 +#1177 @ 41,279: 28x22 +#1178 @ 524,836: 11x23 +#1179 @ 247,413: 26x28 +#1180 @ 209,438: 21x29 +#1181 @ 172,580: 26x20 +#1182 @ 781,900: 24x29 +#1183 @ 776,720: 16x24 +#1184 @ 196,408: 15x10 +#1185 @ 490,888: 17x21 +#1186 @ 813,903: 25x15 +#1187 @ 18,888: 22x11 +#1188 @ 243,420: 10x24 +#1189 @ 939,252: 19x13 +#1190 @ 509,236: 20x15 +#1191 @ 202,813: 12x28 +#1192 @ 908,705: 10x20 +#1193 @ 275,313: 10x20 +#1194 @ 373,808: 16x12 +#1195 @ 54,739: 26x12 +#1196 @ 731,441: 20x13 +#1197 @ 271,710: 29x28 +#1198 @ 596,307: 23x14 +#1199 @ 226,612: 25x18 +#1200 @ 85,99: 15x22 +#1201 @ 326,252: 19x18 +#1202 @ 874,207: 22x10 +#1203 @ 260,117: 24x14 +#1204 @ 467,157: 29x29 +#1205 @ 523,632: 27x25 +#1206 @ 735,718: 14x20 +#1207 @ 880,435: 12x24 +#1208 @ 471,929: 18x15 +#1209 @ 767,253: 23x25 +#1210 @ 9,111: 27x12 +#1211 @ 928,235: 15x27 +#1212 @ 118,9: 22x19 +#1213 @ 683,669: 13x27 +#1214 @ 981,348: 14x27 +#1215 @ 743,809: 28x27 +#1216 @ 261,426: 13x14 +#1217 @ 244,182: 27x15 +#1218 @ 868,906: 3x10 +#1219 @ 425,424: 12x22 +#1220 @ 501,68: 11x19 +#1221 @ 915,183: 21x14 +#1222 @ 889,837: 15x22 +#1223 @ 751,582: 16x20 +#1224 @ 641,381: 26x25 +#1225 @ 367,185: 22x12 +#1226 @ 833,447: 26x21 +#1227 @ 108,32: 25x24 \ No newline at end of file diff --git a/advents/src/main/resources/2018/day04.txt b/advents/src/main/resources/2018/day04.txt new file mode 100644 index 0000000..351267b --- /dev/null +++ b/advents/src/main/resources/2018/day04.txt @@ -0,0 +1,986 @@ +[1518-08-29 00:24] falls asleep +[1518-08-06 00:20] falls asleep +[1518-03-12 00:21] falls asleep +[1518-06-17 00:45] wakes up +[1518-06-27 00:46] falls asleep +[1518-09-07 00:36] falls asleep +[1518-07-22 00:23] wakes up +[1518-05-18 00:35] falls asleep +[1518-09-27 00:40] wakes up +[1518-04-10 23:52] Guard #3559 begins shift +[1518-03-16 00:44] wakes up +[1518-05-16 00:23] wakes up +[1518-06-18 00:00] Guard #1499 begins shift +[1518-11-21 00:48] wakes up +[1518-05-19 00:29] falls asleep +[1518-03-20 23:58] Guard #73 begins shift +[1518-09-28 00:18] falls asleep +[1518-10-21 00:00] Guard #983 begins shift +[1518-05-19 00:57] wakes up +[1518-10-08 00:47] wakes up +[1518-05-04 00:19] falls asleep +[1518-07-30 00:30] falls asleep +[1518-05-04 00:22] wakes up +[1518-10-01 00:20] wakes up +[1518-03-24 23:47] Guard #2411 begins shift +[1518-06-19 00:00] Guard #1499 begins shift +[1518-09-15 00:38] falls asleep +[1518-07-26 00:50] falls asleep +[1518-06-13 00:00] Guard #3499 begins shift +[1518-08-30 00:03] Guard #983 begins shift +[1518-04-18 00:44] wakes up +[1518-07-09 00:53] falls asleep +[1518-06-09 00:02] falls asleep +[1518-10-09 23:56] Guard #3559 begins shift +[1518-04-15 23:46] Guard #313 begins shift +[1518-10-06 00:03] Guard #3499 begins shift +[1518-10-27 23:59] Guard #2617 begins shift +[1518-10-21 00:33] wakes up +[1518-03-23 00:47] falls asleep +[1518-07-21 00:31] wakes up +[1518-06-05 00:21] falls asleep +[1518-03-11 00:54] wakes up +[1518-05-06 00:11] wakes up +[1518-04-09 00:39] wakes up +[1518-06-10 00:00] Guard #919 begins shift +[1518-11-10 00:57] falls asleep +[1518-09-27 00:27] falls asleep +[1518-07-29 00:53] falls asleep +[1518-07-26 00:38] falls asleep +[1518-08-05 00:01] falls asleep +[1518-06-07 00:59] wakes up +[1518-11-22 00:39] falls asleep +[1518-11-17 00:58] wakes up +[1518-11-04 00:22] falls asleep +[1518-09-10 00:34] wakes up +[1518-04-11 00:25] wakes up +[1518-04-14 23:58] Guard #3203 begins shift +[1518-06-22 00:22] falls asleep +[1518-04-07 00:48] falls asleep +[1518-11-15 00:57] wakes up +[1518-05-24 23:56] Guard #983 begins shift +[1518-07-29 00:59] wakes up +[1518-11-15 00:05] falls asleep +[1518-11-22 00:02] Guard #3499 begins shift +[1518-11-01 00:46] wakes up +[1518-08-31 00:01] Guard #2411 begins shift +[1518-06-30 00:39] falls asleep +[1518-04-29 00:24] wakes up +[1518-04-12 23:54] Guard #2099 begins shift +[1518-05-04 00:48] falls asleep +[1518-09-25 00:49] falls asleep +[1518-09-21 00:28] falls asleep +[1518-04-25 00:44] falls asleep +[1518-04-13 00:43] falls asleep +[1518-08-24 00:16] falls asleep +[1518-07-02 00:43] wakes up +[1518-04-26 00:00] Guard #241 begins shift +[1518-06-26 00:29] falls asleep +[1518-04-17 00:47] wakes up +[1518-11-23 00:28] falls asleep +[1518-10-04 00:53] wakes up +[1518-11-20 00:46] falls asleep +[1518-06-28 00:37] wakes up +[1518-09-12 00:21] falls asleep +[1518-04-20 23:54] Guard #73 begins shift +[1518-03-21 23:57] Guard #1811 begins shift +[1518-07-04 00:48] wakes up +[1518-09-25 00:34] wakes up +[1518-04-13 00:35] wakes up +[1518-08-29 00:02] Guard #2657 begins shift +[1518-03-30 00:03] Guard #1811 begins shift +[1518-11-16 00:22] falls asleep +[1518-08-16 00:29] falls asleep +[1518-08-07 00:27] falls asleep +[1518-03-26 23:57] Guard #1091 begins shift +[1518-09-13 00:21] falls asleep +[1518-11-12 00:42] wakes up +[1518-05-14 00:01] Guard #1291 begins shift +[1518-03-21 00:39] falls asleep +[1518-04-23 00:22] falls asleep +[1518-09-19 00:05] falls asleep +[1518-04-02 00:42] falls asleep +[1518-04-27 00:39] wakes up +[1518-03-24 00:02] Guard #1033 begins shift +[1518-03-16 00:59] wakes up +[1518-05-11 23:50] Guard #3109 begins shift +[1518-04-18 00:06] falls asleep +[1518-08-31 00:33] wakes up +[1518-09-18 23:48] Guard #3559 begins shift +[1518-04-21 00:30] wakes up +[1518-10-07 00:44] wakes up +[1518-09-30 00:57] falls asleep +[1518-10-08 00:56] wakes up +[1518-06-19 00:37] wakes up +[1518-10-22 00:33] falls asleep +[1518-10-20 00:52] falls asleep +[1518-11-13 00:27] wakes up +[1518-07-05 00:11] falls asleep +[1518-08-17 00:48] wakes up +[1518-07-25 00:45] wakes up +[1518-05-01 23:59] Guard #3109 begins shift +[1518-07-31 00:10] falls asleep +[1518-05-26 00:54] falls asleep +[1518-08-10 23:57] Guard #3203 begins shift +[1518-06-26 00:06] falls asleep +[1518-09-24 00:12] falls asleep +[1518-04-11 00:01] falls asleep +[1518-06-01 00:02] Guard #2657 begins shift +[1518-06-30 23:49] Guard #241 begins shift +[1518-10-29 00:49] wakes up +[1518-06-12 00:44] wakes up +[1518-04-16 00:01] falls asleep +[1518-10-13 00:55] wakes up +[1518-05-21 00:28] falls asleep +[1518-06-21 00:17] falls asleep +[1518-06-05 00:47] falls asleep +[1518-05-10 00:19] falls asleep +[1518-09-05 00:04] falls asleep +[1518-04-23 00:12] falls asleep +[1518-07-16 00:56] wakes up +[1518-07-26 00:00] Guard #3499 begins shift +[1518-08-27 00:47] falls asleep +[1518-09-24 00:32] falls asleep +[1518-09-15 00:03] Guard #313 begins shift +[1518-11-21 00:04] Guard #3499 begins shift +[1518-07-11 00:49] wakes up +[1518-06-27 00:35] falls asleep +[1518-07-17 00:59] wakes up +[1518-05-13 00:10] falls asleep +[1518-09-28 00:04] Guard #3559 begins shift +[1518-10-03 00:00] Guard #313 begins shift +[1518-06-15 00:27] falls asleep +[1518-09-24 00:59] wakes up +[1518-10-29 23:50] Guard #983 begins shift +[1518-06-17 00:48] falls asleep +[1518-09-24 00:01] Guard #241 begins shift +[1518-05-28 23:56] Guard #2657 begins shift +[1518-04-17 00:00] Guard #1291 begins shift +[1518-05-29 00:34] wakes up +[1518-03-16 00:48] falls asleep +[1518-05-25 00:59] wakes up +[1518-04-11 00:42] falls asleep +[1518-06-02 23:59] Guard #241 begins shift +[1518-04-13 00:00] falls asleep +[1518-07-22 00:35] falls asleep +[1518-09-19 23:56] Guard #3109 begins shift +[1518-08-05 23:52] Guard #3449 begins shift +[1518-08-25 00:18] wakes up +[1518-07-14 23:57] Guard #2617 begins shift +[1518-05-08 00:19] falls asleep +[1518-10-11 00:02] Guard #2657 begins shift +[1518-03-21 00:22] falls asleep +[1518-06-23 00:10] falls asleep +[1518-05-28 00:41] falls asleep +[1518-09-01 00:02] Guard #3109 begins shift +[1518-09-13 00:43] wakes up +[1518-05-19 00:16] wakes up +[1518-10-03 00:59] wakes up +[1518-05-04 00:59] wakes up +[1518-06-15 00:53] falls asleep +[1518-07-16 00:09] falls asleep +[1518-08-11 00:48] falls asleep +[1518-08-15 00:00] Guard #823 begins shift +[1518-07-31 00:44] wakes up +[1518-04-28 23:51] Guard #73 begins shift +[1518-04-21 00:46] falls asleep +[1518-09-21 00:42] wakes up +[1518-05-27 00:26] falls asleep +[1518-08-23 00:04] Guard #3203 begins shift +[1518-07-13 00:01] falls asleep +[1518-08-14 00:01] falls asleep +[1518-07-10 00:50] wakes up +[1518-11-05 00:37] wakes up +[1518-08-12 00:58] wakes up +[1518-03-11 00:33] falls asleep +[1518-09-20 00:32] falls asleep +[1518-09-03 00:56] wakes up +[1518-03-21 00:40] wakes up +[1518-07-03 00:22] falls asleep +[1518-08-16 23:46] Guard #313 begins shift +[1518-10-31 00:00] Guard #919 begins shift +[1518-08-11 00:32] wakes up +[1518-08-25 23:58] Guard #1033 begins shift +[1518-09-01 23:57] Guard #2617 begins shift +[1518-06-17 00:53] wakes up +[1518-10-18 00:42] falls asleep +[1518-07-11 00:14] falls asleep +[1518-03-13 00:27] falls asleep +[1518-10-28 00:58] wakes up +[1518-07-31 00:01] Guard #3499 begins shift +[1518-04-22 00:49] wakes up +[1518-10-17 00:42] wakes up +[1518-03-14 00:02] Guard #1033 begins shift +[1518-08-09 00:38] falls asleep +[1518-04-26 23:58] Guard #3109 begins shift +[1518-05-09 00:34] falls asleep +[1518-11-09 23:57] Guard #2099 begins shift +[1518-05-22 00:28] falls asleep +[1518-08-08 00:28] wakes up +[1518-11-23 00:42] wakes up +[1518-09-16 00:19] falls asleep +[1518-04-08 00:12] falls asleep +[1518-10-03 00:47] wakes up +[1518-04-10 00:22] falls asleep +[1518-07-30 00:37] wakes up +[1518-11-16 00:47] wakes up +[1518-08-12 00:13] falls asleep +[1518-08-04 00:33] falls asleep +[1518-09-24 00:14] wakes up +[1518-09-13 00:56] wakes up +[1518-10-10 00:25] falls asleep +[1518-04-14 00:01] Guard #3559 begins shift +[1518-06-25 23:59] Guard #241 begins shift +[1518-07-19 00:02] falls asleep +[1518-03-15 00:01] Guard #1033 begins shift +[1518-09-18 00:15] falls asleep +[1518-11-09 00:35] falls asleep +[1518-08-22 00:11] falls asleep +[1518-10-07 23:59] Guard #2411 begins shift +[1518-08-02 23:59] Guard #3361 begins shift +[1518-06-26 00:53] wakes up +[1518-04-01 00:16] falls asleep +[1518-11-08 23:58] Guard #2617 begins shift +[1518-09-02 00:57] wakes up +[1518-07-06 00:46] falls asleep +[1518-07-21 00:17] falls asleep +[1518-05-01 00:58] wakes up +[1518-06-21 00:23] wakes up +[1518-07-01 00:47] wakes up +[1518-09-07 00:41] wakes up +[1518-05-05 00:34] wakes up +[1518-04-02 00:01] Guard #2099 begins shift +[1518-07-03 00:19] wakes up +[1518-06-01 00:39] falls asleep +[1518-04-06 00:08] falls asleep +[1518-08-24 00:01] Guard #2657 begins shift +[1518-07-01 23:51] Guard #3109 begins shift +[1518-08-13 00:04] Guard #2099 begins shift +[1518-08-09 00:34] wakes up +[1518-05-31 00:40] wakes up +[1518-06-26 00:45] falls asleep +[1518-06-26 23:59] Guard #983 begins shift +[1518-07-01 00:36] wakes up +[1518-03-24 00:26] falls asleep +[1518-04-19 00:55] falls asleep +[1518-04-06 00:09] wakes up +[1518-10-15 00:24] falls asleep +[1518-04-30 00:47] falls asleep +[1518-05-08 00:08] falls asleep +[1518-09-24 00:56] falls asleep +[1518-04-24 00:04] Guard #3361 begins shift +[1518-07-06 00:59] wakes up +[1518-06-24 00:28] wakes up +[1518-08-11 00:19] falls asleep +[1518-04-19 23:58] Guard #1291 begins shift +[1518-03-18 00:32] wakes up +[1518-10-23 00:04] falls asleep +[1518-10-19 00:04] Guard #3203 begins shift +[1518-04-05 00:31] wakes up +[1518-03-13 00:04] Guard #3449 begins shift +[1518-06-15 00:22] wakes up +[1518-03-26 00:10] falls asleep +[1518-07-07 00:34] wakes up +[1518-04-27 00:24] falls asleep +[1518-04-30 00:49] wakes up +[1518-04-17 00:18] falls asleep +[1518-09-11 00:20] falls asleep +[1518-05-07 00:56] wakes up +[1518-05-23 00:24] wakes up +[1518-03-28 00:44] wakes up +[1518-08-10 00:12] falls asleep +[1518-06-12 00:13] falls asleep +[1518-09-23 00:58] wakes up +[1518-08-29 00:59] wakes up +[1518-09-04 00:33] falls asleep +[1518-05-29 00:09] falls asleep +[1518-04-25 00:00] Guard #3203 begins shift +[1518-07-30 00:55] wakes up +[1518-10-31 23:57] Guard #983 begins shift +[1518-11-05 00:29] falls asleep +[1518-06-06 00:12] falls asleep +[1518-03-18 00:29] falls asleep +[1518-08-30 00:58] wakes up +[1518-11-08 00:13] wakes up +[1518-08-08 00:11] falls asleep +[1518-07-12 23:50] Guard #2099 begins shift +[1518-03-15 00:56] wakes up +[1518-06-07 00:39] falls asleep +[1518-11-02 00:29] wakes up +[1518-06-13 00:43] wakes up +[1518-07-21 23:47] Guard #2099 begins shift +[1518-10-12 00:38] wakes up +[1518-08-23 00:36] falls asleep +[1518-08-04 23:53] Guard #1091 begins shift +[1518-06-29 00:51] wakes up +[1518-03-28 00:10] falls asleep +[1518-10-20 00:23] falls asleep +[1518-11-12 00:04] Guard #2411 begins shift +[1518-04-17 00:59] wakes up +[1518-10-07 00:32] falls asleep +[1518-09-06 00:39] wakes up +[1518-03-27 00:34] falls asleep +[1518-05-27 00:53] wakes up +[1518-10-05 00:15] falls asleep +[1518-10-02 00:15] falls asleep +[1518-07-12 00:37] wakes up +[1518-07-16 23:57] Guard #983 begins shift +[1518-09-03 00:20] falls asleep +[1518-04-13 00:46] wakes up +[1518-06-14 23:50] Guard #983 begins shift +[1518-09-12 00:48] falls asleep +[1518-09-11 23:57] Guard #73 begins shift +[1518-07-26 00:51] wakes up +[1518-09-01 00:45] falls asleep +[1518-05-30 00:53] wakes up +[1518-08-09 00:28] falls asleep +[1518-10-03 00:29] falls asleep +[1518-09-02 00:49] wakes up +[1518-09-06 00:03] falls asleep +[1518-03-18 23:49] Guard #3449 begins shift +[1518-07-04 00:03] Guard #2411 begins shift +[1518-08-01 00:21] falls asleep +[1518-06-15 00:44] wakes up +[1518-11-22 23:56] Guard #3499 begins shift +[1518-06-14 00:08] falls asleep +[1518-08-01 00:03] Guard #1291 begins shift +[1518-05-26 00:56] wakes up +[1518-07-17 23:47] Guard #1091 begins shift +[1518-11-02 00:03] Guard #3559 begins shift +[1518-04-07 00:51] wakes up +[1518-06-03 00:56] wakes up +[1518-10-15 00:40] wakes up +[1518-07-29 00:40] falls asleep +[1518-06-25 00:18] falls asleep +[1518-08-06 00:51] falls asleep +[1518-05-23 00:11] falls asleep +[1518-09-10 23:59] Guard #2411 begins shift +[1518-08-23 00:59] wakes up +[1518-03-15 00:29] falls asleep +[1518-06-25 00:00] Guard #3499 begins shift +[1518-06-02 00:38] wakes up +[1518-07-25 00:29] falls asleep +[1518-04-19 00:49] wakes up +[1518-04-01 00:46] wakes up +[1518-11-10 23:49] Guard #241 begins shift +[1518-06-06 00:24] wakes up +[1518-07-04 00:22] falls asleep +[1518-05-28 00:54] wakes up +[1518-07-25 00:57] wakes up +[1518-03-30 00:54] falls asleep +[1518-11-10 00:58] wakes up +[1518-06-15 00:58] wakes up +[1518-03-25 23:58] Guard #1033 begins shift +[1518-08-10 00:00] Guard #3109 begins shift +[1518-11-05 23:48] Guard #73 begins shift +[1518-10-25 00:08] falls asleep +[1518-08-25 00:35] falls asleep +[1518-04-25 00:52] wakes up +[1518-04-05 23:57] Guard #2617 begins shift +[1518-09-20 00:55] falls asleep +[1518-08-11 00:52] wakes up +[1518-05-09 00:49] wakes up +[1518-08-02 00:38] wakes up +[1518-07-07 23:57] Guard #983 begins shift +[1518-09-29 00:42] wakes up +[1518-05-31 00:50] falls asleep +[1518-08-04 00:57] falls asleep +[1518-08-20 00:42] wakes up +[1518-10-28 00:57] falls asleep +[1518-11-20 00:54] wakes up +[1518-10-08 00:13] falls asleep +[1518-09-30 00:58] wakes up +[1518-07-18 23:53] Guard #3499 begins shift +[1518-03-15 23:50] Guard #1811 begins shift +[1518-07-23 00:33] falls asleep +[1518-08-26 00:35] wakes up +[1518-11-07 00:17] falls asleep +[1518-07-20 00:30] wakes up +[1518-10-13 23:52] Guard #2657 begins shift +[1518-05-21 00:31] wakes up +[1518-11-01 00:21] falls asleep +[1518-10-24 00:26] falls asleep +[1518-04-28 00:02] Guard #1811 begins shift +[1518-08-02 00:18] falls asleep +[1518-10-26 00:09] falls asleep +[1518-06-26 00:21] wakes up +[1518-11-17 00:48] falls asleep +[1518-08-28 00:45] falls asleep +[1518-09-08 00:26] wakes up +[1518-09-30 00:00] Guard #3499 begins shift +[1518-09-25 00:00] Guard #1091 begins shift +[1518-09-17 00:03] Guard #313 begins shift +[1518-05-11 00:10] falls asleep +[1518-11-18 00:32] wakes up +[1518-06-08 00:48] wakes up +[1518-08-06 00:00] falls asleep +[1518-09-23 00:06] falls asleep +[1518-05-25 00:29] falls asleep +[1518-08-31 00:22] falls asleep +[1518-07-11 00:55] falls asleep +[1518-11-10 00:50] falls asleep +[1518-04-28 00:33] falls asleep +[1518-11-13 00:05] falls asleep +[1518-07-25 00:49] falls asleep +[1518-04-07 00:14] falls asleep +[1518-09-05 23:50] Guard #3559 begins shift +[1518-03-31 23:58] Guard #3203 begins shift +[1518-07-24 00:03] Guard #823 begins shift +[1518-06-07 00:34] wakes up +[1518-05-15 00:19] falls asleep +[1518-04-09 00:05] falls asleep +[1518-07-30 00:06] falls asleep +[1518-10-17 00:01] Guard #3203 begins shift +[1518-06-19 00:45] falls asleep +[1518-05-16 00:20] falls asleep +[1518-08-22 00:33] wakes up +[1518-06-08 00:14] falls asleep +[1518-11-10 00:35] wakes up +[1518-08-19 00:50] wakes up +[1518-03-28 00:03] Guard #241 begins shift +[1518-07-23 00:04] Guard #2617 begins shift +[1518-06-13 00:26] falls asleep +[1518-05-08 23:56] Guard #2099 begins shift +[1518-03-22 23:50] Guard #3361 begins shift +[1518-08-21 23:58] Guard #313 begins shift +[1518-05-18 00:40] wakes up +[1518-04-29 00:01] falls asleep +[1518-08-08 00:54] wakes up +[1518-11-01 00:53] falls asleep +[1518-10-06 00:36] falls asleep +[1518-03-19 00:19] wakes up +[1518-05-28 00:11] falls asleep +[1518-04-03 00:04] Guard #313 begins shift +[1518-11-02 23:59] Guard #73 begins shift +[1518-03-24 00:42] wakes up +[1518-05-31 00:33] falls asleep +[1518-05-17 00:23] wakes up +[1518-08-08 00:41] falls asleep +[1518-09-22 00:08] falls asleep +[1518-11-01 00:31] wakes up +[1518-11-06 00:22] wakes up +[1518-04-08 23:51] Guard #3559 begins shift +[1518-11-11 00:39] wakes up +[1518-08-01 23:56] Guard #1033 begins shift +[1518-05-05 23:58] Guard #3499 begins shift +[1518-10-11 23:58] Guard #2099 begins shift +[1518-06-08 00:54] wakes up +[1518-05-23 00:21] falls asleep +[1518-04-04 00:22] falls asleep +[1518-05-26 00:02] Guard #919 begins shift +[1518-04-14 00:51] wakes up +[1518-07-20 00:13] falls asleep +[1518-07-07 00:02] Guard #2099 begins shift +[1518-10-18 00:15] falls asleep +[1518-09-09 23:58] Guard #241 begins shift +[1518-07-31 00:41] falls asleep +[1518-05-26 00:46] wakes up +[1518-11-09 00:39] wakes up +[1518-09-02 00:27] falls asleep +[1518-10-31 00:49] falls asleep +[1518-06-30 00:56] falls asleep +[1518-08-07 00:55] wakes up +[1518-06-06 23:59] Guard #3499 begins shift +[1518-03-24 00:58] wakes up +[1518-06-11 00:02] Guard #919 begins shift +[1518-06-11 00:14] falls asleep +[1518-07-17 00:41] wakes up +[1518-05-27 00:00] Guard #3499 begins shift +[1518-11-19 00:02] Guard #3109 begins shift +[1518-09-17 00:21] falls asleep +[1518-11-03 00:53] falls asleep +[1518-03-24 00:51] falls asleep +[1518-04-30 00:02] Guard #1499 begins shift +[1518-07-22 00:01] falls asleep +[1518-03-25 00:00] falls asleep +[1518-06-05 00:43] wakes up +[1518-06-05 00:56] falls asleep +[1518-08-24 00:35] wakes up +[1518-06-22 00:02] Guard #2411 begins shift +[1518-09-22 23:59] Guard #2657 begins shift +[1518-06-14 00:48] wakes up +[1518-07-09 00:00] Guard #3361 begins shift +[1518-10-20 00:53] wakes up +[1518-05-03 23:56] Guard #3559 begins shift +[1518-10-09 00:10] falls asleep +[1518-08-25 00:31] wakes up +[1518-06-10 00:57] wakes up +[1518-07-05 23:58] Guard #3361 begins shift +[1518-04-05 00:26] falls asleep +[1518-10-07 00:00] Guard #1811 begins shift +[1518-05-16 00:58] wakes up +[1518-08-25 00:11] falls asleep +[1518-04-24 00:58] wakes up +[1518-03-12 00:29] wakes up +[1518-05-07 00:35] wakes up +[1518-08-14 00:39] wakes up +[1518-08-16 00:36] wakes up +[1518-07-10 00:22] falls asleep +[1518-10-31 00:09] falls asleep +[1518-04-08 00:03] Guard #2411 begins shift +[1518-10-01 00:05] falls asleep +[1518-10-15 00:46] falls asleep +[1518-09-09 00:30] wakes up +[1518-03-14 00:50] wakes up +[1518-08-17 00:02] falls asleep +[1518-08-03 00:59] wakes up +[1518-03-26 00:56] wakes up +[1518-10-28 00:08] falls asleep +[1518-07-23 00:52] wakes up +[1518-05-15 00:49] wakes up +[1518-10-21 00:15] falls asleep +[1518-06-17 00:00] Guard #983 begins shift +[1518-05-07 00:52] falls asleep +[1518-08-31 00:58] wakes up +[1518-07-04 23:59] Guard #2099 begins shift +[1518-04-09 00:46] wakes up +[1518-06-03 00:36] falls asleep +[1518-05-06 00:06] falls asleep +[1518-04-07 00:01] Guard #1291 begins shift +[1518-06-17 00:15] falls asleep +[1518-09-24 00:53] wakes up +[1518-09-13 00:01] Guard #2099 begins shift +[1518-07-14 00:04] Guard #2579 begins shift +[1518-06-28 00:20] falls asleep +[1518-06-27 00:58] wakes up +[1518-05-02 00:19] falls asleep +[1518-04-19 00:44] falls asleep +[1518-08-09 00:45] wakes up +[1518-04-27 00:44] wakes up +[1518-07-15 00:53] wakes up +[1518-10-06 00:55] wakes up +[1518-09-08 00:25] falls asleep +[1518-06-03 00:55] falls asleep +[1518-05-28 00:43] wakes up +[1518-07-11 00:04] Guard #3559 begins shift +[1518-07-09 23:59] Guard #3499 begins shift +[1518-09-18 00:57] wakes up +[1518-11-14 00:01] falls asleep +[1518-10-08 23:58] Guard #1811 begins shift +[1518-04-12 00:50] wakes up +[1518-04-08 00:28] wakes up +[1518-04-10 00:59] wakes up +[1518-10-29 00:16] falls asleep +[1518-11-07 00:29] wakes up +[1518-08-13 23:50] Guard #2099 begins shift +[1518-10-10 00:49] wakes up +[1518-06-02 00:09] falls asleep +[1518-03-25 00:30] wakes up +[1518-09-04 23:46] Guard #2657 begins shift +[1518-03-30 23:58] Guard #1867 begins shift +[1518-05-03 00:04] falls asleep +[1518-11-19 00:50] falls asleep +[1518-07-08 00:37] wakes up +[1518-07-16 00:20] wakes up +[1518-08-27 00:31] falls asleep +[1518-04-15 00:23] wakes up +[1518-08-05 00:27] wakes up +[1518-07-05 00:13] wakes up +[1518-08-06 00:42] wakes up +[1518-05-28 00:03] Guard #3449 begins shift +[1518-04-14 00:13] falls asleep +[1518-10-16 00:45] falls asleep +[1518-07-29 00:00] Guard #1811 begins shift +[1518-05-24 00:57] wakes up +[1518-06-01 00:48] wakes up +[1518-09-12 00:29] wakes up +[1518-04-06 00:15] falls asleep +[1518-06-06 00:03] Guard #2657 begins shift +[1518-07-28 00:41] wakes up +[1518-09-30 00:39] falls asleep +[1518-06-30 00:59] wakes up +[1518-09-01 00:51] wakes up +[1518-08-04 00:59] wakes up +[1518-03-22 00:46] falls asleep +[1518-05-13 00:00] Guard #1499 begins shift +[1518-07-08 00:36] falls asleep +[1518-04-09 00:45] falls asleep +[1518-05-01 00:01] Guard #1499 begins shift +[1518-09-22 00:03] Guard #3559 begins shift +[1518-05-12 00:54] wakes up +[1518-11-04 00:57] wakes up +[1518-04-21 00:00] falls asleep +[1518-11-19 23:56] Guard #2617 begins shift +[1518-07-16 00:42] falls asleep +[1518-04-10 00:00] Guard #1811 begins shift +[1518-11-10 00:34] falls asleep +[1518-08-18 00:01] Guard #241 begins shift +[1518-08-04 00:45] wakes up +[1518-11-21 00:36] falls asleep +[1518-06-07 00:15] falls asleep +[1518-10-28 00:36] wakes up +[1518-07-15 23:57] Guard #2657 begins shift +[1518-06-29 00:46] falls asleep +[1518-03-17 00:54] wakes up +[1518-08-22 00:12] wakes up +[1518-11-20 00:26] wakes up +[1518-10-02 00:23] wakes up +[1518-07-26 00:43] wakes up +[1518-04-23 00:57] wakes up +[1518-04-22 23:57] Guard #2099 begins shift +[1518-03-21 00:46] falls asleep +[1518-04-04 00:30] wakes up +[1518-04-20 00:45] wakes up +[1518-08-31 00:47] falls asleep +[1518-09-16 00:34] wakes up +[1518-10-05 00:03] Guard #3499 begins shift +[1518-04-11 23:57] Guard #3499 begins shift +[1518-08-29 00:29] wakes up +[1518-10-13 00:43] falls asleep +[1518-07-12 00:29] falls asleep +[1518-05-08 00:55] wakes up +[1518-03-29 00:01] Guard #2579 begins shift +[1518-10-31 00:56] wakes up +[1518-11-17 00:49] wakes up +[1518-06-03 23:46] Guard #313 begins shift +[1518-05-02 00:48] wakes up +[1518-05-17 23:58] Guard #3499 begins shift +[1518-03-27 00:30] wakes up +[1518-09-21 00:02] Guard #2099 begins shift +[1518-05-22 00:30] wakes up +[1518-10-04 00:40] wakes up +[1518-03-23 00:49] wakes up +[1518-08-16 00:00] Guard #3361 begins shift +[1518-10-09 00:59] wakes up +[1518-03-30 00:48] wakes up +[1518-11-13 23:49] Guard #1811 begins shift +[1518-06-28 23:59] Guard #2657 begins shift +[1518-04-22 00:11] falls asleep +[1518-05-17 00:15] falls asleep +[1518-09-28 23:56] Guard #1811 begins shift +[1518-07-15 00:59] wakes up +[1518-09-26 23:59] Guard #3109 begins shift +[1518-03-14 00:56] falls asleep +[1518-08-06 00:11] wakes up +[1518-03-23 00:28] wakes up +[1518-11-07 23:52] Guard #3559 begins shift +[1518-10-14 00:44] wakes up +[1518-04-16 00:59] wakes up +[1518-07-20 00:00] Guard #241 begins shift +[1518-09-20 00:58] wakes up +[1518-05-01 00:49] falls asleep +[1518-05-15 00:03] Guard #241 begins shift +[1518-10-24 00:29] wakes up +[1518-10-03 23:59] Guard #2657 begins shift +[1518-10-24 00:47] wakes up +[1518-03-23 00:00] falls asleep +[1518-10-11 00:41] wakes up +[1518-08-28 00:03] Guard #983 begins shift +[1518-10-04 00:49] falls asleep +[1518-09-05 00:51] wakes up +[1518-04-03 00:58] wakes up +[1518-05-24 00:17] falls asleep +[1518-06-16 00:56] wakes up +[1518-06-20 23:57] Guard #3361 begins shift +[1518-06-27 00:37] wakes up +[1518-04-11 00:53] wakes up +[1518-03-24 00:41] falls asleep +[1518-04-05 00:01] Guard #2099 begins shift +[1518-06-14 00:00] Guard #3499 begins shift +[1518-03-27 00:44] wakes up +[1518-11-07 00:01] Guard #73 begins shift +[1518-09-25 00:55] wakes up +[1518-04-24 00:34] falls asleep +[1518-06-15 00:03] falls asleep +[1518-08-25 00:22] falls asleep +[1518-04-20 00:28] falls asleep +[1518-10-30 00:05] falls asleep +[1518-10-19 00:21] falls asleep +[1518-10-03 00:39] falls asleep +[1518-07-01 00:05] falls asleep +[1518-06-30 00:52] wakes up +[1518-04-26 00:40] wakes up +[1518-10-20 00:04] Guard #3203 begins shift +[1518-03-19 00:04] falls asleep +[1518-04-07 00:40] wakes up +[1518-05-05 00:55] wakes up +[1518-05-22 00:04] Guard #313 begins shift +[1518-06-08 23:47] Guard #241 begins shift +[1518-08-17 00:28] wakes up +[1518-06-17 00:25] wakes up +[1518-03-12 00:35] falls asleep +[1518-07-30 00:04] Guard #3109 begins shift +[1518-03-14 00:57] wakes up +[1518-07-11 00:56] wakes up +[1518-04-21 23:56] Guard #1811 begins shift +[1518-08-27 00:36] wakes up +[1518-06-09 00:53] wakes up +[1518-08-08 00:04] Guard #241 begins shift +[1518-03-22 00:58] wakes up +[1518-04-19 00:58] wakes up +[1518-04-18 00:00] Guard #1091 begins shift +[1518-09-28 00:48] wakes up +[1518-08-01 00:52] wakes up +[1518-03-19 00:29] falls asleep +[1518-04-04 00:02] Guard #983 begins shift +[1518-09-22 00:19] wakes up +[1518-06-15 23:59] Guard #1499 begins shift +[1518-05-10 00:29] wakes up +[1518-06-18 00:28] falls asleep +[1518-03-20 00:59] wakes up +[1518-08-26 00:15] falls asleep +[1518-10-24 00:01] Guard #3109 begins shift +[1518-07-15 00:57] falls asleep +[1518-06-05 00:59] wakes up +[1518-11-02 00:14] falls asleep +[1518-05-26 00:11] wakes up +[1518-11-04 23:56] Guard #3499 begins shift +[1518-10-08 00:53] falls asleep +[1518-09-25 00:25] falls asleep +[1518-09-25 23:56] Guard #3361 begins shift +[1518-06-24 00:04] Guard #1033 begins shift +[1518-05-07 00:04] Guard #1091 begins shift +[1518-08-18 00:29] falls asleep +[1518-09-13 00:47] falls asleep +[1518-04-02 00:53] wakes up +[1518-11-08 00:51] wakes up +[1518-09-02 23:56] Guard #3203 begins shift +[1518-08-06 00:55] wakes up +[1518-10-01 23:58] Guard #2411 begins shift +[1518-06-29 23:59] Guard #1811 begins shift +[1518-05-07 00:48] wakes up +[1518-11-12 00:37] falls asleep +[1518-10-16 00:00] Guard #2657 begins shift +[1518-07-07 00:29] falls asleep +[1518-07-17 00:45] falls asleep +[1518-11-01 00:57] wakes up +[1518-10-26 00:02] Guard #1291 begins shift +[1518-11-06 00:04] falls asleep +[1518-09-29 00:22] falls asleep +[1518-08-20 00:03] Guard #3499 begins shift +[1518-07-03 00:47] wakes up +[1518-05-01 00:25] wakes up +[1518-08-10 00:49] wakes up +[1518-03-13 00:55] wakes up +[1518-08-13 00:59] wakes up +[1518-06-08 00:53] falls asleep +[1518-07-17 00:06] falls asleep +[1518-06-25 00:41] wakes up +[1518-10-31 00:11] wakes up +[1518-05-05 00:32] falls asleep +[1518-06-23 00:40] wakes up +[1518-05-13 00:33] wakes up +[1518-04-17 00:53] falls asleep +[1518-05-01 00:09] falls asleep +[1518-03-14 00:22] falls asleep +[1518-10-27 00:01] Guard #1291 begins shift +[1518-06-04 00:01] falls asleep +[1518-10-16 00:50] wakes up +[1518-07-08 00:45] falls asleep +[1518-04-12 00:37] falls asleep +[1518-10-18 00:38] wakes up +[1518-09-14 00:10] falls asleep +[1518-07-01 00:40] falls asleep +[1518-11-08 00:20] falls asleep +[1518-03-30 00:59] wakes up +[1518-06-12 00:00] Guard #3499 begins shift +[1518-08-27 00:00] Guard #1291 begins shift +[1518-03-20 00:37] falls asleep +[1518-09-30 00:44] wakes up +[1518-09-20 00:43] wakes up +[1518-10-27 00:08] falls asleep +[1518-09-09 00:02] Guard #1091 begins shift +[1518-08-13 00:21] falls asleep +[1518-04-21 00:49] wakes up +[1518-11-16 23:56] Guard #919 begins shift +[1518-07-22 00:47] wakes up +[1518-10-03 00:50] falls asleep +[1518-09-26 00:50] wakes up +[1518-06-08 00:02] Guard #1811 begins shift +[1518-05-22 23:59] Guard #2617 begins shift +[1518-07-31 00:34] wakes up +[1518-10-22 23:52] Guard #313 begins shift +[1518-08-03 00:49] falls asleep +[1518-10-24 00:43] falls asleep +[1518-05-08 00:01] Guard #1033 begins shift +[1518-10-19 00:48] wakes up +[1518-10-13 00:04] Guard #1091 begins shift +[1518-07-18 00:18] wakes up +[1518-10-20 00:36] wakes up +[1518-10-04 00:33] falls asleep +[1518-05-08 00:11] wakes up +[1518-05-19 00:04] falls asleep +[1518-04-06 00:55] wakes up +[1518-08-10 00:38] wakes up +[1518-06-10 00:34] falls asleep +[1518-07-15 00:38] falls asleep +[1518-08-18 00:35] wakes up +[1518-03-27 00:18] falls asleep +[1518-08-10 00:45] falls asleep +[1518-07-30 00:22] wakes up +[1518-06-22 23:59] Guard #2657 begins shift +[1518-07-11 23:57] Guard #2617 begins shift +[1518-10-15 00:47] wakes up +[1518-08-25 00:02] Guard #1291 begins shift +[1518-06-24 00:12] falls asleep +[1518-03-16 23:57] Guard #2657 begins shift +[1518-10-18 00:02] Guard #2657 begins shift +[1518-05-11 00:58] wakes up +[1518-03-30 00:37] falls asleep +[1518-08-21 00:53] wakes up +[1518-07-09 00:57] wakes up +[1518-08-07 00:00] Guard #1499 begins shift +[1518-09-02 00:56] falls asleep +[1518-10-14 23:56] Guard #2099 begins shift +[1518-09-19 00:48] wakes up +[1518-05-30 00:04] Guard #1499 begins shift +[1518-11-11 00:04] falls asleep +[1518-03-21 00:57] wakes up +[1518-05-20 23:57] Guard #1811 begins shift +[1518-10-23 00:08] wakes up +[1518-07-02 23:57] Guard #1811 begins shift +[1518-10-28 23:58] Guard #241 begins shift +[1518-05-12 00:05] falls asleep +[1518-11-18 00:26] falls asleep +[1518-03-21 00:27] wakes up +[1518-07-29 00:50] wakes up +[1518-10-24 23:56] Guard #2657 begins shift +[1518-05-14 00:37] wakes up +[1518-08-04 00:00] Guard #1033 begins shift +[1518-06-20 00:52] wakes up +[1518-05-10 00:00] Guard #73 begins shift +[1518-08-19 00:02] Guard #1033 begins shift +[1518-03-16 00:03] falls asleep +[1518-03-12 00:03] Guard #2657 begins shift +[1518-06-22 00:48] wakes up +[1518-08-22 00:31] falls asleep +[1518-05-11 00:02] Guard #1811 begins shift +[1518-03-19 23:58] Guard #241 begins shift +[1518-04-10 00:53] falls asleep +[1518-10-21 23:57] Guard #919 begins shift +[1518-06-28 00:04] Guard #2657 begins shift +[1518-11-17 00:56] falls asleep +[1518-07-09 00:45] wakes up +[1518-06-11 00:44] wakes up +[1518-04-10 00:48] wakes up +[1518-11-01 00:37] falls asleep +[1518-05-20 00:36] falls asleep +[1518-05-23 23:56] Guard #1811 begins shift +[1518-04-18 23:56] Guard #3109 begins shift +[1518-05-31 00:02] Guard #2657 begins shift +[1518-05-17 00:00] Guard #241 begins shift +[1518-05-28 00:52] falls asleep +[1518-10-30 00:07] wakes up +[1518-08-30 00:26] falls asleep +[1518-03-17 23:57] Guard #241 begins shift +[1518-07-19 00:43] wakes up +[1518-08-09 00:03] Guard #3109 begins shift +[1518-09-11 00:41] wakes up +[1518-07-27 23:50] Guard #2099 begins shift +[1518-10-17 00:26] falls asleep +[1518-05-30 00:14] falls asleep +[1518-10-12 00:26] falls asleep +[1518-06-16 00:44] falls asleep +[1518-05-20 00:02] Guard #1033 begins shift +[1518-06-16 00:24] falls asleep +[1518-06-19 23:57] Guard #2411 begins shift +[1518-10-27 00:53] wakes up +[1518-06-10 00:53] falls asleep +[1518-05-05 00:43] falls asleep +[1518-09-04 00:03] Guard #2099 begins shift +[1518-05-23 00:14] wakes up +[1518-09-08 00:04] Guard #1291 begins shift +[1518-05-03 00:52] wakes up +[1518-07-25 00:03] Guard #1033 begins shift +[1518-07-08 00:59] wakes up +[1518-10-25 00:54] wakes up +[1518-11-08 00:00] falls asleep +[1518-06-20 00:47] falls asleep +[1518-05-08 00:49] wakes up +[1518-11-15 23:59] Guard #3109 begins shift +[1518-06-18 00:55] wakes up +[1518-03-11 00:04] Guard #1499 begins shift +[1518-08-29 00:44] falls asleep +[1518-05-16 00:28] falls asleep +[1518-11-03 23:56] Guard #1291 begins shift +[1518-04-26 00:18] falls asleep +[1518-07-21 00:00] Guard #919 begins shift +[1518-08-21 00:04] falls asleep +[1518-10-14 00:05] falls asleep +[1518-06-19 00:57] wakes up +[1518-08-27 00:54] wakes up +[1518-09-13 23:56] Guard #1499 begins shift +[1518-08-20 23:48] Guard #3559 begins shift +[1518-09-30 23:50] Guard #313 begins shift +[1518-08-20 00:37] falls asleep +[1518-07-18 00:03] falls asleep +[1518-04-23 00:17] wakes up +[1518-05-14 00:17] falls asleep +[1518-06-20 00:27] falls asleep +[1518-06-01 23:59] Guard #241 begins shift +[1518-06-05 00:52] wakes up +[1518-06-26 00:37] wakes up +[1518-05-28 00:14] wakes up +[1518-11-12 23:49] Guard #3449 begins shift +[1518-11-10 00:53] wakes up +[1518-06-05 00:00] Guard #983 begins shift +[1518-10-26 00:45] wakes up +[1518-11-03 00:55] wakes up +[1518-09-10 00:31] falls asleep +[1518-05-31 00:56] wakes up +[1518-11-14 00:31] wakes up +[1518-06-20 00:43] wakes up +[1518-06-09 00:45] falls asleep +[1518-10-18 00:48] wakes up +[1518-07-30 00:43] falls asleep +[1518-08-12 00:04] Guard #2657 begins shift +[1518-09-15 00:59] wakes up +[1518-05-07 00:16] falls asleep +[1518-09-14 00:56] wakes up +[1518-08-25 00:45] wakes up +[1518-04-07 00:55] falls asleep +[1518-07-13 00:32] wakes up +[1518-03-24 00:28] wakes up +[1518-11-22 00:40] wakes up +[1518-09-12 00:59] wakes up +[1518-03-12 00:47] wakes up +[1518-09-17 23:59] Guard #1291 begins shift +[1518-05-26 00:40] falls asleep +[1518-04-07 00:57] wakes up +[1518-03-17 00:48] falls asleep +[1518-09-10 00:56] wakes up +[1518-06-16 00:29] wakes up +[1518-09-04 00:41] wakes up +[1518-05-02 23:53] Guard #241 begins shift +[1518-08-17 00:43] falls asleep +[1518-09-17 00:59] wakes up +[1518-09-07 00:01] Guard #3499 begins shift +[1518-10-11 00:29] falls asleep +[1518-05-18 23:53] Guard #3109 begins shift +[1518-07-02 00:00] falls asleep +[1518-04-03 00:06] falls asleep +[1518-05-04 23:58] Guard #2657 begins shift +[1518-06-03 00:48] wakes up +[1518-06-10 00:48] wakes up +[1518-09-09 00:06] falls asleep +[1518-06-04 00:32] wakes up +[1518-08-19 00:32] falls asleep +[1518-06-17 00:31] falls asleep +[1518-11-17 23:59] Guard #1811 begins shift +[1518-04-27 00:43] falls asleep +[1518-05-26 00:06] falls asleep +[1518-07-03 00:07] falls asleep +[1518-05-16 00:00] Guard #983 begins shift +[1518-07-26 23:57] Guard #1867 begins shift +[1518-10-22 00:36] wakes up +[1518-09-10 00:39] falls asleep +[1518-05-20 00:59] wakes up +[1518-09-26 00:20] falls asleep +[1518-05-07 00:38] falls asleep +[1518-10-05 00:53] wakes up +[1518-07-05 00:39] falls asleep +[1518-11-20 00:09] falls asleep +[1518-03-19 00:34] wakes up +[1518-11-14 23:47] Guard #1291 begins shift +[1518-06-19 00:14] falls asleep +[1518-09-15 23:58] Guard #2617 begins shift +[1518-08-28 00:46] wakes up +[1518-07-28 00:04] falls asleep +[1518-11-19 00:57] wakes up +[1518-04-15 00:17] falls asleep +[1518-05-08 00:52] falls asleep +[1518-10-03 00:32] wakes up +[1518-07-05 00:51] wakes up +[1518-06-09 00:16] wakes up +[1518-04-28 00:43] wakes up +[1518-07-09 00:38] falls asleep \ No newline at end of file diff --git a/advents/src/main/resources/2018/day05.txt b/advents/src/main/resources/2018/day05.txt new file mode 100644 index 0000000..0146936 --- /dev/null +++ b/advents/src/main/resources/2018/day05.txt @@ -0,0 +1 @@ +RrhGgHUQOzZoeErRpPBbiIhHquNnHhUgGsSbBZzNXfFxnRrupaoOXxrRAaAPDdNORnNDdrCcsSKkSsoyYnSsJjjsSJiIMjJkKhUuHmPpEkKedDTOnNotBbTSsoTnNGglLtkKadpPDGgAxXUuOtoDdOoxXUzZHhzEeGgYyqQZuUullJjKdDNnXxkDdpPLBbZzLQqOzAaZdnNipLlPIHhDooOxXrRiIGgOooOoOGgXxOgGiiIIYykXcCxmMAaDdKWwIiAaCbBYyEZzpPaAwWsSeSGgQqsSDdinNdDjJnNbGglLfFBicCIrRdDIkKwWsWTtwXxbBceEvVDdeeERrsSRroIHEeuUhsSicSsQqGgkYyKCOZKkzAhHyYaTTttfFBbiICFKkftTcjJkKjbYyBEeqtTQnNwzZKNnkrRTtlAaNEeneeEJjOoUuNnELfWwFtTWJPqQEetPpTgPpNbBnsSqQGphHxXRVvXxWwrucWwCUEJyWwYiIjJjnNKwWQqSbeEbBBMmWwCcsklLGQhHqyqFfQDJyYjTYyTtoNnOVUuVvFfgGWwgGLlCcvtdCUuOocTtsSEgGQqTteeEXxbmMBaAMmbJjBbBcCQqdDOAaokKkKHcsSVvChTtYqQAajJrfFySsYBbRrERreBSCcsgeEGtTeEbgRrOoGLbIiTtBsSQvVIiqjJlRzZBiIBbZBbziIiIvVTtxbBdXxvVDXbIiMpPNnQqmjJtMgZztTGmvVaAWtTsdjJvVDJqQjMfFmMGjJsSgmSgzZGdDLlGlLwWvVgkKzZhHlLqIiKkpPQJOoVvgGWqQwJjfFjheEsSHwBbgGstTtjJtTTSeeEEKkFfHeEhTvVVvnIigIiIiUCcJjOoSnPpMmhvVuUNnHNIPpiPYXxypLlvVoONFJjzZAafoOnhdZzHhDHANamMAYyhHvVxXOCEQqtvDdVIiTelLBbgGccCRFfCcnNyGgVvYXxrcDdrRCBTtbhHVoOGgsSeEQqIiuUnNvnNlLKkeKhHoOkCDdcExXRqrRMmsSCcQhHqQRrrqQOoYyHhxrZzDIirRyYdBwgGOoWAaqQYyTHhsSJpPjtEepPbhDdYygsHKkhStTsSYyzDdZiIZzcnNCGOoHMXxmsSLjJlNnuMmSsTrRPptXbrJjPpRYyBxqQgGcqXxQDeEdxvaCcAVXSscJjWwCRhHwWrRDdrcCCTwWtQWwqmMBbhuVvUHhDdHdDoOcCngnOaAokdnNDKkKGlLtKkgGTgCcwWNHhuUGeESgGTtsgGmcCPwWpvVzZFffFeEMNFfEEeGWnNWwwHLlhTtgdDeSsWpPqiIQWwweEtTypPinNdZzDIhHYWHhwFfwWmMZzIiiGgpPzZJQqjmMdDcbBQqCJjbgGmMBGgzSdDsZKkMxXlLiIAyYTtaFUVNnvgOIicConNGugmMlvyYfnNFVhbBFogGNnYyzZOPlKkLlLOopqkKkfFKVKkDpPdpRrPcCMUueErRpPMmlgGyYQqLmvduyYUsSRrDtCoOopPOOUuoLYhHyUcmMrRCuiIfFwYyWlJjMmFwdDqOCcsSoVvAaXxgGgwEeKkmIiMWiIgGlLFfGIiTHhtQEgGeUgGuuUhHWiIqQlLgKkGgGlLnNmMHWwaACZzMmPpchuUDdLlPpoOwWVvURrYyTTttKCcTtwlLWkXxXrtTsSRaAaOjJEeYytoOCWZzwcTksSKfFAahHSsiIWQqzXPpLldDxKWwmMzZHNnxXAHhcCXxamMhQqnNJrRjkQgGGCczDdqQvVZghUuHuVvURrMmSYbKkBdOoDRrTFfBbUqQyYupPIifphHpJjPEePYyFtmkKMOoXxxnNXMtEeTLlRMmbBukKUXZzAaxyYHhyYrqgGAaQdDgPpGiIVuJjUqQvPYyvsuUSVkgaNkKnArRGmoROoDAadcaAhHjJCrtDhHsfFaAWwaWwiIhHASEdOoDLQqRrlNndbBDlLPpedsLlTDdtSJjsSlqKmMkEvwWpPVDABbadeVvBbSsxXfvVoOjJuKkUdDQqFwWRnNAarCcylQqLkKgGVWwvCcIioOkNnKrRYyDKkaADdAfHhFQqrhHdCWwJjDdZzHBbhcaAZPRrpPxeEXRrzZYyUDdukdDKBXxWwgfFGbpPhBBbUUuuEeTtaEeAutiIgGTrRUbBOopPVvjJeEqQUutrRetTHhRvVXxrPltTPRrwWpDSslLKoOklLdJNnvVUujNnHhDdqQOoeELQuUtBbTKnNkzZgLauJjBbTtaAnsSWnNwWwcChDjJdDbBrRBbRrdjyYJeEqQLlDdhEPpeHoyvVAaFfYMmOgGpbLaxXfFPpxXJCcRrjApaAPeEwWhHlCchpPOoxXHdDBBbyznNZkFfVvuPpUsSftvhHVPBbpfoOduUDugGRrUBHhzUiIusSgGKkZZzsSbycCYFtxXiWwIsSKlIiLkEesUxPnvVAaNuUTnNtxoOXxqQhWwBbMcCNXxRGglLeErnfFGuUaAYygUuSsXGXxjJgxMmfkYyKwGgWqQHhgbjJBnNxKkXWwGpPFhzZOoHmMmiRrLNnlCcMDvVhHdDddDyWVBbvwYbBCcchHCvGqQxXkNnjJVvkEeKXhFfoHxPpimMIKkKZzddDsNnSDLlVhHMmvkgvVGkbBGgPpkKKFfoORsIIiFfsSiSJjlLVbBvZVDdvWkERrWwJPpCcjaQqBbAwWiaAIrGgyBbYbBRxXNZzZGguUIiAPpLlpPPYZzdDFiIfmMyWweAaEZYyFfzpjJHaAjNnGgJcCzZGGggdDPpnNMxtTkMlLxOOouUIpPiaAyuUmMaAEnNjHhQqUuXSUusAaxaAJxgGIiXetTyYsScCENnkKiIAfFajJaAeHGgxxXXddStBbTfFxXWwsfFDDSNnmAaqQbUueRzcCZrdDpORJjrouUcCvVstTSPaARrFWFfwOOVvYyObBDdHhvfOoFgGdDVQgGEelLqkKSsttTEeddDDTZIHTtlbLlBRpaAdDPryYZlnNoOLElLEeepPQOoeEpnsPHiIfaAJjFkKIihpgieEIGdDHhAaQqQNnqMqQHGTtFfkJvIsSsqxbBadDAsSJjXusnNKLNnJjTtJpUuMmIiPZzjlkgCcGgftTFzZuUFoORAuUafUuFObBadDDdPpANEgIHhiLlGYycSssCcSCIlWfFwtTtAaTGZhHzeEnNExXeBOuUvVoXfFxyLzZdDJGkKgGdDgkiIFfWwdDbBBbHhuUkKVvpCcQqJjZQuUUuqyOoYIdDkKhHiRriIziBQGglLqUsSuaAjJKMmfFHfFRrzZuUhcCaALluUDdhHuULlDddqdDKnsUuSdDSNnVvleEgGyYyYwWLWwgGgJjPCcHhGgpGOoLPFfYgGZzyphHzOrRoZcCwMmyMmkKuXgGxmMiIzZUqZzmMHhQWwvVxgeIiFfKkpPchVvCcHCEmMrtqYyQTPuUpMmLlLluGgUhHRQVeriIRxXEvsJKkjdDSbBBDdbkKbEeHhBWwBJjGoDEedZzOgZyYzDFfIiRrIidNaALeJjElKCckCcvMcCmVpPnbBjJdZzJjpPkdSsDKUufcTGQkeEKqBiIUuUugGbRsvVSrTkKpPgGtBbKkyHhuxXUSsYtBbGgTfAakKFxCcqwpEePhHWWWwwAaqQzdDeNZwWYydzbuUBoKHhkVWwiIbBNnxXHSNnFfeEtTJNnPyYpqQCfFNaAfGgsSqQFpPncicCdDIoOVvqPrRQhsSDdcCCnNvVSIisqQgYyhHjtTJGcVzHhZIiIRhDdHbaIiABCcdDZzrivvZZzzcCduzZwsSjJMeEmPfFwWXxNNnnFfWwPNnpHhYWwLLllDdyLlphciIlZtTzLJuFcCfxIiVvXUXblLAaBWEetTCcEewyYcCeDdEUueEjCcKwJeRrEjWUEeuCeEclLpPAabXxokKZzFfGzZRrGgleAaEFfVMmvLRJjJjEeGNNvVnUuZzmaAhHZzPpPptTMEeTtMmUuSsFCcfpPxdDiIfIGgEeaunNUkKNnHNvVnNntuUbBTxXhGUuuUgQqjiIWQfMmFqWwkjJsSKaLlQBbqAmVvEemMKkMmAGrRgajJyYAanocCOXRZzrxwLYylWHhNVBbPJjKBbpPkpvmMXTtgGLleETVvtAaRrMDdlLUuupSJjsPuUEepwWkqQKAaxXxXnbOojNnJBcCpPKgmMlLgpqQPtTLSsSsScCjmMJsftTFVmMveESDdjJCwWcPpryYhpPcCEyYlUuOoRrRrEeVvLvueENnUJjTtkfFKViINSJlLjCykKTKkXxtCLlcGgJJjjSsaAnNSswAyYaSsFgDoXbdDIhigGhgWwRHhSsrkLwWcsSCWFysSYKkdWqQwDoOdDQqfHhKkBbhQqQDdqnrDdRffQqnVQYyqUuLlkKfZzFzZbBbBUuoyYcFWwjnNZiIzJuZzUffzZNaHhAnFsepPEsOoSJjGgSJjCMmxeEecCEXfPpFIXxsTtSRrDEedjuUNlLpPeEnoOJsIiBbSDivtTVVvIKhHkiPgGfYakNsSnKoRrqtTOoNnGgQLlLlIiJjpeEPiIHhhHVvswmTtMWENnuUNnZKMmkzRDdrdDsSlJwWRrzZoRrwWwWaBsSbpPLkKlXxQfUuWEewFKpCcPiImMkqrRtTJjEzfFZeIWUuwzZaDcCEVvvVMXgGxLoKEeCcIikOprRPSsYyeEhHOoiIyYWzZgBQgGqRrbpIiPOouUhnNdDIHhiHMlIiLmVLqQRrSLlqQslmMaArzyYZRFNVLSslvnFffpPpPvTdDtuIFfimMmMUvVGUuPFfpkqXCYTtugGUUuoOycNnhHBbXsSToOoNZJjjFZzfQqRyYPkKprJymMYyYYytPpTZyYzBDdcCbvZzWKksSwrqQRSoTtCzfFyYWwYyPprIibBIeFfzZFTsStyYftCcTRrEpPeTXxtxXEiXxjJWwaWwjdiIDHhoOiIWwUzZZSszSQqTSskKvVAcEpeEzZKkBgGKpPkOoEeyRNnAiIXxsSpWWFhHfWwwvdDVwPUaAqsScCQoOpiICchHPJBbmCPpcMtTwqUuQMXxFfmmNnSbBsqJVvmIsSiUulLGgNncCTrRttTcbBJjxBbXIPhHyYpigGByYrRyYbRrOoCXnTtJjbBdDOaAqpPciInQsSqNnbBNCSYygcCGynXxfFcPZzVvrRpfFBpPBbZWwXEexfFQqkKozZOOjilLloOLpPIEuUYyeAUuRIiruxJdDjRrBbuUdDiIXMCyYctmMEhHeTufiIFZzUhMmvVTtHFlLLvRrXCcHhcCdDrRLVvlEeiwWfFnxhyPpFfNhHcCAXxtXwpCcPwWIVOviZzPnNHJTtjhVvphHXSGUugCcUugNnbBuUmMamsSqQMAEedqQDEeDZzSsWJjjUuoOoUupPOCcJYpNZzWyJjGgYtTwAaCcCeESsJjnNHhpPrROoTtcIrRSsiIiQjwxUuYyPRrpLKkqWwxRrVaFfAvinNxXRJuUjIhHLxXFNCcniIYqQyLWTUHNRTipPIlLcNidDoGgZzObBmQqTgHqTtOoQIGzZtqEEeefEeLlSsYptaUuATkKPDdyYuUKkyYcYSsXxRrGgLlsSHhRrsSMpvVIiiIpPcCYPuUpXYyxyWwckNdUuDneETPjJMUudDnNKkROoKkvmahsSjJFfkKCcjXIixJqtoONXxnyxXeEYTKkwWicjJNIPpsSpLlvZzVGSsgLvVljZzJkkKcCpPKFMmZzmNnMVvPKiBMmbkUuKTLHheEtTjJiAatTqKOKkojJiIkhHPzZMmpVOovdsQEeoOBbYgGupjJPttTloVvhHbBOlLSssNnBbJjjsNxXhHnOonQqFfirxXUGguccUuEeCCcCTZWwJjTtcQqvVCYoOyQqZlJjSsvVyYfWwFLltfFLlTzZjZmUuMtTzINnizZwpPoQqkYybBXxaAHkKdDZzRoEeQzZgGqmMnPBbpmMjJSRSsNoeZzErRUuQnNcDjJdSlLstKkTCYsSTUuQVveEZCqzZbBaiIoEItTiGCwicCgiIyYGIFkKNngGpPzZgGfWhHPpieEKkqNHPphnLGgVvllLQIKkjtuUTQxXpPIiyYqabBuRsLlFeEfSrtuckKLOooOiEeIlmMqQcCyZzYlOoLCcnzZncCOpPosSGgZaADyYdzNVZTOotbBzNtTnHhJjrRUuTTttPQqUaFuQhHqlLlLhSsCZzyxxXvVifyYFIgGiCKoOZzkcnWfFcCkaAKUuTtpPvUuxvVXOPJHhjpoROadDTtnqQNIDiILltTduaAEeUPGKkgecqQiwWInOpPoJjLlJjZYyPpRvVgGOHhorfFtWwTPsYZzaAyfFSpHhSnNsJjYyxXEeQRrqKdDjIGgiWMmcCFrRPPphHpfOeEzZNnoZzCuUDOodxXcVyRBBbriRPZtTWvrRPpnGgQcCTmMBDdGgNnbiXxHsSGQqnPiIpNXVvxOJnNjoUmtTMLllPmMBrJsSjLQXHhiqQIxUVCZzYycvVvRVvrMOoMmvdbBIiAJjaDTRrpSsPUuKqPpZzDdQaAQqkDdvVKUqEewWcfFXxCswWRrWZzwBbImMifpsStTfFomqQkKQqcFkLryYgGqyYQYbBRrvZzVrRtRrtTWwgGIiiMRrmCckigdDGWsBbSwXxYFfWIoOcCXHiICkPpfFThHymMYtKmTRrtMEfFJjYyBRrvOoVAaxXbzAaZZmMoVZaAzyYvsCcqQWwCcSvMmqQVFvpQqjJPkKVxlLXgGfrFrRImMTtUubJMbLlBVvdDjJiCiIcIMmnNOnNpPodduUuUnNcCDMYyZzYymeEeELuUlWaAwDdWwPLlpwWCcDCcoPpOUZhmMGJgGjOorRNneEpvVqBbQCcxtTSuUsLLLPoOLyoOYdnAZzaNrRDOolLzZnomoOMiIOazZFqDdQxXIieEfedEeFjJcCfDuqQmMUEQqeEAGcCgNpMFfwWQiIqYygtjJThHgGCdTfFtDcGQptplLPTPPpjrjJRiIxcjaZzIMeEmQXaAxqIQqxNnKkiYTtyIfFrRYyyrStREeYyhTtiIMLlmHRrZWwKPOnFmeEFfMEeAaHhuOoaMmhHhRjJjkKPpsSutQqCcTBhHaxWwsIWYyRrMmGgwLlXxqCgGcaApPDdQmMOoQiIaAqWwkKAmFfMFmMkKlkpKRrjJoKknyYMTUlENnvHhMmVPpWOxxXXoDdDyMoRrOlaALkYPpVvyEeofFooOOaiIyEeYEeDdPoOpYnrRNYyVduUDPpvDdRAaWNnLlwXyYHhxOSsxXlLbBnNDSFfsdVACRtzZTjJPUutkKtTTiDdRrjJIeEaADdpRrnNiDdCcIlbBDdYbQqzZTtByqQDMmBWwbekuUuURrKnNXxErDdnbBKRrsiISHhkgGJjqFIBLlCUuZhHzLlgMmGpPKkfAaFjlWwUuyYiIXnNSsxAauUYjoOJCxXqkKxXbMmBbcCcCtoOJjnNASshRAaIiExXSJjlLZzVFfPRjEeQqFYyyVIinSsNPpDmbBvVoORrMYydlLZzTtOoWwAuUlLaHhiVyaAYCaAvVcgGPpGoOgATtbBjJaAiOSliILsRrBrRBdDbgGcCrAiIaAYyVvmMAyYsSahHvFURruQWwvBbVRrmDMmGgFhHXbBxSoFfLllLxXpPQqzZHhlTjqQwYJjtHhTwVvWozZOgGUuQgVBpPbQhHSsjAapnNqQPwUVvaAurBpJrRjqQMUudDZsSLAalpPxXiIoOBYybJjVTtaAYyNnacFjdDqzPpZQGgcmZzSsgUufFyqQYfcCwWFMVqFfQUuRBDdcGgJjCvrRVCddDOocTtBbHXOQqloOvlGgVhZEuUgGeVvsPoONnxXtJXxJTPpUutigGIFQLlrPpRJVvvOoVjtTqfyIXmoOikKJjiVzHhsSsmMSyYgFxdDXWwfOorRGizwXdDxGdDjJgdqQDZqXaAPRbPiIpppPFpPhHfsBfFbfbBFKkAaoODaAdKuUhHkefFaAcCGywWYGUXxHhGgrROoukKgAalhHLPcWwCgFffgLlWqQOLlFWKkPpNnwxXTtHjJhcEeCxXftOVvxXyYoDdVttIHhRriIqQiTyYZgGzTtnNJjvzZfpPFoOLlTVvtVNnlugGQqUuXxMmUZzCGgaAcVvgYqQyYiaAIyKltQsnsbBxXrZzSkfFknhYsNKkePpuIcbBOoBbCizZPaXxApAagBCRrcDYKkhsSHGgywElLCLDfFdAaluUiDdMVvxxXpzHhCclTtLzGeKkwhHTtkKdnNDBbWpoOPEsmoOMcAatpaAmQEqQOoeHXxhqeWwtTJjtHhJRBbepPErRtRrRXxIisSrMmfdDVvFwUuGkKkjhHrwwWuUWNngGGdCHUFrvVFfBTyYHhidDItvHhVkKCkRrPLlpKcQaAWlBbLwFnNUuXiIxcxXzZCAafmMZjFPpjJOoYyDpPQqmMjrRjdDRGvVgZzHhiXoXxOxlcCRUufFUuUHhBbcCCcuUfcCFEeIUUuSsNcolLijJVvIPTtCcxpYdDIisHhqYBpCdDDdcdDeEcCyMQqmTYhcCvxXQqAhHaeQcCCzZSyYsKugGcgGCaAUsXRVqQovVxXXxOAzPpqQtTDlLHhdEeihHItToORIiTtVvrAvVOeSgGsBwCxueEUfhHFVfFAEeyYdDRdDVvygGZzuLHbHtTIlJjLKkizZdAaiIIUuioVctnNWwOvpPXCctgGdDFiIfTLbBEVvDdeljXxDiIdJoOHhGBEebjJyYgOEFnNUHbBAaIihqQqmOjJhHUunNoMuURxXnNrtToOAdWwDaATtsBbCCccSReEJMmjAFaqtEEekrLlRLlKNJjnhvcCcZzBldxXyrlNnLHMmhVivVIcCdDlLIDdWsgiIeSsEeETtEqscNPTtSvVWwsYqQrxMKkrRkKjEEezbBRiIDBPoTCcQquyYBGgaAyYfVQqvFtTFaAfbPpCcvVCUuzEelLyYZzZtTYyKklLOoPPppDdpQqPKhYMmyKePpKpPIIXoOxUuiuUGzGgZgewWOZzonNEqARraeEQePLlvAGgMxXxgGVvPpXGKkBbMmgREnNoOdRTtrXDdZzxrRDYytTNtbBugjJiyYIEeOoGAEWwekjGgGMtTbBOomgpPjJJKvEeVXxMmaPfFlOTFftTOwWyRreELoOAasSBblYizZSgGdDIismlZzLKfRHhZzjJDGgdhHEaAoPcCpOZzLleGJjgrEeVhRrXxCcHXxEeoOVDdbBErwWBbHhRzZeiAKkIEkKeDLlsStTdvVTtUsSNnuPpiYSjqMmYyVvVvczZCyHhvrRDPpdjkKYwWqkQqyYuUIiUuJEeMpqhljJLQbBqupPUHZMmoXxbHeEhkKgGgIzZSiIRrpPeEihJjBsUuhpPHiITZhDdoPeEuUpEeCcOvVgGnNNRrsNnMmuvVlmlOIZzCciOHhTtHKRGNngAarJjAaVDdvtTkGghBvvVVbNcBbBbfHhNnFmFfMCmMGyYBObMmVvRrBobGggnWEewtsSXxgqQFxXdDuUoOoOYcFfCWwflLxXFLHhBbBbYybrRHfFhfFiIqCcXxRVFbFLfFcCFfHnmMwWpPNhDwZIizWROJVvjolLuUYyCgTOotFwWJJVSVvsuHhUXxvfdDJjLlnPpNVMAamvEemJjMmIgGiMmnNdkYNFAOoZzLDdgfFYyJjoqQOtTnNRraAkKiiIYUuyIHhbBpPHhfKUuKkgcCZzGrRYAlLwWMjFbyYtxZzvVOeEBmMbpzEeZPzZlLOoLsbBWqQwgGShHvVUdDuCcOKSssKkSRMmKkHhrsSWwfUuwWhHZzkiIdsSpPgGSaanNAMOYHhyRroXKkUnNKkTtUDdFfukKMWJiAaINnyTYyWwtYhwWHcCgGDdrdDRjPpwNnmeEsYGgyrApPaEoOepPKCGgnNkKczXxLlfQKkxXqyYjJPVvUuEejJXxyYOygAfItTaAnCcKkNhEZzEezUfFuuUuWwfkKnwWtaATNuFpPfNnUuUVvnNSstBEebXCRUuMjJJeEVvTtLlYmMFotnNwCcDTbVvjWweEHWdDduLlUiNnEeJQqWwjTtIsSiIDLlRrAajJjfFaAazZhHOaAHhRrewOofNEenqQwPpnNWrRoihGTHhLpvKIsSieEShHqQHDdhLAaKkFfgGleEFGglLWwfuEJjPdDilLaAEebBKaGbSNBbngGIidSBbxXRruUnNgGlcHxXUukKzZDdamsRrQeEiIqnNRQqYyGgrFFihnNHsSIiXxUuhBygGnHhJjicsSCNWwntTJoFfJpPTthHFxXzYoynNYbxXJjjzkKZNnEewyWlLwZzmMKkHhYKkOoKkRQdQqrLlRkaAsiGSoOmWSNGoOgCceEiyYzoJzpPZMQqbjLnmgtTxXeEGLMDdkKgGgoOGEbVvBRrCTqhHQCctcwsSWdDyYDdWwabQDdiItfFTgeEfKUPpmhIiHpPHhtyQqYJANnpPXpPxFCcIixsDcWAaLrRlweEyYJIXtHlggGkrRKGqqtmiqjJXTLlwWRrRrOollWmMsSsSUuoOPjJUcCuCDdrchHCfyYFRZwWaAYyVvAaziYybhHPpBRqxDvvVrRqQJxXxSsXjPBbpVxGgXQqNnZowzClLPzZvVpquGXxgaAPpUXDdlQgGqLUusSxQgdyGgYhHoOzPprRZGmrwoOyYWRMWQqewWVdDmgZuoBbeENnQqLlNnfFxIyYtTPpiBHdBbvDdXxkKbBbabCKWwkZMmHytGgNnVUZQqTtsSPUuxGWwgGhHhjeEKkJnNHxjiIKQqtTDjJkKIWEMmebzZBsDdSpPYhHlwWlRrLBbLHhuUnZIizPJOoxXmMBbrnZzonNOtcgGFfCsofZzlLWKkJjWPUTtTtHQNyIiYkKHhEnsSNeCcAabIiGgeEJjAaRdgGmMzJUuGgivVjJEeKMICciinNiIyYAaoXiIvJVajJAvTIibBjJtuNJjnUXxAayeEzZZIiGgsSjJIwqdDnkKPpNzyuUwdLYehTtmMgUCchzZHZzukKgGzUQquZGgzAaHhAavVSspPZvfBbFVlLWwBOMKfFkmJjoSsJjoyZzYLlXxVvOvjcohHroOnhHehxXAlFfghhXrdraQqeEBbQqARWWwFdDftTrVijdDWwvVYJWleHhyYzLlZIPHhZzecCUuHaAhAKqrHgLDWwuUrRWwnNEeWwrReUuMmrPpRsKkjcOoCwKkWMBbUlLqSsQdsQqSDZoOzRHhsSGQKJjkDdvVZzEeeWmAeExXvVwWaeEMHhfFZzxXzZXxidoqnqbBQNWwLlQrRZzIiFFfevVvkKVhHkIyYTUzZucCUuzZoGgoOsZzTaCcAZzLlXOBouUObyIVvifTteGgMmrREfXMuUKTXjzZAatfFiIMmtfkKFnNzZTiSHWwhXFFfflLLGsSBbzZBUujJJOyYbBXxdBbSUubBPqQtaATpsDOoyMmDHhknaAlXxmMxXoOsSCMTtLIiNnDAaswHDdDOodAJAyYyfWwFvVSsRSsNMmvkKAaKWwkzZOAaoVrZzRjJDlLYywWzcXxYjUBPEeMmvhHVCcpdDbKkZrRhsbNOodemMWzxXjKqbcGgCBbqmMuJGpPtTyhHYxXlLSsNKkrksSKRnpPgGEeZedYyDRmrcCRAkCcKoCclpLoOwWUuxXyCcDdYSOosiVvcQJbKuUFfkYyBMJjeGgfxXJjPpNnLpPQqOdDoVFfXtHhTsfSsFfNpopPOjAaoOxXCOoBCnNEepjgqKkQxRRrEPpeAqQarbbBBXOZPpWwkNnKOZKFfsSvVvVkQqbBHZxFmMcLGglhHeQqffFnPGgQdMmPxMmcCWwXlLNnGDdDdgzooYyyuKHoMmlfIZziOksSKoJiUuIjvKgeEpPpuUpPjJMLlmoKkvVSXxsnOozteEDdbGHrdQFPpcCfqPpDWwfFfyYyGuUGNnWiNnXUvVKkMbIiBmxXbSgGSsNnIjtTCiYyIcyYeENTtMHhLlFfgGDuUoOEeXjJyYakKPpvRykwjRrJRiIreVvcCcCEAaoxXOYzxmEAIWwiJjIrRHcZzqQCKkEehLjAaRpPRhHrirRIwNnQwJSsjWiIlLEKaWrRwxZzUPTJjZLlzXxyYeErGNPmgGuANnaLlUlRraABbIiLZUmMzZtTOooOkKoXwWxfFHQOozZmMqhJjQuUkKlCJcChTtAaRrHKrBbRTtEpPLlmiIVqgjxXJYyDgGJiHjJhQqcPpQqpKXxNiOoIeEvcXCcsSdDxHhuUxVHhvXRkKiuUIssSZiTtIzpYytsSajYGtLMxAaAadQqDrznNtaLlAWoOwbwWzZiIBcCGTtgsgBbGSHGgVUuvbBhCczdFfDaZixXkpPwHhpdDiCcIFfUXxbBMmFuUadbAlwWLWHhhAaoHhLrRlXSsxNnZIikKoOpZkKzimMXxvVVvbBlwJXJjgGxZfACcarRFhqQHIpPRyYRxoOXrrOoiuiIbBmffFArRUuyYaqmMgGQkLPpdRrYJmMjMmLlbBVvptSNndRrRrKSsIiTtIbBBbietSsgTTtqyYBuUbTtAabySZXuUbugkKGOfFpPzZPpRdDRfFfVkDdfFJjvnNnNfoOFBZeEzFWwcCYoiIsSOdDerRWwEZzvVTTmIiCcOoMloAaOLQJmGZzLcmMCloSsQbTtUuuUBwqQRZvCcpOXxmWwMwWIioPVuaTtrGduVYbByYxXyvBbCyYppTNnMkKsSVYaAYyymESsepjRrPpJmMuYDdyIiYyisPKktTJqcCeEiIiIQizAaZqwgGWBdbzJjZpJjKkpPRrYzaAzZcCEXxjJMmbBtHxXnNeuoOUeEgQZKwWsSOoEDQrRkKIUFCcxXYyMNwaoklIsSdDiLNuUnkKAamfFMlguUmhHgGLlMXxrsSRlLmMoMgGzZtTCzmMRSsiHMXxzeebBZwxXWPpSshvVhHHzRjJbBraAYyZlDwWeEvVYydgGqVvULEHhbBoOkKelpAWEewGgRrYGmMGhHguUdjJuUFfQgzZGYyFZeTXegGVRVfFwWvAiIWwUNMMmAwBbtRZSszZwhEePpRYLWdhuQqUeEeEyYXYDeEPpVIpsSnOLQqlllLLuUozZIvViNPeEDgqQpPBbqgjYGgCcjRrJKkUqQqQuIeEXjJKkZzGgmMpPGAaAzZdDlrRUuLIimMHZiIzaAFUugGNVMmvYyntaiVosSeWYywEYWwaAbtvVTQqCcwxXqQxXGiIkFfDdCHhfFcpPGJjCcrbBRNnPyYcZhHuRrojFaAfCcAapPmANQKknNqmesOoSbBEeSszZfqvVfkwrRWKFLlUuOpPXtEXjJnNxOEeJGGwvlFfEjjkKvVJyYNTcCBjFfqUgoOegzoFpDKDXdDxULxNXxnveWMRPprwYywTJjJSHhcCRaAwwwlyYBbgGIapAPsxXHwyKkedtnHhNcRISOoUQqQqcCQXxkVRGgDdrvcCugGzMVwJjUxXuWndzZpPBbzfFCKkOocgYyQMyxXhOBbrRvrxLlEXCcxhHeleNnPVBbqQoRHMmpEeAlZzayYALaGgPVvSsNxQTtioBbnckxsePpbFjJVgGtXxbBTvdDfLEPzSsZXLlEzhHZPrCcCccCjKkJRtFgGTjJVvteElsSLbBbvVsrRSnNBGgQvdKcprAuaAiIRrUQNnzZGgqfFuxXHhiIasSAHhfweEWMvwWltsvVlLLlSOCcKfEaARLiwWIciIqQCIiTWwdjJDgGLfbfFBGZOozgFPRrXrXiIxObBiIoVKJVvjTtkGgRrrRCcBbUuUSpLlAaxVvXlRrLixXJjIPRXMJCYyrRkjjJUcWwMrRUlcOJjoStbcCNndOopPDAarhHwQAMmaqWXxRUYvInbBNisSCSsSzOfEegGFcfFCuUtTXdDxIrRrNjJOoVvsLflLFrRTtiLlSdDIiscDpPdyjTtyYdoOYUuyyYDQqzyYumMUZtTbAaKCdYcsSzZniINsgiIGiIWTYykHhqQOoMmrReECNnczGgRTmMtEeBAaAtfnvHhHyOoYhVTnMiMmKxGJWOwWNzZzbisSrRHhRALdAaDxXZzlLKkEeVODdcCzZplLPoKcCkcCFfQUutBbTPRrpVRTlLLlQqWcwEetTTtKXxefFEBTZztjLlQqscPpCSnhTtFqQfBsSbpyRraMmBDwbBiIKCcgTtGerRGmlLMvYFfQqFguYVvsilLTtwWUOokFGuXjQqJgyYlzZLMmqDJjdZzVgwWTtoOSfFiNEeqQngmHhMLloYoOyukvlRrZKCcCdDQNnjmtDdhZUQvVqanNaAlDdTJqZzwFfWiPTcnNCkKJVvMmKsSGIFfzBnNYQfFYIrgMKkmpPGTIHhitTtNoLlONDIwWYyidwdDrHhxXRWQQWwqcsSkmPpdDMKNYeEMmyEeAaAtzsSiBwWGgbIJSsjTeMhHmEeXxcCkmAaMWwqGguzZclSsLCuGnNnNQXtTeENoYInNtTwgGNPpytTmHhMWRAYXGwTthHKkWslvHhxpaAPRMpTtZDIwWsKkKQVvoOInNKEekiQmpUBAaJhaAHLlbyubBAaUcJjgdydDeEIiYDxXFffCXgFfGYqQqQHhymMKkzZmiKHhfBuMrReEmcCoKoOksScuSCcZoOjJbBNfUuFYwXxNVJQqKDdLFoOflPpknmGsSVvPpOxSsfDUufRrTNnJjtKrZFfzRkaAufGQuUPmMYypPIkGgArFbBfPumBuHiiIfnWwNFFyYyKkJjcAampPDdMdCZppPSsQCcqLHuvuUfFXxZzgcZzhHhiuUoOhHAaOotyEeEeYMmlLTTCUuoOQqdlLklohCcSsSscCHrROLEfnEpcuZzUxXuUPpreELaxGPpgIiXoQVbSiITtAhHreiGZvVsrRFfiIYzZyhHSPpfuvVToFtTUjJGayYAGgbBhfMYQCctTUuFcCrRtBbrRLlnkCKYykaXxfqQOlLiIeEMVGTfFtEeWwrxlGgkPAayjfUSQqssNncCShHRJbBjeYBaHhwtTWAlqQMgdhHVkBbKDEeuUdvHhQqDNnrLDWwucrZzRWwomRrMmMGgKQdDgiPpfDdFjJDdIdDZMpTgvAigoaAOGdRpdDarIiuSlIiinNwJjmMAIieExXacCQqkKSsdIiCcjhbBjaAyikKIXxmzZIqXxyCRYnNrmMHhToOgjJciICiIOoZzLHeGgDdYyviIVAEZzvRrcdDCgGoOGUugVOuEtTeOOosFzDdxQFfqSsqZYyIiNaAnwWEnNePpwwRSsYAwoOWigRiSAVcCvbBArRJSGgGxNnXXxgoBbZEePpCcoTCUudoOUdlYEeyKkMmLiOnNPFfpTQLXxRrzYOoyZrpWwFqjJfFQVvfjJaWIibBenNEHhLlAaDpPFLayYqdDkKQeEeEGgNUunMyULheGgEgbrRSSTtjhHGDdgTtJNnjPzXxZpjlLJNlLQqnQqfzZwWSpIwLlWeEgHhJznAaNGgsdDatLgXqFWwxXFbfhOorRlLHJTtjTtAajgGGgISsKBxXnNbbBooOXezUzZRvUDQIHtNNrRmGgrROoZJvUuXEevVeEouUhvxMmpPXVQYpPyGDxXQnNqbBQqkKegdDEeGgKkGEbDdDdukFTtrRzZfKUwWtTEWJktbBHhyxjyYBbdXxEeuUylMFoFfkbBpkeYyQbBqEyYKBPpYmMBbfFjJyYPtTQqDdcUmTtBQhCaAfrtxXMWvKkKrCUlkKSThmWpIRJjyaAuqMmvVleEYYyEehkKHNDdxnNMvVZzmPFfJMoXvuiVsuzvYuUuLlEeCcoUuOobBYyOcRkBnNpSDJjZzDQqqteETpPwPpxJjXZzWsmbkKBwWbsZzSqczjJpPBRrTRDZzdrwiJjDdlauUAoOQqLsdDiEcCIJjiQqKHhudKdEJjKkeiIkdDKVvnNDreSJjqYyQSkKslSzZjJnIirrgQqSsOoFjibBWwIjJDEvAQFfcKTZwcGyYyPtTdDYUugGrIXxMwXxMpGrgGTAWJjBiIJhKkCcPpHIOoimMwWjaTtTtAYOwWonNrTwEeWtRSdzZDzVrRvUdBbznKocSFqQKkfBbsvJXxYvnNxEeXifxXvVeEFQoQqIitTIgGiOzZqoRgihpNzlLyYSsAaNFVvnvVOodQXLAxXadDlaAxrRtdDTtOjKDNDdEniINvdgRrGDNnVVvBHXXWFkKfwxpVvPmMdpGPpdxXrJjXBbxEtTaDdUDnFfyYNUuhuUHLlFOoAaooliPpSUKkRdEeaADJwQpvVUSXUuvkXxKqQrhHawVvzGgmJjpPzZTtFfGSTeuUyYEhInNiFSmqQcCdDMbBsfPpYwgGtTWyHCcgGXHhxtsZzpVpBUWwErItTiJjTvVtCcJoRrOoIijuUuUTjsjMmUdJFPytTiILSslziZzzlLPvIiVZTtNOmpqlLkKQUufgBuUPVNZUecKkyYoZjrRBbJIuKkjjJJLfFlkKSsZLTtSsEeuqqmMCDrGgtQaACcXxVVzZXxzZCKJjwWMjJZzmVQFftTqobznhHNeEtTnmMNeNBbnQdDUxaAHkyLmsXSyGgRryXxPJjlANLHhDdxOAsrRwVvWSPPjzAYyaWbBrXkKrNnQNnnKocCrgksaGSyYRyYrwWwtTezZZtTKVvkhbpPFnNsSDTtcCxXlLbBeVIpPqQGqULJMmzirdyYDTXEIiexnOoqTCQqcUcCurLWLlCcUcIsWwpuUPOfNWwwTxXMhHAdDbBapugTtwBbcCbBiieOoaAEIHamoiIOaARoviTogewWBDddemqYpPPpyjJKkKLlBriIVvGxGCXwWxgwAaPpqQPpdDnNnnNNDdxlLxRDJPpjArcCxXTJpPsSlLeEjXJLhHJHdkKUucSKmOTSsznBbtThHhczZHhCyNMmBPpDJRVvrOHaPONvkaAKbBrvVNqvVkKQuIiWUuwUBBXxcCbMJjVlLiSBEebsLrRFPtRDZjBXrRxYyEzZnPYymYKjJrRDdJKkOtTozZXcCqqQltMVvKkaCABYJjKkfUeuUoIDUEgsSBbGJMCSjeopBnqQNbPvVdAatxLlIiwUMeuUFfEBsOiAoOGsSklaSsNhrTgGgGtRoHXxcXRfFaNLyCiIcnJJjjNVvwkKAsAabQaAqwUMmsGXXbBRrUiItyYJhHjhFfxtXISsnrRNIrDZRrzjTtwWJFbwwWjQbcCDiIzaybgRriIGgpPeEsSpPcCyBbYAatwOGAaXZzZcvJEGBJjbExXRoOlXxLAtjJkAYyaAWdlDeJjEdhHCXAuYNzZzZRCuZDafFdDOoASZDOUupJjBqQbPibBGNqQwvMmVWYymYQqkIJjCuUFfHMpiVvYyIdnNDAeEwWaAjhHtCbBQqroOwwsSgXxOmXxmcRrOqNffOrNnRPoOpzlDDGSsuoOYLXxwOwhGgNlzZLuGDCcdpoODqQdWTVCcvwWtFkKPSbTaAVhHwzZaTotTfEefFFzLRrsSRruUkTYJdDYTgGUuCSxXsWHIzdBAnbBpPZNieXJNXxFJMUtZCgJjaTPpnCcNtbBczYKaAZBbPpzkKkGkKpPlLfFNnXWwlLxDdfFoQoOzZqjkdcbjCcUuJbwhYONbNXAfZHuVdXxPFxXtTfiIMkwWKWqIEcCmrRnWOMcCmoGZzaEeylnVvNnSsNoJKwWhzWwDdcpTtPLeaASHtTYZDdtzTEapfFPieSHhQAfJmCmMNLXxlnTtSrROrIiRovpPpMeEFVHhKkHhARrFfygAaGsdigkxIfQUuUyYYSkhVvKcCkMmiNnzZiIQPmMWWwrqQtTRDcYrRylUuYyLGMmEFHhLYRrcRrTFPPJPNntyBjJcCeEOVDdiInmMNvTMmNtSfXokbFfBIiQqaIgWWmNnuOovcjjfFvVJBbjRnrTRZzTijfFJQwlfGgqjGeEgeBcDxXCNnpMmFLmnVlsolLXHhbQqBErRUqdDgDdqQgZzlLFaAomMOAaaAZzpOIhHbeEqSsWSAnNHhBOexXRlLSMmsrOoAaEAaFcCYqQVvyfZzSqgnQZkKzqyYEIiCcHrZzRVpLNnlnKgGSHhFfbBskSdiIIooOOlKOgBRrbztToOSsuUuUZxmMXcCWwvdOMmXahHgGdDPpQqAwWqQxjJLGFfxrUnwWBPZzKukzttTJjTpOrkhHtsmMaANnRzTTyxXxHDeEPkWKpPMxQJbBzIiZkKgXDxXtzkKLqQPMrgrRPaApiEHheItBtTPpkcGSsEtKQqGgyYckKhmaAMxXQqwWEiWwJIiLHcChFIYwRcOooOCGgdBfFbXKpPkxNPSzkdDGCrRKWcCEFfRrcdSMmsbJcAaCjFXxpqQuUPeEgwrRWoPPTHZlbGHhhdAatwWTXZzOKPzfxXuUanFHrPzhTYuISnTOoTiIjJtJLlFfgZIizWYysShySJNwBbWSTIiGnMHRxmCXxCdAhBAxXViImEtoOguUYewWCGXxnNaAYPpkCKefEUueTKseEDdEogGOtvVfFYyTxXAwWOqQbBUdhiISzZwtDNnzmaAwOKDdAqQvpmMwWPBbifFIYoOAfFFLQqqyaMmCThtRTGgSdDsOoIDdiJjuUMmHuUhtoDVJjrFcmJKkCjJbBAFfkWPpPNaAntIrZzptjJTpwghshgIrRiokKfVhUudgiiRBbYRroOHoTtZLlbgGBjJNnHhwKkJRrVdVnNovFXxypEwPOoMgMmGbBlLXzZowWOxmWtvVTdDwgjJdDzmaAVYitdYtTHhVvfSaRKovoCiyPFfBQGGNnzlLXjqQwZzWQHhzZqJxxXiJXxaTCVPrRpKhCEeclgzZMmQveSaSrgGWOhciIuXxCctTUEkKghGYLUoFoOlLRhHIirWeXxOSyYQXNlWOwWDWdlqHjJhQTtgGoOxXTtegGvidDBbmMDdnXxbxdOoDXMmBCNngDdGnNiIZNnIcCiNyEyxXYTxvwWgkpPZzbBgEhQMoOIiLlQgUumXxufpWECSsOoRxLlkbUusHhSItTSWwfnDCJrEbBtTWRwbTRmMEoluJjCcUrBbRxTwnDMAoMmDCoOdNnLFfTtqBbBdDMuUmQgGYypIdDfFOvVRRrrEhJaXxXxbBiNnOvrRVrRabBhHAfrJcuUuUAaIiJKkjLlzZCZwnNAagLOvSZHhFfPpzsVDdtTpfFrRYyPhlLHAazZnOnJTaqmaAUuDdDxXvUMmuuUVvqQDDpPdnyHTuMIqQJSQqwWYybOoBwaDOoNMGOrRiIqsTfkjrRJtuvQzGjJASUubHmtgTtTfFCKkrRctfoOFGRfFERdVZQGyYICciDEoeElXxWjtTJMgOBbwljkliILFRmqQMGRrtSsSsPpEMNbEeUurRPBqQHxXoBkKkKbEexXLUUWwDdMmeHhEmTWwIHheiIaAaEJUNnbBtjJTHhrRumMjxVXFfCpPDnNfFdzBbZfFBWwZzbGrRxXrqGyYkKgWecrXxRVohHuoOMmYszNDoQqxlLDdyYYQefFECPilLLiAYfFQqlQATtgGoNyuUiZzICcYuPTGvXpPxBbqoCcfhEzZfdDGggoOlLKkllxAhHZzUjYywheElLlLSsSdoOfvVEeCcDkzQAoWmMgJNUtNtTYmMfFnNyjJpLdDeOopfofFeEAqCLuoRreZBHdlLuUCXxqfTAadDdAaWJAXxaGPpYcLFfCoCMmiIMHtqYxWcCjJnbXNncVwQquUiItTbeEBEeonNOYWUMmbBvCcmMlLUSzNwZZzzveEkEVMfJCwWkoOKPpVMxAaXwWeEzZRrNnmqcCdUDdOtPIKxXBRjmMPpxekmuJEvCcVoWaXMBbmrRAHhymwJJCcyYYkydDYqBtTYyVghEeCcHVlDTsdPNSsDdhHDUudrYafKksYybBQBbgFnNfGZzqUKkLhHBbPugGWqQepqgxXvFVvfynNvinYjyYJpPueEkldoORrBbUoRyYeETIbBxXJjivVtAJoOsbBTuYjJNnNnRrLeElaESOoSbBsfTzZtcCZDdriIyqQIifhvAaKsZkuUMmmzoJjVvVNUFfyKkknNCLFflQLhLlWDyAXxSuUEeDrRdsSsuWNWqgoOFfkDdKGiIKkEuUlHkjPTtUuGYaLlWwkObpyLlFchHvSsQCIiYnNKpSVvsAaHQiLyczoqgQqLyMmvVYuUyYTOoEheEmdclFfoOBlUuLLlMzVXJjpdDGwKkWghqQHHcChuIiPMmCEehGgfXnNQxXUBMUTtRpvVpmYyKkodxMbYSxpVjSKjJdKkCbBeUVIgnmUuQvVLlYyIihHzkUdDaAXBElLTUtTXxuIMmhRMrRYGXloqMmYgGyayYXHRUQaASHzRrzZfFKyBXxISJjRrSZnclvAiNOKCcCcctTtrRTdDkKCZgGLhOBbopIilNdVkxNfFjEYAaJFfjTtyZsjJnybNnrLqfhQKkqDYyKkyYxTtNQQqyYyYpCcJEeAvTtMiIieEnNQcOcNnUQmnNBAemsnEXxluJjHhlLoOBbjJrRjPpJcaAQOcTTzBuUMaAXxmgDoXxVNntTsjuBIizfFZAaAvVaLlbBgvHNnYNBOnbBaANFfoAabnSEeCkHcCbBpHGaJaSOOXxilLUdmMNStTUuDSsdiIgDCHpxspPFfWwvVFfCNglEWpKDdjJtlvbUuVPJiILlNmElEqaAPpJEXWCiXxMmIEVxLYiIyMmsmtTXxMiIvdVvZycCFfYzswEYyMiImnVGsgjBEeIVvIeIojGAabsvVSPwvVWGaHhCcIiAIQCXDbIiViIvrdzZqQAcCaOvgGfJZzdODdoOsFgKkZeEkDdKfFMYBwCcwBbGkxFUujEMfyZzYFnLdoHtThODlNZzpjJPyYjUJjuJMmsABbhHaQieEVvfJsOoFlLjTtJjQIQqKkeIiTFpucSsMXuLdGiSztnMiJfUuxXfoQfKJWwjNPteNTtuICcHSGKBbkgPpQqsvVkYJpTtrGvZKktNnuyYUTuVQqkFfKhWMHzZxaMmaqVvSvrSsPpjJNnXxxXSvpELbBHhRZREeYDDscCSsSEeEsxFcIfjJxOTvoOosjxXOoHhmunNLlhhHvWXxbARruUFmjULlYRHNhHhwLpZzCvVvHWcCJVLvVoOlZzVcCaSrRryYoCQQYquGFtTfxgigakKCLQpsNnRWwJEeOoJtBmMVcyhIZoONtTFAsCHmrDBhyMMutlnalLPIgGUuRtBmuGgGKkgGgUolvVUuLRrVJlLMmOGglyYrRpPBhHbLuUoWeuUIirZCqPKkafFtFfTSsSSIrRNniiIhJvRrYyWigADLVQVvsNyACcshxUuVAHEeUWwiIWvXysDFfdhCPCppQqbBPXfFSVGkCTfrRFgXxGtRtTrcfFgmDTtQqPcCYHVmMtTvDdiyxsSAaoOtkvZYbJrRgNcGdQUXLyYcNnVvryNyYnjzZJewAznpwpwWevVGgWHpOoykbBQZkYyNqQrvVtTJjgezZFAaXwSLyDdkjJKJkKRkKACVxcoORhdmMoOylHdlLDVBmdkDCqDdyYGWbXFZzfxzcNnwWCiIvXPAcjJkHJqhHmMxXTtOSsdhCfjdJjDDqIuRmPpPpHWcKvHtTwsIiWEetGBbflpsyIeEtllJBFfbYLqBhLlLAajlLkQxXdDpgjJFiTpDdPThWiyBGhVLUulZzgDIyYmMieijJURSlBBvVbjJbLtviLOVhHnNhMQqQvqQhOeytPSKeEksnOnqXxwKPpkcWbBHBbqQbARjnNkBbKVMvVaZRtaxvfqUlTjodDRurRgGuUBgxXMmoPkeHaUOnaAZzBbyXxEeYNOjTyGuMhDdcGjJaAghHufUvWwFCIepAAakmuVLxtKlLOXmMxqQGGXsStdDAaYnNlENITsjiIJntTcFDUmMIpyYvVIikqhHfkKJKkeEjJjOPYVnNvmpPcdWIBbjJGUNoeElqXxbPpBMjXEVbsSoOEGOexXEgeURdAaDiIjMKMmiIlheGgxXlAXErRKZjXuYvDXxJstOOMStXMQCatqhHzZQTXxoGLzdzZDrJMXxdTSrbpcmfCIieERcYySsaRpPhrRHQVMmxXiIFoyKBMKkdoQHAaXwdDiatTyYAIeodVvmzqQZMDBbAaUuUGUoOeDlAmgdDIiXxkOHhDVvUuobBOoyYOnTeEYnNmMqQLazrpqiOoIQgJGgtNGosLklLKEextwNlLSseZzEnAeEwGgcxjmundDgLWoRrrsOoSSHdHOxXXzXjJxMWksgGGYyyYgSnTQibGqwyDdMZYOjnNJooxqcaAnqAamXxbJHoOJjhcgDlGAahQbdDUXxuBLaIOITrQqFFgGfLlhIYiNdDlswkoQUpTAaMNuXnVkyjdwDuwWDdDdKWBqwQMdxrLmTyaAYnNiAOEUidQqepsSCeOytpsPbBAaKkpSPsmNnMLCcfFxzOxXovdaAqqQwYidkKuUDSLldDsUOYyoudJjDLlzrIiULhUnnuUduRfCjeEgljAaXMmxQHhqVLsSFhHRYrPGHhyZIunQkdayGJFWMINsBbiryYcfFwduhHUCnmfFhCGdeEDfKkKkaEoasSAaJbxudqRrRrKiYXSsanUJuUjuNPHBbpPaAIMmMmENpoOPnDUAceECbBrRlgyNAwWOLPpHhIitToOkRTzgRrGyMNOEXaPTyrROdSoSJATqxJGrRApaiDnNCGiZLlgEoxqvFfkqxsiaMmZkBSsbwWtLtSsdtBbRrTiIEtAerREaszZUuoDxXyxXKFpMmbjJjJEjJeDCWlYahHTuUjYdgjXDmdbbBYyXxWjRUOmnNMmgGMqxXVhrizkKjJZTfFyhQcswWgGRMmPIiAaDddqQYKsQzAaMmcyaAKXnNyFfIiYNotyERrKahyiPpfFddDOPpiSDdWjBtitTnMNnmQqEIcemMdvDdVcsSVaqkLlnluHKCcaAgXAWwNZznayYxJjfKXxilLIYyYytTDdswLhHBlLzoOqHZUIeOtTfMgqvdmmtAaTcGgrrVTtvuuUbuUdyYLrOoTmEeRYYyyoSZDdaeWwIiEAXxWYzBbZCZyyIGBbQjxXFfWBoBLIvukKNgGcCnaYyTJZvqWwQsEjTdrvpqDPuUpdQYYyNTMmazYEQeeAasSnmtTrRKkARrGrHhHYBbrRhHFpQrRCcoLTeVvEkxXdcyqQmMqQEprHGFIdRqMiNnqAawHzRBbruBbKoObLcUKMqzZPpqDLpFxYIjdmbqQTNnWsSwbcCBtiQmMHRnNrGgDdQDVBbBfUuIBlYvdjJfFVAalaAtZCQVvqfFtOocVUjeEJoyYVdDgYyyZkDQxXLtjJatFfeRIjMmVnNHhoOnXxbkEeKLlnfFQqjaqQbqcgHCgGwxlLdsxYDnuhPnNSFymnXjKJNnHvVhaheQqEnNHVSXxNAaQmMqhmTkKNKrMgOVtNSdGihKkHbDuUBAvNcuHhMdvVgGzrFiIfpCPohIJOVpPbFMJYfqQqScCIisqngobXxaoLlOAHGgIYQFFffHhdDRRfeENRPXxcCliIaARrmMDrRdoMmaestllLYFRrLlYpAamMiexXEVRvVrvWwOoPplBrUuJfUuiPpsDlKEuPpPfZzFICiIbPpBrRWjZbBdkKDJLljCDdINkbMmRPNFfGsSgBbnNNnMhHFcCPSFOOsaPpxXAvAVyYhHLlRBbrPOopvCFhOCcpHXWcGpXISwckEWRBBYjJybbLHfFhHKkhkKAyOYSsPHhDIYybuydoOWzZwJhyVLjfjHbNnBXIiUkKjjfTfFtoBAJjvVaNETcOWsfYdDrRfqjoCcuwWGcPNsCcSKbNvVVvEeKkKCUmnNpebDAwnZcCEujJTtrUsXPfAJMmIuUiJjKkFybBUuiQqzzZHUAatFyYpPIEwqqwrcCXXRrxjqaAJjDdoIicFUusAIAJNqQxcCBbhiYCxXFUfbqQBdDFuTaWyrUngvOHmMhbIeQiXlLuUThiFrRXMmzZAHMmsfFQXlvdDKBacCGwRkeENPbBsePNdfEeFgnIiSqFEatonysGmzOVjUXoWwlioSVLlKaSPpWwIfFisSTaAyyYxlLXodPcCpiUnaufUuFOSsGnInNTtQqHrSssSOEDduVqJsYpZVnNCkxFfXKRrSntUutfFTcaGhIiSOojDqjJDMcCNnkKfgGFmpPIVwWdrRNoOReEeEBhTylTLWxXVmQgGdtTicVvKkNQkxpSjlKkLrDiIZBLlZZzxTmWQNGgHJAhibiXxWwIBIHLRNnxXyYnQnNqZWkYeWxlXxYmHhPBHhPaUiIusSsmZRkKCcNnrsLworqQqJjQRKaYKqvMddndMmuCuoOXxMZqMUOKrXPpRgcdbpsfuoMmSdrtWBZzBXxbfTpPhFZWwEqpPRrQqpgXYBPLTtfrRPaqToRnNrRdDgkfoqOojqQVqOkNuyOrRJzhXTUCzuKbBjWwOqQonYnMKkmiOoGlBbjPqkZvSsVCntTIDuWABcYzZhWerRLmzPpBZzbsNsSnuRrugackCcKdDEgOtdDUOqRGgcBCSEVTCMykrRfmyYvsIRwvVWOochTWanNvZzxGGgYsSyvTtFfcCrpcpoOVvfLwWSeDLhSghzoOzEeZpUyYaGrRaxXarhNrrKlBenOUcbyNioOIzZbEiiIbURruBUuUHhuvKagkeEKcCGMZOJXxycxXWaiRrpPJjsvVpHhggdaYyrRWoPpcxwJjWgSFwoHYyCXZxTKTtAaoRwViIvtGcxWwvbjJIispYVqjUjJYyYcCyYUPdhaAlGgQqryzkKWwlLlkefqQEydfsSgGFNlvyOoYyqKkQhyoIivVukKcojhHrmMEeYymrjCcqaASaAKqykDoOalLYyeEvVgjJjaMXxsSLOsSoOPTGGiISnNuqQCPHaAhpEympiIiDIrpwuUNgDmfFMhJMnJjqQBOoNnbPwWBxLNnKqPHhCsSeZfKOEOoWeEwPmMpeoyYkFzEvVcpQklXbvVIhzZBbzHMmvVLlhZHipFfNmEejiIEeHmMdfFGnfOoFWPuZzURiAlLadWwIPMYecUUusYyggtpolPpmAJFfGvVABRrbdKYQkszZQqQJXxRMPpUMdDmuRJOCULSsTtlOYPpHrRYEeVHhLnfFSsDYJjeFNHhnEKKXxjJfnNlLFkLOoSsZYRLWwHDphHPpPKmMiIEekpuyjJwWZztTuJQvyPSQqjJBVZzXCgrRTiIWuUrOktXzfFxUCcuchOWfsGwvVJjWXCtGNngTOUkKuJbBjwADGGPmMSrRpPIEeAwCYjozRrmABbksSVzZpFfwWPbBdDIeBnYqQREBbertTBCAauoNEbLzeEZkRVvGgvgGVRrRnHRTtEeAMmAgAuEeLlPZEpPYyeHGsHLlldEslFrBbRPCPvVRVDdgFfXVAiIwiMmTtItHCqQriSVMFKYCcmctvAaDdefFscbCPprKBbkQLlouTiIoDdyYGeLlPpCAGgGUUSZMlEwHyCbasSwZzbBUdikKNrRczKQpJBLlbLgINyNqyYcCQOgGVSsvyYoJkUZBbcNVvKTSssStkYynutxHZBbjodpPDYGgcCUnKtToYyQvJQOFKGrOtQApFlMmpbyxGPxWGgwBZzbXuUQBbezeEftTHtxXoOFSjqNnQJsVvbwTGggGEeRDsOUdDeEFSPpPBzQqRxXrZDCGrxqbBIiQRkoOVvoHvVhumQzmoOUFfNncUDmMNqQDDmIiVhHQqQkyAkOWjJlSRmMrzMSApbpDdMyDdOsSoLXwEHhyKwzNvyYVrlajhnqAjhHJawMtXzbzdRJsPXKqnQqOoCIGgDqMvHhwlHhtLYtwWeEHJjJjbrnDviqQdMmQdJslLHoONngACTeMmEtTNscvzPySjQvqQUeovVlLRhytTYfFUuiNgoOoUANsSTtuItTJfFjDOYtvVWwsAkDdvsOILOxcCuxxlLXXJvQqWwoZMgSYNOTAefQsNGDnsSpEFfSpPpnvVsSWwKtTrWgAbkwpPWVLCcxqShaxfIHthHxhHIqEXxiBoVGNuRYwAtfiIcyIHXnjaiFfauUSfuUTtCLlODJjdrRPpUZzuXxPpQJxRhHWQQWEGgiIeeifTzcCaAZuUuhZIjnRINnirNJYfRrSsrRMmjFfaFpxAaSuRUezNWadtTBbBENzZnPMucjJkntTEeNkKDdnCCcchHBkXxnpCgUlKkBbCcLOJQFyFSwoCjJtnNenKkbOyYFdDJxjJXJIiuxhJFJlvYrRHjBbDYUBFfidpyoYaiIGglrOoweKCiIWEesjJiSsxPZzgCwxhXxPoHfcaVSogGfFGrZzRgoPpfspfmMmnaAprkKBKnnNiQqcwWzCcJwZzcipUektTLdmMXxsSSIFjAaRbLCAacIPyfFkAaJjKfyLTSsxXSEAsBbSOXxwWLpJtTMSsmjrhHDdnFrrTtqUuyiGgleELhBOGNtTfFQxTFeELliIftXQSsFyjjJmBbfBpPvoBbjiHODdrRpcPHhRZDCcbBmHPpAPpaAZzahUCnVmMabdBUuIgDAaaAsnJjTvoGmRkntNnMtTtTFfHHiIhpPnKkiIsvAqQjkVvJxNMYgGfEespHhHUNdyXuUbBSDXWcBbhGWwCQBAJHhNBNvWwJirzZMgGmETAiIoOTlMmqdKzYqHhQGvOuqdDQToOtvyYCTKvVoOklnNMmLczTLvDVyLZzbiFvVcChHblLvpPdqhmVvMqwWxXhHIWwBRrMDJiKhHksSyXfPldQQCcmkuRrClBkUZhWGgQQqImMfFmQrDifghRPegGYCDXxKZzvVtoSsOlOqPfqPpQyhzZRzZgaMNtyYTyOoYEEqeyapTEetFrjJRfeENnPAzAcCaZkRrKZAxXtGgnyPVRcCoOxXRrDtJeSVzZzjTttAQqUViijJIlSsOobPpObwJqgiYYPpzcywTtzsOrMttTRlhHPpDBUVvBbRRCfFMMDmMSsVQGmFWwoEiunNzYyhQdDiIZblkKMmWCcSgGstTSkFdDGkhULNbKkHDdhBRrKpPQAVvvCDmMECieNITuUbJwsIlLgGoDIYHAGgkeYTOnxkYCZqSkykpPVvKDpIjJirKkSCaAqGgHOoYAatIRHvZzQmMoAaurQqJNnwBDeEMdxJWwGDyJtFfAyLwcYydBbBPfsSKkNndHhDkYdJjcCOzsSZCcSTeDTRrlTKzAIBbkKSXQKVDeEdQXluULOeGmMzIgFfcJjdIGgAPagjXQeEtajsTtOsDojvVJoOYtpAxeonmYZtrKlxXVvwVvWoanYGLzAaZaBbudyYeiAanNoOhpAxyLlFfIkkKkKQDUXrRBjnNtTAOeAFgKkcHRrMNcDWCRISnJKkjimhHKkWwnNwfjyYgYADKhoOHqNUizYgpRyrXxflvZHhzJLGJcFrmMUDXxBtTbHhGgLlTtNNuHluRZdFmMflrRLDElLeeEIyIiWQDYyGgVPpOmdDyYMmMeFBbfEoZXlShHJjtTGgTYoaAEcPEYyDIueoapPIYytMKklRXfFDmqWQbwkacWwCELleArRcCCcmMUdWoODznyvVFHhfkKYNZJYKvNbBTtxUnmtPrRuoOqOPpKdDWSLDdEengGgCcyYGIyiHTtfMQvVjTtZzSsJqmRtioiAlcConNOqHgLmMdGCuUWwjpPBnNoOJjhHMQOoNCWgGZzwQFfXOLlyzmYWQgBIqKktxXNKXxwXxmZxohDhdDuUiIssfFbBSROwlhHGBhHbAaNUMJXyYCWaNwWeEnWTXlIiSnNOgnTEexXjGtbBTvVPRZAYypPQqlZzywWpPtXxUuNnNaAPpdwniINnNWoKGMaLdEugkKmMMMmmLluOEdDWTtxhqXxOgGDHhmybBYpPbkYOfvqeErfFAoOIIIFfiWwiiqQgGCrcFwWIiMCPBRsgPpgGGgWwGtQvVqDwWmjRdDZlgMlLcCmOrRAcqmxvVThHsmorRoTSHhjdVyPpUxJzkevVxaLEHLkmJruQqBvqQexKkzZJBbmsnNSsSQLOnugeEzZiKkwDqQCMlLypoAYEsSeyahHFlLWwbHhBQKvXxqQVPiFfudfCxbBXNpPJjStiUuneLFfyTxggokTXlvUMrKkRXxKaPEicfVwWuFUuUCCcQqnNHmUTtYdDyJJjjgYtJoouAhEKAapOGbUrOWwJtLWwuQwWFVXcCATrzAnNgGeESsmfFvyYJbNnBraFfuUweEWBhiIwCWwWeqQEQNjJoNpneENTOoiIYELloHkllLdDLaAKVqoOdDmHvosuUSlIVTstuUTSsruIiIEsSPpbBdGvHgbYIwHttIWwsSfiIGPoOqQqKZzJbBfFCzSnNsZclHbQlyjOBboLLTixPpcCdDsSXYSYkKyPLFgDEeTtdTwIiSpPWhxXVkCwhOoMrnNUOoilLQdJFcHDGgoAjJtTarRQjhamMAKCapeEvVhHxVZBlLwgQAacLlyrLlRYdKDWwMbvEevYyQqVhLYDHrCXvcMdrRDmaryYjxnNXPfFLlpYlseEWdDxHXxhRrgGfEGtTVvxXRZzkKnKWEewzyYqlUuLKYPhNnDdwJjUcCuEPqQWPNZaPpWEWwYKGgkRktTKClxuqKkDgCnGfNnFXdDxjByzVKzZbGgBVvTXYImMhypCHhckKHhdWxXwMGKgvsiZzIxIifYyFPcpcKkZuUzHLHhlSttTfFjJTYxtTVlLwuhTtavXHULldDuXxhHSaYnrCcRSgGqvldaGIJjKkwOoVjFVvfVvHcRrCZzuUsJjQqsnBPBpPbpGgbXxNvKvVkmMVmMAMuUmpQczREwhHUujFfvxXOYyhHMCcuUbqhHBbQTrTQqtipAGgNLTUKkMmmDdfdDFmPpYHbdRMhcSafnziHxXYCvfFbTjCIicNnDrRyHhYdjrSPqlcGgAGIGaAXTtgUQyqqcORsAvsSMEOoemveAaEjlLWwwJjhVcPloOWHnhraAyuJsSMfzZaWwBBbwAQqaVHUMRrJoOSORrCgGWwcCcVtoXFREerirlLjJRCfXcCSedEebBdFfySsrWwObBozaArSsIilePWwwWVsRVFQqfsQAkoOKcCeEAXAabBmMhmwNnHvUzVgROFTtnNTtUufoHhUXxuPjyKhVviLlUnXxZzETpnCcIikFqwWONnAaFFjImNTZsuUIgnNDlUxmORrHhoCpPTtUPftiIEMxXmxXilLqKkJZzfSjFQqIqSmeJyYYyfXKZzGCcggBbWWpPOobTtymNntJjTyYWDdwzzZGfSoDVeeEEaAnNvjFWwfhHFVoDRBdxUucqigiIpgGBgvVwjJWJOFfiEjvVJiibJGgJjZqzZQrRIizGSEegvoONeWSTtDVSvSJjsVlXvecwxFfbBvVejUJjudDLlgGdDQeLXmMxFfeMnfFjpvgCcGeEBPCcpgGVLTzZkPweLGnIUuiaAcSXyYaAPLuUlhcdxXGsnDuISsoosAGgjKkAgMmhPhWryYRwKUkgGKucsyhAaqmMQVwWqQmMGFfbUSsJjJSvOdGmOojJXxNnMbZttsSCoqbBtlLTqQWwCtxXTULeNSMEvVabMqPpuCoCqRrImVaZzjiIPqnXYydlLHFQlSsREetQqjJmMWwTBaAJjYNSzexUuVvDGmMgHhdXJBbpDAgGadzZPnXKvDnFkKoOfLPbBHlqQzkoUuorROnIaVLCNzsmMcCUubBsVvibYkZXMmbLWwkKlcCBxhsrkKRqxXuMJjVvmrhxnNAYyYyQOLxrRgyzqQZRrmrHiMmtefFbxFfuKZvujJUVqMNGivuYyEPpcnpVFfvPNTWwFftDkEesJvPSsXsyvVZzBGgpPmXDOMPmTtMPUuKkrBboqQOORXxrouXxmbuqxFmMcCHcuUpUGzZFfIigSsPQqxvZiImdqQoODtTTtbkKpPLCDKQqkkaAKMHetyYlGPpQOZeECNnfGgFhHqQYlIqSshcWnNwCPkycqVCfzspPSZpPYPBoKAygnNpRrJKHhhLeHhHuUhGgQwnwKkSSszZsUaYyYdeVvEVvwHXxlWDdwqcKWwYunFfvOZMKzSkVHFNnYRzkKFsenNhOoHeEAyZJjzUNntpPSjaoOrOumMDZzLtTKUyNqQIUuVUuszkKZSSsYVGQKkPEPpwcCUpluSFgGAyRqgGsSQdDDUuQqdIinpDStdLyYfFvWwGBbvbcCQFfKxkKXVvyjjWMaAYkKOodDcCsSaNnxAwODderReEUunNjUMKEXJIiYyrbtzZTkipTXxouoODQaAnSsPpWwyKkYpPNvcjFPpkKmvrRyYeKVWndDOoXxZyYYysuaAvVVuwqDdQXxmMyWvCxzZBcCHhNwXSsyQTjJhmcZzOclCyDdPpvVgjlLEeEzZgYyJNnDXxdjyOHhoYXxGeYywDtFyLlYQcDnNhbzpPEOUlCcEecQaOFPEzmMXxZlPSsmgpPGuUMmMnTunjGEewOAMmagGawWUuqTtZOoKdFfFDsHWJxXuaXLLGFeHNVeEvnFOQVgkKtpUUuyYnOoOaoOqLyaIlUuIpcqcCvVyQqXaOoAOdnZSyUPpOvCPpEwQRgvtTVcjJxvXxXuUJjeAEitMcCuulOhHhCcbphHCcBnuUmeOeEoQqTgrQqbByYDdLlLRrlWwWweELlfKJLWoKkgGGNnBFfNyYnbmnxXNwTtLoOOedhHmmMMggQqCPpcCcGqzvDrerRrFfsSbBTMJjhBsaSstBbTgMGLlgmbBPlLpZqVoOUTWHCcLlhwKjJFtSjJQqQxXfFXxIiogmnyYdAWbFfBpPQqhHsjlLimUtdDhqQYNdVdMQWwAtNnjNoNPpolJjGWzbBEsSejRFrRlLaAwWdAdDaDoIAjHemMoiPqcCnNnNbJjBbnwWNQpPlDLlcYycCdOBoObamdgBqQbGRrQTtGgqpPNWtXLOenNrOKkotBWriIEEeewgGeRQqjsiIScdNFIivoOViIsiSsjJElLeBKVvXrqQlLcebBwPFUMGqtTtcCTmqHeGZzKmMmMGIiMmVSsVuUvhHkYyKXtTteYcCnKkzzZUuCcCccNNyYRmmMMeErnMmyYHhIUuVWwEfFIicCwWwWToOtbwyYWBLbBDwImMsSidoMmwwWDdLnMmhHxqsoPpEwmSsMfyYOulygHGeCclLPpFfCHeEzZlLowRuUsAstTvVEpPVqLqQlGLHkTtvctAwWjQeEqIZguUgqaAbFfqOoQyMmYSspYIcOVOkrKkRrAsFyYyDTIyhHvMZGpLlWyYkKQuUqbYyBePHhoQqOYfVOvDvjWYyTtLllLxhHoQqOXzOhHdDXxhyrIIGDPpXxHvjrWZzwRJFOGffFZzCcWwFAaHUuSHGWPbBPRZziOoTtIiGgTtWwTegdDGETtjJpwKacUuXxIifFjMCfPpRvXxdlLOTtxXrTyYDwsSWdiIHtUucAZzYQXxlfayYyJjVwWhHasSkoWIiMgGAaZdoOTsSDtTqQLldWNNnnaAsHDuoaNuIYyiUneSTtktFVvEwWkKsrRSkQoOqdKkDBbcudDUcCKygNncEyVvGTgGeYyUuMvWwavVbHJGMmgjaDzZHhwWccMXLIilnDdNqQqQrhVviImNgdDOotsaTtfFfFAwWnjsDdHhYHmMwGjtbBNsUuiUycCiItNnHZpRXxhjJfnNNAFZpkoxBbBbDHmjJuUEeQqMgLlBLHxXhhHrRzDeCoOcQsSqEdhLXxlrUuRtVvrRpEMmefvVFpOGfgTtWwUuUuHhGLlaAJjBuUDCewkcgJJxXDdyYjjKZspnDcPpCrKkWyifpPOocCFfljIHHhUuUuhcCeawWAAanNHCkTegCKPpbOoTvVGTtRmpTtgGlZTdxGgGgGjqXmkwKpgGEedlLhsmMSbrRBXiIlLPpYttZrSTKRSsoPOoxXhyYHEeOoZKZzbBNnUkuUpbNKPpkuRXHnNhglZzoeEMmDVGokLtTinrRYymMNncCNDsNPvhnNeQqNGQGgaVvAsMhyYHmNnNnobwWagGsUunNVvwjJQPpGyYXxgBikKoPfGxlLXGCcQeEueTKktfFrRxEHnNheOSLRrFhHfvNMlfIxXiuUGgPckgGKPkKprRgyYGtTdCbEAaOqHMmiAarRIhIiaAQoJIiHhQFLWqIKktxXRnNVgGJjvlLGgrrxXtRNrJVvfqQFYyeEJfdDFCUuVUMwwGiAKOuUxFiIWwqQsTnYytobCccCBGgsSZzbSsiIYTNnpjppftwWCylOofegCdRrwpqoOIHKsyuqFFfkKifFVvOeEoOopPXxXKhHGIoODcCSgGNWwnrFMmfhHRYavBAabmMfmPVtTsyIiYcIiMjrRDBfFbdFtTOokKsSasSqVvkKGgsnNEIAdDetsbBOocClLSZMmhLlhHHTzDdyFfoOhsEHhlCZHkYCcLlyqQvVZzjOLPpYAUugwWwNMeiQwmPppDvUhzfFFXxMmaxnBnaAoyCcHWBBCDKkaEcCuUeKkhHAKJqQWwOZzGgEeEBzZpPiWpPwIbecCgKkyZxXCtTAGoOczTQquCcmZGgzjfnjxjJZzEIKknNfFuUnXqhHTtQRqQrxzNabSsDZihwctyjyKktKSslZDdOtdDWVvvtBspfiIwpPNnPEeQqgUkKnHWMmoWOolyUZkKzZzTtgdDddLZouUFuUKkFnPiIpNntJjTQoCMMUuoqBgGqQKkbQGJjWWRwWcTYysdDSJafFZrRXxzPmnNhwWVvNncOoFfiKECJjDdceoOyquUQMngLlKwCcWkgGIodzBbsdzUcrbBnWpPNQqnwyUaxWMmwcmMLDwasdNnDNbBnRrSKTareaADdgetTjVCzxgoWTkKgGaFRrfAGBeEBbmyTtYTtlLQqBCcXxcCcKmbBMkmMCbwWKkrRrRYRryMbBYAZdNnBqqQPpXIixJWBfdIiRiUuikKxTqQsMmnNSXHiITuFGgfxbBxgSfFDduWBSaPpWfFrRYHhyPpbBYlnArmMxCgGAkKqQahOHnAXXxxAaLKgsSBbamMgGsSvVxXSsUMmuWWsSqQdDsSwtOohHTwIokKSbBSuUsbpPmEqQeuWGgXqQTUuBbDOBbHhpSzZsAaPElFfcCXxLhHjJJscmKkjnLFDWwdRrflNeudQqiOdiIbBDVvEjzZlLJLluIizZFybtKkTaRSsrcGtTgAmTLHhQxHhOojYeEykbByMpNebJsSzdrTpMmarNnRAflGgLlMmEewVvWIvQqrRmbQqckKCcsSCnNnuURVnRpProiIpJjAhoKqQkjdbnYHNZJjtoMkFfsCJjDhjdKqQGLlgDDbBPdYyDpddkDVNnvJsSFfiIjlqvVQjxDdbfFBtRaJeEjdrXXYyGgZzWCcUueEGcgXLlgKkRbkHhYEeyQMIiEcCDbwWMmbXxBEGMmLDdllLOtdDiIBbdDIVpfFQqCcPOsSyNnYPpftnNTuUFrMAiIhIWGUPKkmXxtWnFIioSiCnNuwlRtQgGNtYyXnNxRWvVwIZjtTBbluQfFuCBbZzcUPpgieEOovzZtTAaDdEdVvfKkFfkKBHzEWsgASKeKkEGROkNqRxHxXhBbRwzcCyYuUMmZZJvGcCFfioOIgnNVpppgGGPmMpgOoPTHhtWwaAalLyYoiIXlJjnjJaeXxEDdLpYVvYgGsxnNSEIieoOIiMtTlfFVvYcCKNnhXuqEZBObBvMHhmkcMmzZIiWwFfvOovqjqQJtTTqeEQRdcJjmMQQUDdTtlzUbBijyYvVJkKzPpOaACEuznvpRBbrBbbBxpPXwWbxXGFfFZgGhHzPMocCAanzOopEeciICZvVkKIZbBYpfjDVvuJSJbBtUuJRrOjKkIiRuaAUeubBbKkPboOECceBSsvmMZhHzPgFfeExXMZWAZzIiRoOwWXxVxsaAwWuPqWXxNngGjfFTtrusILeEOOzZeEYQqtwWTTtyfBQqbBbDRVvrVvdxeEXduAIieRDgRrPDRKkBZzbrTusSUtXmMEexxhzZbtSsTUuKkenQqdkJohHlLQqVvIiTZzqlGHhgLDKkNfnZnxXPIiKkHWwIGSsrOIVyjIiVCOkjJNZsSQqDuZsybrRwajJtRBbghHPmWpPmibBNnRTtIigGypYBbhQqHJjgNPDdpnCwWWztkiZzIYypPwWCMwWmqaVAIiwWaedsSJiIfnNGqQsSWwGgRRjJpPsSNyYshHLsERXDdxnNDCcdDdOokDUCcxXkUuZzenNISxXIWeEtXxbZuUxXaDdACQBOouBbUMSwOwWoWQYyioOIlLdydDYdsKkPosSObKKkbBrCUxXosSOyyBbSsYMqQmgGVVviIZUSvSQqsIUVFfFsSfxOmeEfTtQqoOFyiNnITtIiYhHPpjpcCXNnCcnhyYtTOoeEqQHjJhHynPpUusPpSHhNLQUYriOoPwMHYyvPpVFftsLucrkKRHSsEehRhHiIkZzVwmTRFxXcHqtTbMuCDvVdaApfDdXxFyUuVvbPKKkOfmLYeEeEDdRrDJXYQqTdDKMmpXXxxPfUuFGgmCuUcahHAMjwelLvAaVXxOorRnSscCEeNlLHhBdgYyCpPckKjJqHOtTLlTpPtxVKkjzbBMeEnRrnThiqTtduVMmruZzrRZExOEsSathHTVvAekXxiJhJjrRHmMFoOBfdDfqQQxGljJTAmMSbiIDQqdkKBbBfFZjGaAiPgGGxXLlPpXxgsTVvtVftTCcAaFvFBbyYJsgGaAsBGqQqQRrHlfJjtTKkFRpPSsrzZuSsKkYRrxXyYHhwWmAleEfdrzZRNPpnwpPAPPpRliHhIqtotTIlKlLIilLtTkSCctaATxPpXtTfFlLsLFfFfFfDuDctvVVKkvmMOzUNnuQqOzZsbBnNjSsamMasIrGIayrtTWWzQXZTtfSooOUJjoehHaEhgGlGrRtRyrcYEekKQEeBbkKiOoMYHJjhJcRrHhCNnjJHJBbDWJjCcILBblLsNnkKKkUfFRATtPWwxXrDgqAOoaBbQGHDdYyhIaUuVxXGtPmzfFGkmMKqSjJskxXIiTtSDdwWsmqQDdBbblLpPlLBMAaPpOaAuUFpPfCUXxdjJlRVXTtxvnCcNnNaAWwNnGgGmLIVbBvxPpXihHlLbUuzZyXPpxEDwWdrTlKtTkLLZzltuFCeWwEcrHhRJTtYtdDwWnNpPzZwDdWTsEeSmMpQKkqKLXRgvmBgGFfboFAcsSGgoOuUKgGNTfqEeySsmFhxXXkKxiIHHiLlIHhNngMmpPufLUulOtjJUFWwYybBIiaLlAitTPpIzlLgIQqERMmaJjsBNnbBvYyqODYydCdDQqjXxJcJjAVvIiuUlRyYCPfFeNFeKnCbVvBcjJNcxXcCCDnBbNctkKNnIaZzAHCGRwWrVmMUWwaAhlORroPzwWcVvDCnZlLzNYfHVvhHhEefFiIJzZjaAgGIhUEuUepPbMbBUzjJcqQCBbkKZjJpRmBbMaKSsiRrmmMMpQqqrRgFUDddhHDFdFXogqQMtTVvaANhaAPpdlLDXKkxEeTtmMHuUjqUuQvnWyHhThHtnzZzsnNUCUuOUbdDFkIRrMtTxccCiIxXFdDsRrSjRrJGrRCJjYBCxXkKcSsVvfFjbXxuzZuUcCPMOoqqrRkoGgPpOSidzPvVWwPpqQmrhHNWYyPVIivpnNwnXVLSgxeErRyavVsSrGoOgcCwYnWiylLkKOnUuxkKqQqFfPpvdDPBbpVxXRrbBgVsSvzWwZUsXydDYxSiIRreEUpPhHQKEtMIibAHhbBcrRCaBmJIicCBbjZTNnanhzZHYyCvVkKqnnRibByqwoOWKkSsybZBCcbVvRnNrVvMmigwWsSkopPOjLcCsjJSXxltpoOPpgaKkAGPpGgIXgGxQHhjtLARruzHyqQYTMCcJeESsGgqcFfdDNnkxXUuzLVpPzZKUOGIsGlLYynNYyvNnVvQGsSxUUutTPpgfKuMmISyUGtTjJQqfIiyQqVgdbBDEkbCcaAzZBWdbAYPxXlKkGgyoOYLZSszJjHNWwSQaAqsAaJFfbkbBWCwtrvTtWwjJtTqDdZNnzvkKluUarSjwWJsTtJjZzPMmsSpIBZnoAaLlwkKuUjgXkOoXhKkHPpxCcIiImFfNtNFFfkSsxXgGVvCeEJjRrBbJkKoOjcKVvXxTPpabDdDNgVvGLlndrZdDuQqUEeuUXxKtwFfUuZzSnNvVCzZyDcYyRrdDkBZJiIjzzGMmgPpaAZJYenNfFBOoTtbECIlwWnNSBPpxVvXbnRicCMmvVLlInNizhHZqQDmMdoZssScVxXyuBTsqQEesJjAahHSCLuZzmmMWwCVvJORrJjojulLJuHoOhUKYRnWwNxXryrRcjmUbBuxHhkKDdrsucnNCKeZzEkEtTeeEfFvbBXxRrRtXxTxplRrobBbBORrfFtWHLlLlhJjNnwlbCcpNnkKuZzUPNnBreFkosYyEesSWwSTLVvVmwWFLlcCUaRPtTCksSDVSswWqfTpexMkRrKmsSkuUrRKpqUhHuBbWwtTZzQelblLBBESmMXDdKCNOIqzZXnSshraAOvpEjJLXRVorRHHwZzOoNSsnWhdDqQlLgGBbmMuUGgbBSsYmqoOoOGCcZvVDNvgGmZGgUKqDyYdusirCTDAaEYWhTtlLSZzAkKivaAmMVqQFfLWvlLPpvaAVVmMPpWINntTwWiWrsjnrDdYyRuUgGFfGgtTNtWzZiiIIWfFBbbBmFfYmMywNnEVXlunNaXYyxsSAdkdPftTOZsSGVvNpPnSsEjJGuQrRJbYytnAaJeLVcCWghHamMvVYyAabBAgjoaAefFTxvVtTojJQtTFfFEMEeGgnEeaMJCcjSsHhoOJOUhHaAzCpsSfFgQiIqKsSgeEWyoObBYIiBaAHhXxbuOxPpXoUBsSyOfQquUFjoOJvcCoOuUIvVATfhOoagxiyUulLJGtTQGjJdpHcChPivdHtTyYhoiaAIOmBbMymvVMxHDLlQqwdDlyrhHHWzrqQVvNntzZPpToOGgTxXUuWaxNcCpPLlVvnTtXJjmvVnuarvhiIPpHExqQtEzfuUgGquUDgyErmMReaBbPEeRrYyAauQRrLzELlEeEZmhIoOsSrZhHcmUuOAauYyUKkPPppvFfeEVQqGcCLKKkKkZzOAlLWnmSszZkKftTuBbiGgqdekzqGCcbZYyTtzsSAahHBEqpPQhTeWwUuMmeEoOIiZbByDdmMPBPpkKPpuSsGgUDVvEeJjhHbQZmMzIjTtpSIUPMvmtrRPIipPPcgGSsZzUWwDgOxdDXoRAUzrTcLldDCtGgWqOkmMKVwWvfFgsShKkHrRMnNKkAaPGgpZzjwYjJyWqttlLLlbBaAOoDdwWZzyfGoOCaMmAcgrRiOsSfFoIbGgVsSKvFrYyrDdaATtKkoSsUPMmsSpBeExzCcIiVvsgGYGtTgBhHQtlaAkKLAfFatTGTEksgGSLlnNDsTSsWwdDvLlVUuPyDdDuUlbBKbBFbBMUrRHhfFtTpPBbzYyXxpPjbEeBYyWLjJeNnOoviIVEWwZzFfXxIPzgGdDagGIiAOZzHwVvMmaBDAMmQqfBbuwWPWYkKOogGPpyKKkBRruUwWbAaeEIzAZEebHhrRQqTfFtBTZACjJcaloOLRcDdrRKkChHXppPPmlTgyNnJTtCUucAnNTtDzqQZdBCwWckKbTCcPqQqQSryTtUuiEeIYCEeuUNnVeEieEeEInXxkJjPOXxoiICRrIjdIigGMHoOhmxLlbLlBXmMGQvjJMgGeRkkKKiIrPFfpkjcLZzQqcCBLYylEebqOuzrROoMpnhUuHgRDdbtTBtkKpuYDdjJwWyXiIWPpOodDuUwAkelLeEqWriOIioIiIJWwKbBtBUuqQtTreERwWzZboOTqmMQbBeEklNnkKmMtToaAOiaOoecCLWwlMlDdpPcCLXZSsyWKjJdDdDIiYrVBbAGgxuUoOMmSsUusSdmnJisBhHqQUPJjpuqQuyYxcCIavVAwkKsRrSggYAaZzFnNRhsWwtPpTLlSBbgBCcIigGYyTzZZNUupPOEVvebdDvVBPGunNUkVFTtfFnWFfwNyYLZzOhkUvVYYyiIOqQbBOMmZZMmzLlqQpDqTtTtpNpOosScCPrRsSFjSsiIYtTyJqQEjJzZDqGgQdCfXzhkKPzZpblLiIwpPHhZzCvVSschHzZhHWBzozmSPpsMoGNnnNJPuUxXlLczZbcpPyYAaiIJiISsQdDrRuZzUiIZzqPnFFfSxvzKkZlSsYxgGXycCFKrRktTEfFmAaiIKkjzZqClLceYneENycCiIECIlPLKklLOaMUDdurEmMrRRrzMLllLbnNBmKkgSsjFfnNnNQqUQEeBBBbbwWvsSVCcQkzZMKkmDiIdPVvpJoOGgZsSJtTjsivVZzISwXKknNuUxNnEwWJjIMcCmqQimMMmKkoODnBWwzZlvVLOoSEeikKeEIJjHHhsEeSnNzxXuyYJyCjJZdwWvVbBPvVpqQnratYHDdhyTgMtTVvmGAJxXjPNnpYdFhHfcCsSsSYyiIDajHhTtUuWwCQkKqcRrnNaSshWjJSNZzndBblRrbBmzZcDdXyLlYxLNLlRnNzZrKIipPddDVvEeYtTrRGgZzoSsjuUbqQXxIPpBbiglxsxXIpVvvVPTWrRwpPJxeEXVvNnxjJlTtRrToODdqQtDdsSLtkmPpxFIiFpPYoTtcCIiLeElMmxPgGptSOgGtqQGgyYiKPpCTQWwLlqtYycEhHfBbCcIilLGsSgODsoOSsFfSIlLcCSsnNGgwPpaALGglEqgHzZhruDdmJSnNwWExEeXNndlGMmhRQKAakjJVvkaoOZzjJcPpkKCAachHCbBExXpPpiEhHOoMmNngXxGMmLiyYPpIwjygXxGJBiIbzZIrRvRwpPYyDJjvVRxHpPHXxxXuUFfGhHEeUuOPpolLLaHpvVPEfKkFNROVvCiIcLlcCCJVbyYgGTtFftTGzZkKHRrPpEDdBhHbylDWdDYLlfvVFZnrRNRrQWizHOoKkhNnrIiGgRYLljVxOgGImDdkrLlRIjZDKyYnNkzZriIBAuUhpPfFHanuUqhuXxLlEeMmpcCwAaOosSzZmMgGwwWtTYyeERrFkKOSYyHhTRrNRjqQQqpNrHqQhkKRgGygGwtTidkkDdBbcHhCKJXMIimeEgXxXSspzjJuvxXZzoOhHTJjYhaAFtTqQHhfzZpPzaAcBABVDhgGIimMDKkeEmMdblLXObBaAUCczZzAaSJjstTmMGNnMvEwAQqnNKkagEegqQGPpDWwBXxbPpGvVcDUudZWOvVwWznDdNdXQrpPgGIrQHhqRxXcEemmMMsSpuUwOIioEeLLSsIiRrRrRreEtxQLUYypPjkKJmMulIMTQQhHgGLcChzZsSTBbaAtTxijCviINnVdSXfNeEKJCcjkntTaAajTiIMukjJFZzCVvjJcVPpvWlLbBnRuUrAaNwGqBiIAeeEHhmcuUCrRlMHhNuUlJlTtLBVvmpNmMlLnPjJkKIijTxXfFWwtOZIzaAZnoTtOswdVLlvnxXNJjNnPpnNDMsgISyYKEeOoHhohHODqrWQxiIXqdDJBODJjdyEeZftTFXaAfFwkKXxoOqQhHWmMxfAlLajuXxyuUYsSYyrREeUjJZmMGgNnzHhOjGVveEJxXjsSCDDddcgxXINmMYFVvfbPNlLnvVFfHhpsMmSHIfVvmcCMfNoOnyZzYSMYyAhCEeTtEePpLsDsBgmGgMAkekKEtTIplLbBeUxXUbByYuJjLlOoOoseEmMYybBTtkKkVPpPlVvhHLltqQgNnHIViIHhvDdJjOfFFTnNUudDtWECcohHCcAaEegGAdUuDJwywrRsvVeESWfFxXYOohkkKKJgoOGaABtdLlWoOFfaNnATGYdDygrRUuCclLNnPqQpaAmMOrRfyjmTIiteEgCTtcDdGrcxKUbBIIkKiiukTEeKaAgxXGjJlUuLfFkFpPUtTZeSsjkKJrRQqpPvVHsSrRsSVYyQqMmGgZHwWBbhEezvtEQqEeecCTiFaGWwYTtopFkrpOoPFfPYypoOuQqwSsWZzUlLRxXKeEZxXkRSuKkxwaAWPpmABbsOoDKFsSaAJjJvVjdDkkKPRrVFfvpolGglaAXegGExpPLuUoXTBVvNnXxfJmMmSFfVfhHFPphHYvVyvIisYuUyaCcykFOoHhGXtnNTcCxlafnyKDikfFAwiSsIWrRtTaPpKIdoOTtDMDAlLaHhMmdFjogGlLOrRjVvHhrRsSfPpwWlLcfFCGcTtMCcmEexXrdPfFUupoOTtlfBfvrLdDFwWflQsSaAsSIiBlqQyhHAaYWwydDfiIGHhgWfvVFPnNpwpPNneEGZzToOvVYyaAoDtonQZzqvVNSsOTdoLMPpyYqQAamHhGpPgWwOocCMLUOoSCcnbzZBJjHztPpvVhGgHSbHOipHGghbxXBPkKIodDICVvcEekKsiGfFBOzSMIimeIiEfFsutTUQAaPkKUqQgGlLHhuoOmAajRrMmXxKzZVpPvQyiIUuXxJxXDdTtVGgYQbuUBmMJfpPuUQqDdFsyaQqIfFvvrRgGFkKkMTttTmMCcIgkKGomMtDdWwpPHjFfJhGgoLpAaUdDTLlniInNoBbkKOerSsyYmofFOxWwXarRrRVPpbBpEiBbCckAaEkyYHkEecoOUtOprRbdrZeJmXjrVzZvRJCcRBbOJzZjoxXyZIizpnvVlLuUCSSsQeGDdaASwJzZjpmrRMPiTtvRYDLbCSsFvVmMffiIFrRkKQqNneEEfFPperRVHUueTQsSAfarRraeEQpPqbBkKQuuUTtFAaffiIeoGJjwNnWHoOaWwAhQqvVOoWyYpweEcCapPAhHOoNgGnvVWPVvJjwgdNnrRbBDqQiIxVTtoTCvYyxUuXcCkKrRbBOlLDUuVvhNCcnYyvVZzncCNBTtAalzZYyLlLhjzAdDafFZJjJpDduUPleEvpPVUYiIrXsSxsPpSlLrRZzhHLmMltTaqQvXcfFFfWAabEsSUuoVvaodekKEAamMaKjJkAKkUuDuUWwcwWZzCOZKHhkqDdQqrRGgFfQSssSavrxrRsgGgGyYSmXxcKkCMkKjJSkcvVqAaEQQqDdpLliIPCcZzqQqLlnAiIadDNKkeEVHOoKkkKKWwkMmFfbbBBytZzYPbJjkuUKoOzZkKyQSQTtHhquJjfFUhHlLyPXpnNOCnZzuiUnNRruEJjeustTSEeXopKkHhPOxrlLzoOlhAaGgHLZuULIeErJpXxPJNndjxXJfpPJzsSRrqbNtTnkKRfuhzZUubBZzcDJjgRJKXxuJjNneEyYNnUDdgQqLllIFfihHQqLWAaTgGJjkKrvVjOoTEcCeEyYFfVvSsxXHhMmSfFzZJGRrgJjjPegGEPppsmMMmMLlUuNnZvVOcCoaAzPwWdoODTCfikKrRIRRrrGgFOoQlLiIeEdDqSWwVvhHgTBDdbtZZaAOoRrPXmhKkjJoOHIiUuIKDdewWVnNvEkDiIMlWwLmoOdcCceWdwWbyYGUZDdzHFfrCcnoONbQqBNnWwRhEOonmPpMSobBOyHNKKsrRRSgeEnNMoOmGkKNSvnNVqxBbXiHmMhTixRrXZBZlLIiNnNnoOzbCclLEzyaANnYnNBcCbZegfFGzMgGmIiVvItsSITAaLLruURKklkqQmAaRrNnieeEEIMYglXxLGcCyfLlVvFXxkKGuGgfmMZzFQqhqQTpPtNQqntTAaaAHTjJhZzHFfWwzZtULTvmMToOAaWmMPpfFwdDowLlJjwWpPGFGJjpgEfGqQgFtTBbmMpAasSPsSSDdPhHfFBrnNPppXxPjJpxQzJjWZIZxXnfFCcNeETtbBvIIfFMxsSVviYjjTeEgGpJjgGzZSzHXxvdDLOomMVLUtTuoFfYyxhCDcQqcCbrAaNnTtvmGMCJbBrmMZzRRrBbfCAvrRKjNnJkzmqQPbRWjtTQaAeEqcCHYyGghWuUwAaJUiIuJsdDSiIqjJaNnAvhEevVbBHWwHhGjJHhSsqqQmRrMAaaeEHhXxoOAAaDdZzytZzlLuUTWVvlLWwJtixXxXIUuLmSsMoOJcCPpVvjDdbjJBlVvLOsoOfdMqExXeLlRrfCcVanZzNRcnjIiJxPpXNCKkWpPMmwboDdqQIauhHUFfjJjJvtDdyYTIvOBvVbQqohHYCcfGgJlDdLrsSYyhHpyYBeMmrRoOrREfcClLFboOFaAfCkKwWcQTtqQViIveMmEmMwWqSseEvJjzZmMSssSnlLNOPpXyYxoaPSIispAsgIisStTGpmiIMVvcCPgEeSsXxGejJmqQjJbOBblLoRiIrrcCRBMrHaTMyYoTtyYegGEeEOSsmBQdDcVEevyhHLJBbcdDqFfUuQmZzOoMVvbifoOzZQUuYyNrcCcCRRwyJjYWPporROoOdHhPGghHzZpbBLJjNnjJaArrTtuURnNXkKBSsbcCETJjtexcOoVvPpavkKoQqrWwIiyAOKmYdwZaAVvaAzZzeyYAaLlLNnuzdDLlZNnQbBqiItkKRrmJjNQqOkPKLSsKkftZzLlTapPboOBnVvKSskNpPfFOoiSXSsrQGbBgqHhRSsolLBbOvQLlqZzbBVJjoOAbUJCOeEoFkKfcUuvVrHAfFdDDdqQiIUfZzHJjhNrRopkzgGriITNDdnseEVvRWwYnMmNJjtTMmRrpDdPuUXiiAJCJjXzZJZzBbBTtbbBqheETtHmPlpAdhHEeDatTlllSsdDJdDVvjJgGjJjJjWwPpShHdDtTsaLlARTtrqGgQyYXWwPfkKFTVvdDtPumMUSspWeIixXEwOoTrRtdDHhgtTcChHHzuAxXYyaYymlLzZZzjHnNLlhGWwgBhaAHJjoPpODdLHhlXxPpifyYRXxEesSXGgxVHZcCzhgGYylYOoypuUPLKkvzKkRkKrZPphHGzZgJGgjOziQqIeXxchHhxiRrwwlLWyIgGdDKVveEIzZTgGhHwEeJjWyRSsEelTtKfCMfgGFIiOPLlhpPaAaiIXxtTANnoOzxRrHhXZLWwlaAsOoSHFSLvVlXxXxQubASsaxXkwWrHhJlLjRxGgfFXPrDdgGRZzpQsSCcqeEbBKBFfXxDdcFfCcCFfczZtTSsCbBOoZqQOoznNRrMmkiInNQqDHhdtHhsUupNnPSVIimnNGgkKuqlqicOoCHHhhIQLlLcClhHRlLbvVpfFYyLuUutTwkKEeWlJjxXoOLLSsdDcClbBmMfFQWwqEzZDdejJNnXDFfCcjWwQCcDdHhQqqJuUdlLxOogqpgGaAIiPQbBWwhxqeEQFfYyXPpIWwtqdDNVwzpjwBbWUuJWwiIdDHhrlLIvVNnDdRbtMmTwWrwWjJRjJrlLYTtMmIJjivDdmMwuUJkCcHhEezNLoOlChHEDdpJjKumMUtuKkUuUTkfZzFeEiqQZzwjJWAoHheEzZaARrJoOuUjWwSscCAIiRrajJCcdJjDiIloOLrRrBbVwNIzZmMHbBhXYDJjqQyYdcdDHUjJfAtTFfIiCBbcRvVrRrdDEenNupxbBXeEmMOoXxMmCzZEeKkJeEaAuUJpPjrRjsScwWvhHZzNPpdDCndDrRLNnliINUToOnaUFfuANJjUqUuqQQYzZqQygGAgqYyoOQOoGXxHhabbBBdDyYAnNtTHhtnwWeEjJOooONTJcyYghHHhnNIqQQqaAiePpOQSsCcqvVcCKkpPZzwWAOoSsPhaAHqQGgpZGgVvzIiQUuzZcCcjJzqtybByYlLcCdQRrqjJDgGVvGSsgFAafwWqOgGtTGDdgYjJynFfhdDHrsNHhBbSsuUOrpPLlhOAaYymMoIrRPpcCHhxXpPiKHhOWqDdQJLIicxXLRrlbBgGgrRWwGCJjzBxXaAbztRAZzalLIoOLliYtzZzZTyAaINdDSztTZwWJSAaCcOoLoaAArRaOvQwWqVSsTUOoXxMdDwWmfHhFtTyqFqgGQqQyYQqFffsSeEFfQqSihHIDPpgGMfKkFmGsSgcCiIUucCeEQVvqQYyIlGCcgPptIkKkmMpUNnuWaAGgRroOwyoORrspPSoOYuvVUfmUuMZQqbDdBrRgnNNnGzhIipPDdHqQBdDbVvPyYiiInCIQPpMmHAMHhIiIiaAVKPWwnAaNpkfFOzvVcCGgZorRrmpLONnolLlkKmMSstvVKDdkKCPGgmnNyCyjJioOkKIxXWwmMMmFsSRreEQTgHhiyYhGWwfFxXtMDXwWxfnNFdGgDdeEInCVvnHiIiIhNteErnEehWwrRutlkKkKlLkKLfFdKkkKsSDYywBzZswLlWSLlblSszZfWGgwlsSNTtnTtxXikpPdDKrUuzHLlXxzuUZbFSsffFBhYyZuzZUajJVMKkmAavHhtwWRrTAIcEeCXkKiIaABbQlXanNlLXwWxlAaLAllwWLEeeECcLWhHJquxXUJLlcCjZUCcqsSQuzHOohnkdHhDKPeEGgCcDdywabwWBAVvZzdhHQzZqcIiCqQSsGsxpPvVEeEelLAafFhHHhWqHhAaVQqsSUulLclrRLCGgMmcNnhCcHNnCvzsSZGgQtTxTaOonJjYTtWwJjHXvSCcrDdRZrRzsSZznxXNsvfQqQqFVVEaAeNYyIyYFbBfcCxXLlxVlhHdDYnEjJeGgTtBblLNoOyZaAzfjfFJtTjxXJSsWwICciNnkoOxvVkKmMXbsqQSBAaOojrRJJjKmoOUDdeExXsSOmBbMomRcCrUzZCcumXxMQEeqfFMHhKkSsnUjJuNaCcuUUukKJoAaKkucCjJUHhyYuoqQOUzbjJPeIiyYnNQqdRrDwWEpUtTpPdDuTtUuXCdDvVcxCbbBBUDduxEeXwWlLtTFfNYqQqQNnsIiTPpCsSVvcCcGgtnNjJgGKkQwYyAaIiWXxnNAULlJjIiuoOaoOozZKIYtTrRyNnmMiQqrpPPpRrkKcCOoRjXxJkNzZDtPpTJjdxLvgXxGgDdBiIBbbGEeVUulMjMmQFJjfMWzLlHhZjvVnNlLuAaaBbyYrTtYuyYEshHSvVJuUCcjeGgpPUbWfAaFhHUubBwcQqCPIipQqMmTgGiVvItBbPHIihoONnePpAaDdBbAanmzZMgZTtHhzXxBbGNPXxpyuKkVvUACcZzVvxmMBbXaYPpCadDwWHhCpSsPcaAYoOytWwsvVusSIBHhbifFtmMTHhmMHhOoJARYQtTsSqwWWwFoOfytTtTGgfFDdqQZLlvVcAaXaAxWwdIiDyYpPseEpBbPVhHPplLsSznOgzZGnNDdwuUWtXxNnxWxXwMmxaApPQHhKwmMWUuhHqQhHwoOAaIilmecCWwdzZeXxEAaAimMACcSsQBbqyXxBbYOxXIijHRrhLtTnNeAaRrVhHvhxXsSHIiSWwJFwWfjOAODdoXPpoiFfIOxiIyFGvVguUpRrBXxCcoObPdDXxRYyIirpgyfFnNYpPGlLCcbBbcytTrREeYCcCZyYLlzBbPpHhJxXNnjBsuUZHhGKkgztTvVIiahzZHASSVsSvOoWbBfFdDwPpsEefFoOaoONntTAIfFwWdXxVvqWwQjrRTtowtTWtToWwOTtOAaJSseCcTtEVviOgUuGQvVLsSltZzrRTgGLdDLllqdbBDvEevVAabBNFfFXxKkFUuJFxXfjTeEtJjpPTtBbxXNHhHdRrDjJwlekKtTHhXxqQrRdDEYyKRiIrAaMmGTiQEequUItHgGSsyYpqQnNPeWTtwGmMeEgIioOEeJjEIRrHrROobHhBRrzZkDdEeKijzZKkIZzEeiOoLlJBXblbBLBzZqQWwnNxQDdcCJlLjQqqtwGgpPWTyYxOoOfFqQdGMmfbXxBKIiAaYyEemncQqrRHhlxWwXLlUogGOKaLlAkuPpLCNMBbmuxXUAazoOZrdDRBbsSvVSpPgGsTtbWSswBvVjJMvVkyoONnYpfMaAmHhFsSPNnKkyYpPWiIYmtTNnpPxXHhZzVvQPcDBbdCeETtpwSPpsWqpPMcNnwWbBNnxXuUsnnNeHOUuoRhHyYqQGgsYylIibBymMYQXxqBMmMmbZGgzFfGGlLkvAaVOoqQNoLlOoOJjPyYUPRreEumMUpPprRIKGgkcCtTegWwGbTtxXkKiIBGgbBEkKEebBibuUOovVfFwWvVyQqYBhHmfFWwmQqMxjJXxMwDdHhJQqCYyYMmyAamMoOcVrRvXxAOoiFlLHhMmXdDKwWeEkCqQcIiDdTtnjJgDdrWwbYyBgOdqrRQEeWwDIiBkJmgGMnrRrRwzZWjJNxPpjlLtTChHKgjJGkcFfzZCTtHWUDQqVqwWQMmHoONnSsqJHXxAllLLaLlhjyYpmfsSFMQiAaIksSKcCdhHDiIsSDdbrRBHvVhjcCscCRrQGgqCchvwWOlEeLLlCcAaFfiIZnNoOYRNdDnrjJFfWwNnyYIiyDirRTtSOUulLosbBIIifdDFuUGZzkAaKDdgQhHqzUuhxXwWccCPpCHXxzcCHhaAAaZnIimMxpPFfUuXEQAahHqZtWwTsSrfabBAFREemUuMMPpmjJyYXxZzJMxXmjQGgXpIiSsHtdDHhvVTfTtlLCcoOFyYqQMmhFfPdDqdqQjJDGBbgjJsSQxXKhHoOkgtnNFfCfBbaASsKkbBzMxXmZHhFPpXxFYykAapPKvVDaATtWTtwrRjHhMXxIYQEeqyimJbWwqOoiISvVOoYyPpJjsNmRrMORroXxgGnGTtCAacNnvsSVZzXOouUYWlFfLqQnNrRlgGvVsrRdDaANusSUQMmqzZgZbBzehHEjJyYGkhHxXtTTtvcCVQDkrsaASBUubRJjYybLlIPuUKNnjlYbgWtTwSsUzZuLiwWfCcSsrSsbBRFfnNzZFlLebBnorfIiLdDFfJjlsvVScsSCOoPpGvzcCjUuJFfTtZuUrRVcCdvVnNhHDpPAaQTtqSOoUAaxXbBQlLuPpXxUEAaeNOIiovVoOzZEemMRrIindDSnNiMzZmXfFoiIOxWwrzKkZBbOoRpHhfFXxPvVVjsPpSKgNnhVpLlPvNnmSYysTtSIipPEeLlaANSsRrAaGtDdTgPeEgRrGWGgwEetTqsSNnKUukKkYyBwWCcSsbBboaAkbBgGKGgpPEeuEeUOgsSGLlhHzLSKkshCcHhBbiCPpRwWZzrcyZzfFYELleqQlDdltTLRrEeLsSzRrAaoFfooOcCKkjJoeEfUubBwWpmpPkKMPtTFcCfKkEBpPxXvVtMmEeTGjJtlLTgMpDdPVvaAzfSsFZsjuUdDJhVvwWvVeEPpTXpPxXxtBuVvWwUyYbYnNzXnNyYTtxZLHhJjlmiINnpPGYygUupPMfFeWwJjECcNuUTtPpnflLFoXmOoaAoOhHYyJVvmzRrdDiIFfZYyMmRrMjKXqQzZmhvCpPcdDbBVRqbBQraglDdLhpQqiIPirRIrRHgGGzAaBYybDSXxCcsdfFtTPcCpbGgBnwHhkKWTtiKsSkHhIxoODdXqHhDdQteEkzZKTELloOesScCsSyYGpPHhgDtTKnNkdsxoOWSdDswXSpPjHhOodDJeSRZzrswDdWPpzZESseKiIxcZoOXxLlzBbCXTtdDUzZWwuIiwRrzXxrqQluUyYLfFEejJixWwXIKglbBLVrLlRNniIBRNQqndDrDfFdzZeEbIimIRwYyWlLQYyqLbBWwlxXiILlrHSlLbBslJjLTSstLlfFyYCcrRXQqOoeyYnNJjEMmxBbXpXwWBbuguUGnaAhHqQNjXXxgGxJSTzZMmTPpbBEezZRrYjJyuSsUFAafPpoOFbBQqKlLdDYNnPqkKpQqsSPQHJjDdjJnNNQcCqUAlCcGYygGVuFfUvQGhHgqXxxPpXuURryTtGgYZzBblLeEKkqmMKkoOhfFZzHhHgGpuUETbotTeENDdnOHFfwWhHLlIiQqINnigGpTtOtTOoxJjXoIikehHvdDdPpDVjJqQEdDKfFDdAaEfFezDHhRMmWYZzAaywhHahHdfFaADdwWYpfFPjTtAavVifFTrRnzZeENtagGAKkMmINwWVvnJCcQLiEPpepPIWwlLTOlhNnHLAacNndDvVCNnaAGgMmMKcCpyDdqQYmNnMHhGgYMmymMbBNnmXxDdEkeErsSdDRLnNlNnKFfeeuUEEBzZXxiIbDdPpHhmMrROomMYlLyhHeywWeEXxHhlLpkmMSsCEecjJEerRKPGgvYyUugGzZNnyujJANEPpenoOaWwUYxRrsSHhXxAJjkKakAOoTYytagGTtduUKkDWwKnNbcCBZgGjJzbBnGgNQqXHhWiIjJwwuUWZrRcxXGgMmtTZnNGgzQRrqCzGfFgSmMsfFtThgGxOoXHTjpPJYCDdDdcDdytUuVslLAjJaqQyYaarRjJAaAAqHoOhZJPpjwCceIiBcjJCbaAzZpPlLOoVvEoVwWSsvoFfTtOMXxmoOUuAJjxYyttTMmTaAhHuchHCmJpPRrjzZxXMfsScTTtorRlLJjOVvwFfWeEyFfDmdDMdYTtoOQZzMmRrQeEDdpPQqYyDdPpZrRzwWqyYQqyYXxfHHLlhzZbBiTtXdDblLfFMmtTcIiwWCmMBDPpSsFfdXcCFfHoNnfFOkKWwhcCHphHPhHiIhKjJkCSPpscSshHxGgtTiISUgGuUuqQszZAbBaxBbImDegGoOCKkcDdBbEZGgpPaAsSzIuyYULlvVioOFfdSenNEOoOorQqRBbsXYyMmsSxJVvJNnjjfFmMBbMaZzGgAkbtBbTzZBKLnNqeEQGwWOhHQEeVviIquAaUofuUPOoqQJjlLpUnNuBbmWlLQaaAAqFoOwXxWTSstfdDzZgGwcCUDduWwDdgGUujJtTIpTLllLNnqQJjtlLPnAaFfuJDdjiGuUgFfINSsnxAJIijnNuUaXUFPkKpfMmNrRWwnNIwWitTFftkKTxXAaUDdIAiIlLQqafUulLwWFiBbCFfczZeEVvxXtLSslTVxXvXxuURXPFfTtTtFfphZzXxHTvVtPVvpBbrRoGgJsFfSNnDdJjKklRrUuSshHLGgXxWSskabBAKRPprNnwjneEiINvVnakKkKyDdYokKLlnnYoOlLyNCcLlNOYyYyRUuyGqQgYrJjOouUsXkKFftTvLlVQqkuUQqeEOosSAJjYylLaGgKKIiQqcfrRFFMmfoNnOCNniIeExXIgGQqdDiWwrwWAmMhHaDdRkQqxJNnlLGBbJvVjgjGgqzZBkKFfbrRUuTtQcCSsaKkXxAairRIkKOoAYyaGgAQqsSlIeEiLIiqQNnmFGgvVfRryYMmhHUuMlLXrRxzZJWEPpeKCcCcZzkPpgGwjSmXCGgcSgGsxHhmcCMbIiBMvVEuUeVvJjsbBDfhHXGgBbxFJjAadFoOrRfdDRrJjQqlLnNutnNTrRLQqJjlGEeVvUkKcCusSNtZzEeTOofjJFOQqorlLRUTtUuXUSspPyEeYKkuKjJRjJrvVpPIsbBSEeiTAZzatGjJgkiIlkKVGgvjJNnLHhVvCcxhHonNORrtTGPpgthwWIPpboOBiYyHzLlZjJUnNuTBcbHhBCbumMIilLhHnNoOuzZrRUiIzZaAAaEICcieoOhpPHTtgCckdDPpSsBbGgWpPwsSutTUYyxXkKeQqQqMmwWEKHhDduUVvMmbBeSsRrVvLlYgLeElEepPosSOzwWZGZzcCmMLlZzyKkuKkHNJjWwQqnSsTtNDOodvVaMmAmWwaALlMmMnheEMnNmXQqxXFhHfxmMWwtpDdPTdJjDUxNndDKTCRrctbBkXEptTWwbwWMmdDBvJjQqslLSLhHlqQAVXxvaYybBVIiaAcCOoVmMqQMQqmcCtsSsSUupdBbDPtTxAaNvVnFfXeETVpPvBbvQqbBvVGgP \ No newline at end of file diff --git a/advents/src/main/resources/2018/day06.txt b/advents/src/main/resources/2018/day06.txt new file mode 100644 index 0000000..879a5ed --- /dev/null +++ b/advents/src/main/resources/2018/day06.txt @@ -0,0 +1,50 @@ +158, 163 +287, 68 +76, 102 +84, 244 +162, 55 +272, 335 +345, 358 +210, 211 +343, 206 +219, 323 +260, 238 +83, 94 +137, 340 +244, 172 +335, 307 +52, 135 +312, 109 +276, 93 +288, 274 +173, 211 +125, 236 +200, 217 +339, 56 +286, 134 +310, 192 +169, 192 +313, 106 +331, 186 +40, 236 +194, 122 +244, 76 +159, 282 +161, 176 +262, 279 +184, 93 +337, 284 +346, 342 +283, 90 +279, 162 +112, 244 +49, 254 +63, 176 +268, 145 +334, 336 +278, 176 +353, 135 +282, 312 +96, 85 +90, 105 +354, 312 \ No newline at end of file diff --git a/advents/src/test/kotlin/net/fish/PermutationsTest.kt b/advents/src/test/kotlin/net/fish/PermutationsTest.kt index 22cecfb..8b53f64 100644 --- a/advents/src/test/kotlin/net/fish/PermutationsTest.kt +++ b/advents/src/test/kotlin/net/fish/PermutationsTest.kt @@ -1,6 +1,7 @@ package net.fish import net.fish.maths.D3 +import net.fish.maths.PairCombinations import net.fish.maths.combinations import net.fish.maths.permutations import org.assertj.core.api.Assertions.assertThat @@ -71,4 +72,17 @@ class PermutationsTest { assertThat(genList(5).permutations().toList()).hasSize(120) assertThat(genList(5).permutations(2).toList()).hasSize(20) } + + @Test + fun `pair combinations`() { + val pc1 = PairCombinations(4) + val asListOfPairsOfIntegers = pc1.map { it } + assertThat(asListOfPairsOfIntegers).containsExactly( + listOf(0, 0), listOf(0, 1), listOf(0, 2), listOf(0, 3), + listOf(1, 0), listOf(1, 1), listOf(1, 2), listOf(1, 3), + listOf(2, 0), listOf(2, 1), listOf(2, 2), listOf(2, 3), + listOf(3, 0), listOf(3, 1), listOf(3, 2), listOf(3, 3), + ) + } + } \ No newline at end of file diff --git a/advents/src/test/kotlin/net/fish/geometry/PointTest.kt b/advents/src/test/kotlin/net/fish/geometry/PointTest.kt index a906426..a832a64 100644 --- a/advents/src/test/kotlin/net/fish/geometry/PointTest.kt +++ b/advents/src/test/kotlin/net/fish/geometry/PointTest.kt @@ -78,4 +78,36 @@ internal class PointTest { assertThat(Point(1, 1).manhattenDistance(Point(-1, -1))).isEqualTo(4) } + + @Test + fun `edge points of boundry`() { + val boundary = listOf(Point(1, 1), Point(4,3)).bounds() + val edgePoints = boundary.edgePoints().toList() + assertThat(edgePoints).containsExactly( + Point(1,1), + Point(2,1), + Point(3,1), + Point(4,1), + Point(4,2), + Point(4,3), + Point(3,3), + Point(2,3), + Point(1,3), + Point(1,2), + ) + } + + @Test + fun `sequence of all points in boundary`() { + val boundary = listOf(Point(1, 1), Point(2,3)).bounds() + val allPoints = boundary.points() + assertThat(allPoints.toList()).containsExactly( + Point(1,1), + Point(2,1), + Point(1,2), + Point(2,2), + Point(1,3), + Point(2,3), + ) + } } \ No newline at end of file diff --git a/advents/src/test/kotlin/net/fish/y2018/Day03Test.kt b/advents/src/test/kotlin/net/fish/y2018/Day03Test.kt new file mode 100644 index 0000000..1a7fd5c --- /dev/null +++ b/advents/src/test/kotlin/net/fish/y2018/Day03Test.kt @@ -0,0 +1,37 @@ +package net.fish.y2018 + +import net.fish.geometry.Point +import net.fish.resourcePath +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class Day03Test { + @Test + fun `can generate all points in claim`() { + val c1 = Day03.Claim(1, 0, 0, 2, 3) + assertThat(c1.allPoints()).containsExactly( + Point(0, 0), Point(0, 1), Point(0, 2), + Point(1, 0), Point(1, 1), Point(1, 2) + ) + + val c2 = Day03.Claim(2, 2,3, 1, 1) + assertThat(c2.allPoints()).containsExactly( + Point(2, 3) + ) + } + + @Test + fun `can do part 1 on test data`() { + val claims = Day03.toClaims(resourcePath("/2018/day03-test.txt")) + val answer = Day03.doPart1(claims) + assertThat(answer).isEqualTo(4) + } + + @Test + fun `can do part 2 on test data`() { + val claims = Day03.toClaims(resourcePath("/2018/day03-test.txt")) + val answer = Day03.doPart2(claims) + assertThat(answer).isEqualTo(3) + } + +} \ No newline at end of file diff --git a/advents/src/test/kotlin/net/fish/y2018/Day04Test.kt b/advents/src/test/kotlin/net/fish/y2018/Day04Test.kt new file mode 100644 index 0000000..de262fd --- /dev/null +++ b/advents/src/test/kotlin/net/fish/y2018/Day04Test.kt @@ -0,0 +1,38 @@ +package net.fish.y2018 + +import net.fish.resourcePath +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +internal class Day04Test { + @Test + fun `should parse test data`() { + val d = Day04.parseInstructions(resourcePath("/2018/day04-test.txt")) + assertThat(d.keys).containsExactly(10, 99) + assertThat(d[10]!!.sleeps).hasSize(49) // unique minutes asleep, not total time asleep! + assertThat(d[99]!!.sleeps).hasSize(19) + + assertThat(d[10]!!.sleeps[24]).isEqualTo(2) + assertThat(d[99]!!.sleeps[45]).isEqualTo(3) + + assertThat(d[10]!!.totalSleep()).isEqualTo(50) + assertThat(d[99]!!.totalSleep()).isEqualTo(30) + + assertThat(d[10]!!.mostAsleepAt()).isEqualTo(24) + assertThat(d[99]!!.mostAsleepAt()).isEqualTo(45) +// println(d[10]) +// println(d[99]) + } + + @Test + fun `can do part 1 with test data`() { + val d = Day04.parseInstructions(resourcePath("/2018/day04-test.txt")) + assertThat(Day04.doPart1(d)).isEqualTo(240) + } + + @Test + fun `can do part 2 with test data`() { + val d = Day04.parseInstructions(resourcePath("/2018/day04-test.txt")) + assertThat(Day04.doPart2(d)).isEqualTo(4455) + } +} \ No newline at end of file diff --git a/advents/src/test/kotlin/net/fish/y2018/Day05Test.kt b/advents/src/test/kotlin/net/fish/y2018/Day05Test.kt new file mode 100644 index 0000000..e48789c --- /dev/null +++ b/advents/src/test/kotlin/net/fish/y2018/Day05Test.kt @@ -0,0 +1,17 @@ +package net.fish.y2018 + +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +class Day05Test { + @Test + fun `can reduce strings`() { + // dabAcCaCBAcCcaDA + assertThat(Day05.reduce("dabAcCaCBAcCcaDA")).isEqualTo("dabCBAcaDA") + } + + @Test + fun `can do part 2`() { + assertThat(Day05.doPart2("dabAcCaCBAcCcaDA")).isEqualTo(4) + } +} \ No newline at end of file diff --git a/advents/src/test/kotlin/net/fish/y2018/Day06Test.kt b/advents/src/test/kotlin/net/fish/y2018/Day06Test.kt new file mode 100644 index 0000000..bead534 --- /dev/null +++ b/advents/src/test/kotlin/net/fish/y2018/Day06Test.kt @@ -0,0 +1,48 @@ +package net.fish.y2018 + +import net.fish.geometry.Point +import net.fish.resourcePath +import net.fish.y2018.Day06.Location +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.Test + +class Day06Test { + @Test + fun `can parse locations`() { + val locations = Day06.toLocations(resourcePath("/2018/day06-test.txt")) + assertThat(locations).containsExactly( + Location(Point(1,1), isBounded = false), + Location(Point(1,6), isBounded = false), + Location(Point(8,3), isBounded = false), + Location(Point(3,4), isBounded = true), + Location(Point(5,5), isBounded = true), + Location(Point(8,9), isBounded = false) + ) + } + + + @Test + fun `can do part 1`() { + val locations = Day06.toLocations(resourcePath("/2018/day06-test.txt")) + assertThat(Day06.doPart1(locations)).isEqualTo(17) + assertThat(Day06.ownershipString(locations).trim()).isEqualTo(""" + aaaaa.cccc + aAaaa.cccc + aaaddecccc + aadddeccCc + ..dDdeeccc + bb.deEeecc + bBb.eeee.. + bbb.eeefff + bbb.eeffff + bbb.ffffFf + bbb.ffffff + """.trimIndent()) + } + + @Test + fun `can do part 2`() { + val locations = Day06.toLocations(resourcePath("/2018/day06-test.txt")) + assertThat(Day06.safeLocations(locations, 32)).isEqualTo(16) + } +} \ No newline at end of file diff --git a/advents/src/test/kotlin/net/fish/y2022/Day08Test.kt b/advents/src/test/kotlin/net/fish/y2022/Day08Test.kt index fa6e5b2..5dcfb26 100644 --- a/advents/src/test/kotlin/net/fish/y2022/Day08Test.kt +++ b/advents/src/test/kotlin/net/fish/y2022/Day08Test.kt @@ -2,6 +2,7 @@ package net.fish.y2022 import net.fish.geometry.Direction import net.fish.geometry.Point +import net.fish.maths.PairCombinations import net.fish.resourcePath import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test @@ -39,4 +40,37 @@ internal class Day08Test { assertThat(grid.maxScenicScore()).isEqualTo(8L) } + @Test + fun `can do interesting things with pair combinations`() { + val treeColumns = PairCombinations(4).groupBy { it[0] }.values.map { it.map { p -> Point(p[0], p[1]) } } + val treeRows = PairCombinations(4).groupBy { it[1] }.values.map { it.map { p -> Point(p[0], p[1]) } } + + /* + [[Point(x=0, y=0), Point(x=0, y=1), Point(x=0, y=2), Point(x=0, y=3)], + [Point(x=1, y=0), Point(x=1, y=1), Point(x=1, y=2), Point(x=1, y=3)], + [Point(x=2, y=0), Point(x=2, y=1), Point(x=2, y=2), Point(x=2, y=3)], + [Point(x=3, y=0), Point(x=3, y=1), Point(x=3, y=2), Point(x=3, y=3)]] + */ + // List of lists, by columns + assertThat(treeColumns).containsExactly( + listOf(Point(x=0, y=0), Point(x=0, y=1), Point(x=0, y=2), Point(x=0, y=3)), + listOf(Point(x=1, y=0), Point(x=1, y=1), Point(x=1, y=2), Point(x=1, y=3)), + listOf(Point(x=2, y=0), Point(x=2, y=1), Point(x=2, y=2), Point(x=2, y=3)), + listOf(Point(x=3, y=0), Point(x=3, y=1), Point(x=3, y=2), Point(x=3, y=3)) + ) + + /* + [[Point(x=0, y=0), Point(x=1, y=0), Point(x=2, y=0), Point(x=3, y=0)], + [Point(x=0, y=1), Point(x=1, y=1), Point(x=2, y=1), Point(x=3, y=1)], + [Point(x=0, y=2), Point(x=1, y=2), Point(x=2, y=2), Point(x=3, y=2)], + [Point(x=0, y=3), Point(x=1, y=3), Point(x=2, y=3), Point(x=3, y=3)]] + */ + // List of lists, by rows + assertThat(treeRows).containsExactly( + listOf(Point(x=0, y=0), Point(x=1, y=0), Point(x=2, y=0), Point(x=3, y=0)), + listOf(Point(x=0, y=1), Point(x=1, y=1), Point(x=2, y=1), Point(x=3, y=1)), + listOf(Point(x=0, y=2), Point(x=1, y=2), Point(x=2, y=2), Point(x=3, y=2)), + listOf(Point(x=0, y=3), Point(x=1, y=3), Point(x=2, y=3), Point(x=3, y=3)) + ) + } } \ No newline at end of file diff --git a/advents/src/test/resources/2018/day03-test.txt b/advents/src/test/resources/2018/day03-test.txt new file mode 100644 index 0000000..98b5ae9 --- /dev/null +++ b/advents/src/test/resources/2018/day03-test.txt @@ -0,0 +1,3 @@ +#1 @ 1,3: 4x4 +#2 @ 3,1: 4x4 +#3 @ 5,5: 2x2 \ No newline at end of file diff --git a/advents/src/test/resources/2018/day04-test.txt b/advents/src/test/resources/2018/day04-test.txt new file mode 100644 index 0000000..62c3a7a --- /dev/null +++ b/advents/src/test/resources/2018/day04-test.txt @@ -0,0 +1,17 @@ +[1518-11-01 00:00] Guard #10 begins shift +[1518-11-01 00:05] falls asleep +[1518-11-01 00:25] wakes up +[1518-11-01 00:30] falls asleep +[1518-11-01 00:55] wakes up +[1518-11-01 23:58] Guard #99 begins shift +[1518-11-02 00:40] falls asleep +[1518-11-02 00:50] wakes up +[1518-11-03 00:05] Guard #10 begins shift +[1518-11-03 00:24] falls asleep +[1518-11-03 00:29] wakes up +[1518-11-04 00:02] Guard #99 begins shift +[1518-11-04 00:36] falls asleep +[1518-11-04 00:46] wakes up +[1518-11-05 00:03] Guard #99 begins shift +[1518-11-05 00:45] falls asleep +[1518-11-05 00:55] wakes up \ No newline at end of file diff --git a/advents/src/test/resources/2018/day06-test.txt b/advents/src/test/resources/2018/day06-test.txt new file mode 100644 index 0000000..30cd42a --- /dev/null +++ b/advents/src/test/resources/2018/day06-test.txt @@ -0,0 +1,6 @@ +1, 1 +1, 6 +8, 3 +3, 4 +5, 5 +8, 9 \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 0a77357..8323022 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -21,6 +21,7 @@ allprojects { maven(url = "https://kotlin.bintray.com/kotlinx") maven(url = "https://oss.sonatype.org/content/repositories/snapshots") maven(url = "https://raw.githubusercontent.com/kotlin-graphics/mary/master") + maven(url = "https://jitpack.io") } }