AdventOfCode-2017/day21.kt

162 lines
5.3 KiB
Kotlin

import java.io.File
class Pattern(val size: Int){
val map = Array(size) { CharArray(size) { ' ' } }
fun flipV(): Pattern {
val newPattern = Pattern(size)
for(x in 0 until size){
for(y in 0 until size){
val newX = size - 1 - x
val newY = y
newPattern.map[newY][newX] = map[y][x]
}
}
return newPattern
}
fun flipH(): Pattern {
val newPattern = Pattern(size)
for(x in 0 until size){
for(y in 0 until size){
val newX = x
val newY = size - 1 - y
newPattern.map[newY][newX] = map[y][x]
}
}
return newPattern
}
fun rotate(): Pattern {
val newPattern = Pattern(size)
for(x in 0 until size){
for(y in 0 until size){
val newX = y
val newY = size - 1 - x
newPattern.map[newY][newX] = map[y][x]
}
}
return newPattern
}
override operator fun equals(other: Any?): Boolean {
if(other !is Pattern) return false
return oneEquals(other)
}
fun equalsPattern(other: Pattern): Boolean {
if(other.size != size) return false
for(x in 0 until size) {
for(y in 0 until size){
if(other.map[y][x] != this.map[y][x]) return false
}
}
return true
}
fun oneEquals(other: Pattern): Boolean {
val first = rotate()
val flipH = flipH()
val flipV = flipV()
val thisMatches = equalsPattern(other) ||
rotate().equalsPattern(other) ||
rotate().rotate().equalsPattern(other) ||
rotate().rotate().rotate().equalsPattern(other)
val flipHMatches = flipH.equalsPattern(other) ||
flipH.rotate().equalsPattern(other) ||
flipH.rotate().rotate().equalsPattern(other) ||
flipH.rotate().rotate().rotate().equalsPattern(other)
val flipVMatches = flipV.equalsPattern(other) ||
flipV.rotate().equalsPattern(other) ||
flipV.rotate().rotate().equalsPattern(other) ||
flipV.rotate().rotate().equalsPattern(other)
return thisMatches || flipHMatches || flipVMatches
}
fun toStrings(): List<String>{
return map.map { it.joinToString(" ") }
}
fun split(): List<List<Pattern>> {
val toReturn = mutableListOf<MutableList<Pattern>>()
if(size % 2 == 0){
for(y in 0 until size / 2){
val newRow = mutableListOf<Pattern>()
for(x in 0 until size / 2){
val newPattern = Pattern(2)
for(newX in 0..1){
for(newY in 0..1){
newPattern.map[newY][newX] = map[y * 2 + newY][x * 2 + newX]
}
}
newRow.add(newPattern)
}
toReturn.add(newRow)
}
} else {
for(y in 0 until size / 3){
val newRow = mutableListOf<Pattern>()
for(x in 0 until size / 3){
val newPattern = Pattern(3)
for(newX in 0..2){
for(newY in 0..2){
newPattern.map[newY][newX] = map[y * 3 + newY][x * 3 + newX]
}
}
newRow.add(newPattern)
}
toReturn.add(newRow)
}
}
return toReturn
}
}
fun fromString(s: String): Pattern {
val lines = s.split("/")
val newPattern = Pattern(lines.size)
for(i in 0 until newPattern.size){
newPattern.map[i] = lines[i].toCharArray()
}
return newPattern
}
fun combine(list: List<List<Pattern>>): Pattern {
val newPattern = Pattern(list[0][0].size * list.size)
for(y in 0 until list.size){
for(x in 0 until list.size){
val copying = list[y][x]
for(oldY in 0 until copying.size){
for(oldX in 0 until copying.size){
newPattern.map[y * copying.size + oldY][x * copying.size + oldX] =
copying.map[oldY][oldX]
}
}
}
}
return newPattern
}
fun Map<Pattern, Pattern>.findMatching(pattern: Pattern): Pattern? {
return keys
.firstOrNull { it == pattern }
?.let { get(it) }
}
fun main(args: Array<String>){
// val file = File("test.txt")
val file = File("../puzzle_21.txt")
val lines = file.readLines()
val patternMap = mutableMapOf<Pattern, Pattern>()
lines.forEach {
val split = it.split(" => ")
patternMap.put(fromString(split[0]), fromString(split[1]))
}
val inputPattern = fromString(".#./..#/###")
var pattern = inputPattern
var count = 0
while (count < 18){
val split = pattern.split()
pattern = combine(split.map { it.map { patternMap.findMatching(it)!! } })
pattern.toStrings().forEach { println(it) }
println()
count += 1
}
println(pattern.toStrings().joinToString("").count { it == '#' })
}