User Appreciation Challenge #1: Dennis ♦

58

2

I got the spontaneous idea of making a series of challenges of users that have helped and continue to help the PPCG community be an enjoyable place for everyone, or maybe just specifically for me. :P

If you convert Dennis's name to an array of 1s and 0s where each consonant is 1 and each vowel is 0, the array is [1, 0, 1, 1, 0, 1], which is symmetrical. Thus, your challenge is to determine what other names are like this.

Challenge

Given an ASCII string, remove all characters that aren't letters and determine if the configuration of vowels and consonants are symmetrical. y is not a vowel.

Please note that your program does not have to be this type of string itself.

Test Cases

Dennis -> truthy
Martin -> truthy
Martin Ender -> truthy
Alex -> falsy
Alex A. -> truthy
Doorknob -> falsy
Mego -> falsy

Reference Implementation

This Python 3 code will give the correct output given a test case. It is as ungolfed as I could make it without being ridiculous.

Python 3

s = input()
l = []
for c in s:
	if c in 'AEIOUaeiou':
		l.append(0)
	elif c in 'BCDFGHJKLMNPQRSTVWXYZbcdfghjklmnpqrstvwxyz':
		l.append(1)
print(l == list(reversed(l)), end = '')

Try it online!

HyperNeutrino

Posted 2017-05-28T12:41:52.477

Reputation: 26 575

When and who is #2? – caird coinheringaahing – 2017-06-10T15:58:55.790

@cairdcoinheringaahing Thanks for reminding me. It's going to be about Mego (TNB RO hence the italics) but I haven't gotten around to finalizing it yet. – HyperNeutrino – 2017-06-10T17:08:30.097

@cairdcoinheringaahing I'm pretty sure he knows already; I said I'd do one about him but I haven't decided if I'm going to do something relating to penguins or TNB yet. – HyperNeutrino – 2017-06-10T17:32:00.730

@HyperNeutrino Umm, you can't use italics in titles. – Erik the Outgolfer – 2017-06-10T18:47:31.313

@EriktheOutgolfer Aww :( That sucks. – HyperNeutrino – 2017-06-11T01:20:36.980

@Hyperneutrino so multicharacter variable names are ridiculous now? ;) – dylnan – 2018-01-15T18:51:18.517

@dylnan Yes, this is code golf :P At least I don't have spaces in my variable names (cough Kotlin) – HyperNeutrino – 2018-01-15T20:02:20.143

Answers

17

05AB1E, 9 bytes

žM¹álSåÂQ

Try it online!

-2 thanks to Adnan.

This attacks Jelly's pain point exactly. It uses l and A, 1-byte equivalents for Jelly's Œl and Øa respectively.

Erik the Outgolfer

Posted 2017-05-28T12:41:52.477

Reputation: 38 134

Are you sure that this works? Run this

– MCCCS – 2017-05-28T16:34:46.537

@MCCCS Hmm, you may be right. – Erik the Outgolfer – 2017-05-28T16:48:52.960

You can replace by á and DR by Â. – Adnan – 2017-05-28T18:39:16.823

@Adnan Forgot about á, didn't know what  does, thanks! – Erik the Outgolfer – 2017-05-28T18:45:24.947

Not to rain on your parade, but I'm pretty sure this is not 9 bytes in any encoding. :-) Nine characters is another thing entirely... Is there some guidance on this in the site docs? – alexis – 2017-05-28T21:59:26.637

12@alexis most of these golfing languages use 256 different characters and a custom codepage that maps hex 00 to FF to those 256 characters, see the Jelly answer – Stephen – 2017-05-29T01:11:51.307

18

Jelly, 11 bytes

ŒufØAe€ØCŒḂ

Try it online!

Alternate versions:

ŒlfØae€ØCŒḂ

ŒufØAe€ØcŒḂ

ŒlfØae€ØcŒḂ

Of course a challenge appreciating Dennis must have an answer in a language of his.

Erik the Outgolfer

Posted 2017-05-28T12:41:52.477

Reputation: 38 134

17Œuf is Egg in french. Just sayin' – YSC – 2017-05-29T13:59:53.513

16

x86 32-bit machine-code function, 42 41 bytes

Currently the shortest non-golfing-language answer, 1B shorter than @streetster's q/kdb+.

With 0 for truthy and non-zero for falsy: 41 40 bytes. (in general, saves 1 byte for 32-bit, 2 bytes for 64-bit).

With implicit-length strings (C-style 0-terminated): 45 44 bytes

x86-64 machine-code (with 32-bit pointers, like the x32 ABI): 44 43 bytes.

x86-64 with implicit-length strings, still 46 bytes (the shift/mask bitmap strategy is break-even now).

This is a function with C signature _Bool dennis_like(size_t ecx, const char *esi). The calling convention is slightly non-standard, close to MS vectorcall/fastcall but with different arg registers: string in ESI and the length in ECX. It only clobbers its arg-regs and EDX. AL holds the return value, with the high bytes holding garbage (as allowed by the SysV x86 and x32 ABIs. IDK what MS's ABIs say about high-garbage when returning bool or narrow integers.)


Explanation of the algorithm:

Loop over the input string, filtering and classifying into a boolean array on the stack: For each byte, check if it's an alphabetic character (if not, continue to next char), and transform it to an integer from 0-25 (A-Z). Use that 0-25 integer to check a bitmap of vowel=0/consonant=1. (The bitmap is loaded into a register as a 32-bit immediate constant). Push 0 or 0xFF onto the stack according to the bitmap result (actually in the low byte of a 32-bit element, which may have garbage in the top 3 bytes).

The first loop produces an array of 0 or 0xFF (in dword elements padded with garbage). Do the usual palindrome check with a second loop that stops when pointers cross in the middle (or when they both point to the same element if there were an odd number of alphabetic characters). The upward-moving pointer is the stack pointer, and we use POP to load+increment. Instead of compare / setcc in this loop, we can just use XOR to detect same/different since there are only two possible values. We could accumulate (with OR) whether we found any non-matching elements, but an early-out branch on flags set by XOR is at least as good.

Notice that the second loop uses byte operand-size, so it doesn't care what garbage the first loop leaves outside the low byte of each array element.


It uses the undocumented salc instruction to set AL from CF, in the same way that sbb al,al would. It's supported on every Intel CPU (except in 64-bit mode), even Knight's Landing! Agner Fog lists timings for it on all AMD CPUs as well (including Ryzen), so if x86 vendors insist on tying up that byte of opcode space ever since 8086, we might as well take advantage of it.

Interesting tricks:

  • unsigned-compare trick for a combined isalpha() and toupper(), and zero-extends the byte to fill eax, setting up for:
  • immediate bitmap in a register for bt, inspired by some nice compiler output for switch.
  • Creating a variable-sized array on the stack with push in a loop. (Standard for asm, but not something you can do with C for the implicit-length string version). It uses 4 bytes of stack space for every input character, but saves at least 1 byte vs. optimal golfing around stosb.
  • Instead of cmp/setne on the boolean array, XOR booleans together to get a truth value directly. (cmp/salc isn't an option, because salc only works for CF, and 0xFF-0 doesn't set CF. sete is 3 bytes, but would avoid the inc outside the loop, for a net cost of 2 bytes (1 in 64-bit mode)) vs. xor in the loop and fixing it with inc.
; explicit-length version: input string in ESI, byte count in ECX
08048060 <dennis_like>:
 8048060:       55                      push   ebp
 8048061:       89 e5                   mov    ebp,esp  ; a stack frame lets us restore esp with LEAVE (1B)
 8048063:       ba ee be ef 03          mov    edx,0x3efbeee ; consonant bitmap

08048068 <dennis_like.filter_loop>:
 8048068:       ac                      lods   al,BYTE PTR ds:[esi]
 8048069:       24 5f                   and    al,0x5f    ; uppercase
 804806b:       2c 41                   sub    al,0x41    ; range-shift to 0..25
 804806d:       3c 19                   cmp    al,0x19    ; reject non-letters
 804806f:       77 05                   ja     8048076 <dennis_like.non_alpha>
 8048071:       0f a3 c2                bt     edx,eax    # AL = 0..25 = position in alphabet
 8048074:       d6                      SALC     ; set AL=0 or 0xFF from carry.  Undocumented insn, but widely supported
 8048075:       50                      push   eax
08048076 <dennis_like.non_alpha>:
 8048076:       e2 f0                   loop   8048068 <dennis_like.filter_loop>   # ecx = remaining string bytes
 ; end of first loop

 8048078:       89 ee                   mov    esi,ebp  ; ebp = one-past-the-top of the bool array
0804807a <dennis_like.palindrome_loop>:
 804807a:       58                      pop    eax      ; read from the bottom
 804807b:       83 ee 04                sub    esi,0x4
 804807e:       32 06                   xor    al,BYTE PTR [esi]
 8048080:       75 04                   jne    8048086 <dennis_like.non_palindrome>
 8048082:       39 e6                   cmp    esi,esp             ; until the pointers meet or cross in the middle
 8048084:       77 f4                   ja     804807a  <dennis_like.palindrome_loop>

08048086 <dennis_like.non_palindrome>:
 ; jump or fall-through to here with al holding an inverted boolean
 8048086:       40                      inc    eax
 8048087:       c9                      leave  
 8048088:       c3                      ret    
;; 0x89 - 0x60 = 41 bytes

This is probably also one of the fastest answers, since none of the golfing really hurts too badly, at least for strings under a few thousand characters where the 4x memory usage doesn't cause a lot of cache-misses. (It might also lose to answers that take an early-out for non-Dennis-like strings before looping over all the characters.) salc is slower than setcc on many CPUs (e.g. 3 uops vs. 1 on Skylake), but a bitmap check with bt/salc is still faster than a string-search or regex-match. And there's no startup overhead, so it's extremely cheap for short strings.

Doing it in one pass on the fly would mean repeating the classification code for the up and down directions. That would be faster but larger code-size. (Of course if you want fast, you can do 16 or 32 chars at a time with SSE2 or AVX2, still using the compare trick by range-shifting to the bottom of the signed range).


Test program (for ia32 or x32 Linux) to call this function with a cmdline arg, and exit with status = return value. strlen implementation from int80h.org.

; build with the same %define macros as the source below (so this uses 32-bit regs in 32-bit mode)
global _start
_start:
    ;%define PTRSIZE 4   ; true for x32 and 32-bit mode.

    mov  esi, [rsp+4 + 4*1]  ; esi = argv[1]
    ;mov  rsi, [rsp+8 + 8*1]  ; rsi = argv[1]   ; For regular x86-64 (not x32)

%if IMPLICIT_LENGTH == 0
        ; strlen(esi)
         mov     rdi, rsi
         mov     rcx, -1
        xor     eax, eax
        repne scasb    ; rcx = -strlen - 2
        not     rcx
        dec     rcx
%endif

    mov  eax, 0xFFFFAEBB   ; make sure the function works with garbage in EAX
    call dennis_like

    ;; use the 32-bit ABI _exit syscall, even in x32 code for simplicity
    mov ebx, eax
    mov eax, 1
    int 0x80           ; _exit( dennis_like(argv[1]) )

    ;; movzx edi, al   ; actually mov edi,eax is fine here, too
    ;; mov eax,231     ; 64-bit ABI exit_group( same thing )
    ;; syscall

A 64-bit version of this function could use sbb eax,eax, which is only 2 bytes instead of 3 for setc al. It would also need an extra byte for dec or not at the end (because only 32-bit has 1-byte inc/dec r32). Using the x32 ABI (32-bit pointers in long mode), we can still avoid REX prefixes even though we copy and compare pointers.

setc [rdi] can write directly to memory, but reserving ECX bytes of stack space costs more code-size than that saves. (And we need to move through the output array. [rdi+rcx] takes one extra byte for the addressing mode, but really we need a counter that doesn't update for filtered characters so it's going to be worse than that.)


This is the YASM/NASM source with %if conditionals. It can be built with -felf32 (32-bit code) or -felfx32 (64-bit code with the x32 ABI), and with implicit or explicit length. I've tested all 4 versions. See this answer for a script to build a static binary from NASM/YASM source.

To test the 64-bit version on a machine without support for the x32 ABI, you can change the pointer regs to 64-bit. (Then simply subtract the number of REX.W=1 prefixes (0x48 bytes) from the count. In this case, 4 instructions need REX prefixes to operate on 64-bit regs). Or simply call it with the rsp and the input pointer in the low 4G of address space.

%define IMPLICIT_LENGTH 0

; This source can be built as x32, or as plain old 32-bit mode
; x32 needs to push 64-bit regs, and using them in addressing modes avoids address-size prefixes
; 32-bit code needs to use the 32-bit names everywhere

;%if __BITS__ != 32   ; NASM-only
%ifidn __OUTPUT_FORMAT__, elfx32
%define CPUMODE 64
%define STACKWIDTH 8    ; push / pop 8 bytes
%else
%define CPUMODE 32
%define STACKWIDTH 4    ; push / pop 4 bytes
%define rax eax
%define rcx ecx
%define rsi esi
%define rdi edi
%define rbp ebp
%define rsp esp
%endif

    ; A regular x86-64 version needs 4 REX prefixes to handle 64-bit pointers
    ; I haven't cluttered the source with that, but I guess stuff like %define ebp rbp  would do the trick.


    ;; Calling convention similar to SysV x32, or to MS vectorcall, but with different arg regs
    ;; _Bool dennis_like_implicit(const char *esi)
    ;; _Bool dennis_like_explicit(size_t ecx, const char *esi)
global dennis_like
dennis_like:
    ; We want to restore esp later, so make a stack frame for LEAVE
    push  rbp
    mov   ebp, esp   ; enter 0,0 is 4 bytes.  Only saves bytes if we had a fixed-size allocation to do.

    ;         ZYXWVUTSRQPONMLKJIHGFEDCBA
    mov  edx, 11111011111011111011101110b   ; consonant/vowel bitmap for use with bt

;;; assume that len >= 1
%if IMPLICIT_LENGTH
    lodsb   ; pipelining the loop is 1B shorter than  jmp .non_alpha
.filter_loop:
%else
.filter_loop:
    lodsb
%endif

    and   al, 0x7F ^ 0x20  ; force ASCII to uppercase.
    sub   al, 'A'          ; range-shift to 'A' = 0
    cmp   al, 'Z'-'A'      ; if al was less than 'A', it will be a large unsigned number
    ja  .non_alpha
    ;; AL = position in alphabet (0-25)

    bt    edx, eax              ; 3B
%if CPUMODE == 32
    salc                        ; 1B   only sets AL = 0 or 0xFF.  Not available in 64-bit mode
%else
    sbb   eax, eax              ; 2B   eax = 0 or -1, according to CF.
%endif
    push  rax

.non_alpha:
%if IMPLICIT_LENGTH
    lodsb
    test   al,al
    jnz .filter_loop
%else
    loop .filter_loop
%endif
    ; al = potentially garbage if the last char was non-alpha
    ; esp = bottom of bool array

    mov   esi, ebp  ; ebp = one-past-the-top of the bool array
.palindrome_loop:
    pop   rax

    sub   esi, STACKWIDTH
    xor   al, [rsi]   ; al = (arr[up] != arr[--down]).  8-bit operand-size so flags are set from the non-garbage
    jnz .non_palindrome

    cmp   esi, esp
    ja .palindrome_loop

.non_palindrome:  ; we jump here with al=1 if we found a difference, or drop out of the loop with al=0 for no diff
    inc   eax     ;; AL transforms 0 -> 1  or  0xFF -> 0.
    leave
    ret           ; return value in AL.  high bytes of EAX are allowed to contain garbage.

I looked at messing around with DF (the direction flag that controls lodsd / scasd and so on), but it just didn't seem to be a win. The usual ABIs require that DF is cleared on function entry and exit. Assuming cleared on entry but leaving it set on exit would be cheating, IMO. It would be nice to use LODSD / SCASD to avoid the 3-byte sub esi, 4, especially in the case where there's no high-garbage.


Alternate bitmap strategy (for x86-64 implicit-length strings)

It turns out this doesn't save any bytes, because bt r32,r32 still works with high garbage in the bit-index. It's just not documented the way shr is.

Instead of bt / sbb to get the bit into / out of CF, use a shift / mask to isolate the bit we want from the bitmap.

%if IMPLICIT_LENGTH && CPUMODE == 64
    ; incompatible with LOOP for explicit-length, both need ECX.  In that case, bt/sbb is best
    xchg  eax, ecx
    mov   eax, 11111011111011111011101110b   ; not hoisted out of the loop
    shr   eax, cl
    and   al, 1
%else
    bt    edx, eax
    sbb   eax, eax
%endif
    push  rax

Since this produces 0/1 in AL at the end (instead of 0/0xFF), we can do the necessary inversion of the return value at the end of the function with xor al, 1 (2B) instead of dec eax (also 2B in x86-64) to still produce a proper bool / _Bool return value.

This used to save 1B for x86-64 with implicit-length strings, by avoiding the need to zero the high bytes of EAX. (I had been using and eax, 0x7F ^ 0x20 to force to upper-case and zero the rest of eax with a 3-byte and r32,imm8. But now I'm using the 2-byte immediate-with-AL encoding that most 8086 instructions have, like I was already doing for the sub and cmp.)

It loses to bt/salc in 32-bit mode, and explicit-length strings need ECX for the count so this doesn't work there either.

But then I realized that I was wrong: bt edx, eax still works with high garbage in eax. It apparently masks the shift count the same way shr r32, cl does (looking only at the low 5 bits of cl). This is different from bt [mem], reg, which can access outside the memory referenced by the addressing-mode/size, treating it as a bitstring. (Crazy CISC...)

Intel's insn set ref manual doesn't document the masking, so maybe it's undocumented behaviour that Intel is preserving for now. (That kind of thing is not uncommon. bsf dst, src with src=0 always leaves dst unmodified, even though it's documented to leave dst holding an undefined value in that case. AMD actually documents the src=0 behaviour.) I tested on Skylake and Core2, and the bt version works with non-zero garbage in EAX outside of AL.

A neat trick here is using xchg eax,ecx (1 byte) to get the count into CL. Unfortunately, BMI2 shrx eax, edx, eax is 5 bytes, vs. only 2 bytes for shr eax, cl. Using bextr needs a 2-byte mov ah,1 (for the number of bits to extract), so it's again 5 + 2 bytes like SHRX + AND.


The source code has gotten pretty messy after adding %if conditionals. Here's disassembly of x32 implicit-length strings (using the alternate strategy for the bitmap, so it's still 46 bytes).

The main difference from the explicit-length version is in the first loop. Notice how there's a lods before it, and at the bottom, instead of just one at the top of the loop.

    ; 64-bit implicit-length version using the alternate bitmap strategy
    00400060 <dennis_like>:
      400060:       55                      push   rbp
      400061:       89 e5                   mov    ebp,esp
      400063:       ac                      lods   al,BYTE PTR ds:[rsi]

    00400064 <dennis_like.filter_loop>:
      400064:       24 5f                   and    al,0x5f
      400066:       2c 41                   sub    al,0x41
      400068:       3c 19                   cmp    al,0x19
      40006a:       77 0b                   ja     400077 <dennis_like.non_alpha>
      40006c:       91                      xchg   ecx,eax
      40006d:       b8 ee be ef 03          mov    eax,0x3efbeee  ; inside the loop since SHR destroys it
      400072:       d3 e8                   shr    eax,cl
      400074:       24 01                   and    al,0x1
      400076:       50                      push   rax
    00400077 <dennis_like.non_alpha>:
      400077:       ac                      lods   al,BYTE PTR ds:[rsi]
      400078:       84 c0                   test   al,al
      40007a:       75 e8                   jne    400064 <dennis_like.filter_loop>

      40007c:       89 ee                   mov    esi,ebp
    0040007e <dennis_like.palindrome_loop>:
      40007e:       58                      pop    rax
      40007f:       83 ee 08                sub    esi,0x8
      400082:       32 06                   xor    al,BYTE PTR [rsi]
      400084:       75 04                   jne    40008a <dennis_like.non_palindrome>
      400086:       39 e6                   cmp    esi,esp
      400088:       77 f4                   ja     40007e <dennis_like.palindrome_loop>

    0040008a <dennis_like.non_palindrome>:
      40008a:       ff c8                   dec    eax  ; invert the 0 / non-zero status of AL.  xor al,1 works too, and produces a proper bool.
      40008c:       c9                      leave  
      40008d:       c3                      ret    

   0x8e - 0x60 = 0x2e = 46 bytes

Peter Cordes

Posted 2017-05-28T12:41:52.477

Reputation: 2 810

8

Retina, 49 47 45 bytes

\P{L}

i`[aeiou]
1
\D
2
+`^(.)(.*)\1$
$2
^.?$

Try it online!

Saved 2 bytes thanks to Neil.

Saved another 2 bytes thanks to Martin.

Removes non-letters then replaces vowels with 1 and consonants with 2, to get consistent values. Then repeatedly removes the first and last character if they are the same. Once they aren't, the word was symmetric if there are one or zero characters remaining.

FryAmTheEggman

Posted 2017-05-28T12:41:52.477

Reputation: 16 206

Does \D 2 work to save you a couple of bytes over T`lL`2? – Neil – 2017-05-28T20:42:03.307

@Neil Yes it seems to, nice catch! – FryAmTheEggman – 2017-05-28T21:49:39.137

Well done. I was trying to do this :( – Christopher – 2017-05-28T23:32:58.153

7

PHP, 82 Bytes

<?=strrev($s=preg_replace(["#[^a-z]#i","#[aeiou]#i","#\pL#"],["",0,1],$argn))==$s;

Try it online!

Jörg Hülsermann

Posted 2017-05-28T12:41:52.477

Reputation: 13 026

You could prepend typecasting (bool) and remove the $s= and the ==$s check to save 1 byte. – kaiser – 2017-05-29T17:33:38.580

If I am not mistaken, you could replace the (bool) with just 0|| to say false, or … instead, saving 3 additional bytes. – kaiser – 2017-05-29T17:35:32.443

Hm. Couldn't you use \w for word characters instead of the a-z? – kaiser – 2017-05-29T17:38:46.563

@kaiser \w contains digits underscore and letters . This will not work and [^/p{L}] is longer as [^a-z] plus i. I compare the reverse string with the string so $s is needed to create the boolean – Jörg Hülsermann – 2017-05-29T18:06:28.033

That is true. Still the others should work. "Should" … they do. – kaiser – 2017-05-30T04:56:04.697

@kaiser If really neccessary somewhere then typecast to bool is best done by !!. – Christoph – 2017-06-01T08:00:26.603

6

MATL, 14 bytes

t3Y2m)13Y2mtP=

Try it at MATL Online.

Here is a slightly modified version to check all test cases.

Explanation

        % Implicitly grab the input as a string
        %     STACK: {'Martin Ender'}
t       % Duplicate the input
        %     STACK: {'Martin Ender', 'Martin Ender'}
3Y2     % Push the string 'ABC...XYZabc...xyz'
        %     STACK: {'Martin Ender', 'Martin Ender', 'ABC...XYZabc...xyz'}
m       % Find which characters of the input are letters using this string
        %     STACK: {'Martin Ender', [1 1 1 1 1 1 0 1 1 1 1]}
)       % Use this boolean array to select only the letters
        %     STACK: {'MartinEnder'}
13Y2    % Push the string literal 'aeiouAEIOU' to the stack
        %     STACK: {'MartinEnder', 'aeiouAEIOU'}
m       % Check for membership of each letter of the input in this string.
        %     STACK: {[0 1 0 0 1 0 1 0 0 1 0]}
tP      % Create a reversed copy
        %     STACK: {[0 1 0 0 1 0 1 0 0 1 0], [0 1 0 0 1 0 1 0 0 1 0]}
=       % Perform an element-wise comparison yielding a truthy (all 1's) or 
        % falsey (any 0's) result
        %     STACK: {[1 1 1 1 1 1 1 1 1 1 1]}
        % Implicitly display the result

Suever

Posted 2017-05-28T12:41:52.477

Reputation: 10 257

You demonstrate it with "Martin Ender" instead of "Dennis"? i have to look at the challenge title again. – Roman Gräf – 2017-05-28T17:36:07.563

1Presumably Suever wanted a demonstration that had some amount of filtering at the first step. – Greg Martin – 2017-05-28T19:58:18.887

Then he should use "Alex A." instead, it has a period too. – Erik the Outgolfer – 2017-05-29T07:49:07.403

2I'm confused what the issue is. I chose Martin Ender because it would actually be true if you remove spaces and false otherwise. I also included a link to all test cases – Suever – 2017-05-29T12:51:21.983

6

Haskell, 84 75 74 69 bytes

-10 thanks to @nimi
-5 thanks to @Zgarb

f x=(==)<*>reverse$[elem c"aeiouAEIOU"|c<-x,'@'<c,c<'{','`'<c||c<'[']

The list comprehension replaces each letter with a boolean and removes all other characters. The first part checks whether or not the resulting list is a palindrome.

Try it online!

bearbear2k

Posted 2017-05-28T12:41:52.477

Reputation: 71

Two tips: 1) A list comprehension is often shorten than filter followed by map even if you have to switch to non-poitfree. 2) The <$>id is superfluous. f x=(==)<*>reverse$[elem c"aeiouAEIOU"|c<-x,celem['A'..'Z']++['a'..'z']]. – nimi – 2017-05-28T14:54:50.860

You can drop the space between c and " for one more byte. – nimi – 2017-05-28T16:27:29.527

1I think c`elem`['A'..'Z']++['a'..'z'] can be shortened to '@'<c,c<'{','`'<c||c<'[' – Zgarb – 2017-05-29T09:49:00.590

5

Pyth, 18 15 bytes

_I/L"aeiou"@Gr0

Try it here.

-2 thanks to KarlKastor, and subsequently -1.

Erik the Outgolfer

Posted 2017-05-28T12:41:52.477

Reputation: 38 134

16 bytes: _I/L"aeiou"@Grz0 (using the invariance operator I) – KarlKastor – 2017-05-28T18:11:10.593

@KarlKastor I knew there had to be some operator like that...thanks. (BTW I can now remove the z too, I will assume quoted input) – Erik the Outgolfer – 2017-05-28T18:38:12.150

4

Brachylog, 13 bytes

ḷ{∈Ṿg|∈Ḅg}ˢ.↔

Try it online!

Explanation

ḷ                Lowercase the input
 {       }ˢ.     Select each char if:
  ∈Ṿg              it's a vowel, and replace it with ["aeiou"]            
     |             Or
      ∈Ḅg          it's a consonant, and replace it with ["bcdfghjklkmnpqrstvwxyz"]
           .↔    The resulting list is a palindrome

Fatalize

Posted 2017-05-28T12:41:52.477

Reputation: 32 976

3

JavaScript (ES6), 72 69 bytes

Saved 3 bytes thanks to Neil

Returns a boolean.

s=>(a=s.match(/[a-z]/gi).map(c=>!/[aeiou]/i.exec(c)))+''==a.reverse()

Test cases

let f =

s=>(a=s.match(/[a-z]/gi).map(c=>!/[aeiou]/i.exec(c)))+''==a.reverse()

console.log(f("Dennis"))        // -> truthy
console.log(f("Martin"))        // -> truthy
console.log(f("Martin Ender"))  // -> truthy
console.log(f("Alex"))          // -> falsy
console.log(f("Alex A."))       // -> truthy
console.log(f("Doorknob"))      // -> falsy
console.log(f("Mego"))          // -> falsy

Arnauld

Posted 2017-05-28T12:41:52.477

Reputation: 111 334

Save a couple of bytes by replacing the 2 empty strings with 2. – Shaggy – 2017-05-28T19:56:54.977

1Do you even need the +'' at the end? That would save 3 bytes instead. – Neil – 2017-05-28T20:24:17.030

I like @Neil's idea better! – Shaggy – 2017-05-28T20:45:13.513

3

Python 3, 72 71 bytes

-1 byte thanks to @ovs

def f(s):s=[c in'AEIOU'for c in s.upper()if'@'<c<'['];return s==s[::-1]

Try it online!

Trelzevir

Posted 2017-05-28T12:41:52.477

Reputation: 987

def f(s):s=[c in'AEIOU'for c in s.upper()if'@'<c<'['];return s==s[::-1] for 71 bytes – ovs – 2017-05-28T19:06:16.583

3

Alice, 28 bytes

/uia.QN."-e@
\1"lyuy.Ra$i1/o

Try it online!

Outputs 1 as truthy and nothing as falsy.

Explanation

Every command in this program executes in ordinal mode, but with a slight twist in the template that allows me to save a byte. If a newline is an acceptable truthy value, I can save one more byte by the same method.

Linearized, the program is as follows:

1il.uN."aei ou"ayQy.R-$@1o1@

1                           % Append "1" to top of stack
                            % STACK: ["1"]
 i                          % Push input to stack
                            % STACK: ["1", "Dennis"]
  l                         % Convert to lowercase
                            % STACK: ["1", "dennis"]
   .                        % Duplicate
                            % STACK: ["1", "dennis", "dennis"]
    u                       % Convert to uppercase
                            % STACK: ["1", "dennis", "DENNIS"]
     N                      % Take multiset difference; this removes all non-alphabetic characters
                            % STACK: ["1", "dennis"]
      .                     % Duplicate
                            % STACK: ["1", "dennis", "dennis"]
       "aei ou"             % Push "aei ou"
                            % STACK: ["1", "dennis", "dennis", "aei ou"]
              a             % Push newline
                            % STACK: ["1", "dennis", "dennis", "aeiou", "\n"]
               y            % Transliterate: replace all vowels with newlines
                            % STACK: ["1", "dennis", "d\nnn\ns"]
                Q           % Reverse stack
                            % STACK: ["d\nnn\ns", "dennis", "1"]
                 y          % Transliterate: replace remaining characters with "1"
                            % STACK: ["1\n11\n1"]
                  .         % Duplicate
                            % STACK: ["1\n11\n1", "1\n11\n1"]
                   R        % Reverse top of stack
                            % STACK: ["1\n11\n1", "1\n11\n1"]
                    -       % Remove occurrences: for same-length strings, result is "" iff strings are equal.
                            % STACK: [""]
                     $      % Pop stack, and skip next command if ""
                      @     % Terminate (skipped if c/v pattern is palindromic)
                       1o   % Output "1"
                         1  % Push "1" (useless)
                          @ % Terminate

Nitrodon

Posted 2017-05-28T12:41:52.477

Reputation: 9 181

2

CJam, 26 bytes

lel_'{,97>--"aeiou"fe=_W%=

Try it online!

-1 thanks to Esolanging Fruit.

Erik the Outgolfer

Posted 2017-05-28T12:41:52.477

Reputation: 38 134

You can replace 26,'af+ with '{,97> to save a byte. – Esolanging Fruit – 2018-02-01T05:14:40.257

@EsolangingFruit such an old answer... – Erik the Outgolfer – 2018-02-01T12:21:40.043

A byte saved half a year ago is no different than a byte saved now. It's not like there's byte inflation or anything :P – Esolanging Fruit – 2018-02-01T16:19:04.790

@EsolangingFruit I was referring to my always developing experience with golfing...of course you got a credit as usual, don't worry! – Erik the Outgolfer – 2018-02-01T17:37:16.760

2

Mathematica, 113 bytes

PalindromeQ@StringCases[StringReplace[#,{Characters["aeiouAEIOU"]->"1",CharacterRange["A","z"]->"0"}],{"0","1"}]&

J42161217

Posted 2017-05-28T12:41:52.477

Reputation: 15 931

You can get rid of quite a few bytes: PalindromeQ@StringReplace[#,{Characters@"aeiouAEIOU"->"1",LetterCharacter->"0",_->""}]& – Not a tree – 2017-05-30T08:16:02.583

2

q/kdb+, 42 38 bytes

Solution:

{x~|:[x]}{inter[x;.Q.a]in"aeiou"}lower

Example:

q){x~|:[x]}{inter[x;.Q.a]in"aeiou"}lower"Dennis"
1b
q){x~|:[x]}{inter[x;.Q.a]in"aeiou"}lower"Adam"
0b
q){x~|:[x]}{inter[x;.Q.a]in"aeiou"}lower"Alex A."
1b

Explanation:

lower        // converts argument on the right to lowercase
.Q.a         // lowercase alphabet "abc..xyz"
inter[x;y]   // intersection of x and y (thus only return a-z)
x in "aeiou" // returns boolean list whether x is a vowel; "dennis" = 010010b
|:           // k shorthand for 'reverse'

Edits:

  • -4 bytes; switching out reverse for k equivalent |:

streetster

Posted 2017-05-28T12:41:52.477

Reputation: 3 635

2

GolfScript, 42 bytes

{123,65>.26>6<-?)},{"AEIOUaeiou"?)!}%.-1%=

Try it online!

The hard part is generating both the uppercase and lowercase alphabet in one string, which we'll use in a filter function to filter the letters out of the input. Luckily, since strings in GolfScript are just codepoint arrays with a special property, so we can just generate the codepoints in an efficient way. Here's how we generate them:

First, we generate range [0..122], 122 being the codepoint for z. Then, we take the elements from the element at index 65 onwards. 65 is the codepoint for A. Right now, we have [65..122]. All fine, except we have some unwanted codepoints ([91..96]) in there. So, we first make a duplicate of that range. Then, we take the elements from index 26 onwards, and we have [91..122]. After that, we get the elements up to and including index 5. Now we have [91..96]. Finally, we remove those elements from our [65..122], leaving us wil [65..90, 97..122]. Those are the codepoints we want.

Now that we made the upper/lower alphabet codepoint list, we continue our filtering function. The function gets mapped to each character on the input string, which, as I initially said, gets parsed as its codepoint instead. So now we essentially have [codepoint, [65..90, 97..122]]. To find out if char codepoint is a letter, we simply take its index in the list we made. If it isn't there, we'll get -1 as the index instead.

Right now, we get a falsey value only if codepoint == 65, i.e. the first index of our list, since only then would the index be 0. But a single increment will fix this problem, and, now, if codepoint is in our list, we'll get its index + 1, which is always a positive number, thus always truthy, while if it's not there we'll get -1 + 1 = 0, i.e. falsey.

We finally apply the function I described to every char of the input, and we only take the chars for which the function returned a truthy result.

Next up we have to determine if each char is a vowel or consonant. Since the vowels are fewer than the consonants, creating a string of vowels so that we check for that condition is shorter than creating a string of consonants, so we check if each char is a vowel. But, to check if the boolean list is palindromic, we need booleans, which we don't get just by taking the index + 1, since that can result in any number of [1..10] if the char is a vowel. And, as most golfing languages, this one, doesn't have a bool function either. So, we simply use not not x, since not always returns a boolean. But wait; do we really need to have specific booleans? Since not always returns a boolean, why don't we just remove the second not, and actually check if each char is a consonant? Yeah, that's exactly what we'll do!

After the check, which returns a list of booleans, we check if this boolean list we got is a palindrome, which is what this challenge asks us to do. Well, what is the definition of a palindrome? Yes, a palindrome is a list or string which is equal to its reverse. So, how do we check? Simple, we duplicate it, take its reverse, and check against the original list. The result we get is, finally, what our code should return.

Erik the Outgolfer

Posted 2017-05-28T12:41:52.477

Reputation: 38 134

1Giant explanation for a 42-byte program. Now I guess that it's pretty much self-explanatory... – Erik the Outgolfer – 2017-05-28T20:22:39.447

2

PHP, 87 bytes

Regex free PHP version. Added a "vowel" since stripos can return 0 which is false in PHP.

Flaw fixed by Jörg.

for(;a&$c=$argn[$p++];)!ctype_alpha($c)?:$s.=stripos(_aeiou,$c)?0:1;echo$s==strrev($s);

Try it online!

M.E

Posted 2017-05-28T12:41:52.477

Reputation: 91

Same Byte count. for(;a&$c=$argn[$p++];)ctype_alpha($c)?$s.=stripos(_aeiou,$c)?0:1:0;echo$s==strrev($s); but it get the right result for strings that contains zero – Jörg Hülsermann – 2017-05-29T14:08:11.157

@JörgHülsermann Thank you. – M.E – 2017-05-29T14:24:03.820

2

Braingolf,  4  3 bytes

&JP

-1 byte thanks to Erik the Outgolfer

Turns out I had P all along, even before this challenge.

J however, despite being created before this challenge, wasn't pushed to github before the challenge, thus is still non-competing.

Explanation:

&JP  Implicit input, push ASCII value of each char in string to stack
&J   Replace each item in stack with 1 if vowel, otherwise 0
  P  Pop entire stack, push 1 if stack is palindromic, 0 otherwise
     Implicit output of last item on stack

Skidsdev

Posted 2017-05-28T12:41:52.477

Reputation: 9 656

Why do you need n? – Erik the Outgolfer – 2017-05-30T15:05:41.647

@EriktheOutgolfer because I'm a certified moron – Skidsdev – 2017-05-30T15:34:52.173

Hmm, you forgot to remove it from the explanation. – Erik the Outgolfer – 2017-05-30T15:39:02.030

@EriktheOutgolfer I was gunna write "Erick" then strike out the c, but it just looks like "Eriek" – Skidsdev – 2017-05-30T16:02:19.877

Won't this fail for the likes of Alex A.? – Shaggy – 2018-02-01T12:39:30.550

@Shaggy no, because after J, the stack would be 101001, assuming you exclude the dot, if you include it there'd be an extra 0 at the end. Either way the result would be 0 for false, as expected because Alex A. is not a Dennis name – Skidsdev – 2018-02-07T16:21:19.157

You might want to double check the spec ;) Non-letter characters should be ignored completely, making Alex A. truthy. – Shaggy – 2018-02-07T16:37:43.577

1

APL (Dyalog Unicode), 34 33 24 bytes

Saved bytes thanks to Adám

≡∘⌽⍨'AEIOU'∊⍨⎕a∩⍨819⌶⍨∘1

Try it online!

819⌶⍨∘1 uppercase argument

⎕a∩⍨ intersection with uppercase alphabet

'AEIOU'∊⍨ belongs-to-'AEIOU'? resulting in a boolean vector

≡∘⌽⍨ reversed equivalent to self?

user41805

Posted 2017-05-28T12:41:52.477

Reputation: 16 320

Save a byte with 819⌶⍨∘1 – Adám – 2017-05-28T15:15:05.967

And two with (⊢≡⌽) – Adám – 2017-05-28T15:18:22.903

… but I can solve this in 24. Want any hints? – Adám – 2017-05-28T15:39:41.207

@Adám That trick is nice, thanks, got 24 too after over two years – user41805 – 2020-01-30T17:31:18.853

In a few of months, you can save another 2 bytes with 819⌶⎕C, or you can go Extended today, and do 819⌶⍨∘1 – Adám – 2020-01-30T21:01:53.897

1

Python 3, 92 87 74 72 69 68 bytes

l=[c in'aeouiAEOUI'for c in input()if c.isalpha()]
print(l==l[::-1])

Try it online!

Martmists

Posted 2017-05-28T12:41:52.477

Reputation: 429

You can remove the space before the for c in s – user41805 – 2017-05-28T13:23:03.127

And you can remove the s variable by replacing s on the second line to input().lower() – user41805 – 2017-05-28T13:23:54.627

1

Python 2, 83 bytes

def f(x):k=map(lambda y:y.lower()in"aeiou",filter(str.isalpha,x));return k==k[::-1]

Defines a function that either gives True or False

Loovjo

Posted 2017-05-28T12:41:52.477

Reputation: 7 357

You can save 2 bytes by using "aeiouAEIOU".__contains__ instead of lambda y:y.lower()in"aeiou". – Blender – 2017-05-31T08:07:12.533

1

CJam, 79 bytes

First-timer! (I did what I could)

r{:X"AEIOUaeiou"#W>{X"BCDFGHJKLMNPQRSTVWXYZbdfghjklmnpqrstvwxyz"#W={'0}&}'1?~}%

Try it online!

Iaka Noe

Posted 2017-05-28T12:41:52.477

Reputation: 133

1Welcome to PP&CG! – Greg Martin – 2017-05-28T19:58:58.363

1

Japt v2.0a0, 19 11 bytes

k\L mè\v ê¬

Try it online


Explanation

        :Implicit input of string U.
 k\L    :Remove all non-letter characters from U.
 m      :Map over resulting string, replacing each character ...
 è\v    :with the count of the number of vowels in each single character substring.
 ê¬     :Is the above a palindrome?
        :Implicit output of boolean result.

Shaggy

Posted 2017-05-28T12:41:52.477

Reputation: 24 623

1

Ruby, 57 bytes

->s{x=s.scan(/\p{L}/).map{|c|c=~/[aeiou]/i};x==x.reverse}

Try it online!

daniero

Posted 2017-05-28T12:41:52.477

Reputation: 17 193

1

Bash, 82 bytes

i=${1//[^a-zA-Z]};a=aeouiAEOUI;b=${i//[$a]/0};c=${b//[!0$a]/1};[ $c = `rev<<<$c` ]

Try it online!

Recives name as parameter, removes non-leters, replaces vowels with 0, non-vowels nor 0 with 1 and compares with same reversed.

Could golf some more if can get to work double or triple substitution

Exit status is 0 for true and 1 for no.

marcosm

Posted 2017-05-28T12:41:52.477

Reputation: 986

In recent bash versions, i=${i^^*}; converts i to uppercase. But I think it only saves you an a-z and an aeiou, which is less than the 10B it costs. – Peter Cordes – 2017-05-30T10:49:20.767

1

64-bit machine code, 89 bytes.

A function of following signature: eax = f(char * edi)

48 89 F8 48 89 FE 41 B8 22 82 20 00 8A 0E 84 C9
74 23 89 CA 83 E2 DF 0F BE D2 83 EA 41 83 FA 19
77 0E 44 89 C2 48 FF C0 D3 FA 83 E2 01 88 50 FF
48 FF C6 EB D7 C6 00 02 48 FF C7 48 FF C8 8A 17
40 8A 30 40 38 77 FF 75 05 80 FA 02 75 EA 31 C0
80 FA 02 0F 94 C0 C3

Assembled using NASM, from such assembly code:


; edi => input string.
; eax <= 1 or 0.

; notes:
; the string needs to be null terminated and located in a
; writable memory location, as it will be mutated.

BITS 64

DENNIS: MOV RAX, RDI
        MOV RSI, RDI
        MOV R8D, 0x208222
.CTOR:  MOV CL, BYTE [RSI]
        TEST CL, CL
        JE .SP
        MOV EDX, ECX
        AND EDX, -33
        MOVSX EDX, DL
        SUB EDX, 65
        CMP EDX, 25
        JA .LI
        MOV EDX, R8D
        INC RAX
        SAR EDX, CL
        AND EDX, 1
        MOV BYTE [RAX-1], DL
.LI:    INC RSI
        JMP .CTOR
.SP:    MOV BYTE [RAX], 2
.EQL:   INC RDI
        DEC RAX
        MOV DL, BYTE [RDI]
        MOV SIL, BYTE [RAX]
        CMP BYTE [RDI-1], SIL
        JNE .EQE
        CMP DL, 2
        JNE .EQL
.EQE:   XOR EAX, EAX
        CMP DL, 2
        SETE AL
        RET

Not a killer, not even close, but it has a couple of advantages over the 41-byte answer:

  • Requires no memory (not even stack).
  • Doesn't require to check the length of a string - it uses null-termination instead.
  • Doesn't use undocumented CPU instructions.

Just my $0.02 :).

Krzysztof Szewczyk

Posted 2017-05-28T12:41:52.477

Reputation: 3 819

0

PowerShell, 108 bytes

read-host|%{[char[]]$_|%{$d=$_-replace'\P{L}'-replace'[aeiou]',0-replace'\D',1;$s="$s$d";$r="$d$r"};$s-eq$r}

Andrei Odegov

Posted 2017-05-28T12:41:52.477

Reputation: 939

0

Axiom, 126 bytes

g(x)==~member?(x,alphabetic());v(s:String):Boolean==(w:=remove(g,s);a:=[member?(w.r,"aeiouAEIOU")for r in 1..#w];a=reverse(a))

test

(8) -> [[i,v(i)] for i in ["Dennis", "Martin", "Martin Ender", "Alex", "Alex A.", "Doorknob", "Mego"]]
   (8)
   [["Dennis",true], ["Martin",true], ["Martin Ender",true], ["Alex",false],
    ["Alex A.",true], ["Doorknob",false], ["Mego",false]]
                                                      Type: List List Any

RosLuP

Posted 2017-05-28T12:41:52.477

Reputation: 3 036

0

Actually, 20 bytes

ù⌠úc⌡░⌠"aeiou"c⌡M;R=

Try it online! (runs all test cases)

-3 bytes from Erik the Outgolfer's suggestion on a different answer

Explanation:

ù⌠úc⌡░⌠"aeiou"c⌡M;R=
ù                     lowercase input
 ⌠úc⌡░                characters where function is truthy:
  úc                    is the character a lowercase letter?
      ⌠"aeiou"c⌡M     for each letter:
       "aeiou"c         does the vowel string contain the letter?
                 ;R=  compare equality with reverse (is it a palindrome?)

Mego

Posted 2017-05-28T12:41:52.477

Reputation: 32 998

0

Retina, 47 bytes

i(`[^a-z]

[aeiou]
1
\D
0
+`^(.)(.*)\1$
$2
^.?$

Try it online!

This is just a different approach for non alphabet chars

Christopher

Posted 2017-05-28T12:41:52.477

Reputation: 3 428

0

Pyke, 12 bytes

#B)l1~-L{D_q

Try it here!

#B)          -    filter(is_alpha, input)
   l1        -   ^.lower()
     ~-L{    -  ^ - "bcdfghjklmnpqrstvwxyz"
         D_q - ^ == reversed(^)

Blue

Posted 2017-05-28T12:41:52.477

Reputation: 26 661

0

PowerShell, 87 Bytes

$s=("$args"-replace '\P{L}'-replace'[aeiou]',0-replace'\D',1);$s-eq(-join($s[-1..-99]))

Get a copy of the string where vowels are 0 and consonants are 1, with all special chars removed, compare that string to a reversed version joined back to a string

Output:

PS C:\Users\Connor> "Dennis","Martin","Martin Ender","Alex","Alex A.","Doorknob","Mego" | % {
    $s=("$_"-replace '\P{L}'-replace'[aeiou]',0-replace'\D',1);$s-eq(-join($s[-1..-99]))
}
True
True
True
False
True
False
False

colsw

Posted 2017-05-28T12:41:52.477

Reputation: 3 195

0

Google Sheets, 248 bytes

=ArrayFormula(REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(UPPER(A1),"[^A-Z]",""),"[AEIOU]","0"),"[^0]","1")=REGEXREPLACE(REGEXREPLACE(REGEXREPLACE(UPPER(JOIN("",(MID(A1,LEN(A1)-ROW(INDIRECT("1:"&LEN(A1)))+1,1)))),"[^A-Z]",""),"[AEIOU]","0"),"[^0]","1"))

Three nested REGEXREPLACE functions transform it from the original to a string of ones and zeroes. The JOIN function is used to reverse the original string so it's nested into the same REGEXREPLACE functions to transform it to the reverse string of ones and zeroes. It's a nightmare.

Engineer Toast

Posted 2017-05-28T12:41:52.477

Reputation: 5 769

0

Perl, 42 bytes

s!(.)\PL*!1+aeiou=~lc$1!ge;$_=$_==reverse

Run with perl -p.

Grimmy

Posted 2017-05-28T12:41:52.477

Reputation: 12 521

0

Excel VBA, 115 Bytes

Anonymous VBE immediate window function that takes input from range [A1] and outputs to the VBE immediate window.

For i=1To[Len(A1)]:a=Mid([A1],i,1):b=IIf(Instr(1,"AEIOU",a,1),1,IIf(a Like"[A-Za-z]",0,""))&b:Next:?b=StrReverse(b)

Taylor Scott

Posted 2017-05-28T12:41:52.477

Reputation: 6 709

0

Kotlin, 75 bytes

filter{it.isLetter()}.map{"aeiou".contains(it,true)}.let{it==it.reversed()}

Beautified

filter { it.isLetter() }.map { "aeiou".contains(it, true) }.let { it == it.reversed() }

Test

data class Test(val input: String, val output: Boolean)

val tests = listOf(
    Test("Dennis",true),
    Test("Martin",true),
    Test("Martin Ender",true),
    Test("Alex",false),
    Test("Alex A.",true),
    Test("Doorknob",false),
    Test("Mego",false)
)

fun String.f() =
filter{it.isLetter()}.map{"aeiou".contains(it,true)}.let{it==it.reversed()}
fun main(args: Array<String>) {
    for ((input, expected) in tests) {
        val actual = input.f()
        if (actual != expected) throw AssertionError()
    }
}

TIO

TryItOnline

jrtapsell

Posted 2017-05-28T12:41:52.477

Reputation: 915

0

Julia 0.6, 65 bytes

f(s,b=[c in "aeiouAEIOU" for c in s if isalpha(c)])=b==reverse(b)

Try it online!

gggg

Posted 2017-05-28T12:41:52.477

Reputation: 1 715

0

Pyt, 59 bytes

ɬ←ąĐ0↔ą∈⇹6²Ĩ*ž1ᴇ-5²⁺%⁺+ĐĐĐĐ1=⇹5=⇹04Ș9=06Ș+35*=0↔+37*=∨∨∨∨+₽

Try it online!

Much of this code is because Pyt is not very good at strings.

Explanation:

ɬ               Push "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
←ą              Get input string as an array of characters
Đ               Duplicate the array of characters
0↔              Push 0 and flip the stack
ą               Get the top of the stack as an array of characters
∈               Is each character in the input a letter?
⇹               Swap top two on the stack (input as array of characters)
6²Ĩ             Interpret element-wise as base-36 **
*ž              Remove all non-letters
1ᴇ-             Subtract 10 from each element
5²⁺%            Mod 26
⁺               Increment
+               Let's get rid of that 0
ĐĐĐĐ            Push 4 additional copies of the top of the stack
1=⇹             Is it equal to 1 ('a')
5=⇹04Ș          Is it equal to 5 ('e')
9=06Ș           Is it equal to 9 ('i')
+               Get rid of a 0
35*=            Is it equal to 15 ('o')
0↔              Push 0 and flip the stack
+               Get rid of a 0
37*=            Is it equal to 21 ('u')
∨∨∨∨            OR the arrays
+               Get rid of that last 0
₽               Is the top of the stack a palindrome?

mudkip201

Posted 2017-05-28T12:41:52.477

Reputation: 833

0

GolfScript, 34 bytes

{32|}%.123,97>--{"aeiou"?)!}%.-1%=

Try it online!

Explanation

{32|}%                             # Convert to lowercase (Works at least with alpha)
      .123,97>--                   # Keep only lowercase letters
                {"aeiou"?)!}%      # Foreach: is it a vowel?
                             .-1%= # Is it a palindrome?

user85052

Posted 2017-05-28T12:41:52.477

Reputation: