重复字节计数器


19

您的任务是编写一个字节数为L的非空程序/函数,该程序/函数重复M次后,将检查给定的正整数N是否等于L×M

理论上,您应该支持任意数量的重复(M的任意正整数值),但是如果由于语言限制,它不能超过某个阈值就可以了。严格禁止阅读程序的源代码或访问有关它的信息。

为了提供输出,您应该为一个状态(真或假)选择一个一致的值,并为另一种状态使用其他任何(不一定一致)的可能输出(Discussion)。

您的答案将由您初始程序的长度L(以字节为单位)进行评分,字节越少越好。

假设您的(初始)程序为ABCDE。然后:

  • ABCDE(1次重复)应检查输入是否等于5
  • ABCDEABCDE(2次重复)应检查输入是否等于10
  • ABCDEABCDEABCDE(3次重复)应检查输入是否等于15。等等...

该示例代码的分数为5,因为初始源的长度为5个字节。


只是为了澄清一下:源代码的长度L在其自身M时间之后连接起来应该返回其输入N是否等于L*M

Answers:


12

果冻,1字节

匹配的输出为0,不匹配的输出为非零。

在线尝试!

怎么运行的

这利用了过于宽松的输出格式。重复 M次只会使输入M递减,因此,当且仅当输入为LM时L = 1),结果才为零。


哦,天哪,我没想到会这样...(inb4每个人都将其移植到其他esolangs ...
Xcoder先生,18年

我确实有一个0字节的答案,但是,quine。:P
暴民埃里克(Erik the Outgolfer)

我的第一个想法。被23分钟殴打:(
Khuldraeseth na'Barya

11

Haskell,8个字节

(-8+).id

在线尝试!

像许多其他答案一样,它通过重复从输入数字中减去代码的长度,对真值返回0,对虚假值返回非0。


我是如此接近修修补补来得到这个...
totallyhuman

8

视网膜21 20字节

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

_

在线尝试!只需在“ 代码”窗口中重复该零件以查看其如何处理倍数即可。

给出0其他所有内容的正确的整数和正整数。

说明

首先让我们看一下单个程序:

\d+
*

这会将十进制数转换为一元数(使用 _用作一进制数字)。

^$
_

如果字符串为空(由于保证输入为正,所以此时无法发生),我们将其替换为单个 _

^_{20}

现在我们摆脱了前20个下划线。如果输入为20,则结果为空字符串。

_

最后,我们计算结果中的下划线数量,如果输入为 20


现在,当我们重复源代码时会发生什么。由于我们在加入程序时不插入换行符,因此第一行将在最后一行的末尾,因此在将程序加倍时会得到以下提示:

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

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

_

现在,我们不用计算下划线,而是进入以下阶段:

_\d+
*

此阶段不执行任何操作,因为此时工作字符串中没有更多数字,因此正则表达式无法匹配。

^$
_

现在,此阶段变得有意义。如果输入是20的较小倍数,则该字符串已由源代码的先前副本清空。在这种情况下,我们将其变成单个下划线,我们知道该字符串永远不会被程序再次变为空字符串。这样,我们保证中号个多被接受(而不是所有倍数达中号次)。

^_{20}

我们再次删除前20个下划线。因此,如果有可能,M重复源代码将删除字符串中的20M下划线。

_

而且,当我们到达程序末尾时,我们仍会计算下划线,以便有效输入为零。


6

x86 32位机器代码片段,1个字节

48                      dec    eax

在EAX中输入,在EAX中输出:0为true,非零为false。(还将ZF标志设置为true,未设置为false,因此可以je was_equal)。作为“奖励”,您不必担心包装。32位x86只能寻址4GiB的内存,因此您不能使M足够大以至于不能一路回绕并找到内容1 == 2**32 + 1

要使函数可调用,请0xC3 ret在重复0x48M次后追加一条指令。(不计入总数中,因为许多语言只需重复函数体或表达式即可竞争)。

Calleable从GNU C与原型__attribute__((regparm(1))) int checkeqM(int eax); GNU C的regparm x86函数属性调用,例如-mregparm,使用EAX传递第一个整数arg。

例如,此完整程序将2个args和JIT将指令+ a的M个副本复制ret到缓冲区中,然后将其作为函数调用。(需要可执行堆;使用编译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
}

非PIE可执行文件在虚拟内存中的位置较低;可以做更大的连续malloc。

$ 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         

请注意,GNU C不支持大于ptrdiff_t(带符号的32位)对象的大小,但是mallocmemset做还是工作,所以这个计划成功。

ARM Thumb机器代码片段,2个字节

 3802            subs    r0, #2

第一个arg输入r0和in的返回值r0是标准的ARM调用约定。这还将设置标志(s后缀)。有趣的事实; 的标志设置版本sub是32位宽的指令。

您需要附加的返回指令为bx lr

AArch64机器代码片段,4个字节

d1001000        sub     x0, x0, #0x4

适用于64位整数。x0按照标准调用约定,在中输入/输出。 int64_t foo(uint64_t);

AArch64还没有Thumb模式,所以我们最好的就是一条指令。


请注意遇到此问题的其他任何人:对的调用__builtin___clear_cache仅是必需的,因为您正在执行从中获取的内存malloc。如果mmap取而代之的是内存,则优化不会发生。
约瑟夫·西布尔-恢复莫妮卡

4

V,16(或1)个字节

无聊的答案:

<C-x>

一个字节。

少无聊的答案:

uÓ^$/0
16Ø^a$

在线尝试!

十六进制转储:

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

我实际上是在挑战出来后约5分钟写的。我花了30分钟修补了我称之为语言的一堆可怕的意大利面条代码。





2

Brain-Flak,24字节

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

在线尝试!

返回0相等值,返回不相等值。

怎么运行的:

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

此代码运行n时间将从n * 24输入中减去,仅当input =时才给出0 n*24



2

TI-Basic(83系列),4字节

:Ans-4

输入以下内容Ans:例如,您可以输入输入17:prgmCODEGOLF来运行它17。如果输入等于L×M,则打印(并返回Ans)值0,非零值。

请注意,这:是代码的一部分,因此,如果将其输入到程序编辑器中,则应看到

PROGRAM:CODEGOLF
::Ans-4

如果您输入一次,

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

如果您输入三次。



1

Befunge-98,15个字节

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

在线尝试!

尝试加倍!

使用0表示相等,其他表示不相等。

说明:

重复多次的这段代码看起来像这样:

]#<@.-&+
>fv
v+]#<@.-&+
>fv
v+]#<@.-&+
>fv
 .
 .
 .
v+]#<@.-&+
>fv
v+
  1. ]右转。向下发送IP。

  2. >向东移动。发送IP权限。

  3. f 推16。

  4. v向南移动。向下发送IP。如果这是最后一次,请转到步骤8。

  5. ]右转。向左发送IP。

  6. +加。将16添加到堆栈的顶部。

  7. v向南移动。向下发送IP。转到步骤2。

  8. <向西移动。向左发送IP。

  9. #跳跃。跳过]并环绕到最后。

  10. +加。将16添加到堆栈的顶部。

  11. &输入。向用户推送号码。

  12. -减去。得到我们正在处理的总和与输入之差。

  13. .打印。打印结果。

  14. @ 结束。



1

木炭,13字节

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

在线尝试!根据我对我将源加倍的回答,您将输出加倍!说明:

         ⊞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

设法输出1真实性和0虚假性。随后重复比较输入反对13263952等,但每个答案套印时间,所以只有最后的答案是看到。


1

JavaScript ES6,32字节

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

如果true为0,其他为false,则为31个字节

(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个字节

用途$a0作为参数和返回值。

0x2084fffc    addi $a0, $a0, -4

MIPS,8个字节(使用MIPS调用约定)

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

x86,5个字节

这是我的第一个x86答案,欢迎反馈。将_fastcall约定与ecx一起用作第一个参数。

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

彼得·科德斯(Peter Cordes)在评论中提供了1个字节的解决方案。


Brainfuck评论:困难的部分是让Brainfuck返回单个值。否则,这样的事情将很容易。

- >,[-<->] < .

1
您的x86代码片段对于32位整数将具有相同的大小,无需限制为8。但是,如果您使用自定义的调用约定(AL中的arg,在其他地方调用retval),则可以使用2字节的AL编码sub $4, %al/ mov %al, %dl。或者仍然返回AL / EAX,然后您将获得Dennis的解决方案,其中包含dec %eax(32位模式下为1字节)。是的,自定义调用约定适合于asm。它是asm,而不仅仅是“可以轻松地从C调用的asm”;用asm编写的真实代码确实会在需要帮助的地方使用自定义调用约定,因此这完全是合理的。
彼得·科德斯

1
ARM的常规调用约定是第一个arg,r0同时也是retval,因此Thumbsub r0, #2是2个字节。
彼得·科德斯

1
请注意,这些都不是函数:它们ret在重复块的末尾需要a ,然后才能调用它们。通常,我会ret为我的x86 asm答案包括in字节数。但是我认为将规则仅放在函数主体上是有意义的,否则许多语言根本无法竞争。
彼得·科德斯

1
(nvm,这不会将retval留在%al中)。 xchg %eax, %ecx/ sub $4, %al/ xchg %eax, %ecx4个字节,并且遵循_fastcall约定。使用AL,imm8和xchg-with-eax短编码通常有助于代码搜寻。
彼得·科德斯

1
我通常objdump -drwC -Mintel用来获取机器码字节的十六进制转储。 add r32, imm8也是3个字节:操作码+ ModR / M + imm8。可以采用imm32的所有指令都有一个采用符号扩展的imm8的备用操作码。例如,请参见felixcloutier.com/x86/ADD.html。可以追溯到8086的所有“经典” ALU指令(但不是MOV)都具有所有这些编码,包括没有modr / m的特殊AL / AX / EAX编码,只是op + imm8 / 16/32。此答案的例子
彼得·科德斯

1

八度:23字节

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

如果N = L * M,则表达式返回0+i(即纯虚数),否则表达式将产生带有实数分量的复数。

为了获得更好的结果,但需要增加一个字节:

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

如果N = L * M,则表达式返回-1,否则为正数。

演示:

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,您可以获得相同的结果,+24;if N==ans;-1;end;ans但字节数相同


1

Lua,56 46字节

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

如果相等,则输出0(无尾随换行符);如果不相等,则不输出任何东西或一系列负数(在某些情况下为零)。

一个人:在线尝试!

重复了一遍:在线尝试!

说明

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

在第一次迭代中(a尚未定义,因此为nil),将其设置a为从输入中获取的数字,否则为自身。在这两种情况下,都从减去46 a

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

a如果小于(等于输入大于总长度的情况)或等于零,则仅打印,否则返回空字符串。

-10字节,用于记住Lua会自动在数字和字符串之间进行转换。哎呀


0

JavaScript(ES6),47个字节

此答案中,它使用的方法与Benoit Esnard相同(从源代码中我加倍,输出就加倍!)。

如果n = 47 * M,则输出0;否则,返回非零值。

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

M = 1的演示

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

M = 2的演示

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.