forked from matelaszlo/advent-of-code-scala
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay15.scala
61 lines (48 loc) · 2.26 KB
/
Day15.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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package com.lmat.adventofcode.year2015
import com.lmat.adventofcode.CommonPuzzle
import com.lmat.adventofcode.year2015.Day15Definitions._
import com.lmat.util.Files.readResource
object Day15Definitions {
case class Ingredient(name: String, capacity: Int, durability: Int, flavour: Int, texture: Int, calories: Int)
}
object Day15 extends CommonPuzzle[Seq[Ingredient], Seq[Map[Ingredient, Int]], Int, Int]{
override def parse(resource: String): Seq[Ingredient] = readResource(resource).flatMap(parseIngredient)
def parseIngredient(row: String): Option[Ingredient] = {
val ingredient = "(.*): capacity (.*), durability (.*), flavor (.*), texture (.*), calories (.*)".r
row match {
case ingredient(name, capacity, durability, flavour, texture, calories) =>
Some(Ingredient(name, capacity.toInt, durability.toInt, flavour.toInt, texture.toInt, calories.toInt))
case _ =>
None
}
}
override def preProcess(ingredients: Seq[Ingredient]): Seq[Map[Ingredient, Int]] =
combinations(ingredients, 100)
/**
* We can do combinations with repetitions by repeating our input first
* Then invoking the combinations function on collections
*/
def combinations(ingredients: Seq[Ingredient], n:Int): Seq[Map[Ingredient, Int]] = {
ingredients
.flatMap(i => List.fill(n)(i.name))
.combinations(n)
.to(LazyList)
.map(_.groupBy(n => ingredients.find(_.name == n).get).view.mapValues(_.size).toMap)
}
override def part1(combinations: Seq[Map[Ingredient, Int]]): Int =
combinations.map(score).max
def score(ingredients: Map[Ingredient, Int]): Int =
ingredients
.map { case (i, n) => score(i, n) }
.fold(Seq())((total, current) =>
if (total.isEmpty) current
else (total zip current).map { case (a, b) => a + b })
.map(c => if (c < 0) 0 else c)
.product
def score(ingredient: Ingredient, n: Int): Seq[Int] =
Seq(ingredient.capacity * n, ingredient.durability * n, ingredient.flavour * n, ingredient.texture * n)
override def part2(combinations: Seq[Map[Ingredient, Int]]): Int =
combinations.filter(calories(_) == 500).map(score).max
def calories(ingredients: Map[Ingredient, Int]): Int =
ingredients.map{case (i : Ingredient, n) => i.calories * n}.sum
}