33
\$\begingroup\$

An alphadrome is a word in which each letter in the first half of the word "reflects" its alphabetical "opposite" in the second half of the word. Write a program or function that returns truthy if the given word is an alphadrome and falsey otherwise.

For example, BEEB is a palindrome. Its first letter B "reflects" its last letter B, and its second letter E reflects its second-to-last letter E.

In contrast, BEVY is an alphadrome. Its first letter B is the second letter of the alphabet, and it reflects the word's last letter Y, which is the second-to-last letter of the alphabet. Likewise, its second letter E is the 5th letter of the alphabet, and it reflects V, the 5th-from-the-end letter of the alphabet.

Like palindromes, an alphadrome can have an odd number of letters, too. WORLD is an alphadrome. W is the 4th-from-the-end letter of the alphabet and D is the 4th letter; O is the 12th-from-the-end letter of the alphabet and L is the 12th letter. The center R reflects itself.

Any single-letter word is an alphadrome.

Rules

Test cases

A        true
ABA      false
ABZ      true
ABBA     false
BEVY     true
GOLF     false
ZOLA     true
WIZARD   true
BIGOTRY  true
RACECAR  false
ABCDEFGHIJKLMNOPQRSTUVWXYZ  true
\$\endgroup\$
13
  • 1
    \$\begingroup\$ Related: Atbash Self Palindromes \$\endgroup\$
    – Jordan
    Oct 12, 2022 at 15:58
  • 4
    \$\begingroup\$ Google returns only 9 results for alphadrome and one of them is this page. \$\endgroup\$
    – chunes
    Oct 13, 2022 at 8:25
  • 11
    \$\begingroup\$ I'm not sure why single-letter inputs are alphadromes; isn't, e.g. the alphabetic reflection of A equal to Z, and "A" doesn't equal "Z"? \$\endgroup\$ Oct 13, 2022 at 14:10
  • 3
    \$\begingroup\$ @97.100.97.109 Fair point, but if you disqualify single-letter words then you must also disqualify all words with an odd number of letters, and I didn't want to do that. \$\endgroup\$
    – Jordan
    Oct 13, 2022 at 16:30
  • 2
    \$\begingroup\$ @TobySpeight You’ve lost me. The question doesn’t specify anything about encoding. \$\endgroup\$
    – Jordan
    Oct 14, 2022 at 13:48

37 Answers 37

11
\$\begingroup\$

J, 25 24 bytes

[:*/155=3,~inv@(+|.)@u:]

Try it online!

-1 thanks to ovs

Based on the observation that this is essentially just requiring that the sum of the ascii codes of the input and its reverse add to 155.

The only exception is that, in the odd case, the middle element can be anything. The inverse of self-append in J ,~inv returns the first half of a list, but "rounds down" in the odd case, and so does what we need.

That is, we can take the sums of the ascii codes as described, take the ,~inv of that result, and check if they are all 155.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ You can save a byte by moving 155= to the left and dropping the ] \$\endgroup\$
    – ovs
    Oct 12, 2022 at 16:55
9
\$\begingroup\$

Python 3, 58 bytes

f=lambda s:len(s)<2or ord(s[0])+ord(s[-1])==155*f(s[1:-1])

Try it online!

Takes lowercase letters as input.

-3 bytes thanks to pxeger

\$\endgroup\$
2
  • \$\begingroup\$ Since the sum of the codepoints will never be 0, you can replace and with * for -3 bytes \$\endgroup\$
    – pxeger
    Oct 12, 2022 at 16:38
  • 2
    \$\begingroup\$ @solid.py multiplication. in the base case where len(s)<2 if we have True (1), the check proceeds normally. if it returns false (0) then we compare the ascii sum with 0 which is not possible so we get the correct result anyway \$\endgroup\$ Oct 12, 2022 at 17:10
8
\$\begingroup\$

Excel (ms365), 147, 111, 110, 98 89 bytes

-15 bytes thanks to @jdt
-4 bytes thanks to @EngineerToast

=LET(l,LEN(A1),n,SEQUENCE(l/2),IF(l>1,SUMSQ(CODE(MID(A1,n,1))+CODE(RIGHT(A1,n))-155),)=0)
A B
A TRUE
ABA FALSE
ABZ TRUE
ABBA FALSE
BEVY TRUE
GOLF FALSE
ZOLA TRUE
WIZARD TRUE
BIGOTRY TRUE
RACECAR FALSE
ABCDEFGHIJKLMNOPQRSTUVWXYZ TRUE

Uploading a small screenshot was not possible at time of posting. Also, the byte-count is high and I'm eager to see if fellow Excel enthusiasts can bring this down.

\$\endgroup\$
1
  • 2
    \$\begingroup\$ -4 bytes: CODE() only care about the first character. Replace MID(A1,l-n+1,1) with RIGHT(A1,n). \$\endgroup\$ Oct 14, 2022 at 15:18
7
\$\begingroup\$

Vyxal, 8 7 bytes

Ḃ+⁺6oLṅ

Try it Online!

-1 thanks to a trick from @Kevin Cruijssen's 05AB1E answer.

\$\endgroup\$
7
\$\begingroup\$

C (clang), 53 44 bytes

-9 bytes thanks to c--!!!

f(*s,*e){return--e<=s||*s+*e==155&f(s+1,e);}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Our of curiosity, why do you use wcslen here? \$\endgroup\$
    – Jonah
    Oct 12, 2022 at 18:58
6
\$\begingroup\$

Raku, 37 bytes

{155==all .ords[^(*+>1)]Z+.flip.ords}

Try it online!

  • .ords is a string method that returns a list of Unicode codepoints.
  • ^(* +> 1) is an anonymous function that returns a list of numbers from 0 to one less than the argument shifted one bit to the right. (* div 2 would be more readable, but is longer.)
  • When a list is subscripted with a function, the list's length is passed to the function, and whatever the function returns is used to index into the list. Most often this is used to index from the end of the list (eg @list[* - 1]) but here, the result is a slice of the first half of the list, not including the middle element, if any.
  • .flip is a string method that returns the reverse of the original string. .flip.ords is thus the list of the input string's Unicode codepoints in reverse order.
  • Z+ zips the two lists of codepoints with addition, up to the length of the shorter list.
  • 155 == all ... is a junction which is truthy if all of the added codepoints are equal to 155.
\$\endgroup\$
5
\$\begingroup\$

x86-64 machine code, 16 bytes

AC 83 EF 02 78 09 02 04 3E 3C 9B 74 F3 31 C0 C3

Try it online!

Following the standard calling convention for Unix-like systems (from the System V AMD64 ABI), this takes the length of the string in EDI and its address in RSI, and returns a value in EAX, nonzero if and only if the string is an alphadrome.

In assembly:

f:  lodsb               # Load a byte from the string into AL, advancing the pointer.
    sub edi, 2          # Subtract 2 from the length in EDI.
    js e                # Jump to the end if the result is negative.
                        #  In this case, the string is an alphadrome.
                        #  AL (which is the low byte of EAX) is nonzero.
    add al, [rsi + rdi] # Add the opposite-positioned byte in the string to AL.
    cmp al, 'A'+'Z'     # Compare the sum with the sum of 'A' and 'Z'.
    je f                # Jump back, to repeat, if they are equal.
    xor eax, eax        # If not, the string is not an alphadrome. Set EAX to 0.
e:  ret                 # Return.
\$\endgroup\$
5
\$\begingroup\$

Raku, 35 bytes

{2>grep *-155,(.ords Z+[R,] .ords)}

Try it online!

Anonymous code block that takes a string and returns a boolean.

Explanation

{2>grep *-155,(.ords Z+[R,] .ords)}
{                                 }  # Anonymous code block
              (.ords Z           )   # Zip the codepoints of the string
                      +                # Adding them
                       [R,]            # To the reverse
                            .ords      # of the codepoints
   grep *-155,                       # From this, filter out the 155s
 2>                                  # And check if there is exactly 1 or 0 of them
\$\endgroup\$
5
\$\begingroup\$

R, 34 35 24 bytes

Edit: +1 byte to fix bug spotted by Kamil Drakari
Edit2: saved 11 bytes by changing to same approach as my Nibbles answer

\(x)sum(x+rev(x)!=155)<2

Attempt This Online!

Input is vector of codepoints.

\$\endgroup\$
3
  • \$\begingroup\$ @KamilDrakari - Thanks: fixed now. \$\endgroup\$ Oct 12, 2022 at 21:52
  • \$\begingroup\$ I think swapping TRUE/FALSE is allowed in decision-problem, so maybe you can remove the first !? \$\endgroup\$
    – pajonk
    Oct 13, 2022 at 4:36
  • 1
    \$\begingroup\$ @pajonk - Yes, I considered removing it (and I see that some answers have used this strategy), but I felt it went against the spec in the text: "returns truthy if the given word is an alphadrome and falsey otherwise"... \$\endgroup\$ Oct 13, 2022 at 8:36
5
\$\begingroup\$

Jelly, 8 bytes

+Un155SỊ

Try it online!

-1 thanks to Jonathan Allan

\$\endgroup\$
4
  • \$\begingroup\$ @Baby_Boy Makes sense, feel free to delete your comments now :) \$\endgroup\$ Oct 17, 2022 at 16:19
  • \$\begingroup\$ @JonathanAllan alr, also would it be possible for u to comment the footer so I can try it out? \$\endgroup\$
    – Baby_Boy
    Oct 17, 2022 at 19:25
  • 1
    \$\begingroup\$ ỴOÇ€żỴj€“ <= ”Y is: (split input at newlines); O (get character codes); Ç€ (call the code for each); ż + (zip with (split input at newlines)); j€“ <= ” (join each with " <= "); Y (join with newlines). I recommend the tutorial :). \$\endgroup\$ Oct 17, 2022 at 19:43
  • 1
    \$\begingroup\$ ATO link. \$\endgroup\$
    – naffetS
    Oct 17, 2022 at 19:53
5
\$\begingroup\$

Perl 5, 49 bytes

sub f{pop=~/.\K.*\B/?155-ord($`)-ord$'?0:f($&):1}

Try it online!

\$\endgroup\$
3
  • 2
    \$\begingroup\$ sadly it doesn't work for words of 2 chars, it's always true, for example AB should be false. also changing + by * doesn't work because /\B.*\B/ matches empty string. otherwise /.\K.*\B/ works \$\endgroup\$ Oct 14, 2022 at 13:13
  • 1
    \$\begingroup\$ 46 bytes with a full program Try it online! \$\endgroup\$ Oct 14, 2022 at 13:42
  • \$\begingroup\$ @NahuelFouilleul – yes, using your regex now and 1 byte extra, thx, nice approach with full program instead. \$\endgroup\$
    – Kjetil S
    Oct 18, 2022 at 12:49
5
\$\begingroup\$

JavaScript (Node.js), 34 bytes

-1 and a bug fixed thanks to @l4m2 (on both versions)

Expects an array of ASCII codes. Returns true for non-alphadrome or false for alphadrome.

a=>a.some((_,i)=>a.pop()+a[i]-155)

Try it online!


JavaScript (Node.js), 51 bytes

Expects a string. Returns true for non-alphadrome or false for alphadrome.

s=>(a=[...Buffer(s)]).some((_,i)=>a.pop()+a[i]-155)

Try it online!

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

Pyth, 14 bytes

!t-+VJCMz_J219

Try it online!

Explanation:

     JCMz         assign input codepoints to J and return list
         _J       reverse J
   +V             map addition over two lists
  -        219    remove all instance of 219 from this list
!t                list has no more than 1 element
\$\endgroup\$
4
\$\begingroup\$

Haskell, 54 bytes

f s=[1]<[1|(x,y)<-zip<*>reverse$fromEnum<$>s,x+y/=219]

Try it online!

Zip input with its reverse, there can be at most one pair not summing to 219, the one in the centre of an odd lengthy string.
So by yielding 1 for unbalanced pairs we must have a list less or equal than [1]

Saved a byte by inverting the output and using greater than [1]

\$\endgroup\$
4
\$\begingroup\$

Fig, \$9\log_{256}(96)\approx\$ 7.408 bytes

M'>2Lo155+$

Try it online!

(link includes extra code for test cases)

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

Wolfram Language (Mathematica), 52 bytes

Count[ToCharacterCode@#//#+Reverse@#&,Except@155]<2&


Count[#+Reverse@#&@*ToCharacterCode@#,Except@155]<2&   


(*   52 bytes too,using @*    diff is just "@*" and "//"    *)

Try it online!

I'm new to codegolf, any suggestion will be appreciated.

The code means, convert string to charactercode list, add it with its reversal, count number of element!=155, judge whether the number is less than 2.

one interesting thing is that, among 26 letter, there's no letter such that CharacterCode==155/2

so this algorithm is absolutely true for input string formed from 26 upper letters

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Welcome to Code Golf! \$\endgroup\$ Jan 13, 2023 at 14:18
3
\$\begingroup\$

Nibbles, 7.5 bytes (15 nibbles)

- 2,|!\$@+%155

Input is array of codepoints. All positive integers are truthy in Nibbles, zero and negative integers are falsy.

- 2,|!\$@+%155
     !          # zip together
      \$        # the reverse of the input
        @       # and the input
         +      # by addition,
    |           # then filter the list
                # to keep only truthy elements upon
          %155  # modulo 155,
   ,            # get the length of the resulting list,
- 2             # and subtract it from 2
                # (so only zero or one non-155 element
                # will give a truthy >0 output)

enter image description here

\$\endgroup\$
3
\$\begingroup\$

Japt, 14 13 bytes

cÈ+UÔcYÃk'Û Å

Try it

Takes input as a lowercase string. Outputs an empty string for true and a non-empty string for false.

cÈ+UÔcYÃk'Û Å
cÈ            # Map the charcode of each input character through:
   UÔcY       #  Get the charcode at the same index in the input reversed
  +           #  Add them together
       Ã      # Treat the results as charcodes for a new string
        k'Û   # Remove the character "Û" whenever it appears
            Å # Remove the first remaining character if possible
              # Implicitly print the result
\$\endgroup\$
2
  • \$\begingroup\$ 13 bytes \$\endgroup\$
    – Shaggy
    Oct 12, 2022 at 22:53
  • \$\begingroup\$ @Shaggy dangit, I had thought swapping the order was byte-neutral but forgot it would let me omit a space \$\endgroup\$ Oct 12, 2022 at 23:00
3
\$\begingroup\$

Ruby, 44 bytes

f=->w{/.(.*)./!~w||w.sum-$1.sum==155&&f[$1]}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Subtracting the sum of the inner characters to get the value of the outer characters is very clever. \$\endgroup\$
    – Jordan
    Oct 13, 2022 at 12:36
3
\$\begingroup\$

Japt, 11 bytes

Input as an array of lowercase codepoints, outputs false for truthy & true for falsey.

£v +UoÃd-#Û

Try it (includes all test cases, footer reverses output)

£v +UoÃd-#Û     :Implicit input of charcode array U
£               :Map
 v              :  Remove & return first element of U
   +            :  Add
    Uo          :  Remove & return last element of U
      Ã         :End map
       d        :Any truthy
        -       :  Subtract
         #Û     :  219
\$\endgroup\$
3
\$\begingroup\$

C# (.Net 6), 73 bytes

int i=0;while(i<s.Length/2)if(s[i++]+s[^i]!=155)return false;return true;

Try it here

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Welcome to Code Golf, and nice answer! Could you save any bytes by returning a 0/1 (falsy/truthy), and keeping track of that with a variable instead of having two returns? \$\endgroup\$ Oct 13, 2022 at 19:59
3
\$\begingroup\$

05AB1E, 7 bytes

ÇÂ+ƵsKg!

Input as a list of capital codepoint-integers (although could alternatively be in lowercase as well by changing s to \). Outputs an 05AB1E truthy result (1) if it's an alphadrome, and an 05AB1E falsey result (in this case any other integer) if it's not.

Try it online or verify all test cases.

Explanation:

        # Bifurcate the (implicit) input-list; short for Duplicate & Reverse copy
 +       # Add the values at the same positions in the lists together
  Ƶs     # Push compressed integer 155
    K    # Remove all 155 from the list
     g   # Pop and push the length
      !  # Get the factorial of this length
         # (0 becomes 1; 1 remains 1; any other integer just increases)
         # (which is output implicitly as result)

See this 05AB1E tip of mine (section How to compress large integers?) to understand why Ƶs is 155 (and Ƶ\ is 219).

\$\endgroup\$
3
\$\begingroup\$

Pip, 23 17 bytes

-6 bytes thanks to DLosc!

#(_!=155FIg+Rg)<2

Try It Online!

Takes in input as a list of codepoints in the arguments. Port of the R answer, so make sure to upvote that too!

#(_!=155FIg+Rg)<2     ; Input = list of codepoints = g
#(            )       ; Get the length of...
          g+Rg        ; the vectorized sum of g and its reverse...
  _!=155FI            ; filtered by if each element is not equal to 155...
               <2     ; and test if the length is less than 2
                      ; (after which the result is implicitly printed out)
\$\endgroup\$
3
\$\begingroup\$

sed -E, 103 102 bytes

-1 byte thanks to user41805

:a
s/./\L&/
y/abcdefghijklmnopqrstuvwxyz/ZYXWVUTSRQPONMLKJIGHFEDCBA/
/../!cT
T
s/^(.)(.*)\1$/\2/
ta
cF

Attempt This Online!

\$\endgroup\$
1
  • 1
    \$\begingroup\$ There exists a shorter alternative to /^.?$/ \$\endgroup\$
    – user41805
    Jan 12, 2023 at 15:34
3
\$\begingroup\$

Factor + math.unicode, 35 29 bytes

[ halves reverse v+ ""⊂ ]

Try it online!

             ! "BIGOTRY"
halves       ! "BIG" "OTRY"
reverse      ! "BIG" "YRTO"
v+           ! { 155 155 155 }
""           ! { 155 155 155 } { 155 }   (string with non-printable char 155)
⊂           ! t     (subset?)
\$\endgroup\$
2
\$\begingroup\$

Go, 104 73 bytes

func f(s string)bool{l:=len(s)
return l<2||s[0]+s[l-1]==155&&f(s[1:l-1])}

Attempt This Online!

Based on @Manish Kundu's answer

  • -31 bytes by @Jordan, @Steffan: Combining the ifs into a single expression
\$\endgroup\$
2
  • \$\begingroup\$ The last three lines can be combined for a number of bytes saved. \$\endgroup\$
    – Jordan
    Oct 12, 2022 at 19:38
  • \$\begingroup\$ @Jordan You can save another three bytes by changing !(...!=155) to ...==155 \$\endgroup\$
    – naffetS
    Oct 12, 2022 at 19:41
2
\$\begingroup\$

Retina 0.8.2, 49 bytes

T`L`RL`^.(.)*(?!(?<-1>.)*$)
+`^(.)(.*)\1$
$2
^.?$

Try it online! Link includes test cases. Explanation:

T`L`RL`^.(.)*(?!(?<-1>.)*$)

Transliterate the first half of the word, flipping between A-Z and Z-A.

+`^(.)(.*)\1$
$2
^.?$

Test whether this results in a palindrome. (This turns out to be the same method as @ovs's answer to Shortest code to determine if a string is a palindrome so I might have remembered the approach.)

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

Charcoal, 15 bytes

⬤∕θ²⁼⌕αι⌕⮌α§⮌θκ

Try it online! Link is to verbose version of code. Outputs a Charcoal boolean, i.e. - for an alphadrome, nothing if not. Explanation:

  θ             Input string
 ∕ ²            First half (excluding middle character if any)
⬤               All characters satisfy
     ⌕          Index of
       ι        Current character
      α         In predefined variable uppercase alphabet
    ⁼           Equals
        ⌕       Index of
             θ  Input string
            ⮌   Reversed
           §    Indexed by
              κ Current index
          α     In predefined variable uppercase alphabet
         ⮌      Reversed
                Implicitly print
\$\endgroup\$
2
\$\begingroup\$

Behaviour, 40 37 bytes

~(a*=ascii\:i<-#a/2a%i+a%(-i-1)~=155)

a must contain input string

a = "ABA"
@~(a*=ascii\:i<-#a/2a%i+a%(-i-1)~=155)

ungolfed and commented:

~(              // invert the result of the following sequence
  a *= ascii    // convert string input to a list of ascii values
  \:i <- #a/2   // iterate from 0 to half the input size
    a%i+a%(-i-1)~=155   // stop if opposites values don't sum to 155
)
\$\endgroup\$
3
  • \$\begingroup\$ I’m not totally sure about the semantics of Behaviour, but if f= isn’t part of the function definition (i.e. if it’s just giving a function expression a name) you can omit it from your answer. \$\endgroup\$
    – Jordan
    Oct 13, 2022 at 14:07
  • \$\begingroup\$ Cool language, by the way! Is there an online interpreter? \$\endgroup\$
    – Jordan
    Oct 13, 2022 at 14:08
  • 1
    \$\begingroup\$ @Jordan Awesome, thanks! Unfortunately there is not, but the source code and offline interpreter are available on github and replit. \$\endgroup\$ Oct 14, 2022 at 12:08
2
\$\begingroup\$

Julia 1.0, 50 48 44 41 bytes

~x=sum((a=Int[x...]).+reverse(a).!=155)<2

Try it online!

Saved 2 bytes thanks to Sʨɠɠan's suggestion: use the return value of the variable assignment.

Saved 4 bytes thanks to amelies: replace collect(x) with [x...].

Saved 3 bytes thanks to MarcMush: replace Int.([x...]) with Int[x...].

\$\endgroup\$
3
  • 1
    \$\begingroup\$ -2 bytes: ~x=sum((a=Int.(collect(x))).+reverse(a).!=155)<2. Also, the question allows taking input as a list of codepoints. \$\endgroup\$
    – naffetS
    Oct 16, 2022 at 0:03
  • 1
    \$\begingroup\$ Use [x…] instead of collect to save 4 bytes \$\endgroup\$
    – amelies
    Oct 16, 2022 at 16:04
  • 1
    \$\begingroup\$ Use a=Int[x...] to save 3 bytes \$\endgroup\$
    – MarcMush
    Oct 21, 2022 at 11:28

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.