162 lines
5.3 KiB
Kotlin
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 == '#' })
|
|
|
|
} |