forked from matelaszlo/advent-of-code-scala
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay11.scala
38 lines (26 loc) · 1.4 KB
/
Day11.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.lmat.adventofcode.year2015
import com.lmat.adventofcode.SimpleCommonPuzzle
import com.lmat.util.Files.readResource
object Day11 extends SimpleCommonPuzzle[String, String, String] {
override def parse(resource: String): String = readResource(resource).head
override def part1(current: String): String = nextPassword(current)
def nextPassword(current:String): String =
LazyList.iterate(current)(increment).drop(1).find(isValid).get
def increment(password: String): String = password.toCharArray.toSeq match {
case start :+ 'z' => increment(start.mkString) :+ 'a'
case start :+ last => (start :+ increment(last)).mkString
}
def increment(char: Char): Char =
(char + 1).toChar
def isValid(password:String): Boolean =
runOfAtLeast(3)(password) && noneOf(Seq('i', 'o', 'l'))(password) && differentDoubles(2)(password)
def runOfAtLeast(n: Int)(string: String): Boolean =
string.toSeq.sliding(n).map(_.unwrap).exists(isRun)
def isRun(string: String): Boolean =
(string zip string.drop(1)).forall { case (l, r) => r - l == 1 }
def noneOf(letters: Seq[Char])(string: String): Boolean =
!letters.exists(string.contains(_))
def differentDoubles(n:Int)(string: String): Boolean =
(for (letter <- 'a' to 'z') yield Seq(letter, letter).mkString).count(string.contains(_)) >= n
override def part2(current: String): String = nextPassword(nextPassword(current))
}