原始位检查


28

编写一个程序/函数,该程序需要一个介于0255两个整数,并返回数字的二进制形式是否恰好相差一位。

例如,10具有二进制形式0000000100000000,它们相差一比特。同样,15224010011000000011000,因此它们返回true。

但是,您的代码必须是原始的,以便如果程序中的任何一位被翻转,它都将引发错误。例如,如果您的程序是单个字节a01100001),则所有8种可能的修改程序:

á ! A q i e c `

必须抛出一个错误。确保您按字节进行修改(例如,á实际上是在上面表示字节225,而不是实际的两个字节字符á)。

测试用例:

0,1     => Truthy
1,0     => Truthy
152,24  => Truthy
10,10   => Falsey
10,11   => Truthy
11,12   => Falsey
255,0   => Falsey

规则:

  • 提供一个可以验证您的程序是否正确的测试框架,因为会有很多可能的程序(字节数* 8),或者完整的原始证明。
    • 发布程序前,确保您的程序有效。
  • 输出需要为真/假(两种方法都可以),或者两个截然不同的非错误值
  • 错误可以是运行时,编译器,解释器等。

7
如果任何人的寻找一种方式来生成自己的解决方案的所有可能的变化,这Japt程序应该(有人请仔细检查)做的工作:petershaggynoble.github.io/Japt-Interpreter/...
长毛

4
这也是Python中的一个:在线尝试!
TF于

自从您提到程序以来,功能是不允许的?
凯文·克鲁伊森

5
@KevinCruijssen我已经指定函数提交可以
Jo King

4
这个评论+1比我最近的大多数解决方案都多!:\
毛茸茸的

Answers:


16

Python 2,35个字节

lambda a,b:(a^b)&-(a^b)in[a^b or[]]

在线尝试!

使用二次幂校验n&-n==n,消除n==0误报。

作为参考,这些是一对一字符的二进制运算符,它们彼此分开一位,使其难以使用:

+ /
- /
* +
% -
< |
< >

幸运的是,&^没有在这些之中。

还请注意,==可以成为<=,并且+可以成为注释字符#


Python 2 2,41个字节

lambda a,b:bin(a^b).count(`+True`)is+True

在线尝试!

TFeld lambda a,b:bin(a^b).count('1')==1并将其1更改为to +True==to 使其变为纯正is。感谢Jo King提供1个字节。


9

Python 2中72个 67 50字节

lambda a,b:sum(map(int,'{:b}'.format(a^b)))is+True

在线尝试!

-5字节,感谢Jo King


为真/假返回True/ False

该程序基本上与相同lambda a,b:bin(a^b).count('1')==1,但是没有数字和其他字符,在翻转时可以工作。

通过确保几乎所有内容都是命名函数(都非常原始)来工作

最后的原始测试会翻转一位(每一位),然后在输入上尝试该功能。如果该方法有效(正确与否),则会打印该变化。没有打印的程序=原始功能。


8

Java 8,68 61 56 45字节

a->b->(a.bitCount(a^b)+"").equals(-~(a^a)+"")

-11字节由于@EmbodimentOfIgnorance,取代常数 java.awt.Font.BOLD-~(a^a)

在线尝试。

说明:

最短的基本函数是:

a->b->a.bitCount(a^b)==1

在线尝试。

对此进行了修改,因此其中没有数字,=也没有其中的一个+/*操作数可用于数值计算(因此,+用于String级联的罚款):

+"".equals是通过比较String.equals(String)来代替int==int
注意:Integer.equals(int)可以在这里使用,但会占用更多字节,因为.bitCount和和java.awt.Font.BOLD都是原始对象int而不是Integer-objects,因此在使用。之前,new Integer(...)需要另外一个将两者之一转换为-object Integer的方法.equals


(int)Math.log(Math.E)是21个字节
过期的数据


@ExpiredData谢谢,实际上刚发现了一个较短的常量java.awt.Font.BOLD,但是Objects.equals是一个不错的高尔夫球手,谢谢!
凯文·克鲁伊森

@ExpiredData实际上,这Objectsjava.util.导入的一部分,因此我必须将其添加到我担心的字节数中,使其成为69字节。.
::

3
-~(a^a)为1工作吗?
无知的体现

7

C(gcc),56个字节

d(a,b){return(sizeof((char)d))^__builtin_popcount(a^b);}

在线尝试!

0如果该对相差1,则返回,否则返回非零。对于C来说有点不寻常,除非您认为EXIT_SUCCESS如果该对相差1,则返回C,否则返回其他值。

用于sizeof((char)d))1原始方式生成常数,同时也强制函数名称为原始。

然后,将1与参数XOR的popcount进行XOR运算。幸运的是,^符号很容易保持原始,很长的标识符也是如此__builtin_popcount

同时,这是用于测试解决方案的脚本:

#!/bin/bash

SOURCE_FILE=$1
FOOT_FILE=$2
TMP_SRC=temp.c

LENGTH="$(wc -c <"$SOURCE_FILE")"
BITS=$((LENGTH*8))

cat "$SOURCE_FILE" >"$TMP_SRC"
cat "$FOOT_FILE" >>"$TMP_SRC"
if gcc -w $TMP_SRC -o t.out >/dev/null 2>&1; then
    if ./t.out; then
        echo "Candidate solution..."
    else
        echo "Doesn't even work normally..."
        exit
    fi
else
    echo "Doesn't even compile..."
    exit
fi

for i in $(seq 1 $BITS); do
    ./flipbit "$i" <"$SOURCE_FILE" >"$TMP_SRC"
    cat "$FOOT_FILE" >>"$TMP_SRC"
    if gcc -w $TMP_SRC -o t.out >/dev/null 2>&1; then
        echo "Testing flipped bit $i:"
        cat "$TMP_SRC"

        ./t.out >/dev/null 2>&1
        STATUS=$?
        if [ "$STATUS" -eq 0 ]; then
            echo "It works!"
            exit
        elif [ "$STATUS" -eq 1 ]; then
            echo "It doesn't work..."
            exit
        else
            echo "It crashes"
        fi
    fi
done

使用./flipbit我编写的工具的来源很简单:

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

int main(int argc, char *argv[]) {
    int bittoflip = atoi(argv[1]) - 1;
    int ch;

    while ((ch = fgetc(stdin)) != EOF) {
        if (bittoflip < 8 && bittoflip >= 0) {
            putchar(ch ^ (1 << bittoflip));
        } else {
            putchar(ch);
        }

        bittoflip -= 8;
    }

    return 0;
}

棘手的是:

  • 空格:所有空格(包括换行符)都有原始的双胞胎,它们的工作原理类似
  • 比较:=效果不好,因为在每种情况下它都可能是一个比较。同样,效果-也不佳。从而^用于断言与1相等。
  • 变量名称:f与b冲突,因此必须使用d作为函数名称。

您如何保持^操作员的原始状态?如果更改了其中的位,该怎么阻止它成为其他运算符?这仍然可以编译,但是只会给您错误的答案。我在这里对“原始”一词的含义有误解吗?
科迪·格雷

4
通过翻转一位,^只能_\ZVN~Þ在代码点30处更改为或不可打印字符中的任意一个。~是其中唯一的一个,它是一个运算符,但它只是一元运算符。
不相关的字符串

1
甚至使用__LINE__代替sizeof(char)。我认为可以很好地假设您的函数位于.c文件的第一行。甚至unix在TIO和其他大多数Linux上都定义为1。
Digital Trauma

2
进行char-casted的sizeof的主要原因是要以d尽可能少的字节放入源中。否则,d就可以更改(或您命名为函数的任何名称),并且代码仍然可以工作。即使(__LINE__)d();不会的工作,因为d();可以更改为任何其他信件,它仍然会编译,因为函数从来没有被调用,因此没有联系。
LambdaBeta

1
@LambdaBeta如果函数的名称更改,则即使d不是自引用的,也会出现链接错误。我个人认为这已经足够。
Digital Trauma

7

R38 37字节

-1个字节感谢Nick Kennedy。

dpois(log2(bitwXor(scan(),scan())),T)

在线尝试!(感谢Giuseppe正确设置了TIO。)

证明它是原始的(使用Nick Kennedy的检查器)。

输出0表示错误,而正值表示真实,我理解这是可以接受的,因为R会将其解释为False和True。

说明:bitwXor(a,b)给出a和之间的按位XOR(作为整数)b。要检查其是否为2的幂,请检查其以2为底的日志是否为整数。该函数dpois提供了泊松分布的概率密度函数:对于非整数值,其值为0,对于非负整数,其值为正。之所以T在那里,是因为dpois需要第二个参数(任何积极的实数,并且T被解释为1)。

如果我们坚持要输出到不同的值,则以下版本以42字节输出FALSE或TRUE(感谢-8字节的Giuseppe):

dpois(log2(bitwXor(scan(),scan())),T)%in%F

并且也是质朴在线尝试!


2
做得比我小得多的东西做得很好!你可以替换pi使用T,以节省一个字节(仍然原始)。另外,您的TIO目前与您的答案不符。
尼克·肯尼迪

@NickKennedy谢谢!(并且感谢您编写代码以检查其是否原始!)。我链接到的TIO是修改后的版本,用于检查所有测试用例。我将在实际代码中添加一个TIO,但是我无法弄清楚如何通过两次调用scan(); 来使TIO正常运行。你有想法吗?(该代码在计算机上可以正常工作。)
Robin Ryder

2
@NickKennedy也许是这样?以获得TIO和代码匹配?
朱塞佩

@Giuseppe太好了,谢谢!
罗宾·赖德

1
您的第二个版本可以使用F代替exp(-Inf),与Nick的用法相同T:-)
Giuseppe

6

R,83字节

t(identical(sum(.<-as.double(intToBits(Reduce(bitwXor,scan())))),sum(T^el(.[-T]))))

在线尝试!

证明这是原始的

回避的事实,工作as.integeras.double等等都只有一点点距离is.integeris.double等是最难的一点。最后,我可以做的最好sum(T^el(.[-T])的办法是既生成一个,又检查as.double返回的长度向量大于1。包装t是为了处理否则identical可能成为事实ide~tical


5

朱莉娅0.7,20字节

(a,b)->ispow2(ab)

在线尝试!

这是一个原始验证器,尝试对某些输入运行每个已修改的匿名函数,但均未成功通过。请注意,该代码具有多字节unicode字符,并且甚至不包括位翻转的某些可能输出,因为这些输出会产生无效的UTF-8字符串。


x而且y相距一小部分,所以我认为这是一个反例。 y并且x分别为1位96
过期数据

该死,在考虑复杂的事情时,我绝对错过了最简单的事情。希望更改变量可以解决该问题。
Kirill L.


4

C#(Visual C#中交互式编译器)128 101 77 70 61 74字节

-27字节,感谢 Ascii-Only

a=>b=>{var d=Math.Log(a^b,(int)Math.E);return d.Equals((int)Math.Abs(d));}

在线尝试!

您必须很有创造力才能在不使用文字的情况下获得C#中的数字。仅使用^运算符。变量a,b彼此之间的距离都超过1位,其他所有内容都是关键字/名称。


您不需要计数比特-检查它的2的幂是否在1到128之间(包括端点)就足够了
仅ASCII的

仅限@ASCII,如果我们不能使用整数,也不能+/*=用于数学或验证操作,请以合理的字节数检查它。;)
Kevin Cruijssen

@KevinCruijssen C#也有枚举:(。damnit
仅ASCII


1
O_o另外-24。顺便说一句,您不再使用+
仅ASCII的

3

JavaScript(严格模式下为ES6),61字节

(y,z,e)=>eval(`(y${(e='^=z)*!(y&~-y)')!='^=z)*!(y&~-y)'||e}`)

在线尝试!确保所有修改的程序都错误


哦,天哪,我没意识到我点击了一个高尔夫代码链接,却发现此答案与上下文无关,几乎心脏病发作了。就像OMG NO
Marie

4
@玛丽小心!您只能通过认证的高尔夫眼镜凝视此代码。否则,可能会灼伤您的视网膜。:p
Arnauld


1

MATLAB,37个字节

@(c,e)eq(nnz(de2bi(bitxor(c,e))),eye)

抱歉,没有TIO链接,因为我无法使测试套件在Octave下工作。感谢@ExpiredData提供一些有用的评论。

测试套件:

program = '@(c,e)eq(nnz(de2bi(bitxor(c,e))),eye)';
number_of_characters = nnz(program);
success = [];
for character_counter = 0 : number_of_characters
    for bit_no = 1:8
        prog_temp = program;
        if(character_counter > 0)
            prog_temp(character_counter) = bitxor(double(prog_temp(character_counter)),2^(bit_no-1));
        elseif(bit_no<8) % Test the unmodified program once
            continue
        end
        try
            eval(prog_temp);
            eval('ans(2,3)');
            disp(prog_temp)
            success(end+1)=1;   
        catch
            success(end+1)=0;
        end 
    end
end
assert(nnz(success)==1)


@ExpiredData感谢您的建议。我选择了MATLAB numel,因为我的测试套件似乎无法在Octave中工作。
桑奇斯

38字节可能..没有Matlab许可证,但应该可以工作
过期的数据

1
@ExpiredData谢谢,实际上可以使一个字节更好eye
Sanchises

1
@ExpiredData我知道,我对Octave也很恼火。但是在OP注释中使用Python程序很方便,看看是否可以引入一个新字符而不会出现问题。
Sanchises

1

Perl 677 43个字节

感谢Jo King提供-33个字节。

{elems(i)eq(sum [+^](@_).polymod(+@_ xx*))}

这相当于

{1 eq(sum [+^](@_).polymod(2 xx*))}

1被改写为elems([""])2被改写为sum(elems([""]),elems([""])) ;elems(["",""])可能似乎elems([""-""])有效,但也有效,并且似乎使测试仪挂起。

在线尝试!


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.