Advent of Code 2016 Day 16 (Scala)

Advent of Code 2016 Day 15 (Typescript)
Advent of Code 2016 Day 14 (Go)

Advent of Code 2016 Day 13 (Lua)
Advent of Code 2016 Day 12 (C#)
Advent of Code 2016 Day 11 (Groovy)

Advent of Code 2016 Day 10 (OcaML)

Advent of Code 2016 Day 9 (Factor)

Advent of Code 2016 Day 8 (c++)
Advent of Code 2016 Day 7 (Javascript)
Advent of Code 2016 – Day 6 (Julia)
Advent of Code 2016 – Day 5( Java 8)

Advent of Code 2016 – Day 4 (Perl 6)

Advent of Code 2016 – Day 3 (Clojure)
Advent of Code – Day 2 (Python 3)
Advent Of Code 2016 – Day 1(Haskell)

Day 16

Start: 12/21/2016

Finish 12/21/2016

Language: Scala

SPOILER ALERT: If you have any inkling, any whatsoever, to work on the Advent of Code…. DO NOT READ THIS BLOG POST.  DO NOT LOOK AT MY GITHUB PROJECT.  It is no fun if you’re not solving it yourself, and you’ll feel so much better about yourself if you can figure it out without looking up an answer.  This blog post is not to give away the answer, but instead, is there for people to learn from.

As always, the following code is in my GitHub: https://github.com/pviafore/AdventOfCode2016

The Challenge

This one felt easy.   It was all about generating an ever expanding string in a preset pattern, and then reducing it back down with a predefined algorithm.  Didn’t sound too bad.

I decided to tackle this guy in Scala.  I’ve done a little Scala at work, but not enough to be able to code up a Hello World without looking up a reference.

Part 1

It is nice working in an expressive language.  I tried to keep this as functional as I could, and ended up with 50 lines of Scala Code


object Challenge1 {

  val input = "01000100010010111"
  val diskSize = 272
  def invertByte(c: Char): Char = {
       if (c == '0')  '1' else '0'
  }

  def invert(s: String): String = {
      s.map(c=>invertByte(c))
  }

  def dragonize(s: String): String = {
      s + "0" + invert(s reverse)
  }

  def getDragon(input: String, maxSize: Int) : String = {
      if (input.length >= maxSize) {
          return input.slice(0, maxSize)
      }
      else {
          return getDragon(dragonize(input), maxSize)
      }
  }

  def condenseBytes(c1: Char, c2: Char): Char = {
      if (c1 == c2) '1' else '0'
  }

  def getChecksum(s: String):String = {
      if (s.length % 2 == 1) {
          s
      }
      else{
          val next:String = s.grouped(2).map(s => condenseBytes(s.charAt(0), s.charAt(1))).mkString
          getChecksum(next)
      }
  }

  def main(args: Array[String]): Unit = {
    val s:String = getDragon(input, diskSize)
    val checksum:String = getChecksum(s)
    println(checksum)
    
  }
}

The first part of this was, given a string, expand it by reversing it, inverting the bits, and appending it to the end of the original string (separated by a 0).  Keep doing this until you hit a max limit.  This wasn’t too bad.  I first went down the path of Scala Streams (I do like infinite sequences), but it turns out I didn’t care about the intermediate values, just the last one, so I converted to a function call


def invertByte(c: Char): Char = {
       if (c == '0')  '1' else '0'
  }

  def invert(s: String): String = {
      s.map(c=>invertByte(c))
  }

  def dragonize(s: String): String = {
      s + "0" + invert(s reverse)
  }

  def getDragon(input: String, maxSize: Int) : String = {
      if (input.length >= maxSize) {
          return input.slice(0, maxSize)
      }
      else {
          return getDragon(dragonize(input), maxSize)
      }
  }

The next part was to take our string, and reduce each pair of characters down to a ‘1’ if the two characters were the same or a ‘0’ otherwise.  Again, repeat until you have a string length that is odd.  That is the answer


 def condenseBytes(c1: Char, c2: Char): Char = {
      if (c1 == c2) '1' else '0'
  }

  def getChecksum(s: String):String = {
      if (s.length % 2 == 1) {
          s
      }
      else{
          val next:String = s.grouped(2).map(s => condenseBytes(s.charAt(0), s.charAt(1))).mkString
          getChecksum(next)
      }
  }

Part 2

Just had to change the input size on this (and up the memory on my JVM) and I got the answer lickity-split.

Wrap-up

I give myself an A for this one.  I did it quick, and I kept it closer to the FP side of Scala than the mutable state side.  The answers were right, and I got to learn about streams along the way (even though I didn’t use them in my final solution).

Next up is Ruby for day 17!  Yay for another expressive language.

5 thoughts on “Advent of Code 2016 Day 16 (Scala)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s