1
0
Fork 0

refactor: use cross products

Signed-off-by: Matej Focko <mfocko@redhat.com>
This commit is contained in:
Matej Focko 2021-12-22 20:07:03 +01:00
parent 431166fa49
commit f4df1fb7df
No known key found for this signature in database
GPG key ID: 332171FADF1DB90B
8 changed files with 29 additions and 22 deletions

View file

@ -31,8 +31,14 @@ fun readGraph(day: Int, name: String) = readInput(day, name).fold(mapOf<String,
*/ */
fun String.md5(): String = BigInteger(1, MessageDigest.getInstance("MD5").digest(toByteArray())).toString(16) fun String.md5(): String = BigInteger(1, MessageDigest.getInstance("MD5").digest(toByteArray())).toString(16)
fun <A, B> product(xs: Sequence<A>, ys: Sequence<B>): Sequence<Pair<A, B>> =
xs.flatMap { x -> ys.map { y -> x to y } }
fun <A, B, C> product(xs: Sequence<A>, ys: Sequence<B>, zs: Sequence<C>): Sequence<Triple<A, B, C>> = fun <A, B, C> product(xs: Sequence<A>, ys: Sequence<B>, zs: Sequence<C>): Sequence<Triple<A, B, C>> =
xs.flatMap { x -> ys.flatMap { y -> zs.map { z -> Triple(x, y, z) } } } xs.flatMap { x -> ys.flatMap { y -> zs.map { z -> Triple(x, y, z) } } }
fun <A, B> product(xs: Iterable<A>, ys: Iterable<B>): Sequence<Pair<A, B>> =
product(xs.asSequence(), ys.asSequence())
fun <A, B, C> product(xs: Iterable<A>, ys: Iterable<B>, zs: Iterable<C>): Sequence<Triple<A, B, C>> = fun <A, B, C> product(xs: Iterable<A>, ys: Iterable<B>, zs: Iterable<C>): Sequence<Triple<A, B, C>> =
product(xs.asSequence(), ys.asSequence(), zs.asSequence()) product(xs.asSequence(), ys.asSequence(), zs.asSequence())

View file

@ -1,5 +1,6 @@
package year2021.day04 package year2021.day04
import product
import readInput import readInput
class Bingo(description: List<String>) { class Bingo(description: List<String>) {
@ -21,8 +22,7 @@ class Bingo(description: List<String>) {
} }
private fun mark(board: MutableList<MutableList<Int>>, number: Int) { private fun mark(board: MutableList<MutableList<Int>>, number: Int) {
board.indices product(board.indices, board.indices)
.flatMap { i -> board.indices.map { j -> Pair(i, j) } }
.filter { (i, j) -> board[i][j] == number } .filter { (i, j) -> board[i][j] == number }
.forEach { (i, j) -> .forEach { (i, j) ->
val before = isWinningBoard(board) val before = isWinningBoard(board)

View file

@ -1,5 +1,6 @@
package year2021.day08 package year2021.day08
import product
import readInput import readInput
class Patterns(private val patterns: MutableList<String>) { class Patterns(private val patterns: MutableList<String>) {
@ -31,9 +32,7 @@ class Patterns(private val patterns: MutableList<String>) {
} }
private fun check(): Boolean = private fun check(): Boolean =
segments product(segments.indices, segments.indices)
.indices
.flatMap { i -> segments.indices.map { j -> Pair(i, j) } }
.all { (i, j) -> .all { (i, j) ->
segments[i].intersect(segments[j]).size == (decoded[i] ?: emptySet()).intersect( segments[i].intersect(segments[j]).size == (decoded[i] ?: emptySet()).intersect(
(decoded[j] ?: emptySet()).toSet() (decoded[j] ?: emptySet()).toSet()

View file

@ -1,18 +1,18 @@
package year2021.day11 package year2021.day11
import product
import readInput import readInput
fun validAdjacentIndices(input: List<List<Int>>, y0: Int, x0: Int): Iterable<Pair<Int, Int>> = fun validAdjacentIndices(input: List<List<Int>>, y0: Int, x0: Int): Sequence<Pair<Int, Int>> =
(y0 - 1..y0 + 1) product(y0 - 1..y0 + 1, x0 - 1..x0 + 1)
.flatMap { y -> (x0 - 1..x0 + 1).map { x -> Pair(y, x) } }
.filter { (y, x) -> .filter { (y, x) ->
(y != y0 || x != x0) && (y >= 0 && y < input.size) && (x >= 0 && x < input[y].size) (y != y0 || x != x0) && (y >= 0 && y < input.size) && (x >= 0 && x < input[y].size)
} }
fun allIndices(octopuses: List<List<Int>>): Iterable<Pair<Int, Int>> = fun allIndices(octopuses: List<List<Int>>): Sequence<Pair<Int, Int>> =
octopuses.indices.flatMap { y -> octopuses[y].indices.map { x -> y to x } } product(octopuses.indices, octopuses.first().indices)
fun getFlashes(octopuses: List<List<Int>>): Iterable<Pair<Int, Int>> = fun getFlashes(octopuses: List<List<Int>>): Sequence<Pair<Int, Int>> =
allIndices(octopuses).filter { (y, x) -> octopuses[y][x] > 9 } allIndices(octopuses).filter { (y, x) -> octopuses[y][x] > 9 }
fun step(octopuses: List<MutableList<Int>>): Int { fun step(octopuses: List<MutableList<Int>>): Int {

View file

@ -1,5 +1,6 @@
package year2021.day17 package year2021.day17
import product
import readInput import readInput
import kotlin.math.absoluteValue import kotlin.math.absoluteValue
import kotlin.math.min import kotlin.math.min
@ -26,8 +27,8 @@ data class Area(val min: Vector, val max: Vector) {
val ySpeeds: IntRange val ySpeeds: IntRange
get() = speeds { it.y } get() = speeds { it.y }
val possibleVectors: Iterable<Vector> val possibleVectors: Sequence<Vector>
get() = xSpeeds.flatMap { vx -> ySpeeds.map { vy -> Vector(vx, vy) } } get() = product(xSpeeds, ySpeeds).map { (vx, vy) -> Vector(vx, vy) }
} }
// region parsing // region parsing

View file

@ -1,5 +1,6 @@
package year2021.day18 package year2021.day18
import product
import readInput import readInput
enum class SnailfishNumberType { enum class SnailfishNumberType {
@ -193,8 +194,7 @@ fun part1(input: List<String>): Long =
fun part2(input: List<String>): Long = fun part2(input: List<String>): Long =
input.map(String::toSnailfishNumber).let { numbers -> input.map(String::toSnailfishNumber).let { numbers ->
numbers.indices product(numbers.indices, numbers.indices)
.flatMap { i -> numbers.indices.map { j -> i to j } }
.filter { (i, j) -> i != j }.maxOf { (i, j) -> .filter { (i, j) -> i != j }.maxOf { (i, j) ->
(numbers[i] + numbers[j]).magnitude (numbers[i] + numbers[j]).magnitude
} }

View file

@ -1,5 +1,6 @@
package year2021.day19 package year2021.day19
import product
import readInputAsString import readInputAsString
import java.time.Instant import java.time.Instant
import java.util.* import java.util.*
@ -44,8 +45,7 @@ val TRIGONOMETRY: Set<Pair<Int, Int>> =
.toSet() .toSet()
val ROTATIONS: Set<Triple<Vector, Vector, Vector>> = val ROTATIONS: Set<Triple<Vector, Vector, Vector>> =
TRIGONOMETRY product(TRIGONOMETRY, TRIGONOMETRY, TRIGONOMETRY)
.flatMap { alpha -> TRIGONOMETRY.flatMap { beta -> TRIGONOMETRY.map { gamma -> Triple(alpha, beta, gamma) } } }
.map { (a, b, g) -> .map { (a, b, g) ->
val (sinA, cosA) = a val (sinA, cosA) = a
val (sinB, cosB) = b val (sinB, cosB) = b

View file

@ -1,10 +1,11 @@
package year2021.day20 package year2021.day20
import product
import readInput import readInput
data class Point(val x: Int, val y: Int) { data class Point(val x: Int, val y: Int) {
val square: Iterable<Point> val square: Sequence<Point>
get() = (y - 1..y + 1).flatMap { y -> (x - 1..x + 1).map { x -> Point(x, y) } } get() = product(y - 1..y + 1, x - 1..x + 1).map { (y, x) -> Point(x, y) }
} }
data class TrenchMap( data class TrenchMap(
@ -24,15 +25,15 @@ data class TrenchMap(
private val ys: IntRange private val ys: IntRange
get() = coordinateRange { it.y } get() = coordinateRange { it.y }
private val indices: Iterable<Point> private val indices: Sequence<Point>
get() = ys.flatMap { y -> xs.map { x -> Point(x, y) } } get() = product(ys, xs).map { (y, x) -> Point(x, y) }
override fun toString(): String = override fun toString(): String =
ys.joinToString("\n") { y -> ys.joinToString("\n") { y ->
xs.joinToString("") { x -> get(x, y).toString() } xs.joinToString("") { x -> get(x, y).toString() }
} }
private fun toIndex(square: Iterable<Point>): Int = private fun toIndex(square: Sequence<Point>): Int =
square.map { if (get(it) == '#') 1 else 0 }.reduce { acc, bit -> acc * 2 + bit } square.map { if (get(it) == '#') 1 else 0 }.reduce { acc, bit -> acc * 2 + bit }
private fun enhancePixel(pixel: Point): Char = algorithm[toIndex(pixel.square)] private fun enhancePixel(pixel: Point): Char = algorithm[toIndex(pixel.square)]