118
\$\begingroup\$

There have been a couple of previous attempts to ask this question, but neither conforms to modern standards on this site. Per discussion on Meta, I'm reposting it in a way that allows for fair competition under our modern rulesets.

Background

A is a string that "reads the same forwards and backwards", i.e. the reverse of the string is the same as the string itself. We're not talking about "convenient palindromes" here, but a strict character-by-character reversal; for example, ()() is not a palindrome, but ())( is.

The task

Write a program or function that takes a string S (or the appropriate equivalent in your language) as input, and has one output Q (of a type of your choice). You can use any reasonable means to take the input and provide the output.

  • When the input S is a palindrome, the output Q should have a value A (that is the same for any palindromic S).
  • When the input S is not a palindrome, the output Q should have a value B (that is the same for any non-palindromic S).
  • A and B must be distinct from each other.

Or in other words: map all palindromes to one value, and all non-palindromes to another.

Additionally, the program or function you write must be a palindrome itself (i.e. its source code must be palindromic), making this a challenge.

Clarifications

  • Although true and false are obvious choices for A and B, you can use any two distinct values for your "is a palindrome" and "isn't a palindrome" outputs, which need not be booleans.
  • We're defining string reversal at the character level here; éé is palindromic regardless of whether the program is encoded in UTF-8 or Latin-1, even though it's not a palindromic sequence of octets after UTF-8 encoding.
  • However, even if your program contains non-ASCII characters, it only needs to work for ASCII input. Specifically, the input S will only contain printable ASCII characters (including space, but not including newline). Among other things, this means that if you treat the input as a sequence of bytes rather than a sequence of characters, your program will still likely comply with the specification (unless your language's I/O encoding is very weird). As such, the definition of a palindrome in the previous bullet only really matters when checking that the program has a correct form.
  • Hiding half the program in a comment or string literal, while being uncreative, is legal; you're being scored on length, not creativity, so feel free to use "boring" methods to ensure your program is a palindrome. Of course, because you're being scored on length, parts of your program that don't do anything are going to worsen your score, so being able to use both halves of your program is likely going to be helpful if you can manage it.
  • Because the victory criterion is measured in bytes, you'll need to specify the encoding in which your program is written to be able to score it (although in many cases it will be obvious which encoding you're using).

Victory criterion

Even though the program needs to be a palindrome at the character level, we're using bytes to see who wins. Specifically, the shorter your program is, measured in bytes, the better; this is a challenge. In order to allow submissions (especially submissions in the same language) to be compared, place a byte count for your program in the header of your submission (plus a character count, if it differs from the number of bytes).

\$\endgroup\$
12
  • 13
    \$\begingroup\$ Would someone please explain why would ()() not be a palindrome?? \$\endgroup\$ Commented Feb 20, 2017 at 6:38
  • 67
    \$\begingroup\$ @EmilioMBumachar Try replacing ( with a and ) with b. Is abab a palindrome? No, it would have to be abba. Then ()() isn't a palindrome either; it would have to be ())(. \$\endgroup\$
    – DLosc
    Commented Feb 20, 2017 at 6:40
  • 7
    \$\begingroup\$ Those solutions entirely using comments to make the program palindromic looks like a loophole to me :( \$\endgroup\$
    – kennytm
    Commented Feb 20, 2017 at 8:26
  • 17
    \$\begingroup\$ @kennytm Disallowing them would be worse, because there's no satisfactory way to do that objectively in a language-agnostic way. (What's a comment? What about putting the unused half in a string literal that is discarded? What about 2D languages where you can have perfectly executable code that is simply never reached?) \$\endgroup\$ Commented Feb 20, 2017 at 9:08
  • 15
    \$\begingroup\$ ()() is not a palindrome, but ())( is. Congratulations, you made it onto reddit! \$\endgroup\$ Commented Feb 25, 2017 at 6:31

76 Answers 76

3
\$\begingroup\$

MathGolf, 2 3 bytes

x=x

Try it online!

Explanation

Nothing fancy here, just some usage of implicit input. x reverses strings. Since the stack is empty, the input is reversed and placed on the stack. = checks for equality for the top two elements on the stack. Since the stack has only one element, the other element is fetched from the input, which is the original string. If they are equal, we get 1, otherwise we get a 0. x also works on integers, but since both 0 and 1 are 1-digit numbers, they remain unchanged.

EDIT: made the code a palindrome thanks to Lyxal's comment.

\$\endgroup\$
6
  • \$\begingroup\$ Additionally, the program or function you write must be a palindrome itself (i.e. its source code must be palindromic), making this a restricted-source challenge - x= is not a palindrome \$\endgroup\$
    – lyxal
    Commented Mar 8, 2021 at 10:17
  • \$\begingroup\$ x=x works for 3 bytes \$\endgroup\$
    – lyxal
    Commented Mar 8, 2021 at 10:20
  • \$\begingroup\$ @Lyxal I need to read the specification more closely, thanks for pointing it out! \$\endgroup\$
    – maxb
    Commented Mar 8, 2021 at 11:54
  • \$\begingroup\$ @maxb Completely unrelated to this challenge, but MathGolf doesn't have a count builtin, does it? \$\endgroup\$ Commented May 27, 2021 at 8:46
  • 1
    \$\begingroup\$ @maxb Yeah, that was indeed what I meant. I also couldn't really come up with a (short) alternative to do the count manually with the current operations available. Ah well, then I'll just skip that challenge for MathGolf. It does sound like a useful builtin to be added in the future perhaps. \$\endgroup\$ Commented May 31, 2021 at 9:28
2
\$\begingroup\$

Dyalog APL, 21 Bytes

I decided to avoid a comment-based solution, and ended up with something pretty ugly. Instead of commenting out the second half of my code, I keep it in and allow the resulting syntax error to be part of my output.

A←⍞⋄0∊A=⌽A⋄A⌽=A∊0⋄⍞←A

This prompts the user to enter a string, and prints

0
SYNTAX ERROR: The function requires a left argument
      A←⍞ ⋄ 0∊A=⌽A ⋄ A⌽=A∊0 ⋄ ⍞←A

If the input is a palindrome, and prints

1
SYNTAX ERROR: The function requires a left argument
      A←⍞ ⋄ 0∊A=⌽A ⋄ A⌽=A∊0 ⋄ ⍞←A

If the input is not a palindrome.

A simple comment based solution would be to replace the middle character () with the comment symbol ():

A←⍞⋄0∊A=⌽A⍝A⌽=A∊0⋄⍞←A

This does the same as above but doesn't include the syntax error in the output.

Here's an ungolfed version:

A←⍞          ⍝ prompt user for input, store in variable A
⋄             ⍝ statement separator 
0∊A=⌽A       ⍝ return '0' if A is equal to A reversed (`⌽A`). Otherwise return '1' 
⋄             ⍝ statement separator
A⌽=A∊0⋄⍞←A   ⍝ reverse of preceding code, throws a syntax error
\$\endgroup\$
2
\$\begingroup\$

CJam, 13 bytes

l_W%=e#e=%W_l

Explanation:

l_W%=e#e=%W_l
l_            e#Read input twice
  W%          e#Reverse one input
    =         e#Test for equality
     e#e=%W_l e#Comment to be a palindrome

Example:

> l_W%=e#e=%W_l
l_W%=e#e=%W_l
1

> l_W%=e#e=%W_l
Hi
0

> l_W%=e#e=%W_l
hh
1
\$\endgroup\$
1
2
\$\begingroup\$

J, 15 bytes, 15 characters

-:|.NB. .BN.|:-

Returns 1 if palindrome, 0 if not.

Output:

   f '())('
1
   f 'nope'
0

Explanation:

-:    NB. "Match" verb, checks for equality
|.    NB. Reverses the string
\$\endgroup\$
2
\$\begingroup\$

Ruby, 39 35 chars

->s{s.reverse==s}#}s==esrever.s{s>-
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Welcome to PPCG! Our usual policy (which is also explicitly affirmed in this challenge) is that answers must be either a full program (with input and output) or a function. I'm not super familiar with Ruby, but your code looks like a snippet instead (it's just an expression, and assumes input pre-stored in the s variable). If you change it so it's either a function or a full program, it will be a valid answer. \$\endgroup\$
    – DLosc
    Commented Feb 23, 2017 at 10:47
  • \$\begingroup\$ @DLosc Sure, thanks, I made it a function \$\endgroup\$
    – Dorian
    Commented Feb 23, 2017 at 10:55
  • 1
    \$\begingroup\$ Then you can remove the () around s and save 4 bytes. \$\endgroup\$
    – G B
    Commented Feb 23, 2017 at 10:57
2
\$\begingroup\$

Golfscript, 11 bytes

Bonus for the bytecount being a palindrome as well.

.-1%=#=%1-.

Duplicate, reverse, compare. Outputs 1 for palindromes and 0 for non-palindromes.

\$\endgroup\$
2
\$\begingroup\$

Ruby -n, 31 bytes

p$_==$_.reverse#esrever._$==_$p

Try it online!

A full program with implicit input (-n) turns out to be slightly shorter than lambda.

\$\endgroup\$
2
\$\begingroup\$

Jelly, 3 bytes

UƑU

Try it online!

Added for the sake of completeness. This uses the fairly new quick Ƒ, which checks whether the argument is the same as the result of the atom being applied. Here, the atom is U, which reverses the argument. The quicklink returns either 1 for palindromes, or 0 otherwise. The second U has no effect on either integer, so leaves it as is.

\$\endgroup\$
2
\$\begingroup\$

R, 71 bytes

any(rev(x<-utf8ToInt(scan(,"")))-x)#)x-)))"",(nacs(tnIoT8ftu-<x(ver(yna

Try it online!

Comments to make it a palindrome. Returns FALSE if the input is a palindrome, TRUE otherwise. Could save 2 bytes off the palindrome using sd if we were guaranteed to have an input size >1.

Interpreting liberally this portion of the asnwer

if you treat the input as a sequence of bytes rather than a sequence of characters, your program will still likely comply with the specification

would lead to:

R, 43 bytes

any(x<-scan()-rev(x))#))x(ver-)(macs-<x(yna

Try it online!

\$\endgroup\$
2
\$\begingroup\$

W, 3 bytes

Pretty trivial, reverse & check equality & reciprocal. (I definitely beat Jelly by tying with Pyth.)

_=_

Explanation

_   Reverse the implicitly inputted string
 =  Check whether this reversed string is equal to the original string
  _ Negate this string
\$\endgroup\$
2
\$\begingroup\$

Google Sheets, 171 167 163

Input is in A1.

=-IFERROR(JOIN(,ArrayFormula(MID(A1,SEQUENCE(LEN(A1),1,LEN(A1),-1),1)))=""&A1,1)&"&)1,1A&""=)))1,)1-,)1A(NEL,1,)1A(NEL(ECNEUQES,1A(DIM(alumroFyarrA,(NIOJ(RORREFI-=
  • Palindrome: -1&)1A&"=)))1,)1-,)1A(NEL,1,)1A(NEL(ECNEUQES,1A(DIM(alumroFyarrA,(NIOJ(RORREFI-=
  • Not: 0&)1A&"=)))1,)1-,)1A(NEL,1,)1A(NEL(ECNEUQES,1A(DIM(alumroFyarrA,(NIOJ(RORREFI-=

How it works:

  1. Compare a string with its reverse. I thought it necessary to handle the empty string as well, so I added IFERROR() for the MID().
  2. Coerce to number with -. 1 becomes -1, 0 stays 0.
  3. The only requirement was two distinct outputs, so just concatenate the program's reverse to the end.
  4. We also exploit the fact that Sheets closes quotes and parens at the end.
  5. The center of the palindrome is the &"&
\$\endgroup\$
1
  • \$\begingroup\$ As of now, Sequence appears to have a bug where I can't omit the second argument with a negative step. \$\endgroup\$ Commented Aug 3, 2020 at 21:26
2
\$\begingroup\$

05AB1E, 3 bytes

RQR

Try it online!

RQR  # full program
 Q   # is...
     # implicit input...
 Q   # equal to...
     # implicit input...
R    # reversed...
 Q   # ? (1 if yes, 0 if no)
  R  # reverse top of stack (no-op since both 1 and 0 are palindromes)
     # implicit output
\$\endgroup\$
2
\$\begingroup\$

x86_64 machine code, 49 bytes

Uses System V ABI calling convention (specifically first arg in RDI, return in RAX, DF cleared by caller).

Hexdump:

00000000: 31c0 575e 31c9 f7d1 f2ae 4883 ef02 803e  1.W^1.....H....>
00000010: 0074 05a6 74f4 ffc0 c3c0 fff4 74a6 0574  .t..t.......t..t
00000020: 003e 8002 ef83 48ae f2d1 f7c9 315e 57c0  .>....H.....1^W.
00000030: 31                                       1

Try it online!

Explanation:

0000000000401020 <test_palindrome>:
  401020:   31 c0                   xor    eax,eax ; clear eax
  401022:   57                      push   rdi
  401023:   5e                      pop    rsi ; copy rdi to rsi

  ; get end of string (by SCASing rdi to find 0)
  401024:   31 c9                   xor    ecx,ecx
  401026:   f7 d1                   not    ecx
  401028:   f2 ae                   repnz scas al,BYTE PTR es:[rdi]

  ; addr of start is in rsi, addr of end (past \0) is 
  ; in rdi, so we subtract 2 from rdi. Thankfully this is needed below too,
  ; so we can combine the two steps into one.

  ; Now, we loop, incrementing rsi and decrementing rdi until [rsi] == '\0'
000000000040102a <testp_loop>:
  40102a:   48 83 ef 02             sub    rdi,0x2 ; Shortest way to do this?

  40102e:   80 3e 00                cmp    BYTE PTR [rsi],0x0 ; [rsi] == '\0'?
  401031:   74 05                   je     401038 <retl> ; If so, str is a palindrome (ret0)

  ; Check that [rsi] == [rdi]
  401033:   a6                      cmps   BYTE PTR ds:[rsi],BYTE PTR es:[rdi] ; Auto increments rsi and rdi, so rdi needs subtracting by 2.
  401034:   74 f4                   je     40102a <testp_loop> ; If so, keep looping.

  ; Otherwise, str is not a palindrome (ret1)
  401036:   ff c0                   inc    eax

0000000000401038 <retl>:
  401038:   c3                      ret    

  ; <nonsense to make code a palindrome>
  401039:   c0 ff f4 74 a6 05 74 00 3e 80 02 ef 83 48 ae f2 d1 f7 c9 31 5e 57 c0 31
\$\endgroup\$
1
\$\begingroup\$

QBIC, 17 bytes

;?A=_fA|#|Af_=A?;

Uses a boring comment-like ttrick to make the code a palindrome. Explanation:

;         Get a string literal from the cmd prompt
?         Print -1 for true and 0 for false in the following comparison
A=        Is A equal to
_fA|      A reversed?

#         Start a 'silent' string literal: This only forces the creation of string B
          with the following text, but doesn't inject a reference to B$ here.
|Af_=A?;  Code, reversed, as a string literal.
\$\endgroup\$
1
\$\begingroup\$

AppleScript, 146 bytes

clutch

set x to(display dialog""default answer"")'s characters--
x=reverse of x--x fo esrever=x
--sretcarahc s')""rewsna tluafed""golaid yalpsid(ot x tes

This should be fairly obvious.

\$\endgroup\$
1
\$\begingroup\$

Common Lisp, 104 bytes

(lambda(s)(format t"~:[F~;T~]"(equal(reverse s)s)));;)))s)s esrever(lauqe("]~T;~F[:~"t tamrof()s(adbmal(

Abusing idea for commenting out part of code from comments under question.

\$\endgroup\$
1
\$\begingroup\$

Javascript, 78 bytes

(s=>s==s.split('').reverse().join(''))//))''(nioj.)(esrever.)''(tilps.s==s>=s(

This is the classic .split, .reverse and .join routine.

Another (longer, but I like it more) 104 bytes solution would be

(s=>!s.split('').find((a,i,l)=>a!==l[l.length-i-1]))//))]1-i-htgnel.l[l==!a>=)l,i,a((dnif.)''(tilps.s!>=s(
\$\endgroup\$
1
\$\begingroup\$

Pyth - 3 bytes

An alternative 3 byte solution. Palindromes give -1 and non-palindromes give 0.

_q_

Test Suite.

A few more 3 byte solutions:

_/_
_}_
\$\endgroup\$
1
\$\begingroup\$

Scala - 58 bytes

def p(s:String)=s.reverse==s//s==esrever.s=)gnirtS:s(p fed

Example -

p("abba") //returns true

p("aabb") //returns false
\$\endgroup\$
1
\$\begingroup\$

Java (with regex), 134 bytes

s->s.matches("|(?:(.)(?<=(?=^.*?(\\1\\2?)$).*))+(?<=(?=^\\2$).*)")//)")*.)$2\\^=?(=<?(+))*.)$)?2\\1\\(?*.^=?(=<?().(:?(|"(sehctam.s>-s

Credits where due

Testing

import java.util.function.*;

class Ideone {
  static Predicate<String> isPalindrome = 
    s->s.matches("|(?:(.)(?<=(?=^.*?(\\1\\2?)$).*))+(?<=(?=^\\2$).*)")//)")*.)$2\\^=?(=<?(+))*.)$)?2\\1\\(?*.^=?(=<?().(:?(|"(sehctam.s>-s
    ;

  public static void main (String[] args) throws java.lang.Exception {
    testPalindrome("", true);
    testPalindrome("x", true);
    testPalindrome("xx", true);
    testPalindrome("xy", false);
    testPalindrome("xyx", true);
    testPalindrome("xxx", true);
    testPalindrome("xxyx", false);
    testPalindrome("racecar", true);
    testPalindrome("step on no pets", true);
    testPalindrome("aManaPlanaCanalPanaMa", true);
    testPalindrome("this is impossible", false);
  }

  static void testPalindrome(String s, boolean expected) {
    if (isPalindrome.test(s) == expected) {
      System.out.println("OK");
    } else {
      System.out.printf("NOK: str=\"%s\", expected=%b%n", s, expected);
    }
  }
}

Test it yourself!

\$\endgroup\$
5
  • \$\begingroup\$ This code is not a lambda expression. \$\endgroup\$
    – Jakob
    Commented Aug 30, 2017 at 0:22
  • \$\begingroup\$ @Jakob No? Why not? It works as a lambda, though. \$\endgroup\$ Commented Aug 30, 2017 at 5:39
  • \$\begingroup\$ My complaint is with the comment. Seems to me that having anything outside the lambda expression makes it an invalid lambda solution. In particular, this solution cannot be embedded in a program the way a lambda expression can (e.g. with code appearing after it on the same line). See also the grammar for a lambda expression, which most lambda solutions adhere to, but this doesn't. \$\endgroup\$
    – Jakob
    Commented Aug 30, 2017 at 20:41
  • \$\begingroup\$ Why can't it be embedded? stream.map(a->a//comment<new_line>).collect(...) (replace <new_line> with an actual new line) works well! Just because 99.99% of lambdas adhere to that principle doesn't make this one invalid. Does it? A lambda isn't defined from how it appears in the source, but how it's compiled, and this one compiles just fine, unless proven otherwise. \$\endgroup\$ Commented Aug 30, 2017 at 21:02
  • \$\begingroup\$ Well, my concern is not that it doesn't work or that it can't be embedded into a full program; it's that it violates the format of a lambda expression solution. I think I'll create a meta post where this discussion can continue. \$\endgroup\$
    – Jakob
    Commented Aug 30, 2017 at 22:19
1
\$\begingroup\$

Scala, 50 bytes

Failed to not write a comment based solution so this is it:

(s:String)=>s.reverse==s//s==esrever.s>=)gnirtS:s(
\$\endgroup\$
1
\$\begingroup\$

Common Lisp, 61 bytes

(lambda(n)(equal(reverse n)n));))n)n esrever(lauqe()n(adbmal(

Try it online!

Outputs T when the string is palindrome, NIL otherwise.

\$\endgroup\$
1
\$\begingroup\$

Pyt, 1 byte

Try it online!

   implicit input
₽  palindromic test
   implicit output

Previous answer

before I knew that 1 byte solutions were allowed

₽ƥƥ₽

Try it online!

₽ checks for palindromicness (is that a word?)
ƥ prints the answer
ƥ prints nothing
₽ checks the palindromicness of nothing
\$\endgroup\$
2
  • 1
    \$\begingroup\$ 1 byte. I don't think it ever says that solutions have to be more than a single byte. \$\endgroup\$ Commented Jan 28, 2018 at 21:09
  • \$\begingroup\$ Oh that's weird. I could have sworn it did, but maybe it was a different challenge. \$\endgroup\$
    – qqq
    Commented Jan 28, 2018 at 21:10
1
\$\begingroup\$

Japt, 2 bytes

êê

Try it

ê on its own in Japt creates a palindrome but, when passed a string as an argument (which the second ê is implicitly cast to in this case), it instead tests if a string is palindromic.

\$\endgroup\$
1
\$\begingroup\$

Add++, 13 bytes

L,dbR=;=Rbd,L

Try it online!

\$\endgroup\$
1
\$\begingroup\$

C (gcc), 118 bytes

Can sadly not come up with any solution without the boring comment approach.

f(char*s){char*t=s+strlen(s);for(;*s&&*s++==*--t;);s=!*s;}//};s*!=s;);t--*==++s*&&s*;(rof;)s(nelrts+s=t*rahc{)s*rahc(f

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Reflections, 125 bytes

  _1=1\ /1#\ /+#_ 
      >~<  >~<
        (0//0)
      \ / >_ / _> / \      
)0//0(        
<~>  <~>      
 _#+/ \#1/ \1=1_  

Test it!

Prints code point 0x04 as true, and nothing as false. There are a few spaces after some lines.

Explanation

The relevant part of the code is:

  _1=1\ /1#\ /+#_
      >~<  >~<
        (0//0)
      \ / >_ /
  • _ reads a line
  • 1=1 copies it to stack 1
  • >~< creates a loop over the complete stack:
    • (0 pushes the top item to stack 0
  • now stack 0 contains the reverse, and stack 1 the original
  • 1 moves stack 1 to mainstack
  • >~< loops again:
    • 0) takes the next character from reversed
    • >_ if original and reversed character are not equal:
      • end the program by navigating downwards, leaving the field
  • + produces the 4
  • _ prints corresponding character
  • then the program stops (leaving the field to the right)

The rest is only for palindromic source. I know this is boring.

\$\endgroup\$
1
\$\begingroup\$

Perl 5, 29 bytes

$_=reverse=~$_#_$~=esrever=_$

Requres -p0. Outputs 1 if the input is a palindrome, empty otherwise.

Try it online!


Perl 5, 33 bytes

+$_=reverse=~$_+q+_$~=esrever=_$+

Commentless version, requires -p0. Outputs 1 if the input is a palindrome, 0 otherwise.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Vyxal, 3 bytes

Ṙ=Ṙ

Try it Online!

 =  # Equal to...
Ṙ   # Self reversed?
  Ṙ # Reverse the result
\$\endgroup\$
1
\$\begingroup\$

Knight, 71 bytes

;=a=pP;=s'';Wp;=s+GpF1s=pSpF1''O?a s a?O''1FpSp=s1FpG+s=;pW;''s=;Pp=a=;

Input the string with a trailing newline.

Try It Online!

In case you're curious, here's the non-palindromized version of the code:

;=a=pP;=s'';Wp;=s+GpF1s=pSpF1''O?a s

Try It Online!

\$\endgroup\$
3
  • \$\begingroup\$ ... How does this not error??? \$\endgroup\$
    – emanresu A
    Commented Aug 18, 2022 at 23:12
  • \$\begingroup\$ @emanresuA How I understand it is that everything after the O?a s isn't evaluated because it is the last instruction the code runs (so there's no chance of any error occurring), so it doesn't matter what you put after the final instruction. \$\endgroup\$
    – Aiden Chow
    Commented Aug 18, 2022 at 23:16
  • \$\begingroup\$ @emanresuA The entire program is a single prefix expression. Once a complete expression is formed, the parser simply stops there. \$\endgroup\$
    – Bubbler
    Commented Aug 18, 2022 at 23:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.