チェビシェフ回転


36

各セルに整数座標がある通常のグリッドを考えてみましょう。セルを(正方形の)「リング」にグループ化できます。各リングのセルは、原点からのチェビシェフ距離(またはチェスボード距離)が同じです。あなたの仕事は、そのようなセル座標を取り、そのセルをリング内で反時計回りに1つの位置だけ回転させることです。これにより、次のマッピングが実装されます。

ここに画像の説明を入力してください

したがって、たとえば、入力が(3, -2)出力の場合は(3, -1)。これ(0, 0)は、それ自体にマップする必要がある唯一の入力であることに注意してください。

ルール

I / O形式はかなり柔軟です。2つの個別の数字、ペア/リスト/配列/数字のタプル、単一の複素数、2つの数字を含む文字列などを使用できます。

あなたはそれを仮定するかもしれません-128 < x,y < 128

プログラムまたは関数を作成し、入力を受け取り出力を提供する当社の標準的な方法を使用できます。

任意のプログラミング言語を使用できますが、これらの抜け穴はデフォルトでは禁止されています。

これはであるため、バイト単位で測定された最短の有効な回答が勝ちます。

テストケース

(0, 0)       => (0, 0)
(1, 0)       => (1, 1)
(1, 1)       => (0, 1)
(0, 1)       => (-1, 1)
(-1, 1)      => (-1, 0)
(-1, 0)      => (-1, -1)
(-1, -1)     => (0, -1)
(0, -1)      => (1, -1)
(1, -1)      => (1, 0)
(95, -12)    => (95, -11)
(127, 127)   => (126, 127)
(-2, 101)    => (-3, 101)
(-65, 65)    => (-65, 64)
(-127, 42)   => (-127, 41)
(-9, -9)     => (-8, -9)
(126, -127)  => (127, -127)
(105, -105)  => (105, -104)

入力形式と出力形式を混在させることはできますか。たとえば、タプルを取得して複素数を出力できますか?
デニス

@デニスはい、それは結構です。
マーティンエンダー

回答:


16

JavaScript(ES6)、60 59バイト

カリー化構文(x)(y)を使用して入力を受け取り、配列を返します[new_x, new_y]

x=>y=>(x|y&&((z=x+(y<0))>-y?z>y?y++:x--:z>y?x++:y--),[x,y])

使い方

私たちの主なタスクは、どの象限にいるのかを判断し、どの方向に進むべきかを判断することです。

この式を最初の近似として使用できます。

x > -y ? (x > y ? 0 : 1) : (x > y ? 2 : 3)

取得するものは次のとおりです。

3 1 1 1 1 1 1 1 1
3 3 1 1 1 1 1 1 0
3 3 3 1 1 1 1 0 0
3 3 3 3 1 1 0 0 0
3 3 3 3 3 0 0 0 0
3 3 3 3 2 2 0 0 0
3 3 3 2 2 2 2 0 0
3 3 2 2 2 2 2 2 0
3 2 2 2 2 2 2 2 2

ほぼそこに。ただし、リングの左下隅と右下隅は無効です。マトリックスの下半分を左に1ポジションだけシフトする必要があるため、次のように定義しますz

z = y < 0 ? x + 1 : x

そして私達は取り替えます xz私たちの式:

z > -y ? (z > y ? 0 : 1) : (z > y ? 2 : 3)

これは以下につながります:

3 1 1 1 1 1 1 1 1 
3 3 1 1 1 1 1 1 0 
3 3 3 1 1 1 1 0 0 
3 3 3 3 1 1 0 0 0 
3 3 3 3 3 0 0 0 0 
3 3 3 2 2 0 0 0 0 
3 3 2 2 2 2 0 0 0 
3 2 2 2 2 2 2 0 0 
2 2 2 2 2 2 2 2 0 

[0, 0]個別に対処する必要がある特別な場合(まったく移動しない)を除き、マトリックス全体が正しくなりました。

テストケース


13

ゼリー20 14 12 バイト

S;IṠN0n/¦Ạ¡+

入力と出力は配列の形式です。オンラインでお試しください!またはすべてのテストケースを検証する

バックグラウンド

移動しなければならない方向を把握するために、象限二等分線x + y = 0(青)およびx-y = 0(赤)に対する開始点の相対位置を観察できます。

diagram

  • 原点は固定されています。[0、0]を開始点に追加して進めます。

  • 一番上の三角形のポイント(最初の象限の二等分線を含む)には、正の合計と非負のデルタ(y-x)があります。開始点に[-1、0]を追加して進めます。

  • 左端の三角形のポイント(2番目の象限の二等分線を含む)には、正でない合計と正のデルタがあります。開始点に[0、-1]を追加して進めます。

  • 一番下の三角形のポイント(3番目の象限の二等分線を含む)には、負の合計と非正のデルタがあります。[1、0]を開始点に追加して進めます。

  • 4番目の象限の二等分線を含む、右端の三角形のポイントには、非負の合計と負のデルタがあります。[0、1]を開始点に追加して進めます。

正しい方向を把握するために、[-sign(x + y)、-sign(y-x)]を計算しますが、結果は9つしかありません。

次の表は、どの結果をどの方向にマッピングする必要があるかを示しています。

    sign(x+y) |  sign(y-x) | -sign(x+y) | -sign(y-x) |     Δx     |     Δy
  ------------+------------+------------+------------+------------+------------
        0     |      0     |      0     |      0     |      0     |      0
        1     |      0     |     -1     |      0     |     -1     |      0
        1     |      1     |     -1     |     -1     |     -1     |      0
        0     |      1     |      0     |     -1     |      0     |     -1
       -1     |      1     |      1     |     -1     |      0     |     -1
       -1     |      0     |      1     |      0     |      1     |      0
       -1     |     -1     |      1     |      1     |      1     |      0
        0     |     -1     |      0     |      1     |      0     |      1
        1     |     -1     |     -1     |      1     |      0     |      1

これにより、3つのケースが残ります。

  • 少なくとも1つの符号が0の場合、[Δx、Δy] = [-sign(x + y)、-sign(yx)]

  • 符号が等しく、ゼロ以外の場合、[Δx、Δy] = [-sign(x + y)、0]

  • 符号が異なり、ゼロ以外の場合、[Δx、Δy] = [0、-sign(yx)]

使い方

S;IṠN0n/¦Ạ¡+  Main link. Argument: [x, y] (pair of integers)

S             Sum; compute x + y.
  I           Increments; compute [y - x].
 ;            Concatenate; yield [x + y, y - x].
   Ṡ          Sign; compute [sign(x + y), sign(y - x)].
    N         Negate; yield [-sign(x + y), -sign(y - x)].
          ¡   Do n times:
         Ạ      Set n to all([-sign(x + y), -sign(y - x)]), i.e., 1 if the signs
                are both non-zero and 0 otherwise.
        ¦       Conditional application:
      n/          Yield 1 if the signs are not equal, 0 if they are.
     0            Replace the coordinate at 1 or 0 with a 0.
              This returns [Δx, Δy].
           +  Add; yield  [Δx + x, Δy + y].


5

Python、55バイト

lambda x,y:(x-(-y<x<=y)+(y<=x<-y),y+(~x<y<x)-(x<y<=-x))

4つの対角象限を検出し、適切な座標をシフトします。


4

Haskell、77 71 69バイト

x#y|y>=x,-x<y=(x-1,y)|y>x=(x,y-1)|y< -x=(x+1,y)|y<x=(x,y+1)|1>0=(0,0)

これは、これらの傾斜した象限のそれぞれをチェックし、それに応じて入力を変更するだけです。スペースが必要であることに注意してください。>-、演算子として定義されます(定義されていません)。

@nimi、さらにいくつかのバイトを削除してくれてありがとう!


,&&最初のガード内ではなく、バイトを保存します。そして、2番目の比較を-x<y別のバイトに切り替えることができます。
nimi

ありがとう、私は知らなかった,
flawr

4

ルビー、68

Lambda関数は引数として複素数を取り、複素数を返します。

->z{k=1
4.times{z*=?i.to_c
x,y=z.rect
y*y>=x*x&&y<-x&&(z+=k;k=0)}
z} 

を乗算して、ポイントを90度4回回転させiます。したがって、4つの象限すべてを通過し、特定の1つにある場合に変更するという事実を除き、変更されずに返されます。同じ象限で常に変更されるという事実は、変更を単純化します。

z右側の象限にあるときに変更すると、最も簡単に追跡できます。この場合、y座標を1増やす必要があります(つまり、izます)。

私たちは、チェックx.abs>=y.absの正方形を比較することによって、xおよびy。これは、ポイントが上部または下部ではなく、右側または左側の象限にあることを示しています。それを確認するために、実際に右側の象限にあることをさらに確認します x>yx=y「最上位」象限に属するケースを除外したいため、厳密に大きくなります)。iz

ゴルフの理由から、追加することiは望ましくありません。代わりに、下の象限にある数値を変更します。その場合、x座標に1を追加する必要があります(1を加算しzます)。この場合y*y>=x*x、上または下の象限にあることを確認するためにテストします。さらに下の象限にあることを確認するために、チェックする必要がありますy<-x(右下隅のケースを厳密に除外しy=-xます。

このチェックの利点は、座標0,0に特別なケースがないことです。残念ながら、ポイントを移動すると別の象限に移動する可能性があり、これはその象限を再度チェックした場合に2番目の移動を抑制する必要があることを意味し、おそらく利点を無効にします。

例1

Input                                        95,-12
Rotate 90deg                                 12,95    
Rotate 90deg                                -95,12    
Rotate 90deg                                -12,-95 
Rotate 90deg                                 95,-12
y.abs>=x.abs=TRUE, y<-x=TRUE, increase x     95,-11

The check and alteration of the coordinate is done AFTER the rotation.
Thus in this case it gets done in the 4th iteration of the loop, not the 1st.
If the code were rewritten to do the check and alteration BEFORE the rotation, 
it would be done in the 1st iteration instead of the 4th.

例2

Input                                        -1,0
Rotate 90deg                                  0,-1
y.abs>=x.abs=TRUE, y<-x=TRUE, increase x      1,-1
Rotate 90deg                                  1,1
Rotate 90deg                                  1,-1
Rotate 90deg                                 -1,-1
y.abs>=x.abs?=TRUE, y<-x=TRUE but DO NOT CHANGE x!

This is an unusual situation due to the fact that the first move caused the
point to advance by one quadrant. We do NOT want to move it again, for this
reason we need to set k to 0 the first time it is moved.

テストプログラムで

f=->z{k=1                   #amount to be added to coordinate
4.times{z*=?i.to_c          #iterate 4 times, rotating point by 90deg till it reaches the original orientation
x,y=z.rect                  #separate out x and y for testing
y*y>=x*x&&y<-x&&(z+=k;k=0)} #if y.abs>=x.abs and y negative and not equal -x, move the point and zero k.
z}                          #return z

puts f[Complex(0, 0)]       # (0, 0)
puts f[Complex(1, 0)]       # (1, 1)
puts f[Complex(1, 1)]       # (0, 1)
puts f[Complex(0, 1)]       # (-1, 1)
puts f[Complex(-1, 1)]      # (-1, 0)
puts
puts f[Complex(-1, 0)]      # (-1, -1)
puts f[Complex(-1, -1)]     # (0, -1)
puts f[Complex(0, -1)]      # (1, -1)
puts f[Complex(1, -1)]      # (1, 0)
puts f[Complex(95, -12)]    # (95, -11)
puts f[Complex(127, 127)]   # (126, 127)
puts
puts f[Complex(-2, 101)]    # (-3, 101)
puts f[Complex(-65, 65)]    # (-65, 64)
puts f[Complex(-127, 42)]   # (-127, 41)
puts f[Complex(-9, -9)]     # (-8, -9)
puts f[Complex(126, -127)]  # (127, -127)
puts f[Complex(105, -105)]  # (105, -104)

次の画像は、(青)の領域x*x>=y*y、(黄)の領域、y<-xおよび(緑)これらの交差点を示しています。これは、正しい変換が1に追加された領域zです。

enter image description here


1
申し訳ありませんが、私は説明に従っていません。例と図のどちらを追加してもよろしいですか?
マーティンエンダー

@Martinの説明が追加されました。これは興味深いアプローチでしたが、最初に移動するときに象限が変わるポイントの二重移動を抑制する必要があるため、期待したほどエレガントではありませんでした。
レベルリバーセント

4

Python、52バイト

h=lambda z:z and 1j*h(z/1j)if'-'in`z*1j-z-1`else z+1

複雑な入力と出力。ポイントを下の対角象限にあるかどうかをテストするには、最初に135を反時計回りに回転してその象限を(x> 0、y> 0)標準象限に移動し、文字列表現にマイナス記号がないかどうかをテストします。最初に1を引くと、境界条件が処理されます。

その象限にない場合は、問題全体を90度回転させます。入力がゼロの場合、特別に処理されて出力されます。

複素数のその他の試み:

## 56 bytes
## Coordinate input, complex output
q=lambda x,y:(y<=x<-y)*(1j*y-~x)or x+1j*y and 1j*q(y,-x)

## 60 bytes
h=lambda z:(z+1)*(z.imag<=z.real<-z.imag)or z and 1j*h(z/1j)

## 63 bytes
from cmath import*
h=lambda z:z and 1j**(phase(z*1j-z)*2//pi)+z

3

Mathematica、34バイト

±0=0
±z_:=z+I^Floor[2Arg@z/Pi+3/2]

これは、±成分がxおよびを表す複素数を取り、返す単項演算子を定義しますy

Lynnが複素数ソリューションを明らかにし、Dennisが私のスコアを破ったので、ゴルフの参照実装を投稿するのはそれほど気になりません。:)(Lynnの答えと事実上同一であることが判明しました。)


これは役に立ちますか?±0 = 0⁢±z_:= z + I ^⌊2⁢Arg @ z / Pi + 3/2⌋(おそらくフロアブラケットに異なる文字を使用)
DavidC

残念ながら@DavidCは、UTF-8エンコードを使用する必要があり、±がそれぞれ2バイトかかるため、そうではありません。
マーティンエンダー

それは7ではなく4バイトではないので、3バイトの経済性が得られますか?
DavidC

@DavidCいいえ、フロアブラケットはそれぞれ3バイトです。
マーティンエンダー

私はそれを知りませんでした。しかし、それでも、1バイトを節約する必要があります。
DavidC

3

MATL19 17バイト

t|?JGJq*X/EYP/k^+

これは、入力および出力として複素数を使用します。

オンラインでお試しください!または、すべてのテストケースを確認します

説明

入力-127+42jを例としてみましょう。

t|       % Implicit input. Duplicate and take absolute value
         % STACK: -127+42j, 133.764718816286
?        % If nonzero
         % STACK: -127+42j
  J      %   Push j (imaginary unit)
         %   STACK: -127+42j, j
  GJq*   %   Push input multiplied by -1+j. This adds 3*pi/4 to the phase of the input
         %   STACK: -127+42j, j, 85-169i
  X/     %   Phase of complex number
         %   STACK: -127+42j, j, -1.10478465600433
  EYP/   %   Divide by pi/2
         %   STACK: -127+42j, j, -0.703327756220671
  k      %   Round towards minus infinity
         %   STACK: -127+42j, j, -1
  ^      %   Power
         %   STACK: -127+42j, -j
  +      %   Add
         %   STACK: -127+41j
         % Implicit end
         % Implicit display

3

Ruby、51バイト

原形

->x,y{d=x*x-y*y
[x+(d>0?0:-y<=>x),y+(d<0?0:x<=>y)]}

Xnorのコメントごとの代替フォーム

->x,y{[x+(x*x>y*y ?0:-y<=>x),y+(x*x<y*y ?0:x<=>y)]}

私の他の答えと同じタイプの不等式を使用しますが、方法は異なります。

テストプログラムで

f=->x,y{d=x*x-y*y
[x+(d>0?0:-y<=>x), #if y.abs>=x.abs: x+=1 if -y>x, x-=1 if -y<x 
y+(d<0?0:x<=>y)]}  #if x.abs>=y.abs: y+=1 if  x>y, y-=1 if  x<y

p f[0, 0]       # (0, 0)
p f[1, 0]       # (1, 1)
p f[1, 1]       # (0, 1)
p f[0, 1]       # (-1, 1)
p f[-1, 1]      # (-1, 0)
puts
p f[-1, 0]      # (-1, -1)
p f[-1, -1]     # (0, -1)
p f[0, -1]      # (1, -1)
p f[1, -1]      # (1, 0)
p f[95, -12]    # (95, -11)
p f[127, 127]   # (126, 127)
puts
p f[-2, 101]    # (-3, 101)
p f[-65, 65]    # (-65, 64)
p f[-127, 42]   # (-127, 41)
p f[-9, -9]     # (-8, -9)
p f[126, -12]   # (127, -127)
p f[105, -105]  # (105, -104)

あるd割り当ての価値は?ただ比較できるように見えますx*x>y*y
-xnor

残念ながら、Rubyには@Xnorの間にスペースが必要なのでy*y?その長さはまったく同じです。あなたのやり方はいくつかの点できちんと考えているので、私はそれを含めました。Rubyはそれをy?正当な関数名として渡すことを試みていると思います。
レベルリバーセント

3

ジュリア、38 34バイト

!z=z==0?0:z+im^int(2angle(z)/pi+1)

デニスは4バイトを節約しました。ありがとう!

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


ジュリアのさまざまなバージョン間でintの動作を混同したように見えます(私の防御では、非常に一貫性がありません)。Julia 0.4(TIOのバージョン)は半分に丸めますので、これはそのままでは機能しません。Julia 0.3ではint(2angle(z)/pi+5)、同じバイトカウントに使用できます(負の累乗は何らかの理由でエラーを引き起こします)。
デニス

また、!z=z+(z!=0)im^...すべてのバージョンで1バイトを保存できます。
デニス

2

C ++、94バイト

#define a(x) (x>0?x:-(x))
#define f(x,y) y>a(x-.5)?x--:-y>a(x+.5)?x++:x>a(y+.5)?y++:x|y?y--:x;

ゴルフをしていない:

#define a(x) (x>0?x:-(x))  //shorter than std::abs from <cmath>
#define f(x,y) 
    y>a(x-.5)?      // shift absolute value function by 0.5 to the right to get upper fourth
        x--:
        -y>a(x+.5)? //same for lower fourth
            x++:
            x>a(y+.5)? //same for right fourth
                y++:
                x|y? //only left fourth and 0 are left
                    y--:
                    x; //can't be empty, just does nothing

使用法:

#include <iostream>
void test(int x, int y, int rx, int ry){
    std::cout << "(" << x << ", " << y << ")=>";
    f(x,y);
    std::cout << "(" << x << ", " << y << ") - " << ((x==rx&&y==ry)?"OK":"FAILURE") << std::endl;
}

//Using the test cases from the question
int main() {
    test(0, 0, 0, 0);
    test(1, 0, 1, 1);
    test(1, 1, 0, 1);
    test(0, 1, -1, 1);
    test(-1, 1, -1, 0);
    test(-1, 0, -1, -1);
    test(-1, -1, 0, -1);
    test(0, -1, 1, -1);
    test(1, -1, 1, 0);
    test(95, -12, 95, -11);
    test(127, 127, 126, 127);
    test(-2, 101, -3, 101);
    test(-65, 65, -65, 64);
    test(-127, 42, -127, 41);
    test(-9, -9, -8, -9);
    test(126, -127, 127, -127);
    test(105, -105, 105, -104);

    return 0;
}

オンラインで試す


それ(x>0?x:-(x))ができると確信している(x>0?x:-x)
Yytsi

残念ながら、トークンxはたとえば-x + .5を取得するx + .5に置き換えられるため、そうではありません。
アネダー

わかった。括弧なしの否定が記号を反転させるという考え方がありました:D
Yytsi

厳密に言えば、C プリプロセッサを使用しました(これは
明らか

2

R、 131110バイト

2つの整数x,yを入力として受け取り、出力をstdoutに書き込む関数。解決策は@Dennisの制御フロースキームに従いますが、おそらくゴルフが可能です。

編集:@JDLの提案に基づいてコードを更新し、大量のバイトを保存しました。

function(x,y){X=sign(x+y);Y=sign(y-x);if(!X|!Y){x=x-X;y=y-Y}else if(X==Y&X&Y)x=x-X else if(X-Y&X)y=y-Y;c(x,y)}

非ゴルフ

f=function(x,y){
    X=sign(x+y)                 # calculate sign 
    Y=sign(y-x)                 #  =||=
    if(!X|!Y){x=x-X;y=y-Y}      # if at least one is 0: subtract sign
    else if(X==Y&X&Y)x=x-X      # if signs are equal and non-zero: add sign to x
    else if(X-Y&X)y=y-Y         # if signs are not equal and non-zero: add sign to y
    c(x,y)                      # print to stdout
}

1
いくつかの論理条件は短縮できると思います:as.logical(-1)is TRUE、soにX==0|Y==0なることができ!X|!Y、条件if(X!=Y...)はになることができif(X-Y)ます。また、場合X==YX!=0、その後はY!=0冗長です。実際、すべての!=0部品は冗長です。if(X!=0)はと同等if(X)です。
JDL

1
また、「I / O形式はかなり柔軟である」ことを考えると、のc(x,y)代わりに暗黙的に出力するのはおそらく公正なゲームですcat(x,y)
JDL

@JDLこれらは、私が考えたことのない非常に便利なゴルフのヒントです。答えを更新しました。
ビリーウォブ

2

JavaScript(ES6)、57バイト(55–63†)

[x、y]配列を受け入れ、インプレースで変更し、それを返します。

c=>([x,y]=c,i=x>y|x==y&x<0,c[i^x<-y|x==-y]-=-i|!!(x|y),c)

使い方

c=>(

これは、return-freeの簡潔な本体を持つ単一パラメーターの矢印関数です。

[x,y]=c

パラメータはすぐにxand y変数に分解されます。

,

コンマ演算子は、最後の結果を使用して、複数の式を1つに結合します。

i=x>y|x==y&x<0

i増分と減分のケースを区別するために使用されます。ときxよりも大きい場合y、我々は(一次元で事前に底部または右象限、および必要性のいずれかであるi=1ブール・ツー・ナンバー強制で)。同様に、x = yの対角線の負の部分にいるとき。起点を含む他のすべての場合、増分は不要です(i=0)。

c[i^x<-y|x==-y]

どの配列インデックスを調整するかを制御するために、やや似た式を使用します。我々は増分ではなく、左または下の象限内(または私たちがされたときている場合ではない増分と左または下)、次いで、ビットごとのXORを生成するであろう1と我々が調整され、Y値。同様に、分割x = -y対角線(原点を含む)の場合も同様です。それ以外の場合、インデックスは0x)になります。

-=-i|!!(x|y)

iisの場合1、指定された値に追加します。ときi0、我々は値から1を差し引きます場合にのみ、私たちは原点ではありません。後者はx|y、非ゼロを生成することで検出され、ブール強制により{0、1}にクリップされiます。また、否定により、論理ではなくビット単位のORを使用できます(ゼロビット-1がないため、変更しても安全です)。

c

配列は最後なので、返されます。

テスト中

†バリエーション

意味のある戻り値をスキップし、入力ミューテーションのみを使用すること、さらに2バイトを節約できます。

c=>([x,y]=c,i=x>y|x==y&x<0,c[i^x<-y|x==-y]-=-i|!!(x|y))

…または、入力ミューテーションをスキップして、6バイトのコストで純粋な関数のすべての変数をローカルにすることができます。

([x,y],i=x>y|x==y&x<0,c=[x,y])=>(c[i^x<-y|x==-y]-=-i|!!(x|y),c)

1

JavaScript(ES6)、80 76バイト

(x,y,s=Math.max(x,y,-x,-y))=>(s?x+s?y-s?x-s?x++:y++:x--:y+s?y--:x++:0,[x,y])

1

Haskell、53バイト

0%0=(0,0)
x%y|y>=0-x,y<x=(x,y+1)|(p,q)<-(-y)%x=(q,-p)

2つの数値を受け取り、タプルを出力します。ポイントが東部セクション-x<=y<xにある場合、2番目の座標を1増やします。それ以外の場合は、入力ポイントを90度回転し、その関数を呼び出してから回転して、象限を循環させます。


1

ラケット191バイト

(cond[(= 0 x y)(list x y)][(= x y)(if(> x 0)(list(sub1 x)y)(list(add1 x)y))][(> x y)(if(>= x(abs y))
(list x(add1 y))(list(add1 x)y))][(< x y)(if(> y(abs x))(list(sub1 x)y)(list x(sub1 y)))])

Ungolfed(中間式を使用せずに図の方向をコードに直接変換する):

(define(f x y)
  (cond
    [(= 0 x y) (list x y)]
    [(= x y)
     (if (> x 0)
         (list (sub1 x) y)   ; left
         (list (add1 x) y))] ; right
    [(> x y)
     (if (>= x (abs y))
         (list x (add1 y))   ; up
         (list (add1 x) y))] ; right
    [(< x y)
     (if (> y (abs x))
         (list (sub1 x) y)   ; left
         (list x (sub1 y)))] ; down
    ))

テスト:

(f 0  0)      
(f 1  0)     
(f 1  1)     
(f 0  1)     
(f -1  1)    
(f -1  0)    
(f -1  -1)   
(f 0  -1)    
(f 1  -1)    
(f 95  -12)  
(f 127  127) 
(f -2  101)  
(f -65  65)  
(f -127  42) 
(f -9  -9)    
(f 126  -127) 
(f 105  -105) 

出力:

'(0 0)
'(1 1)
'(0 1)
'(-1 1)
'(-1 0)
'(-1 -1)
'(0 -1)
'(1 -1)
'(1 0)
'(95 -11)
'(126 127)
'(-3 101)
'(-65 64)
'(-127 41)
'(-8 -9)
'(127 -127)
'(105 -104)

1

実は、16バイト

これは、入力として複素数を取り、別の複素数を出力します。ゴルフの提案を歓迎します!オンラインでお試しください!

;`₧╦@/τuLïⁿ+0`╬X

アンゴルフ

         Implicit input z.
;        Duplicate z.
`...`╬   If z is non-zero (any a+bi except 0+0j), run the following function.
           Stack: z, z
  ₧        Get phase(z).
  ╦@/      Divide phase(z) by pi.
  τuL      Push floor(2*phase(z)/pi + 1).
  ïⁿ       Push 1j ** floor(2*phase(z)/pi + 1).
  +        And add it to z. This is our rotated z.
  0        Push 0 to end the function.
X        Discard either the duplicate (0+0j) or the 0 from the end of function.
         Implicit return.

0

Scala、184バイト

val s=math.signum _
(x:Int,y:Int)=>{val m=x.abs max y.abs
if(x.abs==y.abs)if(s(x)==s(y))(x-s(x),y)else(x,y-s(y))else
if(x.abs==m)(x,y+Seq(0,x).indexOf(m))else(x-Seq(0,y).indexOf(m),y)}

ゴルフをしていない:

import math._

(x: Int, y: Int) => {
  val max = max(x.abs, y.abs)
  if (x.abs == y.abs)
    if (signum(x) == signum(y))
      (x - signum(x), y)
    else
      (x, y - signum(y))
  else
    if (x.abs == max)
      (x, y + Seq(0, x).indexOf(max))
    else
      (x - Seq(0, y).indexOf(max), y)
}

説明:

val s=math.signum _             //define s as an alias to math.signum
(x:Int,y:Int)=>{                //define an anonymous function
  val m=x.abs max y.abs           //calculate the maximum of the absolute values,
                                  //which is 1 for the innermost circle and so on.
  if(x.abs==y.abs)                //if we have a cell at a corner of a circle
    if(s(x)==s(y))                  //if it's at the top-left or bottom-right, we need to
                                    //modify the x value
      (x-s(x),y)                      //if x is positive (bottom-right),
                                      //we need to return (x+1,y),
                                      //(x-1,y) If it's at the top-left.
                                      //This can be simplified to (x-s(x),y)
    else                            //for top-right and bottom-left, 
      (x,y-s(y))                      //modify y in the same way.
  else                            //we don't have a corner piece
    if(x.abs==m)                    //if we're at the left or right edge of the square
      (x,y+Seq(0,x).indexOf(m))       //if it's a piece from the right edge, add one
                                      //to y, else subtract 1
    else                            //it's a piece from the top or bottm edge
      (x-Seq(0,y).indexOf(m),y)       //subtract 1 from x if it's from the top edge,
                                      //else subtract -1
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.