import java.io.BufferedReader import java.io.InputStreamReader private const val DOT_LINE = "........." private val SEMAPHORE_ALPHABET: Map, Char> = mapOf( setOf(Position.LEFT_DOWN, Position.DOWN) to 'A', setOf(Position.LEFT, Position.DOWN) to 'B', setOf(Position.LEFT_TOP, Position.DOWN) to 'C', setOf(Position.TOP, Position.DOWN) to 'D', setOf(Position.DOWN, Position.RIGHT_TOP) to 'E', setOf(Position.DOWN, Position.RIGHT) to 'F', setOf(Position.DOWN, Position.RIGHT_DOWN) to 'G', setOf(Position.LEFT_DOWN, Position.LEFT) to 'H', setOf(Position.LEFT_DOWN, Position.LEFT_TOP) to 'I', setOf(Position.TOP, Position.RIGHT) to 'J', setOf(Position.LEFT_DOWN, Position.TOP) to 'K', setOf(Position.LEFT_DOWN, Position.RIGHT_TOP) to 'L', setOf(Position.LEFT_DOWN, Position.RIGHT) to 'M', setOf(Position.RIGHT_DOWN, Position.LEFT_DOWN) to 'N', setOf(Position.LEFT, Position.LEFT_TOP) to 'O', setOf(Position.LEFT, Position.TOP) to 'P', setOf(Position.LEFT, Position.RIGHT_TOP) to 'Q', setOf(Position.LEFT, Position.RIGHT) to 'R', setOf(Position.LEFT, Position.RIGHT_DOWN) to 'S', setOf(Position.LEFT_TOP, Position.TOP) to 'T', setOf(Position.LEFT_TOP, Position.RIGHT_TOP) to 'U', setOf(Position.TOP, Position.RIGHT_DOWN) to 'V', setOf(Position.RIGHT_TOP, Position.RIGHT) to 'W', setOf(Position.RIGHT_TOP, Position.RIGHT_DOWN) to 'X', setOf(Position.LEFT_TOP, Position.RIGHT) to 'Y', setOf(Position.RIGHT, Position.RIGHT_DOWN) to 'Z' ) private val ALPHABET_TO_SEMAPHORE: Map> = mapOf( 'A' to setOf(Position.LEFT_DOWN, Position.DOWN), 'B' to setOf(Position.LEFT, Position.DOWN), 'C' to setOf(Position.LEFT_TOP, Position.DOWN), 'D' to setOf(Position.TOP, Position.DOWN), 'E' to setOf(Position.DOWN, Position.RIGHT_TOP), 'F' to setOf(Position.DOWN, Position.RIGHT), 'G' to setOf(Position.DOWN, Position.RIGHT_DOWN), 'H' to setOf(Position.LEFT_DOWN, Position.LEFT), 'I' to setOf(Position.LEFT_DOWN, Position.LEFT_TOP), 'J' to setOf(Position.TOP, Position.RIGHT), 'K' to setOf(Position.LEFT_DOWN, Position.TOP), 'L' to setOf(Position.LEFT_DOWN, Position.RIGHT_TOP), 'M' to setOf(Position.LEFT_DOWN, Position.RIGHT), 'N' to setOf(Position.RIGHT_DOWN, Position.LEFT_DOWN), 'O' to setOf(Position.LEFT, Position.LEFT_TOP), 'P' to setOf(Position.LEFT, Position.TOP), 'Q' to setOf(Position.LEFT, Position.RIGHT_TOP), 'R' to setOf(Position.LEFT, Position.RIGHT), 'S' to setOf(Position.LEFT, Position.RIGHT_DOWN), 'T' to setOf(Position.LEFT_TOP, Position.TOP), 'U' to setOf(Position.LEFT_TOP, Position.RIGHT_TOP), 'V' to setOf(Position.TOP, Position.RIGHT_DOWN), 'W' to setOf(Position.RIGHT_TOP, Position.RIGHT), 'X' to setOf(Position.RIGHT_TOP, Position.RIGHT_DOWN), 'Y' to setOf(Position.LEFT_TOP, Position.RIGHT), 'Z' to setOf(Position.RIGHT, Position.RIGHT_DOWN) ) fun main(args: Array) { BufferedReader(InputStreamReader(System.`in`)).use { reader -> val header = reader.readLine().split(' ').map { it.toInt() } val numberOfLetters = header[0] val caesarShift = header[1] val chars = mutableListOf() for (i in 0 until numberOfLetters) { val letter = readLetter(bfr = reader) val detectedPositions = Position.findPatternsInInput(letter) val parsedChar = SEMAPHORE_ALPHABET[detectedPositions] ?: error("Position not found") chars.add(parsedChar) } val shifted = chars.shift(caesarShift) shifted.printSemaphore() } } private fun readLetter(bfr: BufferedReader): Array { return Array(9) { bfr.readLine() } } private fun List.shift(numberOfPositions: Int): List = this.map { val pos = it - 'A' val newPos = (pos + numberOfPositions) % 26 ('A' + newPos) } enum class Position(val pattern: Array, val start: Int) { DOWN(arrayOf("....*....", "....#....", "....#....", "....#...."), 4), LEFT_DOWN(arrayOf("....*....", "...#.....", "..#......", ".#......."), 4), LEFT(arrayOf(".###*...."), 4), LEFT_TOP(arrayOf(".#.......", "..#......", "...#.....", "....*...."), 1), TOP(arrayOf("....#....", "....#....", "....#....", "....*...."), 1), RIGHT_TOP(arrayOf(".......#.", "......#..", ".....#...", "....*...."), 1), RIGHT(arrayOf("....*###."), 4), RIGHT_DOWN(arrayOf("....*....", ".....#...", "......#..", ".......#."), 4); private fun matches(input: Array): Boolean { for (index in input.indices) { val line = input[index] if (line == DOT_LINE) { continue } if (checkIfImportantCharactersMatches(line, this.pattern[0])) { return checkIfWholePatternMatches(index, input) } } return false } private fun checkIfImportantCharactersMatches(line: String, positionLine: String): Boolean { for (i in positionLine.indices) { val positionChar = positionLine[i] if (positionChar != '.' && line[i] != positionChar) { return false } } return true } private fun checkIfWholePatternMatches(startingIndex: Int, input: Array): Boolean { for (i in this.pattern.indices) { val offsetIndex = startingIndex + i val inputLine = input[offsetIndex] val patternLine = this.pattern[i] if (!checkIfImportantCharactersMatches(inputLine, patternLine)) { return false } } return true } companion object { fun findPatternsInInput(input: Array): Set { val allPositions = Position.values() val matchingPositions = mutableSetOf() for (position in allPositions) { if (position.matches(input)) { matchingPositions.add(position) } } return matchingPositions } } } fun List.printSemaphore() { for (c in this) { val positions = ALPHABET_TO_SEMAPHORE[c] ?: error("Undefined") val arr = Array(9) { CharArray(9) { '.' } } addToOutput(arr, positions) printArray(arr) } } fun addToOutput(arr: Array, positions: Collection) { for (pos in positions) { for (i in pos.pattern.indices) { for (j in pos.pattern[i].indices) { if (pos.pattern[i][j] != '.') { arr[i + pos.start][j] = pos.pattern[i][j] } } } } } fun printArray(payload: Array){ for (line in payload){ println(line.joinToString(separator = "")) } }