Tính toán XOR nghịch đảo


13

Để cho fđược chức năng mà các bản đồ một bitfield ( {0 1}) kích thước n+1để bitfield kích thước nbằng cách áp dụng XORvào ithứ và i+1thứ chút và viết kết quả trong bitfield mới.

Thí dụ: f("0101") = "111"

Tính toán không chính thức:

0 XOR 1 = 1

1 XOR 0 = 1

0 XOR 1 = 1

Hãy f_inverselà hàm nghịch đảo của f. Vì nghịch đảo không phải là duy nhất, f_inversetrả về một giải pháp hợp lệ.

Đầu vào: bitfield dưới dạng chuỗi (nghĩa là "0101111101011") và một số tự nhiên nhất địnhk

Đầu ra: bitfield dưới dạng chuỗi, để chuỗi chứa kết quả nếu f_inverseđược áp dụng klần cho bitfield đầu vào. (tức là f_inverse(f_inverse(f_inverse(input))))

Tiêu chí chiến thắng: Nhân vật ít nhất

Tặng kem:

-25Các ký tự nếu f_inversekhông được áp dụng đệ quy / lặp, thay vào đó, chuỗi đầu ra được tính trực tiếp

Bản kiểm tra:

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)

Bạn có thể dán nó vào ví dụ ở đây và sau đó thử nó.


3
Bạn có thể đưa ra một số trường hợp thử nghiệm để xác minh.
Tối ưu hóa

3
Bạn có thể vui lòng ngừng gọi họ {0-1}-Bitfields? Ngoài ra tôi không hiểu định nghĩa f, từ đâu iđến? Đối số thứ hai của XOR là gì? làm thế nào để chúng ta nhận được 111từ 0101?
mniip 6/2/2015

Một cái tên tốt hơn là gì? tôi biểu thị chỉ số
nvidia

Chỉ cần một "bitfield" sẽ làm. Giá trị / của là igì? "0 XOR 1" = 1 "1 XOR 0" = 1 "0 XOR 1" = 1không giải thích bất cứ điều gì: Tôi biết XOR hoạt động như thế nào, nhưng chính xác thì chúng ta XORing là gì và chúng ta đang lưu trữ kết quả ở đâu?
mniip 6/2/2015

9
Tôi nghĩ rằng anh ấy có nghĩa là : f([a,b,c,d]) = [a^b, b^c, c^d]. Và ông muốn nghịch đảo của hàm, ví dụ f'([x,y,z]) = [a,b,c,d]như vậy a^b=x, b^c=y, c^d=z.
bến tàu

Câu trả lời:


14

Bình thường 33 30 - 25 = 5 byte

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

Chạy nó bằng cách nhập từ stdin like (trình thông dịch trực tuyến: https://pyth.herokuapp.com/ ):

111
3

và kết quả sẽ được ghi vào thiết bị xuất chuẩn.

Đây là bản dịch trực tiếp của:

Con trăn 2 127 118 79 - 25 = 54 byte

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)

Gọi nó như thế i("111", 3), và kết quả sẽ được viết vào thiết bị xuất chuẩn.

Lưu ý rằng chúng tôi hy vọng k không quá lớn, vì với mục đích đánh gôn, vòng lặp bên trong sẽ chạy trong O (2 k ) lần.


Tôi nghĩ rằng chúng ta thường gọi hoạt động này là "xorshift" hoặc một cái gì đó. Nếu chúng ta biểu thị đầu vào là số nguyên lớn, thì hàm f chỉ đơn giản là:

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

Nếu chúng tôi áp dụng f hai lần, chúng tôi sẽ nhận được:

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

Tuy nhiên áp dụng 3 lần sẽ có một mô hình khác nhau:

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

Áp dụng 4 lần để trở lại hình thức cơ bản:

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

Và như thế:

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

Lưu ý rằng nếu chúng ta chọn 2 k đủ lớn , thì (x ≫ 2 k ) = 0, nghĩa là f 2 k (x) = x, và nghịch đảo là hàm nhận dạng tầm thường!

Vì vậy, chiến lược cho việc tìm kiếm f -k (x) mà không gọi f -1 (x) ở tất cả là:

  1. Tìm K sao cho:

    • K k
    • K> đăng nhập 2 x
    • K là lũy thừa của 2
  2. Thể hiện f -k (x) = f -K + (Kk) (x) = f -K (f K-k (x)) = f K-k (x)

  3. Do đó, kết quả được fgọi là Kk lần

  4. Lợi nhuận 25 ký tự: p


Cập nhật 1 : Biểu diễn bát phân được sử dụng thay vì nhị phân để chúng tôi có thể sử dụng %định dạng để lưu nhiều byte.

Cập nhật 2 : Khai thác cấu trúc định kỳ của f. Đã nghỉ hưu phiên bản lặp vì phiên bản không lặp lại ngắn hơn ngay cả khi không có phần thưởng -25 byte.

Cập nhật 3 : Giảm 3 byte từ Pyth, cảm ơn isaacg!


Như được mô tả trong các mẹo: codegolf.stackexchange.com/a/45280/20080, bạn có thể thay thế vòng lặp for và các bài tập bằng cách giảm, như sau:Jiz8K+lzQ%"%0*o",KuxG/G8rQ^2KJ
isaacg 7/215

11

CJam, 15 14 byte

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

Có đầu vào như

"111" 3

Kiểm tra nó ở đây.

Giải trình

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.";

Kết quả được tự động in vào cuối chương trình.

Tôi nói "chuỗi / mảng", bởi vì tôi bắt đầu bằng một chuỗi (chỉ là một mảng các ký tự), nhưng tôi vẫn tiếp tục lấy XOR giữa chúng và giữa các số. Character Character ^đưa ra một số nguyên (dựa trên XOR của các điểm mã) Character Integer ^Integer Character ^đưa ra một ký tự (dựa trên XOR của số có điểm mã - được hiểu là điểm mã). Và Integer Integer ^tất nhiên chỉ đưa ra một số nguyên.

Vì vậy, các loại đang bay khắp nơi, nhưng may mắn thay, bất cứ khi nào tôi có một số nguyên thì nó 0hoặc 1bất cứ khi nào tôi có một ký tự '0, '1và kết quả luôn luôn là một số mong muốn (trong cả hai loại). Vì các chuỗi chỉ là mảng các ký tự, nên trộn các ký tự với các số không phải là vấn đề. Và cuối cùng, khi mọi thứ được in, các ký tự không có dấu phân cách đặc biệt, do đó đầu ra không bị ảnh hưởng bởi bit nào được biểu diễn dưới dạng số hoặc ký tự.


Giải thích tuyệt vời của bạn về hành vi loại ký tự / số trong CJam cho phép tôi loại bỏ một byte khỏi giải pháp của mình , đạt 25 - 25 = 0 byte. Cảm ơn và +1!
Ilmari Karonen 7/2/2015

2
Loại hành vi đó thật kinh khủng (+1).
ballesta25

8

J, 17 ký tự

Luôn luôn sử dụng 0 là chữ số hàng đầu.

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

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

Bắt đầu từ trạng thái hàng đầu của 128 1 (trái) và trạng thái ngẫu nhiên (phải), hiển thị 128 chữ số cuối qua lần lặp 129 đầu tiên.

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

âm mưu âm mưu


6

APL 11

((0,≠\)⍣⎕)⎕

Giải trình:

≠\  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

Hãy thử trên tryapl.org


Không thể chạy nó trên tryapl (cách bạn cung cấp đầu vào?) Nhưng ≠\ sẽ không hoạt động thay vì 2|+\ ?
Randomra 6/2/2015

là các đầu vào, nếu bạn sử dụng cùng một biểu thức tôi đã viết, chương trình sẽ hỏi bạn các số bạn muốn, đầu tiên là vectơ nhị phân, sau đó lần thứ hai cho số lần lặp. Tôi đã sử dụng a và b trong liên kết để thử, vì vậy nó được thực hiện mà không cần hỏi. Cũng cảm ơn vì ≠ \ !!
Moris Zucca

Nếu tôi sao chép, ((0,≠\)⍣⎕)⎕tôi nhận được mã thông báo không hợp lệ. Tryapl không thể xử lý đầu vào?
Randomra 6/2/2015

1
Hmmmm ... bạn nói đúng, nó cũng xảy ra với tôi. Tôi đang sử dụng Dyalog APL và sau đó thử chỉ để đăng ở đây, vì vậy tôi không bao giờ nhận thấy, xin lỗi về điều đó.
Moris Zucca

5

CJam, 25 - 25 = 0 byte

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

Đây chỉ là một cổng CJam thẳng của câu trả lời GolfScript bên dưới, vì sau khi đọc câu trả lời của Martin Büttner , tôi nhận ra rằng tôi có thể tiết kiệm được một byte do cách xử lý các kiểu số nguyên và ký tự của CJam. (Về cơ bản, CJam không cần 1&sử dụng để buộc các ký tự ASCII thành các bit trong mã GolfScript, nhưng không yêu cầu qphải đọc trước đầu vào.) Tôi thường coi một cổng tầm thường như vậy là một mánh khóe rẻ tiền, nhưng đạt được điểm 0 IMO đáng giá.

Trong mọi trường hợp, chương trình này hoạt động chính xác như chương trình GolfScript gốc bên dưới, vì vậy vui lòng tham khảo hướng dẫn sử dụng và mô tả. Như thường lệ, bạn có thể kiểm tra phiên bản CJam bằng trình thông dịch trực tuyến này .


GolfScript, 26 - 25 = 1 byte

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

Giải pháp này chỉ lặp lại chuỗi đầu vào một lần, vì vậy tôi tin rằng nó đủ điều kiện nhận phần thưởng byte25 byte. Nó hoạt động bằng cách duy trì một nội k mảng -element rằng các cửa hàng các bit hiện tại của mỗi k -lặp trước.

Đầu vào phải được cung cấp thông qua stdin, theo định dạng "1111111" 3, tức là dưới dạng một chuỗi 01ký tự được trích dẫn , theo sau là số k . Đầu ra sẽ là thiết bị xuất chuẩn, dưới dạng một chuỗi bit không có dấu ngoặc kép.

Kiểm tra mã này trực tuyến. (Nếu chương trình hết thời gian, hãy thử chạy lại; máy chủ Web GolfScript nổi tiếng với thời gian chờ ngẫu nhiên.)


Đây là phiên bản mở rộng của chương trình này, với các bình luận:

~             # 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

Về cơ bản, giống như hầu hết các giải pháp lặp lại, mã này có thể được hiểu là áp dụng sự lặp lại

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

Trong đó b 0, j là bit đầu vào thứ j (với j 1), b k , j là bit đầu ra thứ jb i , 0 = 0 theo giả định. Sự khác biệt là, trong khi các giải pháp lặp, về hiệu quả, tính toán "lặp lại theo hàng" (tức là b 1, j đầu tiên cho tất cả j , sau đó b 2, j , v.v.), giải pháp này thay vào đó tính toán "cột theo cột "(hoặc chính xác hơn là" đường chéo theo đường chéo "), tính toán đầu tiên b i , i cho 1 ≤ ik , sau đó b i , i +1 , sau đó b i , i +2 , v.v.

Một ưu điểm (về mặt lý thuyết) của phương pháp này là về nguyên tắc, phương pháp này có thể xử lý chuỗi đầu vào dài tùy ý chỉ sử dụng lưu trữ O ( k ). Tất nhiên, trình thông dịch GolfScript sẽ tự động đọc tất cả đầu vào vào bộ nhớ trước khi chạy chương trình, chủ yếu là phủ nhận lợi thế này.


2

Con trăn, 94 78

Sẽ được thực hiện ít nhất một lần và do đó cho kết quả tương tự cho n=0n=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

Phiên bản cũ chuyển đổi chuỗi thành một mảng số và "tích hợp" 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

Con trăn 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

Một giải pháp hoàn toàn khó khăn. Dễ hiểu hơn nếu chia thành hai chức năng

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

nơi ftính khác biệt liên tiếp và gsoạn fvới chính nó n lần.

Hàm ftính toán các tổng XOR tích lũy l, là phép toán nghịch đảo với các khác biệt XOR liên tiếp. Vì đầu vào được đưa ra dưới dạng một chuỗi, chúng ta cần trích xuất int(l[0]), nhưng làm như vậy ngắn hơn với so sánh chuỗi l>='1'.


Con trăn 2, 69

Một giải pháp lặp lại sử dụng execvòng lặp bật ra 1 char lâu hơn.

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

Có lẽ có một cách ngắn hơn để đối phó với chuỗi. Nếu chúng ta có thể có đầu vào / đầu ra là danh sách các số, nó sẽ lưu 5 ký tự

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$&

Các tham số được đưa ra trên đầu vào tiêu chuẩn được phân tách bằng khoảng trắng.

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

1

Javascript ES6, 47 ký tự

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

Nhân tiện, không có tác dụng phụ :)


Bạn cần chấp nhận tham số ak cho số lần lặp. (Phần thưởng -25 dành cho việc tính toán kết quả của các lần lặp mà không thực sự thực hiện các lần lặp.)
Brilliand

Tôi nên đọc kỹ thông số kỹ thuật (facepalm)
Qwertiy 6/2/2015

1

C # - 178 161 115 ký tự

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 với khai thác

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])));
        }
    }
}

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.