在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
作为输入的示例,它不仅会返回Chocolate
和Peanuts
,但得分低于Chocolate
的所有内容。我不确定如何解决这个问题的分数正在改变以反映找到的匹配,部分原因是分数是一个val,不能使用中间变量重新分配。
我知道我的问题很模糊,但我不确定在这个问题上的继续,并希望得到任何建议。
答案 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)
}