Hitung invers XOR

13

Membiarkan fmenjadi fungsi yang memetakan bitfield ( {0 1}) ukuran n+1ke bitfield ukuran ndengan menerapkan XORke bit th idan i+1th dan menulis hasilnya di bitfield baru.

Contoh: f("0101") = "111"

Perhitungan informal:

0 XOR 1 = 1

1 XOR 0 = 1

0 XOR 1 = 1

Membiarkan f_inversemenjadi fungsi kebalikan dari f. Karena kebalikannya tidak unik, f_inversemengembalikan satu solusi yang valid.

Input: bitfield sebagai string (yaitu "0101111101011") dan bilangan alami yang diberikank

Output: bitfield sebagai string, sehingga string berisi hasil jika f_inversediterapkan kkali ke bitfield input. (yaitu f_inverse(f_inverse(f_inverse(input))))

Kriteria pemenang: Karakter paling sedikit

Bonus:

-25 Karakter jika f_inverse tidak diterapkan secara rekursif / iteratif, sebagai gantinya string keluaran langsung dihitung

Naskah ujian:

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)

Anda dapat menempelkannya misalnya di sini dan kemudian mencobanya.

nvidia
sumber
3
Bisakah Anda memberikan beberapa test case untuk diverifikasi.
Pengoptimal
3
Bisakah Anda berhenti memanggil mereka {0-1}-Bitfield? Saya juga tidak mengerti definisi f, dari mana datangnya i? Apa argumen kedua XOR? bagaimana kita mendapatkan111 dari 0101?
mniip
Apa nama yang lebih baik? saya menunjukkan indeks
nvidia
Hanya "bitfield" yang bisa dilakukan. Apa / value / dari i? "0 XOR 1" = 1 "1 XOR 0" = 1 "0 XOR 1" = 1tidak menjelaskan apa-apa: Saya tahu cara kerja XOR, tapi apa sebenarnya yang kita XORing dan di mana kita menyimpan hasilnya?
mniip
9
Saya pikir dia berarti: f([a,b,c,d]) = [a^b, b^c, c^d]. Dan dia ingin kebalikan dari fungsi itu, yaituf'([x,y,z]) = [a,b,c,d] seperti yang a^b=x, b^c=y, c^d=z.
marinus

Jawaban:

14

Pyth, 33 30 - 25 = 5 byte

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

Jalankan dengan masukan dari stdin like (juru bahasa online: https://pyth.herokuapp.com/ ):

111
3

dan hasilnya akan ditulis ke stdout.

Ini adalah terjemahan langsung dari:

Python 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)

Sebut saja i("111", 3), dan hasilnya akan ditulis ke stdout.

Perhatikan bahwa kami berharap k tidak terlalu besar, karena untuk tujuan kode-golf loop internal akan berjalan untuk O (2 k ) kali.


Saya pikir kita biasanya menyebut operasi ini "xorshift" atau sesuatu. Jika kita menyatakan input sebagai bilangan bulat big-endian, maka fungsinya f hanyalah:

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

Jika kita menerapkan f dua kali, kita akan mendapatkan:

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

Namun menerapkan 3 kali akan memiliki pola yang berbeda:

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

Menerapkan 4 kali kembali ke bentuk dasar:

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

Dan seterusnya:

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

Perhatikan bahwa jika kita memilih 2 k yang cukup besar , maka (x ≫ 2 k ) = 0, artinya f 2 k (x) = x, dan kebalikannya adalah fungsi identitas yang sepele!

Jadi strategi untuk menemukan f- k (x) tanpa memanggil f -1 (x) sama sekali adalah:

  1. Temukan K sedemikian rupa sehingga:

    • K ≥ k
    • K> log 2 x
    • K adalah kekuatan 2
  2. Ekspresikan f -k (x) = f -K + (Kk) (x) = f -K (f K-k (x)) = f K-k (x)

  3. Jadi, hasilnya fdisebut kali Kk

  4. 25 untung laba: p


Pembaruan 1 : Digunakan representasi oktal bukan biner sehingga kita bisa menggunakan %format untuk menyimpan banyak byte.

Pembaruan 2 : Memanfaatkan struktur periodik f. Menghentikan versi iteratif karena versi yang tidak iteratif lebih pendek bahkan tanpa bonus -25 byte.

Pembaruan 3 : Mengurangi 3 byte dari Pyth, terima kasih isaacg!

kennytm
sumber
Seperti dijelaskan dalam tips: codegolf.stackexchange.com/a/45280/20080 Anda dapat mengganti loop dan penugasan dengan pengurangan, seperti ini:Jiz8K+lzQ%"%0*o",KuxG/G8rQ^2KJ
isaacg
11

CJam, 15 14 byte

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

Mengambil input seperti

"111" 3

Uji di sini.

Penjelasan

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

Hasilnya dicetak secara otomatis di akhir program.

Saya katakan "string / array", karena saya mulai dengan string (yang hanya array karakter), tapi saya tetap mengambil XOR di antara mereka dan di antara angka juga. Character Character ^memberikan integer (berdasarkan XOR dari titik kode), Character Integer ^dan Integer Character ^memberikan karakter (berdasarkan XOR dari angka dengan titik kode - diartikan sebagai titik kode). Dan Integer Integer ^tentu saja hanya memberikan bilangan bulat.

Jadi jenisnya terbang di semua tempat, tapi untungnya, setiap kali saya memiliki bilangan bulat itu baik 0atau 1dan setiap kali saya memiliki karakter itu baik '0dan '1dan hasilnya selalu yang diinginkan (dalam jenis apa pun). Karena string hanyalah array karakter, pencampuran karakter dengan angka bukanlah masalah sama sekali. Dan pada akhirnya, ketika semuanya dicetak, karakter tidak mendapatkan pembatas khusus, sehingga output tidak terpengaruh oleh bit yang direpresentasikan sebagai angka atau karakter.

Martin Ender
sumber
Penjelasan Anda yang sangat baik tentang perilaku tipe karakter / angka di CJam izinkan saya mencukur satu byte dari solusi saya , mencapai 25 - 25 = 0 byte. Terima kasih, dan +1!
Ilmari Karonen
2
Perilaku tipe itu mengerikan (+1).
ballesta25
8

J, 17 karakter

Selalu menggunakan 0 sebagai digit terdepan.

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

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

Mulai dari status 128 1 baris atas (kiri) dan status acak (kanan), menampilkan 128 digit terakhir melalui 129 iterasi pertama.

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

merencanakan merencanakan

randomra
sumber
6

APL 11

((0,≠\)⍣⎕)⎕

Penjelasan:

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

Coba di tryapl.org

Moris Zucca
sumber
Tidak dapat menjalankannya di tryapl (bagaimana Anda memberikan input?) Tetapi ≠\ tidak akan berhasil 2|+\ ?
randomra
⎕ adalah input, jika Anda menggunakan ekspresi yang sama dengan yang saya tulis, program harus menanyakan angka yang Anda inginkan, pertama vektor biner, lalu kedua kali untuk jumlah iterasi. Saya menggunakan a dan b di tautan untuk tryapl, jadi dieksekusi tanpa menanyakan hal-hal. Juga terima kasih untuk ≠ \ !!
Moris Zucca
Jika saya menyalin ((0,≠\)⍣⎕)⎕saya mendapatkan token yang tidak valid. Tryapl tidak dapat menangani input?
randomra
1
Hmmmm ... Anda benar, itu terjadi sama bagi saya. Saya menggunakan Dyalog APL dan kemudian mencoba hanya untuk mengirim di sini, jadi saya tidak pernah memperhatikan, maaf tentang itu.
Moris Zucca
5

CJam, 25 - 25 = 0 byte

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

Ini hanyalah port CJam langsung dari jawaban GolfScript di bawah ini, karena, setelah membaca jawaban Martin Büttner , saya menyadari bahwa saya bisa menghemat satu byte karena penanganan CJam pada tipe integer dan karakter. (Pada dasarnya, CJam tidak perlu 1&digunakan untuk memaksa karakter ASCII menjadi bit dalam kode GolfScript, tetapi memang membutuhkan prepended quntuk membaca input.) Saya biasanya akan menganggap port sepele seperti trik murah, tetapi mencapai skor nol dibuat itu IMO berharga.

Bagaimanapun, program ini bekerja persis seperti program GolfScript asli di bawah ini, jadi silakan merujuk ke deskripsi dan instruksi penggunaannya. Seperti biasa, Anda dapat menguji versi CJam menggunakan penerjemah online ini .


GolfScript, 26 - 25 = 1 byte

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

Solusi ini hanya diulang pada input string sekali saja, jadi saya yakin ini memenuhi syarat untuk bonus −25 byte. Ini bekerja dengan secara internal memelihara k array elemen yang menyimpan bit saat ini dari setiap pre-iterates k .

Input harus diberikan melalui stdin, dalam format "1111111" 3, yaitu sebagai string 0dan1 karakter yang , diikuti oleh angka k . Output akan menjadi stdout, sebagai bitstring tanpa tanda kutip.

Uji kode ini secara online.(Jika program habis, coba jalankan kembali; server Web GolfScript terkenal karena waktu habis secara acak.)


Inilah versi yang diperluas dari program ini, dengan komentar:

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

Pada dasarnya, seperti kebanyakan solusi berulang, kode ini dapat dipahami sebagai penerapan perulangan

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

di mana b 0, j adalah bit input ke- j (untuk j ≥ 1), b k , j adalah bit keluaran ke- j , dan b i , 0 = 0 dengan asumsi. Perbedaannya adalah bahwa, sedangkan solusi iteratif, pada dasarnya, menghitung perulangan "baris demi baris" (yaitu pertama b 1, j untuk semua j , kemudian b 2, j , dll.), Solusi ini malah menghitungnya "kolom oleh kolom "(atau, lebih tepatnya," diagonal demi diagonal "), komputasi pertama b b i , i +1 i , i untuk 1 ≤ ≤ k , lalu i, lalu b i , i +2 , dll.

Satu keuntungan (teoretis) dari pendekatan ini adalah bahwa, pada prinsipnya, metode ini dapat memproses string input panjang yang sewenang-wenang hanya dengan menggunakan penyimpanan O ( k ). Tentu saja, interpreter GolfScript secara otomatis membaca semua input ke dalam memori sebelum menjalankan program, kebanyakan meniadakan keuntungan ini.

Ilmari Karonen
sumber
2

Python, 94 78

Akan dieksekusi setidaknya sekali dan dengan demikian memberikan hasil yang sama untuk n=0dann=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

Versi lama yang mengubah string menjadi array numerik dan "mengintegrasikan" 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
DenDenDo
sumber
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

Solusi yang sangat recusive. Lebih mudah dipahami jika dipecah menjadi dua fungsi

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

di mana fmenghitung perbedaan berturut-turut dan gmenyusun fdengan sendirinya n kali.

Fungsi fmenghitung jumlah XOR kumulatif l, yang merupakan operasi terbalik untuk perbedaan XOR berturut-turut. Karena input diberikan sebagai string, kita perlu mengekstraksi int(l[0]), tetapi melakukannya lebih pendek dengan perbandingan string l>='1'.


Python 2, 69

Solusi berulang menggunakan execloop ternyata 1 char lebih lama.

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

Mungkin ada cara yang lebih pendek untuk menangani string. Jika kita bisa memiliki input / output menjadi daftar angka, itu akan menghemat 5 karakter

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

Perl 5, 34

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

Parameter yang diberikan pada input standar dipisahkan oleh spasi.

$ perl a.pl  <<<"1101 20"
101111011011011011010110
nutki
sumber
1

Javascript ES6, 47 karakter

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

Omong-omong, tidak ada efek samping :)

Qwertiy
sumber
Anda harus menerima parameter ak untuk jumlah iterasi. (Bonus -25 adalah untuk menghitung hasil dari iterasi tanpa benar-benar melakukan iterasi.)
Brilliand
Saya harus membaca spesifikasi dengan cermat (facepalm)
Qwertiy
1

C # - 178 161 115 karakter

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

Tidak diikat dengan tali kekang

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

CJam, 20 byte

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

Inputnya seperti "111" 3

Cobalah online di sini

Pengoptimal
sumber
"011001" adalah hasil dari kode Anda untuk masukan Anda tetapi tidak benar jika Anda memeriksa
nvidia
@ user3613886 Maaf, menyalin versi yang lebih lama. Diperbaiki sekarang
Pengoptimal