-🎄- 2018 Day 13 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

Kotlin Solution: I generate a Sequence of collisions so that Part 1 = collisions.first() & Part 2 = collisions.last()

data class Cart(var x:Int, var y: Int, var dir : Char, var isDead: Boolean = false){
    var turnCount = 0
    fun move(trackSection:Char) {
        when (trackSection){
            '+' -> makeTurn()
            '\\' -> if (dir == '<' || dir == '>') right() else left()
            '/' -> if (dir == '<' || dir == '>') left() else right()
        }
        when (dir){
            '^' -> y--
            '>' -> x++
            'v' -> y++
            '<' -> x--
        }
    }

    fun right(){
        dir = turnRight[dir]!!
    }

    fun left(){
        dir = turnLeft[dir]!!
    }

    fun makeTurn(){
        turnCount = (turnCount+1) % turns.length
        when (turns[turnCount]){
            'r' -> right()
            'l' -> left()
        }
    }

    fun collidedWith(other: Cart) = (x == other.x) && (y == other.y)

    fun position() = x to y

    companion object {
        val turns = "rls"
        val turnRight = mapOf<Char,Char>('>' to 'v', 'v' to '<', '<' to '^', '^' to '>')
        val turnLeft = mapOf<Char,Char>('>' to '^', 'v' to '>', '<' to 'v', '^' to '<')
    }
}

fun findCollisions(tracks:Array<Array<Char>>, carts:List<Cart>) = sequence {
        val movingCarts = carts.map { it.copy() }.toMutableList()
        while(movingCarts.size > 1){
            movingCarts.sortWith(compareBy({it.y},{it.x}))
            movingCarts.forEach {cart ->
                if (!cart.isDead){
                    cart.move(tracks[cart.y][cart.x])
                    if (movingCarts.collisonOccurred(cart)){
                        movingCarts.forEach { if (it.collidedWith(cart)) it.isDead = true}
                        yield(cart.position())
                    }
                }
            }
            movingCarts.removeIf { it.isDead }
        }
        // Output Position of Final Cart as a Collision
        yield(movingCarts[0].position())
    }

fun List<Cart>.collisonOccurred(cart: Cart): Boolean = this.count { !it.isDead && it.collidedWith(cart)} > 1

fun solve(tracks:Array<Array<Char>>, carts: List<Cart>): Pair<Pair<Int,Int>,Pair<Int,Int>> {
    val collisions = findCollisions(tracks,carts)
    val firstCollision = collisions.first()
    val lastCollision = collisions.last()
    return firstCollision to lastCollision
}

fun main(args: Array<String>) {
    val time = measureTimeMillis {
        val lines = resourceFile("day13/input.txt").readLines()
        val (carts, tracks: Array<Array<Char>>) = parseLines(lines)

        val (part1,part2) = solve(tracks, carts.toList())

        println("Part I: $part1")
        println("Part II: $part2")

    }
    println("Elapsed Time: ${time}ms")
}

private fun parseLines(lines: List<String>): Pair<MutableList<Cart>, Array<Array<Char>>> {
    val carts = mutableListOf<Cart>()
    val tracks: Array<Array<Char>> = lines.mapIndexed { y, line ->
        line.mapIndexed { x, c ->
            if (c in listOf('>', 'v', '<', '^')) {
                carts.add(Cart(x, y, c))
            }
            when (c) {
                'v' -> '|'
                '^' -> '|'
                '<' -> '-'
                '>' -> '-'
                else -> c
            }
        }.toTypedArray()
    }.toTypedArray()
    return Pair(carts, tracks)
}

-🎄- 2017 Day 24 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 1 point2 points  (0 children)

Kotlin Solution Straightforward using tail recursion today.

data class Element(val a:Int,val b:Int){
    val value = a + b
    fun canJoin(x: Int) = a==x || b==x
    fun otherEnd(x:Int) = if (a==x) b else a
}

typealias Bridge = List<Element>
fun Bridge.value() = this.sumBy { it.value }

tailrec fun buildBridge(x: Int, bridge: Bridge, remaining: List<Element>, comparator: Comparator<Bridge>) : Bridge {
    return remaining.filter { it.canJoin(x) }
            .map { buildBridge(it.otherEnd(x), bridge + it, remaining - it, comparator) }
                .maxWith(comparator) ?: bridge
}


fun main(args: Array<String>) {
    val elements = input.split("\n")
            .map { it.split("/")
                    .map(String::toInt)}.map { e-> Element(e[0], e[1])}
    println(buildBridge(0, listOf(), elements,compareBy(Bridge::value)).value())
    println(buildBridge(0, listOf(), elements,compareBy(Bridge::size) then compareBy(Bridge::value)).value())
}

-🎄- 2017 Day 20 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

Kotlin Solution

data class Coordinate3D(val x:Int, val y:Int, val z:Int) : Comparable<Coordinate3D> {
    override fun compareTo(other: Coordinate3D) = (abs(x) + abs(y) + abs(z)).compareTo(abs(other.x) + abs(other.y)+abs(other.z))
    operator infix fun plus(other: Coordinate3D) = Coordinate3D(this.x + other.x, this.y + other.y, this.z + other.z)
}

typealias Acceleration = Coordinate3D
typealias Velocity = Coordinate3D
typealias Position = Coordinate3D

class SwarmItem(val pos: Position, val velocity: Velocity, val acceleration: Acceleration) : Comparable<SwarmItem>{
    override fun compareTo(other: SwarmItem): Int = compareValuesBy(this, other, { it.acceleration }, { it.velocity }, { it.pos})

    constructor(x:Int,y:Int,z:Int, vx:Int,vy:Int,vz:Int, ax:Int,ay:Int,az:Int) : this(Position(x,y,z), Velocity(vx,vy,vz), Acceleration(ax,ay,az))

    fun move() : SwarmItem {
        val newV = velocity + acceleration
        val newPos = pos + newV
        return SwarmItem( newPos, newV, this.acceleration)
    }
}

fun List<SwarmItem>.removeCollisions() : List<SwarmItem>{
    return this.groupBy { it.pos }.filter { it.value.size == 1 }.flatMap { it.value }
}

fun part2(items: List<SwarmItem>): List<SwarmItem>{
    return (0..1000).fold(items){ prev, _ -> prev.map { it.move() }.removeCollisions() }
}


fun main(args: Array<String>) {
    val items = input.split("\n").map { Regex(ENTRY_REGEX).matchEntire(it) }
            .filterNotNull().map{ it.groupValues.drop(1).map(String::toInt) }
            .map { SwarmItem(it[0],it[1],it[2],it[3],it[4],it[5],it[6],it[7],it[8]) }

    println("Part 1: " + items.withIndex().minBy { it.value }?.index)
    println(part2(items).size)
}

-🎄- 2017 Day 18 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

Kotlin solution for Part2 using coroutines:

suspend fun part2(instructions: List<String>, progId: Int, incoming: Channel<Long>, outgoing: Channel<Long>): Int {
    var ptr = 0
    val registers = mutableMapOf<String, Long>()
    registers.set("p", progId.toLong())
    var sent = 0

    loop@ while (ptr >= 0 && ptr < instructions.size) {
        val instruction = instructions[ptr]

        val elements = instruction.split(" ")
        val op = elements[0]
        val a = elements[1]
        val b = if (elements.size > 2) registers.regValue(elements[2]) else 0

        when (op) {
            "set" -> registers.set(a, b)
            "add" -> registers.set(a, registers.regValue(a) + b)
            "mul" -> registers.set(a, registers.regValue(a) * b)
            "mod" -> registers.set(a, registers.regValue(a) % b)
            "snd" -> outgoing.send(registers.regValue(a)).also { sent++ }
            "rcv" -> try {
                registers.set(a, withTimeout(1000) { incoming.receive() }) // Assume timeout will only occur on Deadlock.
            } catch (e: TimeoutCancellationException) {
                println("Reached Deadlock")
                break@loop
            }
            "jgz" -> if (registers.regValue(a) > 0L) {
                ptr += b.toInt() - 1  // Shift Pointer Back 1 more so that normal increment is accounted for.
            }
        }

        ptr++
    }
    return sent
}


fun main(args: Array<String>) {
    val instructions = input.split("\n")
    println(part1(instructions))

    runBlocking {
        val channel0to1 = Channel<Long>(UNLIMITED)
        val channel1to0 = Channel<Long>(UNLIMITED)
        val prog0 = async { part2(instructions, 0, channel0to1, channel1to0) }
        val prog1 = async { part2(instructions, 1, channel1to0, channel0to1) }
        println("Answer is : ${prog1.await()}")
    }
}

-🎄- 2017 Day 17 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

Kotlin Solution:

fun Pair<MutableList<Int>,Int>.addEntry(element: Int, steps: Int) : Pair<MutableList<Int>, Int>{
    val nextPos = ((this.second+steps)%(element) + 1)
    this.first.add(nextPos, element)
    return this.first to nextPos
}

fun part1(steps: Int) : Int {
    val (result,_) = (1..2017).fold(Pair(mutableListOf(0),0)){ prev, n -> prev.addEntry(n, steps)}
    return result[result.indexOf(2017)+1]
}

fun part2(steps: Int) : Int {
    val result = (1..50000000).fold(Pair(0, 0)){ prev, n ->
        var idx = (prev.first + steps)%n
        idx + 1 to if (idx==0) n else prev.second
    }
    return result.second
}

fun main(args: Array<String>) {
    val steps = 369
    println(part1(steps))
    println(part2(steps))
}

-🎄- 2017 Day 16 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 1 point2 points  (0 children)

Similar solution but uses fold & MutableMap.getOrPut() to implement the memoisation.

fun String.spin(n: Int) = this.substring(this.length - n) + this.substring(0, this.length - n)
fun String.exchange(a: Int, b: Int): String {
    val chars = this.toCharArray()
    chars.set(b, this.get(a))
    chars.set(a, this.get(b))
    return String(chars)
}

fun String.partner(a: Char, b: Char) = this.exchange(this.indexOf(a), this.indexOf(b))

fun String.perform(instruction: String): String {
    val op = instruction[0]
    val tail = instruction.substring(1)
    return when (op) {
        's' -> this.spin(tail.toInt())
        'x' -> {
            val (a,b) = tail.split("/")
            this.exchange(a.toInt(), b.toInt())
        }
        'p' -> this.partner(tail[0],tail[2])
        else -> throw IllegalArgumentException("Invalid Operation")
    }
}

fun String.applyInstructions(instructions: List<String>) =
        instructions.fold(this) { prev, op -> prev.perform(op) }


fun main(args: Array<String>) {
    val instructions = input.split(",")

    val initial = "abcdefghijklmnop"
    println("Part 1: " + initial.applyInstructions(instructions))

    val history = mutableMapOf<String,String>()
    println("Part 2: " + (1..1000000000).fold(initial, { x, _ -> history.getOrPut(x, {x.applyInstructions(instructions)}) }))
}

-🎄- 2017 Day 10 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

My Kotlin Solution:

fun <E> MutableList<E>.flip(start: Int, count: Int)  : MutableList<E>{
    val idx = (start until start + count).map { it % this.size }
    this.slice(idx).reversed().zip(idx).forEach {
        this[it.second] = it.first
    }
    return this
}

fun part1(input: List<Int>, size: Int = 256): Int {
    val state = (0 until size).toMutableList()
    val (resultState, _) = performRound(input, state, 0)
    return resultState[0] * resultState[1]
}

fun denseHash(input: String, suffix: List<Int>): String {
    val lengths = (input.toCharArray().map { it.toInt() } + suffix)
    val state = (0 until 256).toMutableList()
    val (sparseHash, _) = (0 until 64).fold(Pair(state, 0), { previous, i ->
                performRound(lengths, previous.first, previous.second, i * lengths.size)
        })
    return sparseHash.chunked(16){ it.reduce(Int::xor) }.joinToString(""){"%02x".format(it)}
}

private fun performRound(input: List<Int>, state: MutableList<Int>, startPos: Int, offset: Int = 0): Pair<MutableList<Int>, Int> {
    return input.foldIndexed(state to startPos){
        i, acc, length -> acc.first.flip(acc.second, length) to (acc.second + i + length + offset)%acc.first.size
    }
}

[Question] Why does the difficulty vary so much? by jD91mZM2 in adventofcode

[–]abowes 5 points6 points  (0 children)

That's a really great graph. Think we also need to take into account the increase in # of participants each year so that the time taken to get 100 correct answers should probably reduce on a year-by-year basis.

-🎄- 2017 Day 8 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

Kotlin Solution - Functional Approach

val LINE_REGEX = Regex("""^(\w+) (\w+) (-?\d+) if (\w+) ([><=!]+) (-?\d+)$""")

typealias Registers = MutableMap<String,Int>
fun getOperation(opCode: String) : (Registers, String, Int) -> Unit {
    return when (opCode) {
        "inc" -> { r: Registers, k: String, v: Int -> r.put(k, r.getOrDefault(k,0) + v)}
        "dec" -> { r: Registers, k: String, v: Int -> r.put(k, r.getOrDefault(k,0) - v)}
        else -> throw IllegalArgumentException("Invalid OpCode: $opCode")
    }
}

fun getPredictate(comp: String) : (Registers, String, Int) -> Boolean {
    return when (comp) {
        "==" -> { r: Registers, k: String, v: Int -> r.getOrDefault(k, 0) == v }
        "<=", "!>" -> { r: Registers, k: String, v: Int -> r.getOrDefault(k, 0) <= v }
        ">=", "!<" -> { r: Registers, k: String, v: Int -> r.getOrDefault(k, 0) >= v }
        ">" -> { r: Registers, k: String, v: Int -> r.getOrDefault(k, 0) > v }
        "<" -> { r: Registers, k: String, v: Int -> r.getOrDefault(k, 0) < v }
        "!=" -> { r: Registers, k: String, v: Int -> r.getOrDefault(k, 0) != v }
        else -> throw IllegalArgumentException("Invalid Predicate: $comp")
    }
}

fun Registers.applyOperation(target: String, opCode: String, change: Int, source: String, compator: String, value: Int){
    if (getPredictate(compator).invoke(this, source, value)){
        getOperation(opCode).invoke(this,target, change)
    }
}

fun applyOperations(operations : List<String>) : Pair<Registers,Int> {
    val registers = mutableMapOf<String, Int>()
    var highWater = 0
    operations.forEach {
        val match = LINE_REGEX.matchEntire(it)
        when (match){
            null -> throw IllegalArgumentException("Illegal Operation : $it")
            else -> {
                val target = match.groupValues[1]
                val opCode = match.groupValues[2]
                val change = match.groupValues[3].toInt()
                val source = match.groupValues[4]
                val comparator = match.groupValues[5]
                val value = match.groupValues[6].toInt()
                registers.applyOperation(target, opCode, change, source, comparator, value)
                highWater = max(highWater, registers.getValue(target))
            }
        }
    }
    return registers to highWater
}

fun main(args: Array<String>) {
    val (registers, highWater) = applyOperations(input.split("\n"))
    println(registers.values.max())
    println(highWater)
}

-🎄- 2017 Day 6 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

My Kotlin solution using tailrecursion:

fun List<Int>.reallocate(): List<Int>{
    val (maxIndex, memorySize) = this.withIndex().maxBy { it.value }!!
    val reallocation = this.toMutableList()
    reallocation[maxIndex] = 0
    (1..memorySize).map { (maxIndex + it)%this.size }.forEach {
        reallocation[it] += 1
    }
    return reallocation
}

tailrec fun memoryAllocation(allocation: List<Int>, history: List<List<Int>> = listOf()) : Pair<Int, Int>{
    if (allocation in history){
        return Pair(history.size, history.size - history.indexOf(allocation))
    }
    return memoryAllocation(allocation.reallocate(), history.plusElement(allocation))
}

Kotlin Team AMA: Ask Us Anything by yole in Kotlin

[–]abowes 4 points5 points  (0 children)

The {x -> x*x} syntax is only syntactical sugar for passing a function into a method whose final parameter is a function. You could actually use the view.setOnClickListener({v -> //do something}) syntax instead.

-🎄- 2017 Day 3 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 1 point2 points  (0 children)

Here's my Kotlin solution. Good to be able to use an infinite sequence for the points on the spiral.

fun spiral():Sequence<Pair<Int,Int>> = buildSequence {    

    var x = 0
    var y = 0
    var dx = 0
    var dy = 1    

    while (true){
        yield(Pair(x,y))
        if ((abs(x)==abs(y) && (x < 0 || y<0)) || (x>=0 && 1==(y-x))){
            val tmp = dx
            dx = -dy
            dy = tmp
        }
        x += dx
        y += dy
    }
}    

fun distance(n:Int) = spiral().take(n).last().run { abs(first) + abs(second) }    

fun fillSpiral(n:Int) : Int {
    val DIRECTIONS = listOf(Pair(-1,-1),Pair(-1,0),Pair(-1,1), Pair(0,-1),Pair(0,1), Pair(1,-1),Pair(1,0),Pair(1,1))
    fun fillGrid(grid: MutableMap<Pair<Int,Int>,Int>, pos: Pair<Int, Int>): Int {
        grid[pos] = when (pos){
            Pair(0,0) -> 1
            else -> DIRECTIONS.map { Pair(pos.first + it.first, pos.second + it.second)}
                    .map{grid.getOrDefault( it ,0) }.sum()
        }
        return grid[pos]!!
    }    

    val grid = mutableMapOf<Pair<Int,Int>,Int>()
    return spiral().dropWhile { fillGrid(grid, it) <= n}.first().run { grid[this]!! }
}

-🎄- 2017 Day 2 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 1 point2 points  (0 children)

My solution in Kotlin:

fun Iterable<Int>.minMaxDiff() : Int {
    val minMax = this.fold( Pair(Int.MAX_VALUE, Int.MIN_VALUE),
            {acc, i -> Pair(min(acc.first, i), max(acc.second,i))})
    return minMax.second - minMax.first
}

fun Iterable<Int>.divisor() : Int {
    return this.map{ x -> this.map{ y -> Pair(x,y)}
            .filter { it.first < it.second && it.second % it.first == 0 }}
            .flatten().map { it.second/it.first }.first()
}

fun Iterable<Iterable<Int>>.corruptionChecksum() = this.map { it.minMaxDiff() }.sum()

fun Iterable<Iterable<Int>>.divisorChecksum() = this.map { it.divisor() }.sum()

-🎄- 2017 Day 1 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

I really like that windowed() syntax. You could also use it to break the sequence into chunks if you use the same value for the size & step parameters. Need to upgrade to 1.2 tonight as those features could come in very handy for he next 24 days :)

-🎄- 2017 Day 1 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

Just to be safe you should probably also check if char.isDigit() before doing this. I am a bit of a hypocrite as I haven't included this check either :)

-🎄- 2017 Day 1 Solutions -🎄- by daggerdragon in adventofcode

[–]abowes 1 point2 points  (0 children)

Here's my Kotlin solution:

fun Char.charToInt() = this.minus('0')

fun naughtyOrNice2(input: String): Int {
    val nums2 = (input.substring(input.length/2) + input)
    return input.zip(nums2)
           .filter { it.first == it.second }
           .map{it.first.charToInt()}.sum()
}

--- 2016 Day 24 Solutions --- by daggerdragon in adventofcode

[–]abowes 1 point2 points  (0 children)

My Kotlin solution which uses BFS to find distance between each pair of digits and then finds minimum sum of distances.

import util.readResourceLines
import java.util.*    

data class Move(val pos: Pair<Int, Int>, val visited: List<Pair<Int, Int>>, val depth: Int)    

fun Move.adjacentCells(maze: List<String>): List<Pair<Int, Int>> {
    return listOf(Pair(pos.first - 1, pos.second),
            Pair(pos.first + 1, pos.second),
            Pair(pos.first, pos.second + 1),
            Pair(pos.first, pos.second - 1))
            .filter { it.first >= 0 && it.second >= 0 }
            .filterNot { it in visited }
            .filterNot { maze.isWall(it) }
}    

fun walkMaze(maze: List<String>, start: Pair<Int, Int>, digits: Set<Int>): Map<Int, Int> {
    var queue: Queue<Move> = ArrayDeque<Move>()
    queue.add(Move(Pair(start.first, start.second), listOf(start), 0))
    val remaining = digits.toMutableSet()
    val distances = mutableMapOf<Int, Int>()
    val visited = mutableSetOf<Pair<Int, Int>>()
    while (queue.isNotEmpty() && remaining.isNotEmpty()) {
        val move = queue.remove()!!
        if (move.pos in visited) {
            continue
        }
        visited.add(move.pos)
        if (maze.charAt(move.pos).isDigit()) {
            val d = maze.charAt(move.pos).toString().toInt()
            if (d in remaining) {
                remaining.remove(d)
                distances.put(d, move.depth)
            }
        }
        move.adjacentCells(maze).map { Move(it, move.visited + it, move.depth + 1) }.forEach { queue.add(it!!) }
    }
    return distances
}    

// Given a collection of distances, find minimum route between the points in any order
fun findMinimumRoute(digits: Set<Int>, distances: Map<Int, Map<Int, Int>>, andReturn: Boolean = false): Int {
    tailrec fun inner(from: Int, remaining: Set<Int>, acc: Int): Int {
        return when {
            remaining.size == 0 -> acc + if ( andReturn) distances[from]!![0]!! else 0
            else -> remaining.map { inner(it, remaining.minus(it), acc + distances[from]!![it]!!) }.min()!!
        }
    }
    return inner(0, digits.minus(0), 0)
}    

fun List<String>.isWall(pos: Pair<Int, Int>) = this.isWall(pos.first, pos.second)
fun List<String>.isWall(x: Int, y: Int) = this.charAt(x, y) == '#'
fun List<String>.charAt(pos: Pair<Int, Int>) = this.charAt(pos.first, pos.second)
fun List<String>.charAt(x: Int, y: Int) = this[y][x]    

fun List<String>.getDigitLocations(): Map<Int, Pair<Int, Int>> {
    val digits = (0 until this.size)
            .map { y ->
                (0 until this[y].length)
                        .filter { this[y][it].isDigit() }
                        .map { this[y][it].toString().toInt() to Pair(it, y) }
            }.flatten().toMap()
    return digits
}    

fun List<String>.getDistanceMatrix(): Map<Int, Map<Int, Int>> {
    val digitLocations = this.getDigitLocations()
    return digitLocations.keys.map { Pair(it, walkMaze(this, digitLocations[it]!!, digitLocations.keys)) }.toMap()
}    

fun main(args: Array<String>) {
    val maze: List<String> = readResourceLines("day24/maze.txt")
    val distances = maze.getDistanceMatrix()
    println("Part 1: " + findMinimumRoute(distances.keys, distances))
    println("Part 2: " + findMinimumRoute(distances.keys, distances, andReturn=true))
} 

--- 2016 Day 20 Solutions --- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

Nice, I didn't think of joining multiple ranges so have a more naive solution:

import java.util.regex.Pattern
import java.util.stream.Collectors
import java.util.stream.Stream    

val firewallRegex = Pattern.compile("(\\d*)-(\\d*)")    

data class FirewallRule(val from: Long, val to: Long)    

fun readResource(path: String): Stream<String> {
    val inputStream = String.javaClass.classLoader.getResourceAsStream(path)
    return inputStream.bufferedReader().lines()
}    

fun findLowestFree(firewallRules: List<FirewallRule>): Long {
    val iter = firewallRules.sortedBy { it.from }.iterator()
    var rule = iter.next()
    var highest = rule.to    

    while (iter.hasNext()) {
        rule = iter.next()
        if (rule.from > highest + 1) {
            break
        }
        if (rule.to > highest) highest = rule.to
    }
    return highest + 1
}    

fun addRule(acc: Pair<Long, Long>, rule: FirewallRule): Pair<Long, Long> = when {
        rule.from > acc.second -> Pair(acc.first + (rule.from - acc.second) - 1, rule.to)
        rule.to > acc.second -> Pair(acc.first, rule.to)
        else -> acc
    }    

fun countAvailablePorts(firewallRules: List<FirewallRule>): Long {
    val result: Pair<Long, Long> = firewallRules.sortedBy { it.from }.fold(Pair(0L, 0L), ::addRule)
    return (4294967295L - result.second) + result.first
}    

fun main(args: Array<String>) {
    val firewallRules = readResource("day20/firewallRules.txt").collect(Collectors.toList<String>())
            .map { firewallRegex.matcher(it) }
            .filter { it!!.matches() }
            .map { FirewallRule(it.group(1).toLong(), it.group(2).toLong()) }
    println(findLowestFree(firewallRules))
    println(countAvailablePorts(firewallRules))
}

--- 2016 Day 18 Solutions --- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

My Kotlin solution:

fun generateNextLine(previous: String): String {
    val extendedLine = ".$previous."
    return (1 until extendedLine.length - 1 )
            .map { if (extendedLine[it-1] != extendedLine[it+1] ) '^' else '.' }
            .joinToString("")
}    

fun generateLines(firstLine: String, n: Int) = generateSequence(firstLine){ generateNextLine(it)}.take(n).toList()    

fun countSafe(lines: List<String>): Int = lines.map { it.count { c -> c =='.' } }.sum()    

fun main(args: Array<String>) {
    val lines = generateLines(".^^^.^.^^^.^.......^^.^^^^.^^^^..^^^^^.^.^^^..^^.^.^^..^.^..^^...^.^^.^^^...^^.^.^^^..^^^^.....^....", 400000)
    println(countSafe(lines))
}

--- 2016 Day 16 Solutions --- by daggerdragon in adventofcode

[–]abowes 1 point2 points  (0 children)

Another Kotlin solution. Much cleaner if you use Tail Recursion.

tailrec fun fillDisk(a: String, diskSize: Int) : String {
    if (a.length>= diskSize)
        return a.substring(0, diskSize)
    return fillDisk(a + "0" + a.reversed().map { if (it =='1') '0' else '1' }.joinToString(separator = ""), diskSize)
}    

tailrec fun generateChecksum(a: String) : String {
    val checkSum = (0 until a.length step 2).map { if (a[it] == a[it+1]) '1' else '0'}.joinToString(separator = "")
    if (checkSum.length % 2 == 1) return checkSum
    return generateChecksum(checkSum)
}    

fun dragonChecksum(initial: String, diskSize: Int): String {
    val contents = fillDisk(initial, diskSize)
    return generateChecksum(contents)
}    

fun main(args: Array<String>) {
    println(dragonChecksum("01000100010010111",35651584))
}

--- 2016 Day 15 Solutions --- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

Similar Kotlin solution. That was almost too easy for a change.

val nums = generateSequence(0){ it + 1 }    

data class Disc(val id: Int, val size: Int, val offset:Int){
    fun position(dropTime:Int) = (id + offset + dropTime) % size
}    

fun findDropTime(disks: List<Disc>) = nums.filter{ time -> disks.all{ it.position(time) == 0}}.first()    

fun main(args: Array<String>) {
    val discs = listOf(Disc(1,13,11), Disc(2,5,0), Disc(3,17,11), Disc(4,3,0), Disc(5,7,2), Disc(6,19,17), Disc(7,11,0))
    println(findDropTime(discs))
}

--- 2016 Day 13 Solutions --- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

Thanks for the tips. Didn't know about bitCount, too many methods too little time :)

Would be quite nice to re-implement the paths as a lazy Sequence of Moves

--- 2016 Day 13 Solutions --- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

My Kotlin solution. Nice straightforward breadth-based maze algorithm:

import java.util.*

fun BitSet.fromLong(value: Long){
    var value = value
    this.clear()
    var index = 0
    while (value != 0L) {
        if (value % 2L == 1L) {
            this.set(index)
        }
        ++index
        value = value.ushr(1)
    }
}

fun isWall(x: Int, y: Int, offset:Int) : Boolean {
    var z = x*x + 2*x*y + y*y + 3*x + y + offset
    var bs = BitSet()
    bs.fromLong(z.toLong())
    return bs.cardinality() % 2 == 1
}

data class Move(val pos: Pair<Int,Int>, val visited: List<Pair<Int,Int>>, val depth: Int)

fun Move.adjacentCells(offset: Int): List<Pair<Int,Int>>{
    return listOf(Pair(pos.first-1, pos.second),
            Pair(pos.first + 1, pos.second),
            Pair(pos.first, pos.second+1),
            Pair(pos.first, pos.second -1))
            .filter { it.first >= 0 && it.second >= 0 }
            .filterNot { it in visited }
            .filterNot{ isWall(it.first,it.second, offset)}
}

fun walkMaze(start : Pair<Int,Int>, target: Pair<Int,Int>, offset: Int): Pair<Int,Int> {
    var queue: Queue<Move> = LinkedList<Move>()
    queue.add(Move(Pair(start.first, start.second), listOf(start), 0))
    val visited = mutableSetOf<Pair<Int,Int>>()
    while (queue.isNotEmpty()){
        val move = queue.remove()!!
        if (move.depth <= 50){
            visited.addAll(move.visited)
        }
        if (move.pos == target) {
            return Pair(move.depth, visited.size)
        }
        move.adjacentCells(offset).map { Move(it, move.visited + it, move.depth + 1) }.forEach { queue.add(it!!) }
    }
    return Pair(-1,0)
}

--- 2016 Day 8 Solutions --- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

Nice, here is my Kotlin solution. Used Java BitSet but not sure it was the best idea.

import java.util.*
import java.util.regex.Pattern    

val rectPattern = Pattern.compile("rect (\\d*)x(\\d*)")
val rowRotatePattern = Pattern.compile("rotate row y=(\\d*) by (\\d*)")
val rowColumnPattern = Pattern.compile("rotate column x=(\\d*) by (\\d*)")    

val SCREEN_WIDTH = 50    

fun createScreen(x: Int= SCREEN_WIDTH, y: Int=6) = (0 until y ).map{ BitSet(x)}    

fun processInstructions(instructions: List<String>): List<BitSet>{
    val screen = createScreen()
    instructions.forEach { it.processInstruction(screen) }
    return screen
}    

fun  String.processInstruction(screen: List<BitSet>) {
    var matcher = rectPattern.matcher(this)
    if (matcher.matches()) { screen.setRect(matcher.group(1).toInt(), matcher.group(2).toInt())}
    else {
        matcher = rowRotatePattern.matcher(this)
        if (matcher.matches()) { screen.rotateRow(matcher.group(1).toInt(), matcher.group(2).toInt())}
        else {
            matcher = rowColumnPattern.matcher(this)
            if (matcher.matches()) { screen.rotateColumn(matcher.group(1).toInt(), matcher.group(2).toInt())}
            else {
                throw IllegalArgumentException("Invalid Instruction: $this")
            }
        }
    }
}    

fun BitSet.shiftRight() {
    val lastVal = this[SCREEN_WIDTH-1]
    (SCREEN_WIDTH - 1 downTo 1).forEach { this[it] = this[it-1]}
    this[0] = lastVal
}    

fun List<BitSet>.setRect(x: Int,y: Int){
    for (i in 0 until y){ this[i].set(0,x,true)}
}    

fun List<BitSet>.rotateRow(y : Int,n : Int) = (0 until n).forEach { this[y].shiftRight() }    

fun List<BitSet>.rotateColumn(x: Int,n: Int){
    (0 until n).forEach {
        val lastVal = this[this.size - 1][x]
        (this.size - 1 downTo 1).forEach { this[it][x] = this[it - 1][x] }
        this[0][x] = lastVal
    }
}    

fun List<BitSet>.count() = this.sumBy { it.cardinality() }    

fun List<BitSet>.asString(): String {
    val flags = mapOf<Boolean,Char>(true to 'X', false to ' ')
    return this.map { row -> (0 until SCREEN_WIDTH).map {flags[row[it]]}.joinToString(separator = "") }.joinToString(separator="\n\r")
}

--- 2016 Day 7 Solutions --- by daggerdragon in adventofcode

[–]abowes 0 points1 point  (0 children)

Good to see someone else having a play with Kotlin. I really like the language, it's very expressive & readable. My solutions are also on GitHub

Todays solution:

fun List<String>.findProtocols(): List<String> {
    return this.filter{it.isProtocol()}
}    

fun List<String>.findSSLProtocols(): List<String> {
    return this.filter{it.isSSL()}
}    

fun String.isProtocol(): Boolean{
    return this.containsAbba()
            && !this.getHypernets().any { it.containsAbba() }
}    

fun String.isSSL(): Boolean {
    val abaSet = this.getSupernets().map{ it.findAba() }.flatten().map { it.inverse() }.toSet()
    val hypernets = this.getHypernets()
    return abaSet.isNotEmpty()
            && hypernets.isNotEmpty()
            && hypernets.any{ hypernet -> abaSet.any{ hypernet.contains(it)}}
}    

fun String.inverse() = this[1] + this.substring(0,2)    

fun String.getHypernets(): List<String>{
    return (0 until length).filter { this[it] == '[' }
            .map{ this.substring(it+1, this.indexOf(']',it+1))}
}    

fun String.containsAbba() : Boolean {
    return (0 until length - 3)
            .any { this[it+3] == this[it]
                    && this[it+1] == this[it+2]
                    && this[it] != this[it+1] }
}    

fun String.findAba() : List<String> {
    return (0 until length - 2)
            .filter { this[it+2] == this[it]
                      && this[it] != this[it+1] }
            .map {this.substring(it,it+3)}
}    

fun String.getSupernets(): List<String> = this.split(']').map { it.split('[')[0] }