Calcola XOR inverso


13

Sia fla funzione che mappa un bitfield ( {0 1}) di dimensione n+1a bitfield di dimensione napplicando XORil bit ith e i+1th e scrivendo il risultato nel nuovo bitfield.

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

Calcolo informale:

0 XOR 1 = 1

1 XOR 0 = 1

0 XOR 1 = 1

Lascia che f_inversesia la funzione inversa di f. Poiché l'inverso non è univoco, f_inverserestituisce una soluzione valida.

Input: bitfield come stringa (cioè "0101111101011") e un dato numero naturalek

Output: bitfield come stringa, in modo che la stringa contenga il risultato se f_inverseviene applicata kvolte al bitfield di input. (cioè f_inverse(f_inverse(f_inverse(input))))

Criteri vincenti: meno personaggi

Bonus:

-25I caratteri se f_inversenon vengono applicati in modo ricorsivo / iterativo, invece la stringa di output viene calcolata direttamente

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)

Puoi incollarlo per esempio qui e poi provarlo.


3
Puoi dare alcuni casi di test da verificare.
Ottimizzatore

3
Potresti per favore smettere di chiamarli {0-1}-Bitfields? Inoltre non capisco la definizione di f, da dove iviene? Qual è il secondo argomento di XOR? Come possiamo ottenere 111da 0101?
mniip,

Qual è un nome migliore? denoto l'indice
nvidia

Solo un "bitfield" farebbe. Che cos'è il / valore / di i? "0 XOR 1" = 1 "1 XOR 0" = 1 "0 XOR 1" = 1non spiega nulla: so come funziona XOR, ma cosa stiamo esattamente XORing e dove stiamo memorizzando il risultato?
mniip,

9
Credo che egli intende: f([a,b,c,d]) = [a^b, b^c, c^d]. E vuole l'inverso di quella funzione, vale a dire f'([x,y,z]) = [a,b,c,d]in modo tale che a^b=x, b^c=y, c^d=z.
Marin

Risposte:


14

Pyth, 33 30 - 25 = 5 byte

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

Eseguilo per input da stdin come (interprete online: https://pyth.herokuapp.com/ ):

111
3

e il risultato verrà scritto su stdout.

Questa è una traduzione diretta di:

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)

Chiamalo come i("111", 3), e il risultato sarà scritto su stdout.

Si noti che ci aspettiamo che k non sia troppo grande, poiché ai fini del gioco del codice il circuito interno verrà eseguito per O (2 k ) volte.


Penso che di solito chiamiamo questa operazione "xorshift" o qualcosa del genere. Se esprimiamo l'input come numeri interi big-endian, la funzione f è semplicemente:

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

Se applichiamo f due volte otterremo:

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

Tuttavia l'applicazione di 3 volte avrà un modello diverso:

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

Applicando 4 volte torna al modulo base:

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

E così via:

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

Nota che se scegliamo un 2 k abbastanza grande , allora (x ≫ 2 k ) = 0, che significa f 2 k (x) = x, e l'inverso è banalmente la funzione identità!

Quindi la strategia per trovare f -k (x) senza chiamare f -1 (x) a tutti è:

  1. Trova K tale che:

    • K ≥ k
    • K> registro 2 x
    • K è una potenza di 2
  2. Express f -k (x) = f -K + (Kk) (x) = f -K (f K-k (x)) = f K-k (x)

  3. Pertanto, il risultato si fchiama Kk volte

  4. Profitto di 25 caratteri: p


Aggiornamento 1 : utilizzato la rappresentazione ottale anziché binaria in modo da poter utilizzare la %formattazione per salvare molti byte.

Aggiornamento 2 : sfruttare la struttura periodica di f. Ritirata la versione iterativa poiché quella non iterativa è più breve anche senza il bonus di -25 byte.

Aggiornamento 3 : ridotto di 3 byte da Pyth, grazie isaacg!


Come descritto nei suggerimenti: codegolf.stackexchange.com/a/45280/20080 è possibile sostituire il ciclo for e le assegnazioni con una riduzione, in questo modo:Jiz8K+lzQ%"%0*o",KuxG/G8rQ^2KJ
isaacg

11

CJam, 15 14 byte

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

Accetta input come

"111" 3

Provalo qui.

Spiegazione

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

Il risultato viene stampato automaticamente alla fine del programma.

Dico "stringa / matrice", perché inizio con una stringa (che è solo una matrice di caratteri), ma continuo a prendere XOR tra di loro e anche tra numeri. Character Character ^fornisce un numero intero (basato sull'XOR dei punti di codice) Character Integer ^e Integer Character ^un carattere (basato sull'XOR del numero con il punto di codice - interpretato come un punto di codice). E Integer Integer ^ovviamente fornisce solo un numero intero.

Così i tipi stanno volando in tutto il luogo, ma per fortuna, ogni volta che ho un numero intero che sia uno 0o 1e ogni volta che ho un carattere che è uno '0ed '1e il risultato è sempre quello desiderato (in entrambi i tipi). Poiché le stringhe sono solo matrici di caratteri, mescolare i caratteri con i numeri non è affatto un problema. E alla fine, quando tutto è stampato, i caratteri non ottengono delimitatori speciali, quindi l'output non è influenzato da quale bit è rappresentato come un numero o un carattere.


La tua eccellente spiegazione del comportamento del tipo di carattere / numero in CJam mi ha permesso di radere un byte dalla mia soluzione , raggiungendo 25 - 25 = 0 byte. Grazie e +1!
Ilmari Karonen,

2
Quel tipo di comportamento è terrificante (+1).
ballesta25,

8

J, 17 caratteri

Usando sempre 0 come cifra iniziale.

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

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

A partire dallo stato 128 1 della riga superiore (a sinistra) e uno stato casuale (a destra), che mostra le ultime 128 cifre attraverso la prima 129 iterazione.

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

tracciare tracciare


6

APL 11

((0,≠\)⍣⎕)⎕

Spiegazione:

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

Prova su tryapl.org


Non puoi eseguirlo su tryapl (come dai gli input?) Ma ≠\ non funzionerebbe invece 2|+\ ?
randomra,

gli ⎕ sono gli input, se usi la stessa espressione che ho scritto, il programma dovrebbe chiederti i numeri desiderati, prima il vettore binario, poi una seconda volta per il numero di iterazioni. Ho usato aeb nel link per tryapl, quindi viene eseguito senza chiedere cose. Grazie anche per il ≠ \ !!
Moris Zucca,

Se copio ((0,≠\)⍣⎕)⎕ottengo un token non valido. Tryapl non è in grado di gestire input?
randomra,

1
Hmmmm ... hai ragione, sta succedendo lo stesso con me. Sto usando Dyalog APL e poi tryapl solo per postare qui, quindi non l'ho mai notato, mi dispiace per quello.
Moris Zucca,

5

CJam, 25 - 25 = 0 byte

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

Questa è solo una porta CJam diretta della risposta GolfScript di seguito, poiché, dopo aver letto la risposta di Martin Büttner , mi sono reso conto che avrei potuto salvare un byte a causa della gestione da parte di CJam di numeri interi e tipi di caratteri. (Fondamentalmente, CJam non ha bisogno 1&dell'usato per forzare i caratteri ASCII in bit nel codice GolfScript, ma richiede un antepostoq per leggere l'input.) Di solito considererei una porta così banale un trucco economico, ma ottenendo un punteggio zero fatto ne vale la pena.

In ogni caso, questo programma funziona esattamente come il programma GolfScript originale di seguito, quindi fai riferimento alla sua descrizione e alle istruzioni d'uso. Come al solito, puoi provare la versione di CJam usando questo interprete online .


GolfScript, 26-25 = 1 byte

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

Questa soluzione scorre la stringa di input solo una volta, quindi credo che si qualifichi per il bonus di -25 byte. Funziona mantenendo internamente un array k -element che memorizza il bit corrente di ciascuno dei k pre-iterati.

L'immissione deve essere fornita tramite stdin, nel formato "1111111" 3, ovvero come una stringa tra virgolette di 0e 1caratteri, seguita dal numero k . L'output sarà stdout, come una stringa di bit senza virgolette.

Prova questo codice online. (Se il programma scade, prova a eseguirlo nuovamente; il server Web GolfScript è noto per i timeout casuali.)


Ecco una versione estesa di questo programma, con commenti:

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

Fondamentalmente, come la maggior parte delle soluzioni iterative, questo codice può essere inteso come applicazione della ricorrenza

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

dove b 0, j è il bit di ingresso j -esimo (per j ≥ 1), b k , j è il bit di uscita j -esimo e b i , 0 = 0 per ipotesi. La differenza è che, mentre le soluzioni iterative, in effetti, calcolano la ricorrenza "riga per riga" (cioè prima b 1, j per tutto j , poi b 2, j , ecc.), Questa soluzione invece la calcola "colonna per colonna "(o, più precisamente," diagonale per diagonale "), prima elaborazione b i , i per 1 ≤ ik, quindi b i , i +1 , quindi b i , i +2 , ecc.

Un vantaggio (teorico) di questo approccio è che, in linea di principio, questo metodo può elaborare una stringa di input arbitrariamente lunga usando solo la memoria O ( k ). Naturalmente, l'interprete GolfScript legge automaticamente tutti gli input in memoria prima di eseguire comunque il programma, annullando principalmente questo vantaggio.


2

Python, 94 78

Verrà eseguito almeno una volta e quindi darà lo stesso risultato per n=0en=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

Vecchia versione che converte la stringa in un array numerico e "integra" 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

Una soluzione totalmente recusiva. È più facile capire se suddiviso in due funzioni

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

dove fcalcola le differenze successive e gcompone fcon se stesso n volte.

La funzione fcalcola le somme XOR cumulative di l, che è l'operazione inversa alle successive differenze XOR. Poiché l'input è dato come una stringa, dobbiamo estrarlo int(l[0]), ma lo facciamo in modo più breve con il confronto delle stringhel>='1' .


Python 2, 69

Una soluzione iterativa che utilizza un execciclo si è rivelata più lunga di 1 carattere.

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

Forse c'è un modo più breve per gestire la stringa. Se potessimo avere input / output come elenchi di numeri, risparmierebbe 5 caratteri

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

Parametri forniti sull'input standard separati da uno spazio.

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

1

Javascript ES6, 47 caratteri

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

A proposito, non ci sono effetti collaterali :)


Devi accettare il parametro ak per il numero di iterazioni. (Il bonus di -25 è per calcolare il risultato delle iterazioni senza effettivamente eseguire le iterazioni.)
Brilliand

Avrei dovuto leggere attentamente le specifiche (facepalm)
Qwertiy,

1

C # - 178 161 115 caratteri

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 con imbracatura

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 byte

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

L'input è come "111" 3

Provalo online qui


"011001" è il risultato del tuo codice per l'input ma non è corretto se controlli
nvidia

@ user3613886 Siamo spiacenti, copia la versione precedente. Risolto ora
Ottimizzatore
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.