Scala - 在过滤器和放大器方面遇到问题瓦尔斯

时间:2015-06-17 19:52:03

标签: scala

在Scala中进行exercism.io练习。这是我目前的代码:

case class Allergies() {
  def isAllergicTo(allergen:Allergen.Allergen, score:Int) = {
    if (score < allergen.value || score == 0) false
    else true
  }

  def allergies(score:Int) = {
    val list = List(Allergen.Cats, Allergen.Pollen, Allergen.Chocolate, Allergen.Tomatoes,
      Allergen.Strawberries, Allergen.Shellfish, Allergen.Peanuts, Allergen.Eggs)

    list.filter(isAllergicTo(_, score)).sortBy(v => v.value)
  }
}

object Allergen {
  sealed trait Allergen { def value: Int }
  case object Eggs extends Allergen { val value = 1 }
  case object Peanuts extends Allergen { val value = 2 }
  case object Shellfish extends Allergen { val value = 4 }
  case object Strawberries extends Allergen { val value = 8 }
  case object Tomatoes extends Allergen { val value = 16 }
  case object Chocolate extends Allergen { val value = 32 }
  case object Pollen extends Allergen { val value = 64 }
  case object Cats extends Allergen { val value = 128 }
}

由于测试的格式化方式,这些奇怪的构造中的一些只是在测试中传递语法问题的简单方法。除此之外,快速浏览一下你所看到的......

过敏症得分并返回可能增加此分数的所有过敏原。因此,如果一个人的分数为34,他们必须对巧克力和花生过敏。 isAllergicTo采取过敏原和分数,并确定是否有可能存在过敏原。

我遇到的问题是我的过滤器逻辑是正确的,但是现在以34作为输入的示例,它不仅会返回ChocolatePeanuts,但得分低于Chocolate的所有内容。我不确定如何解决这个问题的分数正在改变以反映找到的匹配,部分原因是分数是一个val,不能使用中间变量重新分配。

我知道我的问题很模糊,但我不确定在这个问题上的继续,并希望得到任何建议。

3 个答案:

答案 0 :(得分:3)

问题只是isAllergicTo执行不正确。如果您修复它,则根本不需要更改分数。作为提示:考虑分数的二进制表示。

答案 1 :(得分:2)

“Bitmasking”通常用于将一组项表示为整数值。

如果您有一系列项目(例如过敏原),则为其指定的值等于2的幂。鸡蛋为2^0,花生为2^1,依此类推。要创建一组这些项目,请按该项目中项目的按位“或”。通过使用2的不同幂,当值以二进制表示时,每个项的值中的1将位于不同的位置。

例如:

   Peanuts:    00000010  (2)
OR Chocolate:  00100000  (32)
----------------------------
= (combined):  00100010  (34)

要检查项目是否在集合(值)中,您可以使用按位“AND”来比较项目的值与集合的值,例如

    Set:     00100010  (34)
AND Peanuts: 00000010  (2)
---------------------------
    result:  00000010  (2)

    Set:       00100010  (34)
AND Shellfish: 00000100  (4)
-----------------------------
    result:    00000000  (0)

如果Peanuts没有进入集合,结果值将为0.

看起来我有点迟了,但无论如何我都是张贴这个

答案 2 :(得分:2)

使用尾递归函数:

  def allergies(score:Int) = {
    val list = List(Allergen.Cats, Allergen.Pollen, Allergen.Chocolate, Allergen.Tomatoes,
      Allergen.Strawberries, Allergen.Shellfish, Allergen.Peanuts, Allergen.Eggs)

    def inner(maybeSmaller: List[Allergen.Allergen], score: Int, allergies: List[Allergen.Allergen]) : List[Allergen.Allergen] =
      if (score == 0 || maybeSmaller.length == 0) allergies.reverse
      else {
        val smaller = maybeSmaller.filter(isAllergicTo(_, score))//(_.value < score)
        inner(smaller.tail, score - smaller.head.value, smaller.head :: allergies)
      }

    inner(list.sortBy(- _.value), score, Nil)
  }