我有几种方法可以伪造一个单词,我需要随机调用它们,直到一个方法来创建一个"人为错误"。
我想用随机方法调用另一种方法,直到它没问题,但绝不会两次相同。
将它们放在一个数组(或列表)中意味着每次我尝试一种方法时都会重写一个数组,这是一个丑陋的计算复杂性,而且我喜欢写" Scala风格"代码,具有最小的var和可变性。
修改
Oleg Pyzhcov solution效果很好,但现在我有一些String params的函数,而其他函数没有。 如何在集合中存储函数及其调用参数?
val rand: Random = new Random()
def m1(a: String): Boolean = rand.nextBoolean()
def m2(): Boolean = rand.nextBoolean()
def m3(a: String, b: String): Boolean = rand.nextBoolean()
def m4(): Boolean = rand.nextBoolean()
def tryUntilOk(): Unit = {
def out = rand.shuffle(Stream(m1 _, m2 _, m3 _, m4 _))
.map(method => method()) // calling without params so error
.find(result => result) // stop when a method return true
}
编辑2:
详情
我有几种方法试图伪造一个单词,但不保证他们能够实现它。有些方法采取动词的情绪和时态,改变时态或情绪,其他方法只需要正确的写作来删除一些字母,其他方法则取名词的性别和数量来改变它的性别。 / p>
我想在所有可能的方法中调用随机方法,如果它无法伪造单词(例如,给定的名词只存在于女性形式中),则随机调用另一个。重复此操作直到没有更多方法可用,所以我们放弃了。 Oleg的解决方案很适合随机部分,但我无法找到如何给方法调用参数。
具体例子:
package Counterfeiters
import Words.Noun
object Noun extends Counterfeiter[Noun] {
override def counterfeit(word: Noun): Unit = {
// For now I call methods without random order
// This one take only one String param
// And split letters that are duplicated like boot -> bot
word.currentWriting = splitDoubleLetters(word.correctWriting)
// Then we compare word.currentWriting and word.correctWriting
// If the word wasn't containing double letters, it isn't counterfeited
if (!word.isCounterfeited)
// This one take 5 String params
// And counterfeit the gender or the number of the word, randomly
word.currentWriting = counterfeitGenderNumberWord("N", word.correctWriting, word.lemma, word.gender, word.number)
}
}
要应用Oleg的解决方案,我只需要找到如何在集合中存储方法,以及相应的参数。在这种情况下(splitDoubleLetters, (word.correctWriting))
和(counterfeitGenderNumberWord, ("N", word.correctWriting, word.lemma, word.gender, word.number))
。
解
我做了Oleg在评论中建议的事情:
object Noun extends Counterfeiter[Words.Noun] {
override def counterfeit(word: Words.Noun): Unit = {
if (word.isCounterfeited) return
def split: () => String = () => splitDoubleLetter(word.correctWriting)
def ctftGenderNumber: () => String = () => counterfeitGenderNumberWord("N", word.correctWriting, word.lemma, word.gender, word.number)
val methods: immutable.Seq[() => String] = Stream(split, ctftGenderNumber)
val res: Option[String] = randomizer.shuffle(methods) // Shuffle methods
.map(method => method()) // Call them one by one
.find(result => result != word.correctWriting) // Until one counterfeit the word
word.currentWriting = res match {
case None => word.correctWriting // If every methods failed
case _ => res.get
}
}
}
SergGr explained这是一个可能的架构,我很清楚。我很清楚。 如果您想更好地了解我的工作,您可以在GitHub找到完整的项目代码。
答案 0 :(得分:2)
使用Stream
进行懒惰和Random#shuffle
方法,您可以获得:
import scala.util.Random
def m1(): Boolean = Random.nextBoolean()
def m2(): Boolean = Random.nextBoolean()
def m3(): Boolean = Random.nextBoolean()
def m4(): Boolean = Random.nextBoolean()
def out = Random.shuffle(Stream(m1 _, m2 _, m3 _, m4 _))
.map(method => method()) // pass in any necessary params
.find(result => !result) // do your check
此处out
的类型为Option[Boolean]
,因为方法m1-m4都返回Boolean
答案 1 :(得分:1)
我同意Oleg的说法,你需要的是将所有方法转换为相同形状的集合。我假设在word
包中你有基类Word
,其中包含具有不同特征的语音的不同部分的子类。像这样:
abstract class Word(val correctWriting: String, var currentWriting: String, val lemma: String) {
def isCounterfeited: Boolean = !correctWriting.equals(currentWriting)
}
sealed trait Gender
case object Masculine extends Gender
case object Feminine extends Gender
case object Neutral extends Gender
sealed trait Number
case object Singular extends Number
case object Plural extends Number
class Noun(correctWriting: String, currentWriting: String, lemma: String, val gender: Gender, val number: Number) extends Word(correctWriting, currentWriting, lemma) {
}
您将特征Counterfeiter
定义为
trait Counterfeiter[-W <: Word] {
def counterfeit(word: W): Unit
}
然后你可以定义助手类RandomCompoundCounterfeiter
type SimpleCounterfeiter[W <: Word] = (String, W) => String
class RandomCompoundCounterfeiter[W <: Word](val children: Seq[SimpleCounterfeiter[W]]) extends Counterfeiter[W] {
override def counterfeit(word: W): Unit = {
Random.shuffle(children).takeWhile(c => {
word.currentWriting = c(word.correctWriting, word)
!word.isCounterfeited
})
}
}
RandomCompoundCounterfeiter
是您要求的主要工作类:它以随机顺序应用其他SimpleCounterfeiter
。它通过首先对children
列表(即真正的造假者)进行混洗并应用它们直到最后word.isCounterfeited
为true
或列表耗尽为止。
请注意,RandomCompoundCounterfeiter
会在每次通话时重新洗牌造假者。如果你想让你的命令在不同的应用程序运行之间有所不同,但是对于单次运行中的不同单词是相同的,只需将shuffling移动到构造函数。
现在定义基本SimpleCounterfeiter
函数的列表,例如
object Noun {
val singularCounterfeiter = (correctWriting: String, word: Noun) => {
if (word.number == Singular)
correctWriting
else
???
}
val pluralCounterfeiter = (correctWriting: String, word: Noun) => {
if (word.number == Plural)
correctWriting
else
???
}
def genderCounterfeiter(newGender: Gender): SimpleCounterfeiter[Noun] = (correctWriting: String, word: Noun) => {
if (word.gender == newGender)
correctWriting
else
???
}
val all = List(
GenericCounterfeiters.splitDoubleLetters,
singularCounterfeiter,
pluralCounterfeiter,
genderCounterfeiter(Neutral),
genderCounterfeiter(Masculine),
genderCounterfeiter(Feminine))
val nounCounterfeiter = new RandomCompoundCounterfeiter[Noun](all)
}
现在,您可以使用Noun.nounCounterfeiter
作为随机Counterfeiter[Noun]
。这里的主要思想是为每个原子伪造者提供相同的形状,这是通过将整个Word
(或其子类)传递给方法来实现的。所以现在每种方法都可以访问所有相关信息,如果需要的话。
如果您希望将伪造者中的典型if
条件移至单个位置,则可以将代码重构为更多OOP方式:
class RandomCompoundCounterfeiter[W <: Word](val children: Seq[Counterfeiter[W]]) extends Counterfeiter[W] {
override def counterfeit(word: W): Unit = {
Random.shuffle(children).takeWhile(c => {
c.counterfeit(word)
!word.isCounterfeited
})
}
}
trait SimpleCounterfeiter[-W <: Word] extends Counterfeiter[W] {
override def counterfeit(word: W): Unit = {
if (isApplicable(word))
word.currentWriting = counterfeitImpl(word.correctWriting, word)
}
def isApplicable(word: W): Boolean
def counterfeitImpl(correctWriting: String, word: W): String
}
object GenericCounterfeiters {
val splitDoubleLetters = new SimpleCounterfeiter[Word] {
override def isApplicable(word: Word) = true
override def counterfeitImpl(correctWriting: String, word: Word) = ???
}
}
object Noun {
val singularCounterfeiter = new SimpleCounterfeiter[Noun] {
override def isApplicable(word: Noun) = word.number != Singular
override def counterfeitImpl(correctWriting: String, word: Noun) = ???
}
val pluralCounterfeiter = new SimpleCounterfeiter[Noun] {
override def isApplicable(word: Noun) = word.number != Plural
override def counterfeitImpl(correctWriting: String, word: Noun) = ???
}
def genderCounterfeiter(newGender: Gender) = new SimpleCounterfeiter[Noun] {
override def isApplicable(word: Noun) = word.gender != newGender
override def counterfeitImpl(correctWriting: String, word: Noun) = ???
}
val all = List(
GenericCounterfeiters.splitDoubleLetters,
singularCounterfeiter,
pluralCounterfeiter,
genderCounterfeiter(Neutral),
genderCounterfeiter(Masculine),
genderCounterfeiter(Feminine))
val nounCounterfeiter = new RandomCompoundCounterfeiter[Noun](all)
}