逆XORを計算する


13

させるfビットフィールド(マップする関数である{0 1}大きさの)のn+1大きさのビットフィールドにn適用することによりXORi目とi+1目のビットと新しいビットフィールドに結果を書き込むこと。

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

非公式の計算:

0 XOR 1 = 1

1 XOR 0 = 1

0 XOR 1 = 1

ましょうf_inverseの逆関数になりfます。逆行列は一意ではないため、f_inverse1つの有効なソリューションを返します。

入力:文字列としてのビットフィールド(つまり"0101111101011")および指定された自然数k

出力:文字列としてのビットフィールド。入力ビットフィールドに時間をf_inverse適用すると、文字列に結果が含まれますk。(すなわちf_inverse(f_inverse(f_inverse(input)))

受賞基準:最少キャラクター

ボーナス:

-25文字f_inverseが再帰的/反復的に適用されない場合、代わりに出力文字列が直接計算されます

テストスクリプト:

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}ビットフィールドと呼ぶのをやめてください。また、私は、の定義を理解していないfiから来るの?XORの2番目の引数は何ですか?どのように我々が得るのです111から0101
mniip

より良い名前は何ですか?iはインデックスを示します
nvidia

ただ「ビットフィールド」がするでしょう。/ value /とはi何ですか?"0 XOR 1" = 1 "1 XOR 0" = 1 "0 XOR 1" = 1XORがどのように機能するかは知っていますが、XORの正確な内容と結果の保存場所は何ですか?
mniip

9
彼は次のことを意味すると思いますf([a,b,c,d]) = [a^b, b^c, c^d]。そして、彼はすなわち、その関数の逆を望んでいるf'([x,y,z]) = [a,b,c,d]ようにa^b=xb^c=yc^d=z
マリヌス

回答:


14

Pyth、 33 30-25 = 5バイト

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

(オンラインインタープリター:https : //pyth.herokuapp.com/)のようなstdinからの入力で実行します

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に書き込まれます。

コードゴルフの目的で内部ループがO(2 k)回実行されるため、kが大きすぎないことを期待していることに注意してください。


私たちは通常、この操作を「xorshift」などと呼びます。入力をビッグエンディアン整数として表現する場合、関数fは次のようになります。

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

fを 2回適用すると、次のようになります。

  • 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、つまりf 2 k(x)= xを意味し、逆は自明な関数であることに注意してください!

したがって、f -1(x)をまったく呼び出さずにf -k(x)を見つけるための戦略は次のとおりです。

  1. 次のようなKを見つけます。

    • K≥k
    • K> log 2 x
    • Kは2のべき乗です
  2. Express f -k(x)= f -K +(Kk)(x)= f -K(f K-k(x))= f K-k(x)

  3. したがって、結果はfKk回と呼ばれます

  4. 25文字の利益:p


更新1:バイナリではなく8進数表現を使用して、%フォーマットを使用して多くのバイトを節約できるようにしました。

アップデート2:の周期構造を利用してくださいf。非反復バージョンは-25バイトのボーナスがなくても短くなるため、反復バージョンは廃止されました。

更新3:Pythからの3バイトを削減、isaacgに感謝!


ヒント:codegolf.stackexchange.com/a/45280/20080で説明されているように、次のようにforループと割り当てをreduceに置き換えることができます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.";

結果はプログラムの最後に自動的に印刷されます。

文字列(単なる文字の配列)で始まるため、「文字列/配列」と言いますが、それらの間および数字の間でもXORを取り続けます。Character Character ^整数(コードポイントのXORに基づく)Character Integer ^Integer Character ^与え、文字(コードポイントとの数値のXORに基づく-コードポイントとして解釈される)を与えます。そしてInteger Integer ^もちろん、整数を与えるだけです。

タイプは幸運にも場所にすべてを飛んでますが、されているので、私は整数を持っている時はいつでも、それはどちらかだ0か、1と私は性格を持っている時はいつでも、それはどちらかだ'0'1、結果が常にある(どちらのタイプで)1を希望しました。文字列は単なる文字の配列であるため、文字と数字を混ぜても問題はありません。そして最後に、すべてが印刷されるとき、文字は特別な区切り文字を取得しないため、出力はどのビットが数字または文字として表されるかに影響されません。


CJamでの文字/数字型の動作に関する優れた説明により、ソリューションから1バイト削り取られ、25-25 = 0バイトになりました。ありがとう、+ 1!
イルマリカロネン

2
そのタイプの動作は恐ろしい(+1)です。
ballesta25

8

J、17文字

常に先頭の数字として0を使用します。

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

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

最初の行の128 1の状態(左)とランダム状態(右)から始まり、最初の129回の繰り返しまでの最後の128桁を示します。

   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に使用したので、スキンなしで実行されます。≠\ !!にも感謝します。
モリスズッカ

コピーする((0,≠\)⍣⎕)⎕と、無効なトークンが取得されます。Tryaplは入力を処理できませんか?
-randomra

1
うーん...あなたは正しい、それは私にも同じことが起こっている。私はDyalog APLを使用していて、ここに投稿するためだけにtryaplを使用しています。
モリスズッカ

5

CJam、25 − 25 = 0バイト

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

これは、以下のGolfScript回答の単なるCJamポートです。MartinBüttner の回答を読んだ後、CJamの整数型と文字型の処理により1バイト節約できることに気付きました。(基本的に、CJamは、1&ASCII文字をGolfScriptコードのビットに強制するために使用する必要はありませんが、q入力を読み取るために先頭に追加する必要があります。)それは価値のあるIMOです。

いずれの場合でも、このプログラムは以下の元のGolfScriptプログラムとまったく同じように機能します。そのため、その説明と使用手順を参照してください。通常どおり、このオンラインインタープリターを使用してCJamバージョンをテストできます。


GolfScript、26 − 25 = 1バイト

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

このソリューションは、入力文字列を1回だけ反復するので、-25バイトのボーナスの資格があると思います。これは、k個の各事前反復の現在のビットを格納するk要素配列を内部的に維持することにより機能します。

入力は、stdinを介して次の形式で指定する必要があります。 "1111111" 3、つまり数字01文字の引用符付き文字列とそれに続く数字k。出力は、引用符なしのビット文字列として標準出力になります。

このコードをオンラインでテストします。(プログラムがタイムアウトした場合は、再実行してみてください。WebGolfScriptサーバーは、ランダムなタイムアウトで有名です。)


コメント付きのこのプログラムの拡張バージョンは次のとおりです。

~             # 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 IJ:= B I、(J -1)B I -1)、(J -1)

ここで、b 0、jj番目の入力ビット(j≥1の場合)、b kjj番目の出力ビット、b i、0 = 0は仮定によります。差は(すなわち、第1すなわち、反復溶液に対し、実際には、「行ごと」再発計算され、B 1、jのすべてについてJ次に、B 2、J、等)、この解決策は、代わりに「列でそれを計算します「(より正確に、または、 "対角線による対角")列、第1の計算B I Iを 1ため≤ iがK、次いでB II +1次に、B 、II 2、等

このアプローチの1つの(理論的な)利点は、原則として、このメソッドはO(k)ストレージのみを使用して任意の長い入力文字列を処理できることです。もちろん、GolfScriptインタープリターはプログラムを実行する前に自動的にすべての入力をメモリに読み込みますが、ほとんどの場合この利点は無効になります。


2

Python、94 78

少なくとも1回実行されるため、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

文字列を数値配列に変換し、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

完全に手ごわいソリューション。2つの機能に分かれていると理解しやすい

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連続する差を計算し、それ自体でn回g構成fします。

この関数fは、の累積XOR和を計算しますl。これは、連続するXOR差の逆演算です。入力は文字列として与えられるため、を抽出する必要int(l[0])がありますが、文字列比較では短くしますl>='1'


Python 2、69

execループを使用した反復ソリューションでは、1文字長くなりました。

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ボーナスは、実際に反復を実行せずに反復の結果を計算するためのものです。)
ブリリアン

仕様を注意深く読む必要があります(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);}

ハーネスなしのゴルフ

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.