การตรวจสอบบิตดั้งเดิม


28

เขียนโปรแกรม / ฟังก์ชั่นที่รับจำนวนเต็มสองจำนวนในช่วง0ถึง255และส่งคืนว่ารูปแบบไบนารีของตัวเลขนั้นแตกต่างกันเพียงหนึ่งบิตหรือไม่

ตัวอย่างเช่น1และ0มีรูปแบบไบนารี00000001และ00000000ซึ่งอยู่ห่างกันหนึ่งบิต ในทำนองเดียวกัน152และ24คือ010011000และ000011000ดังนั้นพวกเขาจึงกลับมาจริง

อย่างไรก็ตามรหัสของคุณต้องเก่าแก่เช่นถ้าหนึ่งบิตในโปรแกรมของคุณพลิกมันควรจะเกิดข้อผิดพลาด ตัวอย่างเช่นหากโปรแกรมของคุณเป็นไบต์เดียวa(01100001) ดังนั้น 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) หรือการพิสูจน์ความสมบูรณ์แบบอื่น ๆ
    • โปรดตรวจสอบว่าโปรแกรมของคุณใช้ได้ก่อนโพสต์
  • ผลลัพธ์จะต้องเป็นจริง / เท็จ (อย่างใดอย่างหนึ่งเป็นเรื่องปกติ) หรืออื่น ๆ สองค่าที่ไม่ใช่ข้อผิดพลาดที่แตกต่างกัน
  • ข้อผิดพลาดอาจเป็น runtime, คอมไพเลอร์, ล่าม ฯลฯ

7
หากใครกำลังมองหาวิธีที่จะสร้างรูปแบบที่เป็นไปได้ทั้งหมดของโซลูชั่นของพวกเขาโปรแกรม Japt นี้ควร (ใครบางคนโปรดตรวจสอบอีกครั้ง) ทำงาน: petershaggynoble.github.io/Japt-Interpreter/ ......
Shaggy

4
นี่คือหนึ่งใน Python เช่นกัน: ลองออนไลน์!
TFeld

ฟังก์ชั่นไม่ได้รับอนุญาตเนื่องจากคุณพูดถึงโปรแกรม?
Kevin Cruijssen

5
@KevinCruijssen ฉันได้ระบุว่าการส่งฟังก์ชั่นนั้นใช้ได้
Jo King

4
ความคิดเห็นนั้นมี+1มากกว่าโซลูชันล่าสุดของฉันส่วนใหญ่! : \
ปุย

คำตอบ:


16

Python 2 , 35 ไบต์

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

ลองออนไลน์!

ใช้การตรวจสอบการจ่ายพลังงานสองครั้งn&-n==nเพื่อกำจัดค่าn==0บวกที่ผิดพลาด

สำหรับการอ้างอิงนี่เป็นคู่ของตัวดำเนินการไบนารีหนึ่งตัวที่แยกออกไปหนึ่งบิตทำให้พวกมันใช้งานยาก:

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

โชคดี&และ^ไม่ได้อยู่ในกลุ่มเหล่านี้

นอกจากนี้ทราบว่า==จะกลายเป็น<=และสามารถกลายเป็นตัวละครที่แสดงความคิดเห็น+#


Python 2 , 41 ไบต์

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

ลองออนไลน์!

การTFeld ของ lambda a,b:bin(a^b).count('1')==1และทำให้มันเป็นที่เก่าแก่โดยการเปลี่ยน 1 ไป+Trueและจะ== 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) หมายเหตุ: สามารถนำมาใช้ที่นี่ แต่จะเป็นไบต์มากขึ้นเนื่องจากทั้งสองและดั้งเดิมแทน-objects ดังนั้นเพิ่มเติมจะต้องเปลี่ยนหนึ่งในสองสระ-object ก่อนที่เราจะสามารถใช้int==int
Integer.equals(int).bitCountjava.awt.Font.BOLDintIntegernew Integer(...)Integer.equals


(int) Math.log (Math.E) คือ 21 ไบต์
ข้อมูลหมดอายุ


@ ExpiredData ขอบคุณจริง ๆ แล้วเพิ่งพบค่าคงตัวที่สั้นลงด้วยjava.awt.Font.BOLDแต่คุณObjects.equalsเป็นสนามกอล์ฟที่ดีขอบคุณ!
Kevin Cruijssen

@ExpiredData ที่จริงObjectsเป็นส่วนหนึ่งของjava.util.การนำเข้าดังนั้นฉันต้องเพิ่มเข้าไปในจำนวนไบต์ฉันกลัวทำให้มัน 69 ไบต์ .. :(
Kevin Cruijssen

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 ค่าอื่นใด

ใช้sizeof((char)d))ในการผลิตค่าคงที่1ในทางที่บริสุทธิ์ในขณะที่ยังบังคับให้ชื่อฟังก์ชั่นที่จะเก่าแก่

จากนั้น XORs ที่ 1 ที่มี 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 เป็นชื่อฟังก์ชันแทน

คุณจะทำให้^ผู้ปฏิบัติงานเก่าแก่ได้อย่างไร หากบิตของสิ่งนั้นเปลี่ยนไปสิ่งใดที่จะหยุดยั้งไม่ให้กลายเป็นโอเปอเรเตอร์ที่แตกต่างกัน สิ่งนี้จะยังคงรวบรวม แต่จะให้คำตอบที่ผิด ฉันเข้าใจบางอย่างเกี่ยวกับความหมายของคำว่า "เก่าแก่" ที่นี่หรือไม่?
Cody Grey

4
ด้วยการพลิกเพียงบิต^เดียวสามารถเปลี่ยนเป็น_\ZVN~Þอักขระใดตัวหนึ่งหรืออักขระที่ไม่สามารถพิมพ์ได้ที่ codepoint 30 ~เป็นเพียงหนึ่งในนั้นซึ่งเป็นตัวดำเนินการ แต่เป็นตัวดำเนินการเอก
สตริงที่ไม่เกี่ยวข้อง

1
หรือแม้กระทั่งใช้ __LINE__sizeof(char)แทน ฉันคิดว่ามันดีที่จะสมมติว่าฟังก์ชั่นของคุณจะอยู่บนบรรทัดที่ 1 ของไฟล์. c ของคุณ หรือแม้กระทั่งunixกำหนดให้เป็น 1 ใน TIO และอาจเป็น Linux อื่น ๆ ส่วนใหญ่
Digital Trauma

2
เหตุผลหลักสำหรับขนาดที่นำแสดงโดยถ่านคือการdอบเข้าไปในแหล่งที่น้อยที่สุดไบต์ที่เป็นไปได้ มิฉะนั้นd(หรือสิ่งที่คุณตั้งชื่อฟังก์ชั่น) ก็สามารถเปลี่ยนได้และรหัสจะยังคงทำงาน ถึงแม้จะ(__LINE__)มีd();การทำงานเคยชินเพราะd();สามารถเปลี่ยนเป็นตัวอักษรตัวอื่น ๆ และมันจะยังคงรวบรวมตั้งแต่ฟังก์ชั่นไม่เคยจะต้องมีการเรียกจึงไม่ได้เชื่อมโยง
LambdaBeta

1
@LambdaBeta หากชื่อของฟังก์ชั่นการเปลี่ยนแปลงแล้วจะมีข้อผิดพลาดการเชื่อมโยงแม้ว่า d ไม่ได้อ้างอิงตนเอง ฉันคิดว่านี่เพียงพอแล้วเป็นการส่วนตัว
Digital Trauma

7

R , 38 37 ไบต์

-1 ไบต์ต้องขอบคุณ Nick Kennedy

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

ลองออนไลน์! (ขอบคุณ Giuseppe สำหรับการตั้งค่า TIO อย่างถูกต้อง)

พิสูจน์ว่ามันเก่าแก่ (ใช้ตัวตรวจสอบของ Nick Kennedy )

เอาต์พุต 0 สำหรับความเท็จและค่าบวกสำหรับความจริงซึ่งฉันเข้าใจว่าเป็นที่ยอมรับได้เนื่องจาก R จะตีความสิ่งเหล่านี้ว่าเป็นเท็จและจริง

คำอธิบาย: bitwXor(a,b)ให้ (เป็นจำนวนเต็ม) บิต XOR ระหว่างabและ หากต้องการตรวจสอบว่าเป็นกำลัง 2 ให้ตรวจสอบว่าการเข้าสู่ระบบฐาน 2 เป็นจำนวนเต็มหรือไม่ ฟังก์ชันdpoisให้ฟังก์ชันความหนาแน่นของความน่าจะเป็นของการแจกแจงปัวซอง: ค่าเป็น 0 สำหรับค่าที่ไม่ใช่จำนวนเต็มและสิ่งที่เป็นบวกสำหรับจำนวนเต็มไม่เป็นลบ Tมีเพราะdpoisต้องใช้อาร์กิวเมนต์ที่สอง (ทำงานจริงใด ๆ ในเชิงบวกและTถูกตีความว่าเป็น 1)

หากเรายืนยันในการแสดงผลเป็นค่าที่แตกต่างรุ่นต่อไปนี้จะแสดงผลลัพธ์เป็น FALSE หรือ TRUE ใน 42 ไบต์ (ขอบคุณ Giuseppe สำหรับ -8 ไบต์):

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

และยังเป็นที่เก่าแก่ ลองออนไลน์!


2
ทำได้ดีมากในการได้อะไรที่เล็กกว่าของฉันมาก! คุณสามารถแทนที่piด้วยTเพื่อบันทึกไบต์ (ยังคงบริสุทธิ์) TIO ของคุณยังไม่สอดคล้องกับคำตอบของคุณในขณะนี้
Nick Kennedy

@NickKennedy ขอบคุณ! (และขอขอบคุณสำหรับการเขียนโค้ดเพื่อตรวจสอบว่ามันเก่าแก่!) TIO I ที่เชื่อมโยงกับเป็นรุ่นที่ได้รับการแก้ไขซึ่งจะตรวจสอบกรณีทดสอบทั้งหมด ฉันจะเพิ่ม TIO กับรหัสจริง แต่ฉันไม่สามารถคิดออกว่าจะได้รับ TIO เพื่อให้ทำงานได้อย่างถูกต้องกับสองสายไปscan(); คุณมีความคิดไหม? (รหัสทำงานได้ดีบนคอมพิวเตอร์)
Robin Ryder

2
@NickKennedy อาจจะเป็นแบบนี้? สำหรับการรับ TIO และรหัสให้ตรงกันหรือไม่
จูเซปเป้

@iuseppe ยอดเยี่ยมขอบคุณ!
Robin Ryder

1
รุ่นที่สองของคุณสามารถใช้Fแทนได้exp(-Inf)ตามบรรทัดเดียวกับ Nick's T:-)
Giuseppe

6

R , 83 ไบต์

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

ลองออนไลน์!

พิสูจน์ว่านี่คือสิ่งที่บริสุทธิ์

ทำงานรอบความจริงที่ว่าas.integer, as.doubleฯลฯ เป็นเพียงเล็กน้อยห่างจากis.integer, is.doubleฯลฯ เป็นบิตยากที่สุด ในที่สุดการใช้sum(T^el(.[-T])เป็นวิธีสร้างทั้งคู่และตรวจสอบว่าas.doubleได้คืนเวกเตอร์ความยาว> 1 เป็นสิ่งที่ดีที่สุดที่ฉันสามารถทำได้ ห่อtคือการจัดการกับความจริงที่ว่ามิฉะนั้นจะกลายเป็นidenticalide~tical


5

Julia 0.7 , 20 ไบต์

(a,b)->ispow2(ab)

ลองออนไลน์!

นี่คือเครื่องมือตรวจสอบที่เก่าแก่ซึ่งพยายามเรียกใช้ฟังก์ชันที่ไม่ระบุตัวตนที่ได้รับการดัดแปลงแต่ละตัวกับอินพุตบางส่วนและไม่ผ่านการทดสอบสำเร็จ โปรดทราบว่ารหัสมีอักขระ Unicode หลายไบต์และผลลัพธ์ที่เป็นไปได้บางอย่างจากการพลิกบิตจะไม่รวมอยู่ด้วยเนื่องจากเป็นรายการที่สร้างสตริง UTF-8 ที่ไม่ถูกต้อง


xและyอยู่ห่างกันเพียงเล็กน้อยดังนั้นฉันเชื่อว่านี่เป็นตัวอย่างที่เคาน์เตอร์ yและxยังเป็น 1 บิต9และ6ตามลำดับ
ข้อมูลที่หมดอายุ

ประณามขณะที่คิดถึงสิ่งที่ซับซ้อนฉันคิดถึงสิ่งที่ง่ายที่สุด หวังว่าการเปลี่ยนแปลงตัวแปรจะแก้ไขได้
Kirill L.

5

C # (Visual C # Interactive คอมไพเลอร์) , 37 ไบต์

a=>b=>a!=b&((a^b)&-(a^b)).Equals(a^b)

a=>b=>ส่วนหนึ่งไม่สามารถเปลี่ยนแปลงหรืออื่น ๆ ฟังก์ชั่นไม่ถูกต้อง

ในa!=bที่=ไม่สามารถเปลี่ยนแปลงได้เนื่องจากไม่สามารถแปลงเป็นintbool

ลองออนไลน์!


4

C # (Visual C # Interactive Compiler) , 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-only ขอให้โชคดีในการตรวจสอบว่ามีจำนวนไบต์ที่เหมาะสมเมื่อเราไม่สามารถใช้จำนวนเต็มหรือ+/*=สำหรับการดำเนินการทางคณิตศาสตร์หรือการตรวจสอบความถูกต้อง ;)
Kevin Cruijssen

@KevinCruijssen C # มีจำนวนมากเกินไป :(. damnit
ASCII เท่านั้น


1
O_o another -24. btw you no longer use +
ASCII-only



1

MATLAB, 37 bytes

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

Sorry, no TIO link, because I can't get the test suite to work under Octave. Thanks @ExpiredData for some helpful comments.

Test suite:

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 Thanks for the suggestion. I went for a MATLAB numel instead, because my test suite does not seem to be working in Octave.
Sanchises

38 bytes maybe.. not got a matlab license but should work
Expired Data

1
@ExpiredData Thanks, one can actually do one byte better with eye!
Sanchises

1
@ExpiredData I know, I'm very annoyed at Octave too. But using the Python program in the OP comments is handy to see if you can introduce a new character without problems.
Sanchises

1

Perl 6, 77 43 bytes

Thanks to Jo King for -33 bytes.

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

This is equivalent to

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

1 was rewritten as elems([""]). 2 was rewritten as sum(elems([""]),elems([""])); elems(["",""]) might seem to work but elems([""-""]) is also valid and seems to hang the tester.

Try it online!


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.