Thử thách đánh giá cao người dùng # 1: Dennis ♦


53

Tôi có ý tưởng tự phát về việc đưa ra một loạt các thách thức của người dùng đã giúp đỡ và tiếp tục giúp cộng đồng PPCG trở thành một nơi thú vị cho mọi người, hoặc có thể chỉ dành riêng cho tôi. : P

Nếu bạn chuyển đổi tên của Dennis thành một mảng 1s và 0s trong đó mỗi phụ âm là 1và mỗi nguyên âm là 0, [1, 0, 1, 1, 0, 1]thì đó là đối xứng. Vì vậy, thách thức của bạn là xác định những tên khác như thế này.

Thử thách

Đưa ra một chuỗi ASCII, loại bỏ tất cả các ký tự không phải là chữ cái và xác định xem cấu hình của nguyên âm và phụ âm có đối xứng không. ykhông phải là một nguyên âm.

Xin lưu ý rằng chương trình của bạn không phải là loại chuỗi này.

Các trường hợp thử nghiệm

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

Thực hiện tham khảo

Mã Python 3 này sẽ cung cấp đầu ra chính xác cho trường hợp thử nghiệm. Nó vô dụng như tôi có thể làm cho nó mà không vô lý.

Con trăn 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 = '')

Hãy thử trực tuyến!


Khi nào và ai là số 2?
caird coinheringaahing

@cairdcoinheringaahing Cảm ơn đã nhắc nhở tôi. Nó sẽ là về Mego (TNB RO do đó là chữ nghiêng) nhưng tôi vẫn chưa tìm được cách hoàn thiện nó.
HyperNeutrino

Tôi nên nói với anh ta hay anh ta sẽ lặn xuống nước để tìm cá?
caird coinheringaahing

@cairdcoinheringaahing Tôi chắc chắn anh ấy đã biết rồi; Tôi nói tôi sẽ làm một điều về anh ấy nhưng tôi chưa quyết định liệu tôi sẽ làm gì đó liên quan đến chim cánh cụt hay TNB chưa.
HyperNeutrino

Tôi nghĩ chim cánh cụt. Đó là những gì anh ấy biết (đối với tôi)
caird coinheringaahing

Câu trả lời:


15

05AB1E , 9 byte

žM¹álSåÂQ

Hãy thử trực tuyến!

-2 cảm ơn Ad Nam .

Điều này tấn công điểm đau của Jelly chính xác. Nó sử dụng lA, tương đương 1 byte cho Jelly ŒlØatương ứng.


Bạn có chắc chắn rằng điều này làm việc? Chạy cái này
MCCCS

@MCCCS Hmm, bạn có thể đúng.
Erik the Outgolfer

Bạn có thể thay thế bởi áDRbởi Â.
Ad Nam

@Adnan Quên đi á, không biết làm gì Â, cảm ơn!
Erik the Outgolfer

11
@alexis hầu hết các ngôn ngữ chơi gôn này sử dụng 256 ký tự khác nhau và một bảng mã tùy chỉnh ánh xạ hex 00đến FF256 ký tự đó, xem câu trả lời Jelly
Stephen


13

Hàm mã máy x86 32 bit, 42 41 byte

Hiện tại, câu trả lời không phải là ngôn ngữ chơi gôn ngắn nhất, ngắn hơn 1B so với q / kdb + của @ streetster .

Với 0 cho trung thực và khác không cho giả mạo: 41 40 byte. (nói chung, tiết kiệm 1 byte cho 32 bit, 2 byte cho 64 bit).

Với các chuỗi có độ dài ngầm định (kiểu C kết thúc 0): 45 44 byte

mã máy x86-64 (với các con trỏ 32 bit, như x32 ABI): 44 43 byte .

x86-64 với các chuỗi có độ dài ẩn, vẫn là 46 byte (chiến lược bitmap shift / mask là hòa vốn ngay bây giờ).

Đây là một chức năng với C chữ ký _Bool dennis_like(size_t ecx, const char *esi). Quy ước gọi hơi không chuẩn, gần với MS vectorcall / fastcall nhưng với các thanh ghi arg khác nhau: chuỗi trong ESI và độ dài trong ECX. Nó chỉ chặn các arg-reg và EDX của nó. AL giữ giá trị trả về, với các byte chứa rác cao (như được cho phép bởi SysV x86 và x32 ABI. IDK những gì ABI của MS nói về rác cao khi trả về bool hoặc số nguyên hẹp.)


Giải thích về thuật toán :

Lặp lại chuỗi đầu vào, lọc và phân loại thành một mảng boolean trên ngăn xếp: Đối với mỗi byte, hãy kiểm tra xem đó có phải là ký tự chữ cái không (nếu không, tiếp tục sang char tiếp theo) và chuyển đổi nó thành một số nguyên từ 0-25 (AZ) . Sử dụng số nguyên 0-25 đó để kiểm tra một bitmap nguyên âm = 0 / phụ âm = 1. (Bitmap được tải vào một thanh ghi dưới dạng hằng số tức thời 32 bit). Đẩy 0 hoặc 0xFF lên ngăn xếp theo kết quả bitmap (thực tế là trong byte thấp của phần tử 32 bit, có thể có rác trong 3 byte trên cùng).

Vòng lặp đầu tiên tạo ra một mảng 0 hoặc 0xFF (trong các phần tử từ được đệm bằng rác). Thực hiện kiểm tra palindrom thông thường với một vòng lặp thứ hai dừng lại khi các con trỏ giao nhau ở giữa (hoặc khi cả hai đều trỏ đến cùng một phần tử nếu có một số ký tự chữ cái lẻ). Con trỏ di chuyển lên trên là con trỏ ngăn xếp và chúng tôi sử dụng POP để tải + tăng. Thay vì so sánh / setcc trong vòng lặp này, chúng ta chỉ có thể sử dụng XOR để phát hiện giống / khác vì chỉ có hai giá trị có thể. Chúng tôi có thể tích lũy (với OR) cho dù chúng tôi có tìm thấy bất kỳ yếu tố không phù hợp nào hay không, nhưng một nhánh xuất hiện sớm trên các cờ được đặt bởi XOR ít nhất là tốt.

Lưu ý rằng vòng lặp thứ hai sử dụng bytekích thước toán hạng, vì vậy nó không quan tâm rác nào mà vòng lặp thứ nhất để lại bên ngoài byte thấp của mỗi phần tử mảng.


Nó sử dụng hướng dẫn không có giấy tờsalc để đặt AL từ CF, theo cách tương tự sbb al,al. Nó được hỗ trợ trên mọi CPU Intel (ngoại trừ ở chế độ 64 bit), thậm chí cả Knight's Landing! Agner Fog cũng liệt kê thời gian cho nó trên tất cả các CPU AMD (bao gồm cả Ryzen), vì vậy nếu các nhà cung cấp x86 khăng khăng buộc byte không gian opcode đó kể từ 8086, chúng tôi cũng có thể tận dụng lợi thế của nó.

Thủ thuật thú vị:

  • unsign - so sánh thủ thuật cho một isalpha () và toupper () kết hợp và zero - mở rộng byte để điền vào eax, thiết lập cho:
  • bitmap ngay lập tức trong một đăng ký cho bt, lấy cảm hứng từ một số đầu ra trình biên dịch đẹp choswitch .
  • Tạo một mảng có kích thước thay đổi trên ngăn xếp với một vòng lặp. (Tiêu chuẩn cho mã asm, nhưng không phải là thứ bạn có thể làm với C cho phiên bản chuỗi có độ dài ẩn). Nó sử dụng 4 byte không gian ngăn xếp cho mỗi ký tự đầu vào, nhưng tiết kiệm ít nhất 1 byte so với chơi golf tối ưu xung quanh stosb.
  • Thay vì cmp / setne trên mảng boolean, các booleans XOR kết hợp với nhau để lấy giá trị thật trực tiếp. ( cmp/ salckhông phải là một tùy chọn, vì salcchỉ hoạt động với CF và 0xFF-0 không đặt CF. setelà 3 byte, nhưng sẽ tránh incvòng lặp bên ngoài, với chi phí ròng là 2 byte (chế độ 1 trong 64 bit )) so với xor trong vòng lặp và sửa nó với 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

Đây có lẽ cũng là một trong những câu trả lời nhanh nhất, vì không có môn đánh gôn nào thực sự gây tổn thương quá nặng, ít nhất là cho các chuỗi dưới vài nghìn ký tự trong đó việc sử dụng bộ nhớ 4x không gây ra nhiều lỗi nhớ cache. (Nó cũng có thể thua các câu trả lời sớm cho các chuỗi không giống Dennis trước khi lặp qua tất cả các ký tự.) salcChậm hơn so với setccnhiều CPU (ví dụ 3 uops so với 1 trên Skylake), nhưng kiểm tra bitmap bằng bt/salcvẫn nhanh hơn tìm kiếm chuỗi hoặc kết hợp regex. Và không có chi phí khởi động, vì vậy nó cực kỳ rẻ cho các chuỗi ngắn.

Làm điều đó trong một lần khi đang bay có nghĩa là lặp lại mã phân loại cho các hướng lên và xuống. Đó sẽ là nhanh hơn nhưng kích thước mã lớn hơn. (Tất nhiên nếu bạn muốn nhanh, bạn có thể thực hiện 16 hoặc 32 ký tự cùng một lúc với SSE2 hoặc AVX2, vẫn sử dụng thủ thuật so sánh bằng cách dịch chuyển phạm vi xuống dưới cùng của phạm vi đã ký).


Kiểm tra chương trình (đối với ia32 hoặc x32 Linux) để gọi hàm này bằng cmdline arg và thoát với status = giá trị trả về. strlentriển khai từ 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

Phiên bản 64 bit của chức năng này có thể sử dụng sbb eax,eax, chỉ có 2 byte thay vì 3 cho setc al. Nó cũng sẽ cần thêm một byte cho dechoặc notở cuối (vì chỉ 32 bit có inc / dec r32 1 byte). Sử dụng x32 ABI (con trỏ 32 bit ở chế độ dài), chúng tôi vẫn có thể tránh các tiền tố REX mặc dù chúng tôi sao chép và so sánh các con trỏ.

setc [rdi]có thể ghi trực tiếp vào bộ nhớ, nhưng dự trữ byte ECX của không gian ngăn xếp sẽ tốn nhiều kích thước mã hơn mức tiết kiệm. (Và chúng ta cần di chuyển qua mảng đầu ra. [rdi+rcx]Cần thêm một byte cho chế độ địa chỉ, nhưng thực sự chúng ta cần một bộ đếm không cập nhật cho các ký tự được lọc để nó còn tệ hơn thế.)


Đây là nguồn YASM / NASM với các %ifđiều kiện. Nó có thể được xây dựng với -felf32(mã 32 bit) hoặc -felfx32(mã 64 bit với x32 ABI) và với độ dài ẩn hoặc rõ ràng . Tôi đã thử nghiệm tất cả 4 phiên bản. Xem câu trả lời này cho một tập lệnh để xây dựng một nhị phân tĩnh từ nguồn NASM / YASM.

Để kiểm tra phiên bản 64 bit trên máy mà không hỗ trợ x32 ABI, bạn có thể thay đổi con trỏ regs thành 64 bit. (Sau đó, chỉ cần trừ số lượng tiền tố REX.W = 1 (0x48 byte) khỏi số đếm. Trong trường hợp này, 4 lệnh cần tiền tố REX để hoạt động trên regs 64 bit). Hoặc chỉ cần gọi nó bằng rspvà con trỏ đầu vào trong không gian địa chỉ 4G thấp.

%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.

Tôi nhìn vào lộn xộn với DF (cờ chỉ đường điều khiển lodsd/ scasdvân vân), nhưng dường như nó không phải là một chiến thắng. Các ABI thông thường yêu cầu DF bị xóa khi nhập và thoát chức năng. Giả sử đã xóa khi nhập cảnh nhưng để nó được đặt khi thoát sẽ là gian lận, IMO. Sẽ thật tuyệt khi sử dụng LODSD / SCASD để tránh 3 byte sub esi, 4, đặc biệt trong trường hợp không có rác thải cao.


Chiến lược bitmap thay thế (cho các chuỗi có độ dài ẩn x86-64)

Hóa ra điều này không lưu bất kỳ byte nào, bởi vì bt r32,r32vẫn hoạt động với lượng rác cao trong chỉ mục bit. Nó chỉ không được ghi lại theo cách shrnày.

Thay vì bt / sbblấy bit vào / ra CF, hãy sử dụng shift / mask để tách bit chúng ta muốn khỏi 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

Vì điều này tạo ra 0/1 trong AL ở cuối (thay vì 0 / 0xFF), chúng ta có thể thực hiện đảo ngược cần thiết của giá trị trả về ở cuối hàm với xor al, 1(2B) thay vì dec eax(cũng là 2B trong x86-64) vẫn tạo ra một giá trị thích hợp bool/_Bool trả lại.

Điều này được sử dụng để tiết kiệm 1B cho x86-64 với các chuỗi có độ dài ẩn, bằng cách tránh việc không cần các byte cao của EAX. (Tôi đã sử dụng and eax, 0x7F ^ 0x20để ép buộc chữ hoa và bằng 0 phần còn lại của eax với 3 byte and r32,imm8. Nhưng bây giờ tôi đang sử dụng mã hóa 2 byte ngay lập tức với hầu hết các lệnh 8086, giống như tôi đã làm cho subcmp.)

Nó bị mất đến bt/ salcở chế độ 32 bit và các chuỗi có độ dài rõ ràng cần ECX cho số đếm để điều này cũng không hoạt động ở đó.

Nhưng sau đó tôi nhận ra rằng mình đã sai: bt edx, eaxvẫn hoạt động với lượng rác cao trong eax. Nó dường như mặt nạ ca đếm theo cùng một cách shr r32, clnào (chỉ nhìn vào 5 bit thấp của cl). Điều này khác với bt [mem], reg, có thể truy cập bên ngoài bộ nhớ được tham chiếu bởi chế độ / kích thước địa chỉ, coi nó như một chuỗi bit. (Điên rồ ...)

Hướng dẫn sử dụng nội bộ của Intel không ghi lại việc che giấu, vì vậy có lẽ đó là hành vi không có giấy tờ mà Intel đang bảo tồn cho đến bây giờ. (Đó là loại điều là không phải là hiếm. bsf dst, srcVới src = 0 luôn lá dst chưa sửa đổi, mặc dù đó là tài liệu rời dst giữ một giá trị không xác định trong trường hợp đó. AMD thực sự tài liệu src = 0 hành vi.) Tôi đã thử nghiệm trên Skylake và Core2, và btphiên bản hoạt động với rác khác không trong EAX bên ngoài AL.

Một mẹo nhỏ ở đây là sử dụng xchg eax,ecx(1 byte) để đếm số vào CL. Thật không may, BMI2 shrx eax, edx, eaxlà 5 byte, so với chỉ 2 byte cho shr eax, cl. Việc sử dụng bextrcần 2 byte mov ah,1(đối với số bit cần trích xuất), do đó, lại là 5 + 2 byte như SHRX + AND.


Mã nguồn đã trở nên khá lộn xộn sau khi thêm các %ifđiều kiện. Đây là sự phân tách các chuỗi có độ dài ẩn x32 (sử dụng chiến lược thay thế cho bitmap, vì vậy nó vẫn là 46 byte).

Sự khác biệt chính từ phiên bản độ dài rõ ràng là trong vòng lặp đầu tiên. Lưu ý làm thế nào có một lodstrước nó, và ở dưới cùng, thay vì chỉ một ở đầu vòng lặp.

    ; 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

8

Võng mạc ,49 47 45 byte

\P{L}

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

Hãy thử trực tuyến!

Lưu được 2 byte nhờ Neil.

Đã lưu thêm 2 byte nhờ Martin.

Loại bỏ các chữ cái không thay thế sau đó thay thế các nguyên âm bằng 1 và phụ âm bằng 2, để có được các giá trị nhất quán. Sau đó liên tục loại bỏ ký tự đầu tiên và cuối cùng nếu chúng giống nhau. Một khi chúng không có, từ này là đối xứng nếu còn một hoặc không có ký tự.


\D 2hoạt động để tiết kiệm cho bạn một vài byte T`lL`2không?
Neil

@Neil Có vẻ như, bắt tốt đẹp!
FryAmTheEggman

Làm tốt. Tôi đã cố gắng để làm điều này :(
Christopher

7

PHP, 82 byte

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

Hãy thử trực tuyến!


Bạn có thể thêm trước typecasting (bool)và loại bỏ $s===$skiểm tra để lưu 1 byte.
kaiser

Nếu tôi không nhầm, bạn có thể thay thế (bool)bằng chỉ 0||nói sai, hoặc thay vào đó, tiết kiệm thêm 3 byte.
kaiser

Hừm. Bạn không thể sử dụng \wcho các ký tự từ thay vì a-z?
kaiser

@kaiser \wchứa các chữ số gạch dưới và chữ cái. Điều này sẽ không hoạt động và [^/p{L}]dài hơn [^a-z]cộng với i. Tôi so sánh chuỗi ngược với chuỗi vì vậy $scần thiết để tạo boolean
Jörg Hülsermann

Điều đó đúng. Vẫn là những người khác nên làm việc. "Nên", họ làm.
kaiser

6

MATL, 14 byte

t3Y2m)13Y2mtP=

Hãy thử nó tại MATL Online .

Đây là một phiên bản sửa đổi một chút để kiểm tra tất cả các trường hợp thử nghiệm.

Giải trình

        % 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

Bạn chứng minh điều đó bằng "Martin Ender" thay vì "Dennis"? tôi phải nhìn vào tiêu đề thách thức một lần nữa.
Roman Gräf

1
Có lẽ Suever muốn một cuộc biểu tình có một số lượng lọc ở bước đầu tiên.
Greg Martin

Sau đó, anh ta nên sử dụng "Alex A." thay vào đó, nó cũng có một khoảng thời gian.
Erik the Outgolfer

2
Tôi bối rối không biết vấn đề là gì. Tôi đã chọn Martin Ender vì nó thực sự sẽ đúng nếu bạn xóa khoảng trắng và sai khác. Tôi cũng bao gồm một liên kết đến tất cả các trường hợp thử nghiệm
Suever

6

Haskell, 84 75 74 69 byte

-10 cảm ơn @nimi
-5 nhờ @Zgarb

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

Việc hiểu danh sách thay thế mỗi chữ cái bằng một boolean và loại bỏ tất cả các ký tự khác. Phần đầu tiên kiểm tra xem danh sách kết quả có phải là một bảng màu hay không.

Hãy thử trực tuyến!


Hai lời khuyên: 1) Việc hiểu danh sách thường được rút ngắn hơn so với filtertheo sau mapngay cả khi bạn phải chuyển sang trạng thái không độc. 2) Sự <$>idthừa thãi. f x=(==)<*>reverse$[elem c"aeiouAEIOU"|c<-x,celem ['A'..'Z']++['a'..'z']].
nimi

Bạn có thể thả khoảng trống giữa c"thêm một byte.
nimi

1
Tôi nghĩ c`elem`['A'..'Z']++['a'..'z']có thể rút ngắn thành'@'<c,c<'{','`'<c||c<'['
Zgarb


4

Brachylog , 13 byte

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

Hãy thử trực tuyến!

Giải trình

ḷ                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

3

Alice , 28 byte

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

Hãy thử trực tuyến!

Đầu ra 1là trung thực và không có gì là giả.

Giải trình

Mỗi lệnh trong chương trình này thực thi trong chế độ thứ tự, nhưng với một chút thay đổi trong mẫu cho phép tôi lưu một byte. Nếu một dòng mới là một giá trị trung thực có thể chấp nhận, tôi có thể lưu thêm một byte bằng cùng một phương thức.

Tuyến tính hóa, chương trình như sau:

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


3

JavaScript (ES6), 72 69 byte

Đã lưu 3 byte nhờ Neil

Trả về một boolean.

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

Các trường hợp thử nghiệm


Lưu một vài byte bằng cách thay thế 2 chuỗi trống bằng 2.
Xù xì

1
Bạn thậm chí cần +''cuối cùng? Điều đó sẽ tiết kiệm 3 byte thay thế.
Neil

Tôi thích ý tưởng của @ Neil hơn!
Xù xì

2

Toán học, 113 byte

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

Bạn có thể thoát khỏi một vài byte:PalindromeQ@StringReplace[#,{Characters@"aeiouAEIOU"->"1",LetterCharacter->"0",_->""}]&
Không phải là một cây

2

GolfScript , 42 byte

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

Hãy thử trực tuyến!

Phần cứng đang tạo cả bảng chữ cái in hoa và chữ thường trong một chuỗi, chúng ta sẽ sử dụng chức năng lọc để lọc các chữ cái ra khỏi đầu vào. May mắn thay, vì các chuỗi trong GolfScript chỉ là các mảng mã hóa với một thuộc tính đặc biệt, vì vậy chúng tôi chỉ có thể tạo các điểm mã theo cách hiệu quả. Đây là cách chúng tôi tạo ra chúng:

Đầu tiên, chúng tôi tạo ra phạm vi [0..122], 122 là điểm mã cho z. Sau đó, chúng tôi lấy các phần tử từ phần tử ở chỉ số 65 trở đi. 65 là mật mã cho A. Ngay bây giờ, chúng tôi có [65..122]. Tất cả đều ổn, ngoại trừ chúng tôi có một số điểm mã không mong muốn ([91..96]) trong đó. Vì vậy, trước tiên chúng tôi tạo một bản sao của phạm vi đó. Sau đó, chúng tôi lấy các yếu tố từ chỉ số 26 trở đi và chúng tôi có [91..122]. Sau đó, chúng tôi nhận được các phần tử lên đến và bao gồm chỉ mục 5. Bây giờ chúng tôi có [91..96]. Cuối cùng, chúng tôi loại bỏ các yếu tố đó khỏi [65..122], để lại cho chúng tôi [65..90, 97..122]. Đó là những mật mã mà chúng ta muốn.

Bây giờ chúng tôi đã tạo danh sách mã bảng chữ cái trên / dưới, chúng tôi tiếp tục chức năng lọc của mình. Hàm được ánh xạ tới từng ký tự trên chuỗi đầu vào, như tôi đã nói ban đầu, được phân tích cú pháp như là điểm mã của nó. Vì vậy, bây giờ chúng ta về cơ bản có [codepoint, [65..90, 97..122]]. Để tìm hiểu xem char codepointcó phải là một chữ cái không, chúng ta chỉ cần lấy chỉ mục của nó trong danh sách chúng ta tạo ra. Nếu nó không ở đó, chúng ta sẽ lấy -1chỉ số thay thế.

Ngay bây giờ, chúng tôi chỉ nhận được giá trị falsey nếu codepoint == 65, chỉ mục đầu tiên trong danh sách của chúng tôi, vì chỉ khi đó chỉ số sẽ là 0. Nhưng một mức tăng duy nhất sẽ khắc phục vấn đề này, và, bây giờ, nếu codepointtrong danh sách của chúng tôi, chúng tôi sẽ lấy chỉ số của nó + 1, luôn luôn là một số dương, do đó luôn luôn đúng, trong khi nếu không có, chúng tôi sẽ nhận được -1 + 1 = 0, tức là falsey.

Cuối cùng chúng tôi áp dụng hàm tôi đã mô tả cho mọi char của đầu vào và chúng tôi chỉ lấy các ký tự mà hàm trả về kết quả trung thực.

Tiếp theo chúng ta phải xác định xem mỗi char là nguyên âm hay phụ âm. Vì các nguyên âm ít hơn các phụ âm, nên việc tạo ra một chuỗi nguyên âm để chúng tôi kiểm tra điều kiện đó ngắn hơn so với việc tạo ra một chuỗi phụ âm, vì vậy chúng tôi kiểm tra xem mỗi char có phải là nguyên âm không. Tuy nhiên, để kiểm tra xem danh sách boolean có phải là palindromic hay không, chúng ta cần booleans, thứ mà chúng ta không nhận được chỉ bằng cách lấy chỉ số + 1, vì điều đó có thể dẫn đến bất kỳ số [1..10] nào nếu char là nguyên âm. Và, như hầu hết các ngôn ngữ chơi gôn, ngôn ngữ này, cũng không có boolchức năng. Vì vậy, chúng tôi chỉ đơn giản sử dụng not not x, vì notluôn trả về một boolean. Nhưng chờ đã; chúng ta thực sự cần phải có booleans cụ thể? Vì notluôn luôn trả về một boolean, tại sao chúng ta không xóa cái thứ hainot, và thực sự kiểm tra xem mỗi char là một phụ âm? Vâng, đó chính xác là những gì chúng ta sẽ làm!

Sau khi kiểm tra, trả về một danh sách các booleans, chúng tôi kiểm tra xem danh sách boolean này chúng tôi nhận được có phải là một bảng màu hay không, đó là điều mà thử thách này yêu cầu chúng tôi làm. Vâng, định nghĩa của một palindrom là gì? Có, một palindrom là một danh sách hoặc chuỗi bằng với đảo ngược của nó. Vậy, làm thế nào để chúng ta kiểm tra? Đơn giản, chúng tôi nhân đôi nó, đảo ngược nó và kiểm tra danh sách ban đầu. Kết quả chúng ta nhận được là, cuối cùng , những gì mã của chúng ta sẽ trả về.


1
Giải thích khổng lồ cho một chương trình 42 byte. Bây giờ tôi đoán rằng nó khá nhiều tự giải thích ...
Erik the Outgolfer

2

PHP , 87 byte

Regex phiên bản PHP miễn phí. Đã thêm một "nguyên âm" vì các chuỗi có thể trả về 0 là sai trong PHP.

Lỗ hổng được cố định bởi Jörg.

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

Hãy thử trực tuyến!


Cùng số lượng byte. for(;a&$c=$argn[$p++];)ctype_alpha($c)?$s.=stripos(_aeiou,$c)?0:1:0;echo$s==strrev($s);nhưng nó nhận được kết quả đúng cho các chuỗi chứa số 0
Jörg Hülsermann

@ JörgHülsermann Cảm ơn bạn.
TÔI

2

q / kdb +, 42 38 byte

Giải pháp:

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

Thí dụ:

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

Giải trình:

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'

Chỉnh sửa:

  • -4 byte; chuyển ra reversecho k tương đương|:

2

CJam , 26 byte

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

Hãy thử trực tuyến!

-1 nhờ trái Esolanging .


Bạn có thể thay thế 26,'af+bằng '{,97>để lưu một byte.
Trái cây Esolanging

@Esolanging Quả như một câu trả lời cũ ...
Erik the Outgolfer

Một byte được lưu cách đây nửa năm không khác gì một byte được lưu bây giờ. Nó không giống như lạm phát byte hoặc bất cứ điều gì: P
Esolanging Fruit

@EsolangingFnut Tôi đã đề cập đến kinh nghiệm luôn phát triển của tôi với việc chơi golf ... tất nhiên bạn có một khoản tín dụng như bình thường, đừng lo lắng!
Erik the Outgolfer

2

Braingolf,  4  3 byte

&JP

-1 byte nhờ Erik the Outgolfer

Hóa ra tôi đã có Ptất cả cùng, ngay cả trước thử thách này.

J tuy nhiên, mặc dù được tạo ra trước thử thách này, nhưng không được đẩy lên github trước thử thách, do đó vẫn không cạnh tranh.

Giải trình:

&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

Tại sao bạn cần n?
Erik the Outgolfer

@EriktheOutgolfer vì tôi là một kẻ ngốc được chứng nhận
Skidsdev

Hmm, bạn quên loại bỏ nó khỏi lời giải thích.
Erik the Outgolfer

@EriktheOutgolfer Tôi đã viết gunna "Erick" sau đó tấn công c, nhưng nó trông giống như "Eriek"
Skidsdev

Điều này không thất bại cho những người thích Alex A.?
Xù xì

1

Python 2, 83 byte

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

Xác định hàm cung cấp TruehoặcFalse


Bạn có thể lưu 2 byte bằng cách sử dụng "aeiouAEIOU".__contains__thay vì lambda y:y.lower()in"aeiou".
Máy xay sinh tố




1

Bash , 82 byte

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

Hãy thử trực tuyến!

Gọi tên là tham số, loại bỏ các từ không cho phép, thay thế các nguyên âm bằng 0, không nguyên âm cũng như 0 bằng 1 và so sánh với cùng một đảo ngược.

Có thể chơi golf nhiều hơn nếu có thể làm việc thay thế gấp đôi hoặc gấp ba

Trạng thái thoát là 0 cho đúng và 1 cho không.


Trong các phiên bản bash gần đây, i=${i^^*};chuyển đổi ithành chữ hoa. Nhưng tôi nghĩ rằng nó chỉ giúp bạn tiết kiệm được một a-zvà một aeiou, ít hơn 10B.
Peter Cordes

1

Japt v2.0a0, 19 11 byte

k\L mè\v ê¬

Dùng thử trực tuyến


Giải trình

        :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.


0

PowerShell, 108 byte

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

0

Tiên đề, 126 byte

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))

kiểm tra

(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


0

PowerShell, 87 byte

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

Lấy một bản sao của chuỗi trong đó nguyên âm là 0 và phụ âm là 1, với tất cả các ký tự đặc biệt được loại bỏ, so sánh chuỗi đó với phiên bản đảo ngược được nối lại thành chuỗi

Đầu ra:

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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.