17
\$\begingroup\$

Challenge

Inspired by this video.

As you may know, a palindrome is a word that is spelled the same forward as it is backward. The word "PULP" is not a palindrome, but when translated into Morse Code (with the spacing between letters removed), "PULP" becomes ".--...-.-...--." which is a palindrome. Your task is to write a program or function which takes a string and returns whether that word is a palindrome in International Morse Code.

A: .-
B: -...
C: -.-.
D: -..
E: .
F: ..-.
G: --.
H: ....
I: ..
J: .---
K: -.-
L: .-..
M: --
N: -.
O: ---
P: .--.
Q: --.-
R: .-.
S: ...
T: -
U: ..-
V: ...-
W: .--
X: -..-
Y: -.--
Z: --..

Rules

Input

Input can be taken in any reasonable format. The input string will contain only letters in any case you prefer. The string will not contain spaces, numbers, or punctuation.

Output

Your program should output 1 of 2 constant distinct results based on whether the input is a palindrome, e.g. True/False, 1/0, HOTDOG/NOTHOTDOG

Scoring

This is so shortest answer in bytes wins. Standard loopholes are forbidden.

Test Cases

Input Output
"PULP" True
"RESEARCHER" True
"HOTDOGS" True
"" True
"A" False
"RACECAR" False
"PROGRAMMING" False
"PUZZLES" False
\$\endgroup\$
7
  • \$\begingroup\$ related \$\endgroup\$ Commented Oct 19, 2018 at 18:57
  • 4
    \$\begingroup\$ Only my vote is a hammer, I'd VTC this as a dupe of the challenge Luis linked; the bulk of most solutions is going to be converting the input to Morse code. \$\endgroup\$
    – Shaggy
    Commented Oct 19, 2018 at 19:12
  • 1
    \$\begingroup\$ It looks like all the solutions are just a Morse code mappings with a "same as reverse" check tacked on, so I'm closing as a duplicate. \$\endgroup\$
    – xnor
    Commented Oct 20, 2018 at 4:05
  • 3
    \$\begingroup\$ It's a shame this is closed as a duplicate, since the duplicate-target has specified (a) that input is from the standard input (disallowing functions) and (b) one must leave non [A-Z]|[A-z]|[0-9] as they are in the input. Together these make some answers here less than trivial to port. \$\endgroup\$ Commented Oct 20, 2018 at 13:06
  • \$\begingroup\$ Oh man - it looks like I hammer open too! I thought I just made a single vote. I've hammered it closed again, but feel maybe it shouldn't be. \$\endgroup\$ Commented Oct 20, 2018 at 13:08

15 Answers 15

9
\$\begingroup\$

Jelly, 28 bytes

ØAŻŻ“¡9o|çṫ¡X1ỴỌġQ’œ?iⱮḃ2FŒḂ

Try it online!

ØA                             The uppercase alphabet.
  ŻŻ                           Prepend two zeroes.
    “¡9o|çṫ¡X1ỴỌġQ’œ?          Get the 73540211105102870315464559332nd permutation.
                                  (= “ETIANMSURWDKGOHVF0L0PJBXCYZQ”)
                     iⱮ        Find indices of input letters in this list.
                       ḃ2      Bijective base 2: map [1,2,3,4,5…] to
                                 [1], [2], [1,1], [1,2], [2,1], …
                         F     Flatten.
                          ŒḂ   Is palindrome?

I wrote this answer looking at one of these (read the rows from right-to-left, and you get my magic string!):

enter image description here

\$\endgroup\$
4
  • \$\begingroup\$ 73,540,211,105,102,870,315,464,559,332nd... what?! How did you find that number? Also how does that not take forever to run? \$\endgroup\$ Commented Nov 2, 2018 at 17:34
  • 2
    \$\begingroup\$ @MagicOctopusUrn Basically, it's an encoding of the order of the letters in that string relative to the order 00ABCDEFGHIJKLMNOPQRSTUVWXYZ. Jelly has built-ins to convert a permutation into such a number, and such a number back into the permutation. See factorial number base on Wikipedia. \$\endgroup\$
    – lynn
    Commented Nov 2, 2018 at 17:54
  • 1
    \$\begingroup\$ That is the coolest thing I've seen in a long time! So basically with factorials you can "know" where the permutation will lie, because the permutations are done in a specific order. Is that a constant time access? Linear? Log? Something else entirely? \$\endgroup\$ Commented Nov 2, 2018 at 18:48
  • \$\begingroup\$ @MagicOctopusUrn Linear time: Python program to compute the 73540211105102870315464559332nd permutation of 00ABCDEFGHIJKLMNOPQRSTUVWXYZ \$\endgroup\$
    – lynn
    Commented Nov 2, 2018 at 21:47
7
\$\begingroup\$

Jelly,  35 32 27  25 bytes

-2 thanks to Dennis (shift the permutation to avoid %32)

Oị“¡\ḣḶɼz3ç³ƝMƒ§’Œ?¤ḃ2FŒḂ

Takes input in upper-case; output is 1 for true, 0 for false.

Try it online! Or see the test-suite.

How?

Oị“...’Œ?¤ḃ2FŒḂ - Link: list of characters (in [A-Za-z]), S   e.g. 'FoOl'
O               - to ordinals                                      [70,111,79,108]
 %32            - modulo by 32 (A->1, a->1, ...)                   [6,15,15,12]
         ¤      - nilad followed by link(s) as a nilad:
  “...’         -   base 250 literal = 41482574787853596522350494865
       Œ?       -   first permutation of [1,N] which resides at that
                -   index when all permutations of [1,N] are sorted
                -   = [8,16,10,24,26,27,18,20,4,23,25,11,1,17,13,15,3,22,12,19,6,5,14,21,28,9,7,2]
                - index into (modular-indexing & vectorises)       [17,14,14,19]
          ḃ2    - to bijective base 2 (vectorises)                 [[1,1,2,1],[2,2,2],[2,2,2],[1,2,1,1]]
            F   - flatten                                          [1,1,0,1,0,0,0,0,0,0,1,0,1,1]
             ŒḂ - is palindromic?                                  1

Previous 35 byte solution (also takes input in upper-case)...

ØẠḣ29“...’œ?iⱮ⁸d⁴BnⱮ/€FŒḂ - Link: list of characters (in [A-Z] only), S
ØẠ                        - alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
  ḣ29                     - head to index 29 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabc'
     “...’                - base 250 literal = 1222276956185766767980461920692
          œ?              - permutation at index = 'EAIWRUSJPaLbFVHcTNMDKGOBXCYZQ'
              ⁸           - chain's left argument = S       e.g. 'FOOL'
             Ɱ            - map with:
            i             -   first index of (char in 'EAI...')  [13,23,23,11]
                ⁴         - literal 16                           16
               d          - divmod                               [[0,13],[1,7],[1,7],[0,11]]
                 B        - to binary (vectorises)               [[[0],[1,1,0,1]],[[1],[1,1,1]],[[1],[1,1,1]],[[0],[1,0,1,1]]]
                     €    - for each:
                    /     -   reduce by:
                   Ɱ      -     map with:
                  n       -       not equal                      [[1,1,0,1],[0,0,0],[0,0,0],[1,0,1,1]]
                      F   - flatten                              [1,1,0,1,0,0,0,0,0,0,1,0,1,1]
                       ŒḂ - is palindromic?                      1
\$\endgroup\$
0
4
\$\begingroup\$

Python 3, 172 148 104 bytes

First code golf ever. Please be kind and offer any help :)

This is based off the C# answer: https://codegolf.stackexchange.com/a/175126/83877. I took the same ideas and applied it to Python 3. I tried my best to golf-ify the code, but I am sure there is a lot more I can do.

EDIT 1: Thanks @Stephen and @Cowabunghole for helping me remove some whitespace and unnecessary code.

EDIT 2: Thanks @JoKing for the suggestion to do it in binary. This is a really neat trick where '-' and '.' are not even necessary. This led to a huge byte decrease.

Solution

def b(w):x=''.join(map(lambda c:bin('  ETIANMSURWDKGOHVF L PJBXCYZQ'.index(c))[3:],w));return x==x[::-1]

Try it online!

\$\endgroup\$
5
  • 1
    \$\begingroup\$ Welcome to PPCG! Here's 152 bytes with whitespace golfed off: Try it online! \$\endgroup\$
    – Stephen
    Commented Nov 5, 2018 at 20:43
  • 1
    \$\begingroup\$ A couple of tips to save a few characters: Remove whitespace everywhere you can. For example, you can change while i > 0: to while i>0: to save 2 bytes. Also, I could be wrong but I think you can do away with the > 0 altogether and just use while i:. Second, the statement in the while loop can go on the same line as the while, saving the newline and indentation. Last, this is terrible advice everywhere except when code golfing, but if you use Python 2 instead of Python 3, you can save 1 byte from using / instead of // for division. \$\endgroup\$ Commented Nov 5, 2018 at 20:43
  • 1
    \$\begingroup\$ Oh, also, you can use ~-i instead of i-1. This is the same number of bytes, but you can then omit the parentheses which saves 2 bytes. \$\endgroup\$ Commented Nov 5, 2018 at 20:47
  • \$\begingroup\$ Thank you @Cowabunghole. Two very useful suggestions. \$\endgroup\$
    – pwaivers
    Commented Nov 5, 2018 at 20:51
  • \$\begingroup\$ Wow @JoKing, that is awesome! You should post that one instead. It so much more clever, that I don't want to take credit for it. \$\endgroup\$
    – pwaivers
    Commented Nov 5, 2018 at 21:51
3
\$\begingroup\$

Dyalog APL, 24 bytes

⎕CY'dfns'
⎕←(⌽≡⊢)∊morse⍞

Try it online!

dfns never ceases to amaze

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

MBASIC, 325 bytes

First attempt, before the big guns get here :-)

1 DATA .-,-...,-.-.,-..,.,..-.,--.,....,..,.---,-.-,.-..,--,-.,---,.--.,--.-,.-.,...,-,..-,...-,.--,-..-,-.--,--..
2 DIM C$(26):FOR I=1 TO 26:READ C$(I):NEXT:INPUT T$:FOR I=1 TO LEN(T$):N=ASC(MID$(T$,I,1))-64:S$=S$+C$(N):NEXT:L=LEN(S$):FOR I=1 TO L:IF MID$(S$,I,1)<>MID$(S$,(L+1)-I,1) THEN 4
3 NEXT:PRINT"True":END
4 PRINT"False

Output

? PULP
True

? RESEARCHER
True

? HOTDOGS
True

?
True

? A
False

? RACECAR
False

? PROGRAMMING
False

? PUZZLES
False
\$\endgroup\$
2
\$\begingroup\$

JavaScript (Node.js), 111 bytes

x=>(u=[...x.replace(/./g,_=>"**ETIANMSURWDKGOHVF*L*PJBXCYZQ".indexOf(_).toString(2).slice(1))])+''==u.reverse()

Try it online!

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

Perl 6, 87 bytes

{$_ eq.flip}o*.trans(/./=>{S/.//}o{'  ETIANMSURWDKGOHVF L PJBXCYZQ'.index($/).base(2)})

Try it online!

Converts the word to a series of 1s and 0s and checks if it is palindromic.

Explanation:

             *.trans(/./=>  # Translate each letter of the input to
                                   '...'.index($/)   # The index of the letter in the lookup string
                                                  .base(2)  # Converted to binary
                          {S/.//}o{                       } # With the first digit removed
{$_ eq.flip}o   # Return if the string is equal to its reverse
\$\endgroup\$
1
\$\begingroup\$

Pyth, 35 33 bytes

The code contains unprintable characters, so here's a hexdump.

00000000: 5f49 7358 7a47 632e 2207 0901 3f08 82ee  _IsXzGc."...?...
00000010: bd3f c256 9d54 c381 7dac 6590 37d3 c8f5  .?.V.T..}.e.7...
00000020: 52                                       R

Try it online. Test suite.

Explanation

Starting from ." the end of the code generates the Morse alphabet, with dots as \x08 and dashes as \x07, and separated by tabs.

c splits the string by the tabs.

XzG translates (X) the input (z) from the alphabet (G) to this "Morse alphabet".

s sums (joins) the Morse symbols together. For empty inputs, returns 0, but this is not a problem.

_I checks if the result does not change (I) when reversed (_). For empty input, checks if 0 does not change when negated.

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

Wolfram Language (Mathematica), 107 bytes

PalindromeQ[##2&@@@(IntegerDigits[Tr@StringPosition[" ETIANMSURWDKGOHVF L PJBXCYZQ",#],2]&/@Characters@#)]&

Try it online!

Similar to this Jelly answer: we think of Morse code as binary, and write down a string " ETIANMSURWDKGOHVF L PJBXCYZQ" where the position of a character, in binary, gives us its Morse code. But with an extra 1 prepended because we want to distinguish S = 000 and H = 0000, for instance. Then ##2&@@@ simultaneously gets rid of this leading 1 and flattens.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Huh, I would've expected Wolfram Language to have a Morse code built-in. Or does it have one, but it's too verbose? \$\endgroup\$ Commented Oct 22, 2018 at 18:20
  • 2
    \$\begingroup\$ I couldn't find one. (And the documentation includes example code for some audio commands which hard-codes Morse code, which I wouldn't expect if a built-in existed.) \$\endgroup\$ Commented Oct 22, 2018 at 18:31
1
\$\begingroup\$

PowerShell, 204 187 bytes

param($a);$a|% t*y|%{$b+=[convert]::ToString("  ETIANMSURWDKGOHVF L PJBXCYZQ".IndexOf($_),2).substring(1)};$c=($b=($b|% *ce 0 .|% *ce 1 -)).ToCharArray();[array]::Reverse($c);$b-eq-join$c

Try it online!

Errors on null string... Can anyone help with this?

Test code (After wrapping the code in a Script Block and assigned to variable $Z...):

$tests = @(
    "PULP", "True"
    "RESEARCHER", "True"
    "HOTDOGS", "True"
    "A", "False"
    "RACECAR", "False"
    "PROGRAMMING", "False"
    "PUZZLES", "False"
)
$outputs = @()
for($i = 0; $i -lt $tests.length/2; $i++){
    $output = New-Object "PSObject"
    $output  | Add-Member -MemberType NoteProperty -Name Name -Value "`"$($tests[2*$i])`""
    $output | Add-Member -MemberType NoteProperty -Name Expected -Value $tests[2*$i + 1]
    $output | Add-Member -MemberType NoteProperty -Name Result -Value $(&$Z -a $tests[2*$i])
    $outputs += $output 
}
$outputs | Format-Table

Output:

Name          Expected Result
----          -------- ------
"PULP"        True       True
"RESEARCHER"  True       True
"HOTDOGS"     True       True
"A"           False     False
"RACECAR"     False     False
"PROGRAMMING" False     False
"PUZZLES"     False     False
\$\endgroup\$
1
0
\$\begingroup\$

Retina 0.8.2, 87 bytes

[B-ILNPRSZ]
$&.
[AJKMOQT-Y]
$&-
}T`L`\EDKN_UMS\EWNRTTMWGAI_ISADKG
+`^(.)(.*)\1$
$2
^.?$

Try it online! Link includes test cases. Explanation:

[B-ILNPRSZ]
$&.

All the Morse codes for the letters in this set end with ..

[AJKMOQT-Y]
$&-

All the Morse codes for the letters in this set end with -.

T`L`\EDKN_UMS\EWNRTTMWGAI_ISADKG

Replace each letter with the letter whose Morse code is the prefix of that letter (here E and T are simply deleted via the unescaped _, but normally they would be turned into spaces). For instance, P is the Morse code for W with an extra . on the end; we added the . above so now all that remains is to decode the W.

}

Repeat the above stages until there are no letters left.

^(.)(.*)\1$
$2

If the first and last characters are the same, delete them both.

+`

Repeat for as many characters that match.

^.?$

If this was a palindrome, then there is at most one character left.

\$\endgroup\$
0
\$\begingroup\$

05AB1E, 37 bytes

v•1êÿµµÈ∞Ƶipδ8?a¡š%=тîδ/•3B0¡Aykè}JÂQ

Try it online!


Encodes the alphabet in base 3, converted to base 255:

12021110212102110101121022101111011012220212012110220210222012210221201210111020112011120122021120212202211

Base 255:

•1êÿµµÈ∞Ƶipδ8?a¡š%=тîδ/•

Then basically, I break it apart on the 0's, construct the string by position and check for palindrome.

\$\endgroup\$
0
\$\begingroup\$

C# (.NET Core), 191 bytes

a=>{var s="";int r=1,x=0,i;foreach(var t in a){var c="";for(i=" ETIANMSURWDKGOHVF L PJBXCYZQ".IndexOf(t);i>0;i/=2)c="-."[i--%2]+c;s+=c;}i=s.Length;for(;x<i;x++)r=s[x]==s[i-x-1]?r:0;return r;}

Try it online!

Part of this answer was adapted from Nick Larsen's morse code golf. Based on the comments on the answer, this could potentially be golfed further.

Ungolfed:

a => {
    var s = "";                 // initialize s
    int r = 1, x = 0, i;        // initialize r, x, and i

    /*
        This portion was adapted from Nick Larsen. He described it as follows:
            -- The string of characters is a heap in which the left child is a dot and the right child is a dash.
            -- To build the letter, you traverse back up and reverse the order.
        I have edited it to remove number support, which saves 34 bytes.
    */
    foreach(var t in a)
    {
        var c = "";
        for(i = " ETIANMSURWDKGOHVF L PJBXCYZQ".IndexOf(t); i > 0; i /= 2)
            c = "-."[i-- % 2] + c;
        s += c;
    }

    i = s.Length;               // reuse i and set to the length of the morse code string
    for(; x < i; x++)           // increment x until x reaches i
        r = s[x] == s[i - x - 1] ?      // if the xth character on the left side of s is equal to the xth character on the right side of s
                                    r :     // true: do not change r
                                        0;  // false: set r to zero (set to false)

    return r;
}
\$\endgroup\$
0
\$\begingroup\$

Scala 3, 121 bytes.

Golfed version. Try it online!

_.map(c=>Integer.toBinaryString("  ETIANMSURWDKGOHVF L PJBXCYZQ".indexOf(c)).substring(1)).mkString.pipe(x=>x==x.reverse)

Ungolfed version. Try it online!

object Main {
  def b(w: String): Boolean = {
    val x = w.map(c => Integer.toBinaryString("  ETIANMSURWDKGOHVF L PJBXCYZQ".indexOf(c)).substring(1)).mkString
    x == x.reverse
  }

  def main(args: Array[String]): Unit = {
    println(b("PULP"))
    println(b("RESEARCHER"))
    println(b("HOTDOGS"))
    println(b(""))
    println(b("A"))
    println(b("RACECAR"))
    println(b("PROGRAMMING"))
    println(b("PUZZLES"))
  }
}
\$\endgroup\$
0
\$\begingroup\$

GNU sed -E, 139 bytes

:r
s/[AFHIJLPRSUVW]/E&/g
s/[BCDGKMNOXYZ]/T&/g
y/ABCDFGHIJKLMNOPQRSUVWXYZ/TSRIRNSEOADTEMGKNIAUMUWD/
tr
:p
s/^(.)(.*)\1$/\2/
tp
/../c0
/0/!c1

This program transforms each line of input (must be upper-case) to either 1 (for a Morse palindrome) or 0 (otherwise).

The first loop (r=reduce) converts to Morse, represented using T for dash and E for dot (so we don't need to convert those two letters).

The second loop (p=palindrome) removes matching start and end characters.

If there are two or more symbols remaining, it's not a palindrome, so output 0.

If we didn't produce 0, then the result should be 1.


I did attempt to convert to an easier alphabet to work with (so we could use character ranges in the s command), but none saved enough to outweigh the conversion cost.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.