最小重复子串

发布于 2024-12-12 01:01:51 字数 731 浏览 0 评论 0原文

我正在查看 Perl 代码高尔夫页面(不要问为什么)并发现了这个:

第 3 洞 - 最小重复图案

编写一个子例程,它接受一个字符串,该字符串可能包含 重复模式,并返回最小的重复子串。如果 该字符串不包含重复模式,子例程 应该返回 undef 或空字符串。例如:

input    output 
'aaaaaa' 'a' 
'ababab' 'ab' 
'aabaab' 'aab' 
'ababaa' ''

显然在 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("")

I was looking at a Perl code golf page (don't ask why) and came across this:

Hole 3 - Smallest Repeating Pattern

Write a subroutine that accepts a string which may consist of a
repeating pattern, and returns the smallest repeating substring. If
the string does not consist of a repeating pattern, the subroutine
should return undef or the empty string. e.g.:

input    output 
'aaaaaa' 'a' 
'ababab' 'ab' 
'aabaab' 'aab' 
'ababaa' ''

Apparently in Perl this can be expressed as sub g3 { pop=~/^(.*?)\1+\z/s&&$1 }

I don't know much Perl so I don't understand how this works. What is the best we can do in Scala? I'm more interested in elegance than the precise number of characters.

Here is my attempt, but it's pretty ugly, which is why I'm asking.

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("")

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

北方。的韩爷 2024-12-19 01:01:51

优雅是主观的...

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, "")

编辑和重新编辑:稍微短一些:

def smallestPat(i: String) = {
   (1 to i.length - 1)
      .map(i.take)
      .find(p => p * (i.length / p.length) == i)
      .getOrElse("")
}

再一个,使用分组

def smallestPat(i: String) = {
  (1 to i.size/2).map(i.take)
  .find(p => i.grouped(p.size) forall(p==))
  .getOrElse("")
}

Elegance is subjective...

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, "")

Edit and re-edited: slighty shorter:

def smallestPat(i: String) = {
   (1 to i.length - 1)
      .map(i.take)
      .find(p => p * (i.length / p.length) == i)
      .getOrElse("")
}

One more, using grouped:

def smallestPat(i: String) = {
  (1 to i.size/2).map(i.take)
  .find(p => i.grouped(p.size) forall(p==))
  .getOrElse("")
}
孤独患者 2024-12-19 01:01:51

您愿意接受基于 Regex 的解决方案吗?

def srp(s: String) = {
  val M = """^(.*?)\1+$""".r
  s match {
    case M(m) => Some(m)
    case _ => None
  }
}

或者一句单行话:

val srp = """^(.*?)\1+$""".r.findFirstMatchIn(_: String).map(_.group(1))

不像 Perl 那样简洁,但我发现两者都更具可读性。

Are you willing to admit a Regex-based solution?

def srp(s: String) = {
  val M = """^(.*?)\1+$""".r
  s match {
    case M(m) => Some(m)
    case _ => None
  }
}

Or a one-liner:

val srp = """^(.*?)\1+$""".r.findFirstMatchIn(_: String).map(_.group(1))

Not as concise as the Perl, but I find both considerably more readable.

决绝 2024-12-19 01:01:51

这是等效的 Scala 单行代码:

"""(?:^(.*?)\1+$)|.*""".r replaceAllIn (_: String, "$1")

This is the equivalent Scala one-liner:

"""(?:^(.*?)\1+$)|.*""".r replaceAllIn (_: String, "$1")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文