คำนวณ XOR ผกผัน


13

อนุญาตfเป็นฟังก์ชั่นที่แมป bitfield ( {0 1}) ขนาดn+1กับ bitfield ขนาดnโดยใช้XORกับith และi+1th บิตและเขียนผลลัพธ์ใน bitfield ใหม่

ตัวอย่าง: f("0101") = "111"

การคำนวณอย่างไม่เป็นทางการ:

0 XOR 1 = 1

1 XOR 0 = 1

0 XOR 1 = 1

อนุญาตเป็นฟังก์ชันผกผันของf_inverse fเนื่องจากการผกผันไม่ซ้ำกันf_inverseส่งคืนโซลูชันที่ถูกต้องหนึ่งรายการ

อินพุต: bitfield เป็นสตริง (เช่น"0101111101011") และจำนวนธรรมชาติที่กำหนดk

เอาต์พุต: bitfield เป็นสตริงดังนั้นสตริงจะมีผลลัพธ์หากf_inverseถูกนำไปใช้kกับเวลาที่ป้อน bitfield (เช่นf_inverse(f_inverse(f_inverse(input))))

เกณฑ์การชนะ: ตัวละครน้อยที่สุด

โบนัส:

-25อักขระถ้าf_inverseไม่ได้ใช้ซ้ำ / ซ้ำแล้วซ้ำสตริงออกจะถูกคำนวณโดยตรง

Testscript:

a = "011001"
k = 3

def f(a):
    k = len(a)
    r = ""
    for i in xrange(k-1):
        r += str(int(a[i]) ^ int(a[i+1]))
    return r

def iterate_f(a, k):
    print "Input ", a
    for i in xrange(k):
        a = f(a)
        print "Step " + str(i+1), a

iterate_f(a, k)

คุณสามารถวางตัวอย่างที่นี่แล้วลอง


3
คุณช่วยให้กรณีทดสอบเพื่อตรวจสอบ
เครื่องมือเพิ่มประสิทธิภาพ

3
คุณกรุณาหยุดโทรหาพวกเขา{0-1}-Bitfields ได้ไหม? นอกจากนี้ฉันไม่เข้าใจความหมายของสิ่งfที่iมาจากไหน อะไรคือข้อโต้แย้งที่สองของ XOR เราจะได้รับ111จาก0101อะไร
mniip

ชื่อที่ดีกว่าคืออะไร? ฉันหมายถึงดัชนี
nvidia

เพียงแค่ "bitfield" เท่านั้นที่ทำได้ ค่า / ของiคืออะไร "0 XOR 1" = 1 "1 XOR 0" = 1 "0 XOR 1" = 1ไม่ได้อธิบายอะไรเลย: ฉันรู้ว่า XOR ทำงานอย่างไร แต่เราคืออะไร XORing และเราเก็บผลลัพธ์ไว้ที่ไหน
mniip

9
f([a,b,c,d]) = [a^b, b^c, c^d]ผมคิดว่าเขาหมายถึง: และเขาต้องการที่ผกผันของฟังก์ชันที่เช่นf'([x,y,z]) = [a,b,c,d]ดังกล่าวว่าa^b=x, ,b^c=y c^d=z
marinus

คำตอบ:


14

Pyth, 33 30 - 25 = 5 ไบต์

Jiz8K+lzQ%"%0*o",KuxG/G8rQ^2KJ

เรียกใช้โดยป้อนจาก stdin like (ล่ามออนไลน์: https://pyth.herokuapp.com/ ):

111
3

และผลลัพธ์จะถูกเขียนไปยัง stdout

นี่คือการแปลโดยตรงของ:

Python 2 127 118 79 - 25 = 54 ไบต์

def i(s,k):
 l=int(s,8);t=len(s)+k
 while k<1<<t:l^=l/8;k+=1
 print'%0*o'%(t,l)

เรียกว่าชอบi("111", 3)และผลลัพธ์จะถูกเขียนไปยัง stdout

โปรดทราบว่าเราคาดหวังว่า k จะไม่ใหญ่เกินไปเนื่องจากเพื่อจุดประสงค์ในการเล่นรหัสวงในจะทำงานเป็น O (2 k ) ครั้ง


ฉันคิดว่าเรามักจะเรียกการดำเนินการนี้ว่า "xorshift" หรืออะไรซักอย่าง หากเราแสดงอินพุตเป็นจำนวนเต็มขนาดใหญ่ฟังก์ชันfเป็นเพียงแค่:

  • f (x) = x ⊕ (x≫ 1)

หากเราสมัครfสองครั้งเราจะได้รับ:

  • f 2 (x) = x ⊕ (x≫ 2)

อย่างไรก็ตามการใช้ 3 ครั้งจะมีรูปแบบที่แตกต่างกัน:

  • f 3 (x) = x ⊕ (x≫ 1) ⊕ (x≫ 2) ⊕ (x≫ 3)

ใช้ 4 ครั้งกลับไปที่รูปแบบพื้นฐาน:

  • f 4 (x) = x ⊕ (x≫ 4)

และอื่น ๆ :

  • f 2 k (x) = x ⊕ (x≫ 2 k )

โปรดทราบว่าถ้าเราเลือกขนาดใหญ่พอที่ 2 kแล้ว (x » 2 k ) = 0, ความหมายฉ2 k (x) = x และผกผันเป็นนิด ๆ ฟังก์ชั่นตัวตน!

ดังนั้นกลยุทธ์สำหรับการค้นหา f -k (x) โดยไม่ต้องเรียก f -1 (x) เลยคือ:

  1. ค้นหา K แบบนั้น:

    • K ≥ k
    • K> บันทึก2 x
    • K คือพลังของ 2
  2. ด่วน f -k (x) = f -K + (Kk) (x) = f -K (f K-k (x)) = f K-k (x)

  3. ดังนั้นผลลัพธ์จะถูกfเรียกว่า Kk คูณ

  4. กำไร 25 ตัวอักษร: p


อัปเดต 1 : ใช้การแทนฐานแปดแทนไบนารีเพื่อให้เราสามารถใช้%การจัดรูปแบบเพื่อประหยัดจำนวนไบต์

การปรับปรุงที่ 2 : fใช้ประโยชน์จากโครงสร้างระยะของ เกษียณเวอร์ชันซ้ำเนื่องจากเวอร์ชันที่ไม่ใช่ซ้ำจะสั้นกว่าแม้ว่าจะไม่มีโบนัส -25 ไบต์

อัปเดต 3 : ลดขนาด 3 ไบต์จาก Pyth ขอบคุณ isaacg!


ตามที่อธิบายไว้ในเคล็ดลับ: codegolf.stackexchange.com/a/45280/20080คุณสามารถแทนที่ for loop และการมอบหมายด้วยการลดเช่นนี้:Jiz8K+lzQ%"%0*o",KuxG/G8rQ^2KJ
isaacg

11

CJam, 15 14 ไบต์

l~{0\{1$^}/]}*

ใช้อินพุตเหมือน

"111" 3

ทดสอบที่นี่

คำอธิบาย

l~{0\{1$^}/]}*
l~             "Read and evaluate input.";
  {         }* "Repeat k times.";
   0\          "Push a 0 and swap it with the string/array.";
     {   }/    "For each element in the string/array.";
      1$       "Copy the previous element.";
        ^      "XOR.";
           ]   "Wrap everything in a string/array again.";

ผลลัพธ์จะถูกพิมพ์โดยอัตโนมัติเมื่อสิ้นสุดโปรแกรม

ฉันพูดว่า "string / array" เพราะฉันเริ่มต้นด้วยสตริง (ซึ่งเป็นเพียงอาร์เรย์ของตัวอักษร) แต่ฉันยังคงใช้ XORs ระหว่างพวกเขาและระหว่างตัวเลขเช่นกัน Character Character ^ให้จำนวนเต็ม (ขึ้นอยู่กับ XOR ของจุดรหัส) Character Integer ^และInteger Character ^ให้ตัวละคร (ขึ้นอยู่กับ XOR ของจำนวนที่มีจุดรหัส - ตีความว่าเป็นจุดรหัส) และInteger Integer ^แน่นอนแค่ให้จำนวนเต็ม

ดังนั้นประเภทจะบินทั่วทุกสถานที่ แต่โชคดีที่เมื่อใดก็ตามที่ฉันมีจำนวนเต็มมันเป็นอย่างใดอย่างหนึ่ง0หรือ1และเมื่อใดก็ตามที่ฉันมีตัวละครมันเป็นอย่างใดอย่างหนึ่ง'0และ'1ผลเสมอที่ต้องการหนึ่ง (ในรูปแบบใด) เนื่องจากสตริงเป็นเพียงอาร์เรย์ของอักขระการผสมอักขระกับตัวเลขจึงไม่ใช่ปัญหาเลย และในตอนท้ายเมื่อทุกอย่างถูกพิมพ์อักขระจะไม่มีตัวคั่นพิเศษดังนั้นผลลัพธ์จะไม่ได้รับผลกระทบจากบิตใดที่แสดงเป็นตัวเลขหรืออักขระ


คำอธิบายที่ยอดเยี่ยมของคุณเกี่ยวกับพฤติกรรมของประเภทตัวอักษร / หมายเลขใน CJam ให้ฉันโกนไบต์ออกจากโซลูชันของฉันถึง 25 - 25 = 0 ไบต์ ขอบคุณและ +1!
Ilmari Karonen

2
พฤติกรรมประเภทนั้นน่ากลัว (+1)
ballesta25

8

J, 17 ตัวอักษร

ใช้ 0 เป็นเลขนำหน้าเสมอ

   (~:/\@]^:[,~[$0:)

   3 (~:/\@]^:[,~[$0:) 1 1 1 
0 0 0 1 0 0

เริ่มต้นจากสถานะของ 128 1 แถวบนสุด (ซ้าย) และสถานะสุ่ม (ขวา) แสดง 128 หลักสุดท้ายผ่าน 129 รอบแรก

   viewmat (~:/\)^:(<129) 128$1               viewmat (~:/\)^:(<129) ?128$2

พล็อต พล็อต


6

APL 11

((0,≠\)⍣⎕)⎕

คำอธิบาย:

≠\  compare increasing number of elements (1 1 1 ->1 0 1)
0,    add a starting zero
()⍣⎕  repeat the function in parenthesis ⎕ times, ⎕ is the second argument
()⎕   apply all to ⎕, that is first argument

ลองใช้tryapl.org


ไม่สามารถเรียกใช้บน tryapl (คุณให้อินพุตได้อย่างไร) แต่≠\ จะไม่ทำงานแทน2|+\ ใช่ไหม
randomra

⎕คืออินพุตหากคุณใช้นิพจน์เดียวกับที่ฉันเขียนโปรแกรมควรถามหมายเลขที่คุณต้องการก่อนอื่นเวกเตอร์ไบนารีจากนั้นเป็นครั้งที่สองสำหรับจำนวนการทำซ้ำ ฉันใช้ a และ b ในลิงก์ไปยัง tryapl ดังนั้นมันจะถูกเรียกใช้โดยไม่ถาม ขอบคุณสำหรับ≠ \ !!
Moris Zucca

หากฉันคัดลอก((0,≠\)⍣⎕)⎕ฉันจะได้รับโทเค็นไม่ถูกต้อง Tryapl ไม่สามารถจัดการอินพุตได้หรือไม่
randomra

1
อืม ... เจ้าพูดถูกมันเกิดขึ้นกับฉันเหมือนกัน ฉันใช้ Dyalog APL แล้วก็ลองโพสต์เพื่อโพสต์ที่นี่ดังนั้นฉันไม่เคยสังเกตเห็นเลยเสียใจด้วย
Moris Zucca

5

CJam, 25 - 25 = 0 ไบต์

q~1,*_@{[\{1$^}/_](;)\}/;

นี่เป็นเพียงพอร์ต CJam ตรงของคำตอบ GolfScript ด้านล่างเนื่องจากหลังจากอ่านคำตอบของ Martin Büttnerฉันรู้ว่าฉันสามารถบันทึกหนึ่งไบต์เนื่องจากการจัดการประเภทจำนวนเต็มและอักขระของ CJam (โดยทั่วไปแล้ว CJam ไม่จำเป็นต้อง1&ใช้เพื่อบังคับให้ตัวละคร ASCII เป็นบิตในรหัส GolfScript แต่ไม่จำเป็นต้องมีการเตรียมqการก่อนอ่านอินพุต) ฉันมักจะพิจารณาว่าพอร์ตเล็ก ๆ น้อย ๆ นั้นเป็นเคล็ดลับราคาถูก มันคุ้มค่า IMO

ไม่ว่าในกรณีใดโปรแกรมนี้ทำงานเหมือนกับโปรแกรม GolfScript ดั้งเดิมด้านล่างดังนั้นโปรดอ้างอิงคำอธิบายและคำแนะนำการใช้งาน ตามปกติคุณสามารถทดสอบเวอร์ชัน CJam โดยใช้ล่ามออนไลน์นี้


GolfScript, 26 - 25 = 1 ไบต์

~1,*.@{[1&\{1$^}/.](;)\}/;

โซลูชันนี้วนซ้ำสตริงการป้อนข้อมูลเพียงครั้งเดียวดังนั้นฉันเชื่อว่ามันมีคุณสมบัติสำหรับโบนัส −25 ไบต์ มันทำงานโดยการบำรุงรักษาภายในk -element array ที่เก็บบิตปัจจุบันของk pre-iterates แต่ละบิต

การป้อนข้อมูลควรจะได้รับผ่านทาง stdin ในรูปแบบ"1111111" 3เช่นเป็นสายยกของ0และ1ตัวอักษรตามด้วยหมายเลขk เอาต์พุตจะเป็น stdout ในฐานะ bitstring โดยไม่มีเครื่องหมายคำพูด

ทดสอบรหัสนี้ทางออนไลน์ (หากโปรแกรมหมดเวลาให้ลองเรียกใช้ซ้ำอีกครั้งเซิร์ฟเวอร์ Web GolfScript มีชื่อเสียงในเรื่องการหมดเวลาแบบสุ่ม)


ต่อไปนี้เป็นเวอร์ชันขยายของโปรแกรมนี้พร้อมความคิดเห็น:

~             # eval the input, leaving a string and the number k on the stack

1,*           # turn the number k into an array of k zeros ("the state array")
.             # make a copy of the array; it will be left on the stack, making up the
              # first k bits of the output (which are always zeros)

@             # move the input string to the top of the stack, to be iterated over
{
  [           # place a start-of-array marker on the stack, for later use
  1&          # zero out all but the lowest bit of this input byte
  \           # move the state array to the top of the stack, to be iterated over

  { 1$^ } /   # iterate over each element of the state array, XORing each
              # element with the previous value on the stack, and leave
              # the results on the stack

  .           # duplicate the last value on the stack (which is the output bit we want)
  ]           # collect all values put on the stack since the last [ into an array
  (;          # remove the first element of the array (the input bit)
  )           # pop the last element (the duplicated output bit) off the array
  \           # move the popped bit below the new state array on the stack
}
/             # iterate the preceding code block over the bytes in the input string

;             # discard the state array, leaving just the output bits on the stack

โดยทั่วไปเช่นเดียวกับวิธีแก้ปัญหาซ้ำ ๆ ส่วนใหญ่รหัสนี้สามารถเข้าใจได้ว่าเป็นการใช้การเกิดซ้ำ

        b i , j : = b i , ( j −1)b ( i −1), ( j −1) ,

โดยที่b 0, jคือบิตอินพุตj -th (สำหรับj ≥ 1), b k , jคือบิตเอาต์พุตj -th และb i , 0 = 0 ตามข้อสมมติ ความแตกต่างคือในขณะที่การแก้ปัญหาซ้ำผลคำนวณ "แถวต่อแถว" ซ้ำ (เช่นแรก1, jสำหรับทุกjแล้วb 2, jฯลฯ ) วิธีนี้แทนที่จะคำนวณ "คอลัมน์โดย คอลัมน์"(หรือกว่าถูกต้อง 'ในแนวทแยงโดยเส้นทแยงมุม') ครั้งแรกคอมพิวเตอร์ฉัน , ฉัน 1 ≤ ฉันkจากนั้นb i , i +1 , จากนั้นb i , i +2 , เป็นต้น

ข้อดีของทฤษฎีนี้คือ (ในทางทฤษฎี) โดยหลักการแล้ววิธีนี้สามารถประมวลผลสตริงอินพุตที่มีความยาวโดยพลการโดยใช้ที่เก็บข้อมูลO ( k ) เท่านั้น แน่นอนล่าม GolfScript จะอ่านอินพุตทั้งหมดลงในหน่วยความจำโดยอัตโนมัติก่อนที่จะเรียกใช้โปรแกรมต่อไปซึ่งส่วนใหญ่จะเป็นการลบความได้เปรียบนี้


2

Python, 94 78

จะถูกดำเนินการอย่างน้อยหนึ่งครั้งจึงให้ผลเหมือนกันสำหรับn=0และn=1

def f(x,n):
 c='0'
 for i in x:c+='10'[i==c[-1]]
 return f(c,n-1)if n>1 else c

เวอร์ชันเก่าซึ่งแปลงสตริงเป็นอาร์เรย์ตัวเลขและ "รวม" modulo 2

from numpy import*
g=lambda x,n:g(''.join(map(str,cumsum(map(int,'0'+x))%2)),n-1)if n>0 else x

2

Python 2, 68

g=lambda l,n,s=0:n and g(`s`+(l and g(l[1:],1,s^(l>='1'))),n-1)or l

ทางออกที่เป็นไปได้ทั้งหมด ง่ายต่อการเข้าใจหากแบ่งออกเป็นสองฟังก์ชั่น

f=lambda l,s=0:`s`+(l and f(l[1:],s^(l>='1')))
g=lambda l,n:n and g(f(l),n-1)or l

โดยที่fคำนวณความแตกต่างอย่างต่อเนื่องและgเรียบเรียงfด้วยตัวเอง n ครั้ง

ฟังก์ชันfคำนวณผลบวก XOR สะสมlซึ่งเป็นการดำเนินการผกผันกับความแตกต่างของ XOR ต่อเนื่อง ตั้งแต่การป้อนข้อมูลจะได้รับเป็นสตริงเราต้องสารสกัดแต่ทำเพื่อให้สั้นลงด้วยการเปรียบเทียบสตริงint(l[0])l>='1'


Python 2, 69

โซลูชันวนซ้ำโดยใช้การexecวนซ้ำกลายเป็น 1 char อีกต่อไป

l,n=input()
exec"r=l;l='0'\nfor x in r:l+='10'[l[-1]==x]\n"*n
print l

อาจมีวิธีที่สั้นกว่าในการจัดการกับสตริง หากเราสามารถให้อินพุต / เอาท์พุตเป็นรายการตัวเลขก็จะประหยัดได้ 5 ตัวอักษร

l,n=input()
exec"r=l;l=[0]\nfor x in r:l+=[l[-1]^x]\n"*n
print l

1

Perl 5, 34

#!perl -p
s/ .*//;eval's/^|./$%^=$&/eg;'x$&

พารามิเตอร์ที่กำหนดในอินพุตมาตรฐานคั่นด้วยช่องว่าง

$ perl a.pl  <<<"1101 20"
101111011011011011010110

1

Javascript ES6, 47 ตัวอักษร

f=(s,k)=>k?f(0+s.replace(s=/./g,x=>s^=x),--k):s

ยังไงก็ไม่มีผลข้างเคียง :)


คุณต้องยอมรับพารามิเตอร์ ak สำหรับจำนวนการวนซ้ำ (โบนัส -25 สำหรับการคำนวณผลลัพธ์ของการทำซ้ำโดยไม่ทำการวนซ้ำจริง ๆ )
Brilliand

ฉันควรอ่านข้อกำหนดอย่างระมัดระวัง (facepalm)
Qwertiy

1

C # - 178 161 115 ตัวอักษร

static string I(string a, int k){var s = "0";foreach(var c in a)s+=c==s[s.Length-1]?'0':'1';return k<2?s:I(s,--k);}

Ungolfed ด้วยสายรัด

using System;
using System.Text;

namespace InverseXOR
{
    class Program
    {
        static string I(string a, int k)
        {
            var s = "0";
            foreach (var c in a)
                s += c == s[s.Length - 1] ? '0' : '1';
            return k < 2 ? s : I(s, --k);
        }

        static void Main(string[] args)
        {
            Console.WriteLine(I(args[0], Convert.ToInt32(args[1])));
        }
    }
}

0

CJam, 20 ไบต์

q~{:~0\{1$!_!?}/]s}*

อินพุตเหมือน "111" 3

ลองออนไลน์ได้ที่นี่


"011001" เป็นผลมาจากรหัสของคุณสำหรับการป้อนข้อมูลของคุณ แต่มันไม่ถูกต้องหากคุณตรวจสอบ
nvidia

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