Berechnen Sie das inverse XOR

13

Sei fdie Funktion, die ein Bitfeld ( {0 1}) der Größe n+1auf ein Bitfeld der Größe abbildet, nindem sie XORauf das th- iund i+1th-Bit angewendet und das Ergebnis in das neue Bitfeld geschrieben wird.

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

Informelle Berechnung:

0 XOR 1 = 1

1 XOR 0 = 1

0 XOR 1 = 1

Sei f_inversedie Umkehrfunktion von f. Da die Inverse nicht eindeutig ist, wird f_inverseeine gültige Lösung zurückgegeben.

Eingabe: Bitfeld als String (dh "0101111101011") und eine gegebene natürliche Zahlk

Output: Bitfeld als String, so dass die Saite des Ergebnisses enthält , wenn f_inverseangewendet wird , kmal mit dem Eingang Bitfeld. (ie f_inverse(f_inverse(f_inverse(input))))

Gewinnkriterien: Wenigste Charaktere

Bonus:

-25Zeichen, wenn f_inversenicht rekursiv / iterativ angewendet, stattdessen wird die Ausgabezeichenfolge direkt berechnet

Testskript:

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)

Sie können es zum Beispiel hier einfügen und dann ausprobieren.

nvidia
quelle
3
Können Sie einige Testfälle zur Verifizierung geben?
Optimierer
3
Könnten Sie bitte aufhören, sie {0-1}-Bitfields zu nennen? Auch verstehe ich die Definition nicht f, woher kommt idas? Was ist das zweite Argument von XOR? wie kommen wir 111davon 0101?
6.
Was ist ein besserer Name? ich bezeichne den index
nvidia
Es würde nur ein "Bitfeld" reichen. Was ist der / Wert / von i? "0 XOR 1" = 1 "1 XOR 0" = 1 "0 XOR 1" = 1erklärt nichts: Ich weiß, wie XOR funktioniert, aber was genau machen wir XOR und wo speichern wir das Ergebnis?
6.
9
Ich glaube , er bedeutet: f([a,b,c,d]) = [a^b, b^c, c^d]. Und er will die Inverse dieser Funktion, das heißt f'([x,y,z]) = [a,b,c,d], dass a^b=x, b^c=y, c^d=z.
Marinus

Antworten:

14

Pyth, 33 30 - 25 = 5 Bytes

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

Führen Sie es durch Eingabe von stdin wie (Online-Interpreter: https://pyth.herokuapp.com/ ):

111
3

und das Ergebnis wird nach stdout geschrieben.

Dies ist eine direkte Übersetzung von:

Python 2, 127 118 79 - 25 = 54 Bytes

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)

Nennen Sie es wie i("111", 3), und das Ergebnis wird in stdout geschrieben.

Beachten Sie, dass wir davon ausgehen, dass k nicht zu groß ist, da die innere Schleife für Code-Golfing-Zwecke O (2 k ) -mal ausgeführt wird.


Ich denke, wir nennen diese Operation normalerweise "xorshift" oder so. Wenn wir die Eingabe als Big-Endian-Ganzzahlen ausdrücken, lautet die Funktion f einfach:

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

Wenn wir gelten f zweimal werden wir erhalten:

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

Die dreimalige Anwendung hat jedoch ein anderes Muster:

  • f 3 (x) = x ≤ (x ≤ 1) ≤ (x ≤ 2) ≤ (x ≤ 3)

Wenn Sie sich 4 Mal bewerben, kehren Sie zum Basisformular zurück:

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

Und so weiter:

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

Beachten Sie, dass, wenn wir 2 k groß genug wählen , (x ≫ 2 k ) = 0 ist, was f 2 k (x) = x bedeutet, und das Gegenteil ist trivial die Identitätsfunktion!

So ist die Strategie für die Suche nach f k (x) ohne Aufruf f -1 (x) überhaupt ist:

  1. Finde K so, dass:

    • K ≥ k
    • K> log 2 x
    • K ist eine Potenz von 2
  2. Express f k (x) = f -K + (Kk) (x) = f -K (f Kk (x)) = f Kk (x)

  3. Das Ergebnis fheißt also Kk-mal

  4. 25 Zeichen Gewinn: p


Update 1 : Verwendete eine Oktaldarstellung anstelle einer Binärdarstellung, sodass wir durch %Formatierung viele Bytes sparen konnten.

Update 2 : Nutzen Sie die periodische Struktur von f. Die iterative Version wurde zurückgezogen, da die nicht iterative Version auch ohne den Bonus von -25 Byte kürzer ist.

Update 3 : Reduziert 3 Bytes von Pyth, danke isaacg!

kennytm
quelle
Wie in den Spitzen beschrieben: codegolf.stackexchange.com/a/45280/20080 können Sie die for - Schleife und Zuweisungen mit einem ersetzen reduzieren, wie folgt aus :Jiz8K+lzQ%"%0*o",KuxG/G8rQ^2KJ
isaacg
11

CJam, 15 bis 14 Bytes

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

Nimmt Eingaben wie

"111" 3

Teste es hier.

Erläuterung

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

Das Ergebnis wird am Ende des Programms automatisch ausgedruckt.

Ich sage "string / array", weil ich mit einem String beginne (das ist nur ein Array von Zeichen), aber ich nehme weiterhin XORs zwischen diesen und zwischen Zahlen. Character Character ^Gibt eine ganze Zahl (basierend auf dem XOR der Codepunkte) Character Integer ^und Integer Character ^ein Zeichen (basierend auf dem XOR der Zahl mit dem Codepunkt - interpretiert als Codepunkt). Und Integer Integer ^natürlich gibt es nur eine ganze Zahl.

Die Typen fliegen also überall herum, aber glücklicherweise ist es immer dann, wenn ich eine Ganzzahl habe, entweder 0oder 1und wenn ich ein Zeichen habe, entweder '0und '1und das Ergebnis ist immer das gewünschte (in beiden Typen). Da Strings nur Arrays von Zeichen sind, ist das Mischen von Zeichen mit Zahlen überhaupt kein Problem. Und am Ende, wenn alles gedruckt ist, erhalten die Zeichen keine speziellen Begrenzer, sodass die Ausgabe nicht davon betroffen ist, welches Bit als Zahl oder Zeichen dargestellt wird.

Martin Ender
quelle
Ihre ausgezeichnete Erklärung des Verhaltens des Zeichen- / Zahlentyps in CJam hat es mir ermöglicht, ein Byte von meiner Lösung zu entfernen und 25 - 25 = 0 Byte zu erreichen. Danke und +1!
Ilmari Karonen
2
Dieses Verhalten ist schrecklich (+1).
ballesta25
8

J, 17 Zeichen

Verwenden Sie immer 0 als führende Ziffer.

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

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

Beginnend mit dem 128 1-Status der obersten Zeile (links) und einem Zufallsstatus (rechts), werden die letzten 128 Ziffern der ersten 129 Iteration angezeigt.

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

Handlung Handlung

randomra
quelle
6

APL 11

((0,≠\)⍣⎕)⎕

Erläuterung:

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

Versuchen Sie es auf tryapl.org

Moris Zucca
quelle
Konnte es nicht auf tryapl ausführen (wie gibst du die Eingaben ein?), ≠\ Würde aber nicht funktionieren statt 2|+\ ?
Randomra
Die ⎕s sind die Eingaben. Wenn Sie den gleichen Ausdruck verwenden, den ich geschrieben habe, sollte das Programm Sie nach den gewünschten Zahlen fragen, zuerst nach dem Binärvektor, dann ein zweites Mal nach der Anzahl der Iterationen. Ich habe in dem Link a und b verwendet, um tryapl zu benutzen, also wird es ohne Fragen ausgeführt. Auch danke für die ≠ \ !!
Moris Zucca
Wenn ich kopiere, ((0,≠\)⍣⎕)⎕erhalte ich ein ungültiges Token. Tryapl kann keine Eingaben verarbeiten?
Randomra
1
Hmmmm ... du hast recht, mir geht es genauso. Ich benutze Dyalog APL und versuche es dann, nur um hier etwas zu posten, also habe ich es nie bemerkt, tut mir leid.
Moris Zucca
5

CJam, 25 - 25 = 0 Bytes

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

Dies ist nur eine direkte CJam-Portierung der unten stehenden GolfScript-Antwort, da nach dem Lesen von Martin Büttners Antwort ich erkannte, dass ich ein Byte einsparen konnte, da CJam Integer- und Zeichentypen handhabte. (Grundsätzlich benötigt CJam 1&im GolfScript-Code keine ASCII-Zeichen, die zum Erzwingen von Bits verwendet werden, erfordert jedoch ein vorangestelltes qLesen der Eingabe.) Normalerweise würde ich einen solchen einfachen Port als billigen Trick betrachten, aber eine Null-Punktzahl erzielen es lohnt sich meiner Meinung nach.

In jedem Fall funktioniert dieses Programm genauso wie das Original-GolfScript-Programm unten. Lesen Sie daher die Beschreibung und die Gebrauchsanweisung. Mit diesem Online-Interpreter können Sie wie gewohnt die CJam-Version testen .


GolfScript, 26 - 25 = 1 Byte

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

Diese Lösung durchläuft die Eingabezeichenfolge nur einmal. Ich glaube, sie qualifiziert sich für den 25-Byte-Bonus. Es funktioniert, indem intern ein k- Element-Array verwaltet wird, das das aktuelle Bit von jedem der Elemente speichert k vorge iteriert.

Die Eingabe sollte über stdin erfolgen, und zwar im Format "1111111" 3, dh in Anführungszeichen 0und 1Zeichen, gefolgt von der Zahl k . Die Ausgabe erfolgt als Bitstring ohne Anführungszeichen auf stdout.

Testen Sie diesen Code online.(Wenn das Programm eine Zeitüberschreitung aufweist, versuchen Sie es erneut. Der Web GolfScript-Server ist für zufällige Zeitüberschreitungen bekannt.)


Hier ist eine erweiterte Version dieses Programms mit Kommentaren:

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

Grundsätzlich kann dieser Code wie die meisten iterativen Lösungen so verstanden werden, dass die Wiederholung angewendet wird

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

wobei b 0, j das j- te Eingangsbit ist (für j ≥ 1), b k , j das j- te Ausgangsbit ist und b i , 0 = 0, vorausgesetzt. Der Unterschied besteht darin, dass die iterativen Lösungen tatsächlich die Wiederholung "zeilenweise" berechnen (dh zuerst b 1, j für alle j , dann b 2, j usw.), diese Lösung sie stattdessen "spaltenweise" berechnet Spalte "(oder genauer" Diagonale für Diagonale "), wobei zuerst b i , i für 1 ≤ berechnet wird b i , i +1 , dann b ik , dann usw. i , i +2

Ein (theoretischer) Vorteil dieses Ansatzes besteht darin, dass dieses Verfahren im Prinzip eine beliebig lange Eingabezeichenfolge nur unter Verwendung von O ( k ) -Speicher verarbeiten kann. Natürlich liest der GolfScript-Interpreter automatisch alle Eingaben in den Speicher, bevor er das Programm trotzdem ausführt, was diesen Vorteil größtenteils zunichte macht.

Ilmari Karonen
quelle
2

Python, 94 78

Wird mindestens einmal ausgeführt und ergibt somit das gleiche Ergebnis für n=0undn=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

Alte Version, die den String in ein numerisches Array konvertiert und Modulo 2 "integriert"

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
quelle
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

Eine absolut wiederverwendbare Lösung. Es ist einfacher zu verstehen, wenn es in zwei Funktionen unterteilt ist

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

Dabei werden faufeinanderfolgende Differenzen berechnet und n-mal mit sich selbst gkomponiert f.

Die Funktion fberechnet die kumulativen XOR-Summen von l, was die inverse Operation zu aufeinanderfolgenden XOR-Differenzen ist. Da die Eingabe als Zeichenfolge angegeben wird, müssen wir sie extrahieren int(l[0]), beim Zeichenfolgenvergleich jedoch kürzer l>='1'.


Python 2, 69

Eine iterative Lösung mit einer execSchleife stellte sich als 1 Zeichen länger heraus.

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

Vielleicht gibt es einen kürzeren Weg, mit der Saite umzugehen. Wenn es sich bei Ein- / Ausgängen um Zahlenlisten handeln könnte, würden 5 Zeichen gespart

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

Perl 5, 34

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

Auf der Standardeingabe angegebene Parameter, durch ein Leerzeichen getrennt.

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

Javascript ES6, 47 Zeichen

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

Übrigens gibt es keine Nebenwirkungen :)

Qwertiy
quelle
Sie müssen einen Parameter für die Anzahl der Iterationen akzeptieren. (Der -25 Bonus ist für die Berechnung des Ergebnisses der Iterationen, ohne die Iterationen tatsächlich durchzuführen.)
Brilliand
Ich hätte die Spezifikation sorgfältig lesen sollen (facepalm)
Qwertiy
1

C # - 178 161 115 Zeichen

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 mit Geschirr

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
quelle
0

CJam, 20 Bytes

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

Eingabe ist wie "111" 3

Probieren Sie es hier online aus

Optimierer
quelle
"011001" ist das Ergebnis Ihres Codes für Ihre Eingabe, aber es ist nicht korrekt, wenn Sie
nvidia
@ user3613886 Ältere Version leider kopiert. Jetzt behoben
Optimierer