Bộ đếm byte lặp đi lặp lại


19

Nhiệm vụ của bạn là viết một chương trình / hàm không trống của số byte L , khi lặp lại M lần, kiểm tra xem một số nguyên dương N đã cho có bằng L × M hay không .

Về lý thuyết, bạn nên hỗ trợ một số lần lặp lại tùy ý (giá trị nguyên dương tùy ý của M ), nhưng sẽ ổn nếu, do giới hạn ngôn ngữ, nó không thể hoạt động trên một ngưỡng nhất định. Đọc mã nguồn của chương trình của bạn hoặc truy cập thông tin về nó đều bị nghiêm cấm .

Để cung cấp đầu ra, bạn nên chọn một giá trị nhất quán cho một trong các trạng thái (trung thực hoặc giả) và sử dụng bất kỳ đầu ra nào khác (không nhất thiết nhất quán) cho trạng thái khác ( Thảo luận ).

Câu trả lời của bạn sẽ được tính theo độ dài L (tính bằng byte) của chương trình ban đầu của bạn , với ít byte sẽ tốt hơn.

Thí dụ

Giả sử chương trình (ban đầu) của bạn là ABCDE. Sau đó:

  • ABCDE (1 lần lặp lại) nên kiểm tra xem đầu vào có bằng không 5 không .
  • ABCDEABCDE(2 lần lặp lại) nên kiểm tra xem đầu vào có bằng 10 không .
  • ABCDEABCDEABCDE(3 lần lặp lại) nên kiểm tra xem đầu vào có bằng 15 không . V.v ...

Điểm của mã mẫu này sẽ là 5 , vì nguồn ban đầu dài 5 byte.


Chỉ cần làm rõ: mã nguồn có độ dài được Lnối sau Mlần chính nó sẽ trả về liệu đầu vào của nó Ncó bằngL*M không?

Câu trả lời:


12

Thạch , 1 byte

Đầu ra là 0 cho một trận đấu, khác không cho một trận đấu.

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

Làm thế nào nó hoạt động

Điều này làm cho lợi thế của định dạng đầu ra quá tự do. Lặp lại M lần đơn giản là giảm số lần M đầu vào , vì vậy kết quả sẽ bằng 0 khi và chỉ khi đầu vào là LM , trong đó L = 1 .


Trời ơi, tôi không thấy điều này sẽ đến ... ( inb4 mọi người chuyển nó sang các esolang khác ... )
Ông Xcoder

Tôi đã có một câu trả lời 0 byte trong tâm trí, nhưng, eh, quine . : P
Erik the Outgolfer 23/03/18

Ý nghĩ đầu tiên của tôi. Bị đánh
bại

11

Haskell, 8 byte

(-8+).id

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

Giống như nhiều câu trả lời khác, nó trả về 0 cho giá trị trung thực và không 0 cho sai lệch bằng cách liên tục trừ đi độ dài của mã từ số đầu vào.


Tôi đã rất gần để mày mò để có được điều này ...
hoàn toàn là

8

Võng mạc , 21 20 byte

\d+
*
^$
_
^_{20}

_

Hãy thử trực tuyến! Chỉ cần lặp lại phần trong cửa sổ để xem cách nó xử lý bội số.

Cung cấp 0cho các số nguyên chính xác và tích cực cho tất cả mọi thứ khác.

Giải trình

Trước tiên hãy xem chương trình duy nhất:

\d+
*

Điều này chuyển đổi một số thập phân thành unary (sử dụng _như là chữ số unary).

^$
_

Nếu chuỗi trống (điều này không thể xảy ra tại thời điểm này, vì đầu vào được đảm bảo là dương), chúng tôi thay thế nó bằng một chuỗi _.

^_{20}

Bây giờ chúng tôi thoát khỏi 20 dấu gạch dưới đầu tiên. Nếu đầu vào là 20, kết quả này là một chuỗi trống.

_

Và cuối cùng, chúng tôi đếm số lượng dấu gạch dưới trong kết quả, bằng không nếu đầu vào là 20.


Bây giờ điều gì xảy ra khi chúng ta lặp lại mã nguồn. Vì chúng tôi không chèn một nguồn cấp dữ liệu khi tham gia các chương trình, dòng đầu tiên sẽ đi ngay ở cuối dòng cuối cùng, chúng tôi nhận được điều này khi nhân đôi chương trình:

\d+
*
^$
_
^_{20}

_\d+
*
^$
_
^_{20}

_

Bây giờ thay vì đếm các dấu gạch dưới, chúng tôi kết thúc với giai đoạn sau:

_\d+
*

Giai đoạn này không làm gì cả, vì không có thêm chữ số nào trong chuỗi làm việc tại thời điểm này, do đó regex không thể khớp.

^$
_

Bây giờ giai đoạn này trở nên có liên quan. Nếu đầu vào là bội số nhỏ hơn của 20, chuỗi đã được làm trống bằng bản sao trước đó của mã nguồn. Trong trường hợp đó, chúng tôi biến nó thành một dấu gạch dưới duy nhất, mà chúng tôi biết không bao giờ có thể biến thành một chuỗi trống một lần nữa bởi chương trình của chúng tôi. Bằng cách này, chúng tôi đảm bảo rằng chỉ có bội số M được chấp nhận (và không phải tất cả bội số lên đến M th).

^_{20}

Chúng tôi loại bỏ 20 dấu gạch dưới đầu tiên một lần nữa. Vì vậy, việc lặp lại M của mã nguồn sẽ loại bỏ 20M dấu gạch dưới khỏi chuỗi, nếu có thể.

_

Và khi chúng tôi kết thúc chương trình, chúng tôi vẫn tính các dấu gạch dưới để các đầu vào hợp lệ cho không.


6

Đoạn mã máy x86 32 bit, 1 byte

48                      dec    eax

Đầu vào trong EAX, đầu ra trong EAX: 0 cho đúng, khác không cho sai. (Cũng để cờ ZF được đặt thành true, không đặt thành false, vì vậy bạn có thể je was_equal). Là một "phần thưởng", bạn không phải lo lắng về việc gói; X86 32 bit chỉ có thể giải quyết 4GiB bộ nhớ, vì vậy bạn không thể làm cho M đủ lớn để quấn quanh và tìm 1 == 2**32 + 1hoặc một cái gì đó.

Để thực hiện chức năng có thể gọi được, hãy thêm một 0xC3 retlệnh sau khi lặp lại 0x48M lần. (Không được tính trong tổng số đếm, vì nhiều ngôn ngữ chỉ cần lặp lại thân hàm hoặc biểu thức để có thể cạnh tranh).

Có thể gọi được từ GNU C với thuộc tính hàm x86 __attribute__((regparm(1))) int checkeqM(int eax); của GNU Cregparm , giống như -mregparm, sử dụng EAX để truyền tham số nguyên đầu tiên.

Ví dụ, chương trình hoàn chỉnh này có 2 đối số và JIT M sao chép lệnh + a retvào bộ đệm, sau đó gọi nó là hàm. (Yêu cầu heap thực thi; biên dịch với gcc -O3 -m32 -z execstack)

/******* Test harness: JIT into a buffer and call it ******/
// compile with gcc -O3 -no-pie -fno-pie -m32 -z execstack
// or use mprotect or VirtualProtect instead of -z execstack
// or mmap(PROT_EXEC|PROT_READ|PROT_WRITE) instead of malloc

// declare a function pointer to a regparm=1 function
// The special calling convention applies to this function-pointer only
// So main() can still get its args properly, and call libc functions.
// unlike if you compile with -mregparm=1
typedef int __attribute__((regparm(1))) (*eax_arg_funcptr_t)(unsigned arg);

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    if (argc<3) return -1;
    unsigned N=strtoul(argv[1], NULL, 0), M = strtoul(argv[2], NULL, 0);

    char *execbuf = malloc(M+1);   // no error checking
    memset(execbuf, 0x48, M);     // times M  dec eax
    execbuf[M] = 0xC3;            // ret
    // Tell GCC we're about to run this data as code.  x86 has coherent I-cache,
    // but this also stops optimization from removing these as dead stores.
    __builtin___clear_cache (execbuf, execbuf+M+1);
     //   asm("" ::: "memory");  // compiler memory barrier works too.

    eax_arg_funcptr_t execfunc = (eax_arg_funcptr_t) execbuf;
    int res = execfunc(N);
    printf("%u == %u  =>  %d\n", N,M, res );
    return !!res;   // exit status only takes the low 8 bits of return value
}

các tệp thực thi không phải PIE được tải thấp hơn trong bộ nhớ ảo; có thể làm một malloc tiếp giáp lớn hơn.

$ gcc -g -O3 -m32 -no-pie -fno-pie -fno-plt -z execstack coderepeat-i386.c
$ time ./a.out 2747483748 2747483748   # 2^31 + 600000100 is close to as big as we can allocate successfully
2747483748 == 2747483748  =>  0

real    0m1.590s     # on a 3.9GHz Skylake with DDR4-2666
user    0m0.831s
sys     0m0.755s

$ echo $?
0

 # perf stat output:
       670,816      page-faults               #    0.418 M/sec                  
 6,235,285,157      cycles                    #    3.885 GHz                    
 5,370,142,756      instructions              #    0.86  insn per cycle         

Lưu ý rằng GNU C không hỗ trợ đối tượng kích thước lớn hơn ptrdiff_t(đã ký 32-bit), nhưng mallocmemsetlàm vẫn làm việc, vì vậy chương trình này thành công.

Đoạn mã ARM ARM, 2 byte

 3802            subs    r0, #2

Đầu tiên arg in r0và return value in r0là quy ước gọi ARM tiêu chuẩn. Điều này cũng đặt cờ ( shậu tố). Sự thật thú vị; các phi phiên bản -flag-thiết của submột hướng dẫn rộng 32-bit.

Các hướng dẫn trở lại bạn cần phải thêm là bx lr.

Đoạn mã máy AArch64, 4 byte

d1001000        sub     x0, x0, #0x4

Hoạt động cho số nguyên 64 bit. Đầu vào / đầu ra x0, theo quy ước gọi tiêu chuẩn. int64_t foo(uint64_t);

AArch64 không có chế độ Thumb (chưa), vì vậy 1 hướng dẫn là cách tốt nhất chúng ta có thể làm.


Lưu ý cho bất kỳ ai khác gặp phải điều này: cuộc gọi đến __builtin___clear_cachechỉ cần thiết vì bạn đang thực thi bộ nhớ mà bạn nhận được malloc. Nếu bạn có bộ nhớ mmapthay vào đó, việc tối ưu hóa sẽ không xảy ra.
Joseph Sible-Phục hồi Monica

4

V , 16 (hoặc 1) byte

Nhàm chán trả lời:

<C-x>

một byte.

Câu trả lời ít nhàm chán hơn:

uÓ^$/0
16Ø^a$

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

Hexdump:

00000000: 75d3 5e24 2f30 0a31 3601 d85e 1261 240a  u.^$/0.16..^.a$.

Tôi thực sự đã viết điều này khoảng 5 phút sau khi thử thách xuất hiện. Tôi mất 30 phút để vá đống mã spaghetti khủng khiếp này mà tôi gọi là ngôn ngữ .





2

Brain-Flak , 24 byte

({}[(((()()()){}){}){}])

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

Trả về 0 cho bằng và một cái gì đó không bằng.

Làm thế nào nó hoạt động:

({} #pop the top of the stack
  [(((()()()){}){}){}] #subtract 24
) #push the result.

nThời gian chạy mã này sẽ trừ đi n * 24đầu vào, chỉ cho 0 khi đầu vào = n*24.



2

TI-Basic (sê-ri 83), 4 byte

:Ans-4

Đưa đầu vào vào Ans: ví dụ: bạn có thể nhập 17:prgmCODEGOLFđể chạy cái này với đầu vào là 17. In (và trả về Ans) giá trị 0nếu đầu vào bằng L × M và giá trị khác không.

Lưu ý rằng đó :là một phần của mã, vì vậy nếu bạn nhập mã này vào trình chỉnh sửa chương trình, bạn sẽ thấy

PROGRAM:CODEGOLF
::Ans-4

nếu bạn nhập nó một lần và

PROGRAM:CODEGOLF
::Ans-4:Ans-4:An
s-4

nếu bạn nhập nó ba lần.



1

Befunge-98 , 15 byte

]#<@.-&+
>fv
v+

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

Hãy thử gấp đôi!

Sử dụng 0 cho bằng nhau và bất cứ điều gì khác cho bất bình đẳng.

Giải trình:

Mã này được lặp đi lặp lại nhiều lần sẽ trông giống như thế này:

]#<@.-&+
>fv
v+]#<@.-&+
>fv
v+]#<@.-&+
>fv
 .
 .
 .
v+]#<@.-&+
>fv
v+
  1. ]rẽ phải. Gửi IP xuống.

  2. >di chuyển về phía đông. Gửi IP đúng.

  3. f đẩy 16.

  4. vdi chuyển về phía nam. Gửi IP xuống. Nếu đây là lần cuối cùng, Goto bước 8.

  5. ]rẽ phải. Gửi IP còn lại.

  6. +thêm vào. Thêm 16 vào đầu ngăn xếp.

  7. vdi chuyển về phía nam. Gửi IP xuống. Đi đến bước 2.

  8. <di chuyển về phía tây. Gửi IP còn lại.

  9. #bỏ qua nhảy qua ]và quấn quanh đến cuối

  10. +thêm vào. Thêm 16 vào đầu ngăn xếp.

  11. &đầu vào. Đẩy một số từ người dùng.

  12. -trừ. nhận được sự khác biệt của tổng số chúng tôi đã làm việc và đầu vào.

  13. .in. In kết quả.

  14. @ kết thúc.



1

Than , 13 byte

PI⁼Iθ×¹³L⊞Oυω

Hãy thử trực tuyến! Dựa trên câu trả lời của tôi để tôi nhân đôi nguồn, bạn nhân đôi sản lượng! Giải trình:

         ⊞Oυω   Push empty string to predefined empty list
        L       Take the length
     ×¹³        Multiply by 13
  ⁼Iθ           Compare to the input
 I              Cast to string
P               Print without moving the cursor

Quản lý để đầu ra 1cho sự thật và giả 0. Lặp đi lặp lại tiếp theo so sánh đầu vào đối với 13, 26, 39, 52vv nhưng mỗi lần câu trả lời là overprinted vì vậy chỉ là câu trả lời cuối cùng được nhìn thấy.


1

JavaScript ES6, 32 byte

((f=k=>n=>n>0?n==k:f(k+32))(32))

nếu đúng là 0 và sai như những người khác, 31 byte

(f=k=>n=>n>0?n-k:_=>f(k+_))(31)

console.log([
    ((f=k=>n=>n>0?n==k:f(k+32))(32)) (31),
    ((f=k=>n=>n>0?n==k:f(k+32))(32)) (32),
    ((f=k=>n=>n>0?n==k:f(k+32))(32)) (33),
    ((f=k=>n=>n>0?n==k:f(k+32))(32)) (64),
    ((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32)) (32),
    ((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32)) (63),
    ((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32)) (64),
    ((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32))((f=k=>n=>n>0?n==k:f(k+32))(32)) (96)
]);


1

MIPS, 4 byte

Sử dụng $a0làm đối số và giá trị trả về.

0x2084fffc    addi $a0, $a0, -4

MIPS, 8 byte (sử dụng quy ước gọi MIPS)

0x2084fff8    addi $a0, $a0, -8
0x00041021    move $v0, $a0

x86, 5 byte

Đây là câu trả lời x86 đầu tiên của tôi vì vậy phản hồi hoan nghênh. Sử dụng quy ước _fastcall với ecx làm đối số đầu tiên.

83 e9 05                sub    $0x5,%ecx
89 c8                   mov    %ecx,%eax

Peter Cordes có một giải pháp 1 byte trong các ý kiến.


Bình luận Brainfuck : Phần khó là nhận được brainfuck để trả về một giá trị duy nhất. Nếu không một cái gì đó như thế này sẽ dễ dàng.

- >,[-<->] < .

1
Đoạn mã x86 của bạn sẽ có cùng kích thước cho số nguyên 32 bit, không cần giới hạn ở 8. Nhưng nếu bạn đã sử dụng quy ước gọi tùy chỉnh (arg trong AL, retval ở một nơi khác,), bạn có thể sử dụng đặc biệt AL 2 byte mã hóa sub $4, %al/ mov %al, %dl. Hoặc vẫn trả về trong AL / EAX và sau đó bạn nhận được giải pháp của Dennis, với dec %eax(1 byte ở chế độ 32 bit). Và vâng, các quy ước gọi tùy chỉnh là tốt cho asm. Đó là asm, không chỉ là "asm mà dễ gọi từ C"; mã thực được viết bằng mã asm sử dụng các quy ước gọi tùy chỉnh nơi nó giúp, vì vậy điều này là hoàn toàn chính đáng.
Peter Cordes

1
Quy ước gọi thông thường của ARM là đối số đầu tiên trong r0đó cũng là giá trị trả về, vì vậy Thumb sub r0, #2là 2 byte.
Peter Cordes

1
Lưu ý rằng cả hai đều không phải là hàm : chúng yêu cầu retở cuối khối lặp lại trước khi bạn có thể gọi chúng. Thông thường tôi bao gồm số retbyte tính theo câu trả lời x86 asm của tôi. Nhưng tôi nghĩ việc bẻ cong các quy tắc ở đây để chỉ cơ thể có ý nghĩa, nếu không, nhiều ngôn ngữ không thể cạnh tranh được.
Peter Cordes

1
(nvm, điều này không để lại giá trị tính theo% al). xchg %eax, %ecx/ sub $4, %al/ xchg %eax, %ecxlà 4 byte và tuân theo quy ước _fastcall. Sử dụng mã hóa ngắn AL, im8 và xchg-with-eax thường hữu ích cho mã golf.
Peter Cordes

1
Tôi thường sử dụng objdump -drwC -Mintelđể có được một hexdump của byte mã máy. add r32, imm8cũng là 3 byte: opcode + ModR / M + imm8. Tất cả các hướng dẫn có thể mất một số 32 có một opcode thay thế có một số 8 được mở rộng đăng nhập. Xem felixcloutier.com/x86/ADD.html chẳng hạn; tất cả các hướng dẫn ALU "cổ điển" (nhưng không phải MOV) có từ năm 8086 đều có tất cả các mã hóa đó, bao gồm cả các mã AL / AX / EAX đặc biệt không có modr / m, chỉ op + im8 / 16/32. Câu trả lời này có ví dụ
Peter Cordes

1

Octave: 23 byte

+23;[ans,i]((N==ans)+1)

Nếu N = L * M, biểu thức trả về 0+i (nghĩa là số ảo hoàn toàn), nếu không, biểu thức dẫn đến một số phức với một thành phần thực.

Để có kết quả đẹp hơn một chút với chi phí thêm một byte:

+24;[ans,-1]((N==ans)+1)

Nếu N = L * M thì biểu thức trả về -1, nếu không thì là số dương.

Bản giới thiệu:

N=48;
+24;[ans,-1]((N==ans)+1)                                                 #>> 24 
+24;[ans,-1]((N==ans)+1)+24;[ans,-1]((N==ans)+1)                         #>> -1
+24;[ans,-1]((N==ans)+1)+24;[ans,-1]((N==ans)+1)+24;[ans,-1]((N==ans)+1) #>> 23

PS, bạn có thể nhận được kết quả tương tự với +24;if N==ans;-1;end;ans nhưng bytecount là như nhau


1

Lua, 56 46 byte

a=(a or io.read())-46io.write(a<=0 and a or"")

Xuất ra 0 (không có dòng mới) nếu bằng và không có gì hoặc một dãy số âm (với số 0 trước trong một số trường hợp) nếu không bằng nhau.

Một mình: Hãy thử trực tuyến!

Lặp đi lặp lại một loạt các lần: Hãy thử trực tuyến!

Giải trình

a=(a or io.read())-46

Trong lần lặp đầu tiên (khi achưa được xác định và do đó nil), đặt athành một số được lấy từ đầu vào, ngược lại với chính nó. Trong cả hai trường hợp, 46 sau đó được trừ đi a.

io.write(a<=0 and a or"")

Điều này chỉ in anếu nó nhỏ hơn (để xử lý các trường hợp đầu vào lớn hơn tổng chiều dài) hoặc bằng 0 và chuỗi trống khác.

-10 byte để nhớ rằng Lua thực hiện chuyển đổi giữa các số và chuỗi tự động. Rất tiếc.


0

JavaScript (ES6), 47 byte

Đây là sử dụng kỹ thuật tương tự như Benoit Esnard trong câu trả lời này (từ tôi nhân đôi nguồn, bạn nhân đôi sản lượng! ).

In 0 nếu n = 47 * M hoặc giá trị khác không.

n=prompt(setTimeout`alert(n)`)-47/*
n-=47//*///

Bản demo cho M = 1

n=prompt(setTimeout`alert(n)`)-47/*
n-=47//*///

Bản demo cho M = 2

n=prompt(setTimeout`alert(n)`)-47/*
n-=47//*///n=prompt(setTimeout`alert(n)`)-47/*
n-=47//*///


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.