【问题标题】:Palindrome Golf回文高尔夫
【发布时间】:2010-09-18 17:10:50
【问题描述】:

目标:任何语言。返回字符串是否为回文的最小函数。这是我用 Python 编写的:

R=lambda s:all(a==b for a,b in zip(s,reversed(s)))

50 个字符。

接受的答案将是当前最小的答案 - 这将随着找到较小的答案而改变。请指定您的代码使用的语言。

【问题讨论】:

  • 第一个发布 PDA 的人获得奖励积分
  • 请使其社区 wiki 可编辑
  • 另一个不是重复的
  • 这不是完全重复的!另一个不是要求最小的实现。密切相关?是的。重复 - 不!!!
  • 我们是否关心在回文中,标点和空格的变化通常是允许的?这里的一些解决方案似乎忽略了这一点。

标签: code-golf rosetta-stone palindrome


【解决方案1】:

J 中的 7 个字符:不确定这是否是最好的方法,我对 J 有点陌生 :)

p=:-:|.

解释:|。反转输入。 -:比较。操作数是隐式的。

p 'radar'
1

p 'moose'
0

【讨论】:

  • 哇,这很神秘。就个人而言,我实际上不能说我见过更神秘的语言。
  • The Wicked Flea:哦,还有更神秘的东西,比如 unlambda、befunge 或 INTERCAL。我的一个朋友写了一个编译器to unlambda...
  • @wnoise:编译成深奥的语言并不难。它们非常简单,因此您只需正确设置它,然后递归处理其余部分。
  • 令人印象深刻......但我不想用那种语言编写一个真正的程序!
  • @Thomas 写 J 实际上很有趣。阅读它(即使你写了它)是困难的部分
【解决方案2】:

这是我的;它是用我发明的一种特定领域的语言编写的,称为“回文”。

p

编辑:不那么轻率的版本(i386 asm,AT&T 语法)

xor %eax, %eax
mov %esi, %edi
#cld    not necessary, assume DF=0 as per x86 ABI
repne scasb
scan:
    dec %edi
    cmpsb
    .byte 0x75, 6    #jnz (short) done
    dec %edi
    cmp %esi, %edi
    .byte 0x72, -9    #jb (short) scan
inc %eax
done:

16 字节,字符串指针在 ESI 中,结果在 EAX 中。

【讨论】:

  • 那为什么是 p?您应该使用字符串作为参数运行解释器
  • 你一定把回文和回文++混淆了,回文++是一种相关但不同的语言。
  • Vinko Vrsalovic,您只是没有阅读“回文”语言的文档。 p - 自动向用户询问参数。
  • 呵呵是的,我担心如果我说“任何语言”会发生这种情况
  • 您必须指定一些内容 - 您使用的是 Intel 的语法还是 AT&T 的?我想是后者,否则第二行会用 EDI 上的任何内容清除寄存器 ESI 的先前内容:(而且我不明白为什么你需要先清除 EAX。
【解决方案3】:

可悲的是,我无法理解一千字以下...

(LabVIEW。是的,他们会让任何流浪汉在这里发帖;)

【讨论】:

  • 哈哈哈那是什么鬼?也许我不应该在喝酒的时候看 SOF.... +1 大声笑
  • LabView 是一种数据流语言,用于对硬件控制器等进行编程。你在看源代码(都是图标和箭头)
  • 顺便说一句,它还被用于有史以来最怪异和最酷的发明玩具:乐高。乐高思维风暴在 LabView 中编程
  • LabView 只是让非程序员更容易编程的另一种尝试。它有它的用途,也许作为一种教学工具,但我不会将它用于严肃的目的......(它不是编程乐高的唯一方法。)
  • ...ni.com/solutions。里面可能有一些严重的。
【解决方案4】:

Haskell,15 个字符:

p=ap(==)reverse

更易读的版本,16个字符:

p x=x==reverse x

【讨论】:

  • 事实上,这与 perl 具有相同的字符数,但执行 "p x=x==reverse x" 是 16 个字符(去掉空格)。如果可以的话,修改你的答案
【解决方案5】:

另一个更短的python版本(21个字符):

R=lambda s:s==s[::-1]

【讨论】:

  • 哇,我不懂 Python,但那令人印象深刻。
【解决方案6】:

冒着被否决票的风险,所有这些都只是调用某种隐藏所有真实编程逻辑的命令reverse

我想知道在每种语言中执行此操作的最短手动方法是什么。

【讨论】:

  • 原来是平台核心库的一部分。可能算法高尔夫就可以了。 1+虽然
  • 那么内置向后迭代的语言呢?从技术上讲,python 的 string[::-1] 不是“内置反向”......它更通用。
  • 查看我对 Kibbee 的回答。在 Lua 中,如果没有字符串库,您将无法访问字符串的单个字符!现在,提供两个版本(对于能够同时执行这两种功能的语言)可能会很有趣,确实是最短的和最短的算法版本。
【解决方案7】:

使用 C# 和 LINQ 运算符:

public bool IsPalindrome(string s)
{
    return s.Reverse().SequenceEqual(s);
}

如果你认为 Reverse 是作弊,你可以通过减少来完成整个事情:

public bool IsPalindrome(string s)
{
    return s.Aggregate(new StringBuilder(),
                       (sb, c) => sb.Insert(0, c),
                       (sb) => sb.ToString() == s);
}

【讨论】:

  • +1,非常有创意地使用 Aggregate...但我不会认为 Reverse 是作弊,因为它是标准的 Linq 运算符,几乎所有其他答案都使用它。
  • 你可以把第一个写成s.Reverse().ToString()==s;,第二个写成!s.Where((c,i)=>c!=s[s.Length-i-1]).Any()
【解决方案8】:

Perl(27 个字符):

sub p{$_[0]eq reverse$_[0]}

Ruby(24 个字符):

def p(a)a==a.reverse end

【讨论】:

  • 你在括号上浪费了两个字符来反转......做得好;我在 Perl 的最初尝试是 39 岁。
  • 这个 Perl 变种太过分了。反例:sub p{$_ eq reverse} while () { chomp; $x = $_; $_ = "aaaaaaaab"; print "$x 是回文\n" if p($x); }
  • @Jonathan,感谢指正,20 字符的版本根本就错了。
  • @_[0] 恰好在这里工作,但明显表明有人不了解 Perl 的印记;另外,我刚刚回答了一个 24 字符的 Perl 解决方案。
  • @ephemient,感谢您指出这一点,我很惊讶没有人更早注意到它。
【解决方案9】:

73 个干净、可读、用 java 编写的字符

boolean p(String s){return s.equals(""+new StringBuffer(s).reverse());}

和平 :)

【讨论】:

  • 既然可读性很强,怎么会出现“”+呢?如果你想要可读性,我推荐 Haskell 解决方案
  • 提醒:投票是针对“无用”的答案(阅读工具提示!);这既正确又有益。请负责任地投票。 +1 取消对朋克投反对票的轻率驾车
  • 不,不是,这是 comwiki 的答案。 :P
  • 我的反对意见既不是轻率的,也不是偷偷摸摸的。我留下评论来解释它
【解决方案10】:

无意义的 Haskell 版本(15 个字符,但除非包含 Control.Arrow 和 Control.Monad 并忽略单态性限制,否则实际上并不能正常工作):

p=ap(==)reverse

【讨论】:

  • “ap”从何而来?
  • 它在 Control.Monad 中,尽管需要 Control.Arrow 来为 (Monad ((->) a) 提供一个实例。ap 也可以写/理解为 "ap fgh = fh (gh )”,在这种情况下就像 S 组合子(在 SKI 演算中)。把它想象成在另一个环境中应用一个函数。
【解决方案11】:

Lua 更注重可读性而不是简洁性,但确实做到了 37 个字符:

function p(s)return s==s:reverse()end

变种,只是为了好玩(相同大小):

p=function(s)return s==s:reverse''end

JavaScript 版本更冗长(55 个字符),因为它没有字符串反转功能:

function p(s){return s==s.split('').reverse().join('')}

【讨论】:

  • 我喜欢JS版本..不会这么想的。
  • 老实说,我在一个 JS FAQ 中发现了这个,我认为这是一个常见的成语,所以我没有提到它。
【解决方案12】:
(equal p (reverse p))

口齿不清。 18 个字符。

好的,这是一个特例。如果直接输入到 lisp 解释器并且 p 已经定义,这将起作用。

否则,这将是必要的:

(defun g () (equal p (reverse p)))

28 个字符。

【讨论】:

  • 第二个 ADEpt - 你的 defun 在哪里?
  • 缺少它不起作用的参数(至少在 SBCL 中)这给我们留下“(defun g(p)(等于 p(反向 p)))”(35 个字符(你的 28实际上是 34)。您可以通过删除不必要的空格将其降至 32:“(defun g(p)(equal p(reverse p)))”。所有都要求 p 是一个字符串。
  • 不,他们没有。 reverse 适用于任何序列,equal 适用于字符串、位向量和 conses(列表),以及其他与回文无关的内容。
  • 由于 Common Lisp 是一个 lisp-2,你可以这样写:(defun p(p)(equal p(reverse p))) :o)
【解决方案13】:

我会更进一步:完整的 c 代码,编译并运行。

90 个字符

main(int n,char**v){char*b,*e;b=e=v[1];while(*++e);for(e--;*b==*e&&b++<e--;);return b>e;}

【讨论】:

    【解决方案14】:

    F#(很像 C# 示例)

    let p s=let i=0;let l=s.Length;while(++i<l)if(s[i]!=[l-i-1]) 0; 1;;
    

    【讨论】:

      【解决方案15】:

      PHP:

      function p($s){return $s==strrev($s);} // 38 chars
      

      或者,只是

      $s==strrev($s); // 15 chars
      

      【讨论】:

        【解决方案16】:

        在你的语言中使用 reverse 函数是不是有点作弊?我的意思是,查看 Ruby 解决方案给出的结果为

        def p(a)a==a.reverse end
        

        您可以轻松地将其重写为

        def p(a)a==a.r end
        

        只是说您在代码中创建了一个扩展方法,以便“r”调用反向。我希望看到人们发布不包含对其他函数的调用的解决方案。当然,字符串长度函数应该是允许的。

        Ruby 没有反转 - 41 个字符

        def m(a)a==a.split('').inject{|r,l|l+r}end
        

        VB.Net - 173 个字符

        Function P(ByVal S As String) As Boolean
            For i As Integer = 0 To S.Length - 1
                If S(i) <> S(S.Length - i - 1) Then
                    Return False
                End If
            Next
            Return True
        End Function
        

        【讨论】:

        • 您可以通过将 return false 放在 if 语句的末尾并删除 end if 来缩短它。
        • 不,这不是作弊,只要反向是标准发行版的一部分(但它有利于具有丰富库的语言)。请注意,没有库,Lua 无法访问字符串中的单个字符!扩展参数不成立,因为代码应该是开箱即用的。
        • 有些语言中几乎整个标准通常都实现为函数。
        【解决方案17】:

        Golfscript,5 个字符

        .-1%=
        
        $ echo -n abacaba | ruby golfscript.rb palindrome.gs
        1
        
        $ echo -n deadbeef | ruby golfscript.rb palindrome.gs
        0
        

        【讨论】:

          【解决方案18】:

          Common Lisp,简写版(23 个字符):

          #L(equal !1(reverse !1))
          

          #L 是由 SHARPL-READER 在 iterate 包中实现的阅读器宏字符。它基本上等同于 (lambda (!1) ...)。

          Common Lisp,仅使用原语的长版本(137 包括空格,可压缩到 108):

          (defun p (s)
            (let ((l (1- (length s))))
              (iter (for i from l downto (/ l 2))
                    (always (equal (elt s i) (elt s (- l i)))))))
          

          再次,它使用 iterate,它基本上是内置 LOOP 工具的更简洁版本,因此我倾向于将其视为核心语言。

          【讨论】:

            【解决方案19】:

            不是最短的,而且是事后的,但我忍不住在 MATLAB 中尝试一下:

            R=@(s)all(s==fliplr(s));
            

            24 个字符。

            【讨论】:

              【解决方案20】:

              C# 没有反向函数 84个字符

              int p(char[]s){int i=0,l=s.Length,t=1;while(++i<l)if(s[i]!=s[l-i-1])t&=0;return t;} 
              

              C# 无反向函数 86个字符

              int p(char[]s){int i=0;int l=s.Length;while(++i<l)if(s[i]!=s[l-i-1])return 0;return 1;}
              

              VBScript 41 个字符

              function p:p=s=strreverse(s):end function
              

              【讨论】:

              • int p(char[]s){int i=0,l=s.Length,t=1;while(++i
              【解决方案21】:

              18 个字符的 perl 正则表达式

              /^(.?|(.)(?1)\2)$/
              

              【讨论】:

                【解决方案22】:

                C 语言中的 52 个字符,需要注意的是最多一半的字符串将被覆盖:

                p(char*s){return!*s||!(s[strlen(s)-1]-=*s)&amp;&amp;p(++s);}

                没有库调用它是 64 个字符:

                p(char*s){char*e=s;while(*e)++e;return!*s||!(*--e-=*s)&amp;&amp;p(++s);}

                【讨论】:

                  【解决方案23】:

                  灵感来自上一篇文章,69 个字符

                  p(char*a){char*b=a,q=0;while(*++b);while(*a)q|=*a++!=*--b;return!q;}
                  

                  编辑:向下一个字符:

                  p(char*a){char*b=a,q=0;while(*++b);while(*a)q|=*a++%*--b;return!q;}
                  

                  EDIT2:65 个字符:

                  p(char*a){char*b=a;while(*b)b++;while(*a&&*a++==*--b);return!*a;}
                  

                  【讨论】:

                  • 非常好 - 第二个 几乎 可以工作,但是当你有两个互为负数的字符时它会失败(当 char 被签名时),例如字符串“\x40\xC0”。
                  • 取模运算符是否可以返回负数实际上是实现定义的。 0xC0 也不在 ASCII 范围内,所以它真的不那么相关。很高兴你真的发现了它,但我没有。
                  • 非常好,但请注意,您的函数在传递空字符串时具有未定义的行为。如果在初始 null 之后的字符串缓冲区中的所有字节都是非零的,并且字符串缓冲区之后的所有字节在映射内存的末尾都是非零的,则while(*++b); 将在访问未映射的内存时崩溃。我不确定是否有任何实现可以发生这种情况,但修复它需要一个字符:while(*b)++b; 因为它目前是 64 个字符(不是 65 个),所以它会增加到 65 个字符。
                  【解决方案24】:

                  Haskell,28 个字符,需要导入 Control.Arrow。

                  p=uncurry(==).(id&&&reverse)
                  

                  【讨论】:

                  • haskell 对我来说仍然很奇怪。不过,我会弄清楚的!就像现在一样,另一个 haskell 比这个短,尽管
                  • 那么,您必须将导入行添加到您的代码中,不是吗?
                  【解决方案25】:

                  受其他 C 答案中的 strlen 启发,使用标准库函数在 C 中直接实现。

                  字符数:57

                  p(char*s){char*r=strdup(s);strrev(r);return strcmp(r,s);}
                  

                  忏悔:我不在这里释放 r 是个坏人。我目前的努力:

                  p(char*s){char*r=strdup(s);s[0]=strcmp(strrev(r),s);free(r);return s[0];}
                  

                  使其达到 73 个字符;我正在想办法缩短它。

                  【讨论】:

                  • p(char*s){return strcmp(strrev(strdup(s)),s);} // 泄漏!
                  • 非常好,但我认为要完全正确,您需要不泄漏内存并且不修改原始字符串。
                  • P(char*s){char r[999];strcpy(r,s);return strcmp(strrev(r));} // 不泄漏,但仅限于字符串最多 998 个字符
                  • 我不认为 strrev 是标准 c 库的一部分(尽管它在大多数 linux 上都可用)。所以公平地说,你必须包括 strrev 的实现。
                  【解决方案26】:

                  使用 37 个字符的 Clojure:

                  user=> (defn p[s](=(seq s)(reverse(seq s))))
                  #'user/p
                  user=> (p "radar")
                  true
                  user=> (p "moose")
                  false
                  

                  【讨论】:

                  • 你不需要在反向中调用 (seq s)。此外,您可以使用匿名函数刮掉一些字符。既然你已经有了 clojure 的答案,我就把我的贴在这里。随意偷它。 (def p #(=(seq %)(reverse %))) 30 个字符。
                  【解决方案27】:

                  Perl 中的 24 个字符。

                  sub p{$_[0]eq+reverse@_}
                  

                  【讨论】:

                    【解决方案28】:

                    Groovy 17B:

                    p={it==it[-1..0]}

                    缺点是它不适用于空字符串。

                    再想一想,为空字符串抛出异常是合理的,因为您无法判断是否没有回文。

                    【讨论】:

                    • 我认为,空字符串根据定义是回文。使定义更短: = |
                    【解决方案29】:

                    不使用任何库函数(因为你真的应该加上#include 成本),这里是 96 中的 C++ 版本:

                    int p(char*a,char*b=0,char*c=0){return c?b<a||p(a+1,--b,c)&&*a==*b:b&&*b?p(a,b+1):p(a,b?b:a,b);}
                    

                    【讨论】:

                    • 在纯 C 中,您不需要包含所有函数的原型 - 如果编译器看到函数调用,它会假定它是一个返回 int 的 __cdecl 函数;虽然它不能验证参数,但它是完全合法的。
                    【解决方案30】:

                    我在 C 语言中的尝试(70 个字符):

                    P(char*s){char*e=s+strlen(s)-1;while(s<e&&*s==*e)s++,e--;return s>=e;}
                    

                    [编辑] 现在实际工作
                    [编辑 2] 通过使用默认的 int return 从 74 减少到 70

                    作为对某些 cmets 的回应:我不确定预处理器滥用是否算数 - 您可以在命令行上定义整个内容并将函数设为一个字符。

                    【讨论】:

                    • 您可以将其减少到...嗯,我数了 72,包括换行符。 int P(chars){chare=s+strlen(s)-1;while(s=e;} 测试字符串“xyx”,“xyzx”“xyyx”“yxx”。
                    • 当然,您可以将其简化为:i P(cs){ce=s+l(s)-1;w(s=e;} 编译器命令行(gcc)为: gcc -Di=int -Dc=char -Dl=strlen -Dw=while -Dr=return palindrome.c
                    • @Jonathan:字符串“ab”和“abb”失败。
                    • @Adam:好的;这就是我列出测试用例(确实有效)的原因,以防我遗漏了那些不起作用的用例。谢谢! (对不起!)
                    • 保存了三个字符:P(char*s){char*e=s;while(*++e);while(s&lt;=--e&amp;&amp;*s++==*e);return s&gt;e;},但不能用空字符串调用P()。并且不需要&lt;string.h&gt; :)
                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 2010-12-17
                    • 2010-12-01
                    • 2010-09-17
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多