整数のペアと正の整数の間の1対1の対応


8

整数のペアと正の整数の間に1対1の対応があることはよく知られています。あなたのタスクは、選択したプログラミング言語で(互いに逆の関数/プログラムのペアを定義することによって)そのような対応を定義するコードを記述し、対応のバイト数が最小の正当性チェック(下記を参照)を行うことです。定義(正当性チェックを考慮しない)。

ソリューションには以下を含める必要があります。

  • 2つの整数引数を持ち、整数を返す関数/プログラムfの定義(全単射の1方向です)。

  • 1つの整数引数を持ち、整数のペア(配列、リスト、何かで区切られた2つの整数の連結など)を返す関数/プログラムgの定義、または2つの関数/プログラムaおよびbのいずれか整数の引数と整数を返します(それが反対方向です)。

  • 上記で定義したfとg(またはfとa、b)について、g(f(x、y))=(x、y)(またはa(f(x、y) )= xおよびb(f(x、y))= y)整数<x、y>の場合、-100 <x <100、-100 <y <100。fおよびgは、外部の値に対して機能する必要があることに注意してください。この範囲の。

もちろん、a、b、f、gの名前を変更できます。2つのソリューションを同じ言語で記述する必要はありません。

以下は、PARI / GPでの最適ではないソリューションで、関数定義に597文字を使用しています。

plane_to_line(x,y)={
my(ax,ay,z);
ax=abs(x);
ay=abs(y);
if((ax<=ay)*(y<0),        z=4*y*y-2*y+x+2;);
if((ax<=ay)*(y>=0),       z=4*y*y-2*y-x+2;);
if((ay<=ax)*(x<0),        z=4*x*x    -y+2;);
if((ay<=ax)*(x>=0)*(y<0), z=4*x*x+4*x+y+2;);
if((ay<=ax)*(x>=0)*(y>=0),z=4*x*x-4*x+y+2;);
if((x==0)*(y==0),z=1;);
return(z);
}


line_to_plane(z)={
my(l,d,x,y);
l=floor((1+sqrt(z-1))/2);
d=z-(4*l*l-4*l+2);
if(d<=l,x=l;y=d;);
if((l<d)*(d<=3*l),x=2*l-d;y=l;);
if((3*l<d)*(d<=5*l),x=(-l);y=4*l-d;);
if((5*l<d)*(d<=7*l),x=d-6*l;y=(-l););
if((7*l<d)*(d<8*l) ,x=l;y=d-8*l;);
if(z==1,x=0;y=0;);
return([x,y]);
}

と正当性チェックコード:

accu=List([])
m=100;
for(x=-m,m,for(y=-m,m,if(line_to_plane(plane_to_line(x,y))!=[x,y],\
listput(accu,[x,y]);)))
Vec(accu)

1
これの2番目の部分はすでに実行しましたが、両方の関数が互いに逆である必要があるという事実は、マルチパートの課題を正当化するのに十分な相互作用である可能性があると思います。
マーティンエンダー

@MartinBüttner独立したマルチパートが機能するかわかりません。課題の一部は、最短の機能を提供するエンコーディングを選択することです。
Level River St

1
双方向で呼び出すことができるプログラムを1つだけ提供できますか?
16

1
@EwanDelanoy Fatalizeは、両方を1回だけ実行できるプログラムを数えることを提案していたと思います。
マーティンエンダー

2
@LevelRiverSt Katenkyoのコメントを補足するためにZ^nn-tuplesを表す理由は、省略された演算子が(ペアワイズ)乗算ではなく、デカルト積であることです。Z^2 = ZxZ
マーティンエンダー

回答:


7

MATL43 36バイト

これはspiral1YL)関数を使用し、値が外向きのらせん状に配置された所定のサイズの正方形の2D配列を生成します。たとえば、入力を使用7すると、

43 44 45 46 47 48 49
42 21 22 23 24 25 26
41 20  7  8  9 10 27
40 19  6  1  2 11 28
39 18  5  4  3 12 29
38 17 16 15 14 13 30
37 36 35 34 33 32 31

を含む配列の中心は1、タプルに対応し[0 0]ます。左上隅は[-3 -3]etcに対応します。たとえば、f(-3、-3)は43になり、g(43)は[-3 -3]になります。

コードは、このスパイラル行列を使用して、変換を実行するために必要な大きさの2D配列を生成します。大きいサイズでは、すでに小さいサイズに含まれているエントリに対して常に同じ結果が得られることに注意してください。

Z 2N(18バイト)。

|X>tEQ1YLGb+QZ}3$)

オンラインでお試しください!

|X>   % input is a 2-tuple. Take maximum of absolute values
tEQ   % duplicate. Multiply by 2 and increase by 1. This gives necessary size of spiral
1YL   % generate spiral
G     % push input 2-tuple again
b+Q   % bubble up, add, increase by 1. This makes the center correspont to [0 0]
Z}    % split tuple into its values
3$)   % use those two value as indices into the spiral array to obtain result

NへのZ 225 18バイト)

Eqt1YLG=2#fhw2/k-q

オンラインでお試しください!

Eq      % input is a number. Multiply by 2, add 1. This assures size is enough and odd
t1YL    % duplicate. Generate spiral of that size
G=      % compare each entry with the input value
2#fh    % 2-tuple of row and column indices of matching entry
w2/k-q  % swap. Offset values so that center corresponds to [0 0]

チェック用のスニペット

G単一の入力がないという事実に対応するために変更する必要があることに注意してください。コードが遅いため、リンクは-9から9までの値を持つタプルのみをチェックします。-99から99の場合、最初の行を置き換えるだけです。

コードは、定義された範囲の値で各タプルをテストします。数値に変換してから、その数値からタプルに戻し、元のタプルと復元されたタプルが等しいかどうかを確認します。結果はすべてであるはずであり1、すべての比較で結果が得られることを示していますtrue

実行には少し時間がかかります。

オンラインでお試しください!

-9:9                     % Or use -99:99. But it takes long
HZ^!"@                   % Cartesian power: gives tuples [-9 -9] ... [9 9].
                         % For each such tuple
|X>tEQ1YL@b+QZ}3$)       % Code from Z^2 to N with `G` replaced by `@` (current tuple)
XJ                       % Copy result into clipboard J
Eqt1YLJ=2#fhw2/k-q       % Code from N to Z^2 with `G` replaced by `J`
@!X=                     % Compare original tuple with recovered tuple: are they equal?

4

JavaScript(ES6)、171バイト

(x,y)=>(h=x=>parseInt((x^x>>31).toString(2)+(x>>>31),4),h(x)*2+h(y))
x=>(h=x=>parseInt(x.toString(2).replace(/.(?!(..)*$)/g,''),2),i=x=>x<<31>>31^x>>>1,[i(h(x>>>1)),i(h(x))])

ビットいじり:負の数はビットが反転します。次に、各整数が2倍になり、元々負だった場合は1が加算されます。次に、整数からのビットがインターリーブされます。逆の操作は、代替ビットを削除し、2で除算し、値が負の場合はすべてのビットを反転します。16ビット値ではなく15ビット値に制限することで、3バイトを節約できました。


3

ゼリー、50 48 46 45 43 40 39 バイト

面から線(18 17 16 バイト):

AḤ_<0$
+RS+
,Ñç/

オンラインでお試しください!

平面への線(32 30 29 27 24 23 バイト):

HĊN⁸¡
³R‘R’U⁹¡F³ịÇ
ç1,¢

オンラインでお試しください!

説明:

説明するだけplane to lineですline to planeが、これは正反対です。

まず、関数によって、各整数を自然数に変換しますf(x) = 2*|x| - (x<0)

次に、関数を使用して、2つの自然数を別の2つの自然数に変換しますg(x,y) = (x+y,y)

最後に、関数によってそれらを1つの自然数に変換します h(x,y) = (x+1)C2 + y


@LuisMendoはい、そして今やオンライン試用リンクの入力は7
Leaky Nun

これは良く見えます:-)私はあなたがチェックスニペットに取り組んでいると思います
ルイスメンド

@LuisMendoチェックスニペットはスコアにカウントされますか?
Leaky Nun

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