DEV Community

Discussion on: Daily Challenge #136 - The Deaf Rats of Hamelin

Collapse
 
avalander profile image
Avalander • Edited

Slightly over-engineered solution in Scala.

object Hamelin {
  trait Character
  case object Piper extends Character
  case object Left extends Character
  case object Right extends Character

  type Town = Seq[Character]

  def of (raw: String): Town = {
    @tailrec
    def iter (chars: Seq[Char], result: Town = List()): Town =
      chars match {
        case Nil              => result
        case 'P' :: xs        => iter(xs, result :+ Piper)
        case 'O' :: '~' :: xs => iter(xs, result :+ Left)
        case '~' :: 'O' :: xs => iter(xs, result :+ Right)
        case _ :: xs          => iter(xs, result)
      }
    iter(raw.toList)
  }

  def countDeafRats (town: Town): Int = {
    val (result, _) = town.foldLeft((0, false)) {
      case ((x, _), Piper)     => (x, true)
      case ((x, false), Left)  => (x + 1, false)
      case ((x, true), Right)  => (x + 1, true)
      case (x, _)              => x
    }
    result
  }

  val solve = countDeafRats _ compose of _
}

And the tests:

class HamelinTest extends FunSuite {
  trait Input {
    val raw1 = "~O~O~O~O P"
    val raw2 = "P O~ O~ ~O O~"
    val raw3 = "~O~O~O~OP~O~OO~"
  }

  trait Parsed {
    val parsed1 = List(Right, Right, Right, Right, Piper)
    val parsed2 = List(Piper, Left, Left, Right, Left)
    val parsed3 = List(Right, Right, Right, Right, Piper, Right, Right, Left)
  }

  test("of") {
    new Input with Parsed {
      assert(of(raw1) == parsed1)
      assert(of(raw2) == parsed2)
      assert(of(raw3) == parsed3)
    }
  }

  test("countDeafRats") {
    new Parsed {
      assert(countDeafRats(parsed1) == 0)
      assert(countDeafRats(parsed2) == 1)
      assert(countDeafRats(parsed3) == 2)
    }
  }

  test("solve") {
    new Input {
      assert(solve(raw1) == 0)
      assert(solve(raw2) == 1)
      assert(solve(raw3) == 2)
    }
  }
}