我正在看一个Perl 代码高尔夫页面(不要问为什么)并且遇到了这个:
第3洞 - 最小的重复模式
编写一个接受字符串的子例程,该字符串可能包含重复模式,并返回最小的重复子字符串.如果字符串不包含重复模式,则子例程应返回undef或空字符串.例如:
input output
'aaaaaa' 'a'
'ababab' 'ab'
'aabaab' 'aab'
'ababaa' ''
Run Code Online (Sandbox Code Playgroud)
显然在Perl中,这可以表示为 sub g3 { pop=~/^(.*?)\1+\z/s&&$1 }
我不太了解Perl,所以我不明白它是如何工作的.我们在Scala能做的最好的事情是什么?我对优雅感兴趣而不是精确的角色数.
这是我的尝试,但它很难看,这就是我要问的原因.
def srp(s: String) =
s.inits.toList.tail.init.map(i => (i * (s.size / i.size), i)).
filter(_._1 == s).map(_._2).reverse.headOption.getOrElse("")
Run Code Online (Sandbox Code Playgroud)
优雅是主观的......
def smallestPat(input: String) = {
(1 to input.length).view
.map(i => input.take(i))
.find{p =>
Iterator.iterate(p)(_ + p)
.takeWhile(_.length <= input.length)
.exists(_ == input) && p != input}
.getOrElse("")
}
List("aaaaaa", "ababab", "aabaab", "ababaa") map smallestPat
// res13: List[String] = List(a, ab, aab, "")
Run Code Online (Sandbox Code Playgroud)
编辑和重新编辑:略微缩短:
def smallestPat(i: String) = {
(1 to i.length - 1)
.map(i.take)
.find(p => p * (i.length / p.length) == i)
.getOrElse("")
}
Run Code Online (Sandbox Code Playgroud)
还有一个,使用grouped:
def smallestPat(i: String) = {
(1 to i.size/2).map(i.take)
.find(p => i.grouped(p.size) forall(p==))
.getOrElse("")
}
Run Code Online (Sandbox Code Playgroud)
你愿意承认Regex基于解决方案吗?
def srp(s: String) = {
val M = """^(.*?)\1+$""".r
s match {
case M(m) => Some(m)
case _ => None
}
}
Run Code Online (Sandbox Code Playgroud)
或者单行:
val srp = """^(.*?)\1+$""".r.findFirstMatchIn(_: String).map(_.group(1))
Run Code Online (Sandbox Code Playgroud)
不像Perl那样简洁,但我发现两者都更具可读性.
| 归档时间: |
|
| 查看次数: |
727 次 |
| 最近记录: |