Skip to content

Instantly share code, notes, and snippets.

@alexruperez
Last active March 16, 2018 15:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alexruperez/0e56cd5f2a89175a2bc6a6810ecda7d0 to your computer and use it in GitHub Desktop.
Save alexruperez/0e56cd5f2a89175a2bc6a6810ecda7d0 to your computer and use it in GitHub Desktop.
package challenge8
import java.io.BufferedReader
import java.io.InputStreamReader
import java.io.PrintWriter
import java.nio.charset.Charset
import java.net.ServerSocket
import java.net.Socket
fun main(args: Array<String>) {
echo(TheGameOfLifeTarget(), args.firstOrNull()?.toIntOrNull() ?: 0)
}
interface Target: Runnable {
fun socket(socket: Socket)
}
fun echo(target: Target, port: Int = 0, backlog: Int = 50) {
if (port == 0 || port in 1024..65535) {
ServerSocket(port, backlog).use {
println("nc localhost ${it.localPort}")
val thread = Thread(target)
while (!thread.isInterrupted) {
target.socket(it.accept())
thread.start()
}
}
} else {
throw IllegalArgumentException("The port $port is outside the specified range of valid port values," +
"which is 0 (automatically allocated, typically from an ephemeral port range)" +
"or between 1024 and 65535, inclusive.")
}
}
open class EchoTarget(private var socket: Socket? = null,
private val autoFlush: Boolean = false,
private val charset: Charset = Charset.defaultCharset(),
private val defaultCharBufferSize: Int = 8192): Target {
override fun socket(socket: Socket) {
this.socket = socket
}
override fun run() {
val socket = socket ?: throw UninitializedPropertyAccessException("Socket has not been initialized, call fun socket(socket: Socket) first.")
val printWriter = PrintWriter(socket.outputStream, autoFlush)
val inputStreamReader = InputStreamReader(socket.inputStream, charset)
val bufferedReader = BufferedReader(inputStreamReader, defaultCharBufferSize)
while (true) {
val line = bufferedReader.readLine()
handle(line, printWriter)
printWriter.flush()
if (line == "Close") break
}
bufferedReader.close()
inputStreamReader.close()
printWriter.close()
socket.close()
}
open fun handle(line: String, printWriter: PrintWriter) {
printWriter.println(line)
}
}
class TheGameOfLifeTarget : EchoTarget() {
override fun handle(line: String, printWriter: PrintWriter) {
var echo = line
val gol = Regex("""^TheGameOfLife\((\d+),(\d+),(\d+)\)$""").find(echo)?.groupValues
if (gol != null && gol.size == 4) {
val rows = gol[2].toInt()
val map = gol[3]
if (map.length % rows == 0) {
val alive = map.mapIndexed { index, char -> if (char == '1') Cell(index % rows, index / rows) else null }.filterNotNull().toSet()
val iteration = gol[1].toInt()
echo = TheGameOfLife(alive).play(iteration)
}
}
super.handle(echo, printWriter)
}
}
interface Game {
fun play(times: Int): String
}
data class Cell(private val x: Int, private val y: Int) {
fun nextTo() = (-1..1).flatMap { x -> (-1..1).map { y -> Cell(this.x + x, this.y + y) } }.filter { it != this }.toSet()
}
class TheGameOfLife(private var alive: Set<Cell>): Game {
override fun play(times: Int): String {
repeat(times) { step() }
return alive.size.toString()
}
private fun cells() = alive.flatMap { it.nextTo() + it }.toSet()
private fun aliveNextTo(cell: Cell) = cell.nextTo().intersect(alive).size
private fun step() {
alive = cells().filter {
when (aliveNextTo(it)) {
2 -> alive.contains(it)
3 -> true
else -> false
}
}.toSet()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment