ガウスからアイゼンシュタイン


18

整数ガウスを与え+ bはIここで、bは整数であり、iは= EXPをπ I / 2 虚数単位であり、(ユークリッド距離にWRT)最も近いを返すアイゼンシュタイン整数K + L ω KLはです整数およびω = EXP 2 π I / 3 = - 1 + I a+biab=expπ/2k+lωklω=exp(2πi/3)=(1+i3)/2

バックグラウンド

すべてのガウス整数は一意のように書くことができることを、おそらく非常に明白である+ B Iと、Bの整数。それはとても明らかそれでも真ではない:任意アイゼンシュタイン整数を一意のように書くことができるK + L個のωKL個の整数。それらは両方とも複素数内でZモジュールを形成し、両方ともそれぞれp = 2または3のp番目のサイクロトミック整数です。なお、3 + 2 I 3 + 2 ωa+biabk+lωklZp=233+2i3+2ω

ソース:commons.wikimedia.org

詳細

  • 指定された複素数に2つまたは3つの最も近い点がある場合、それらのいずれかを返すことができます。

  • 複素数は、直交座標(basis (1,i))で与えられますが、(A,B)or A+BiA+B*1jetcなどの便利な形式ではありません。

  • Eisenstein整数は、基底(1,ω座標として返される(K,L)必要がありますが、or K+LωまたはK+L*1ωetcなどの便利な形式ではありません。

すべての実数の整数は、明らかに実数の整数に再びマッピングされる必要があります。

  6,14 -> 14,16
  7,16 -> 16,18
-18,-2 ->-19,-2
 -2, 2 -> -1, 2
 -1, 3 -> 1, 4




aとbの符号が反対の場合もテストケースを含める必要があります。
SmileAndNod

@SmileAndNodが追加しました。しかし、一つはまた、単に実軸に関して対称性を利用し、ちょうど置き換えることができ(1,w)(-1,1+w)。また、これらのケースに適切な結果を提供するだけでは不十分であることを明確にするために、このセクションの名前をに変更しました。
-flawr

回答:


7

APL(Dyalog Extended)、16バイトSBCS

0+⌈3÷⍨1 2×⌊⎕×√3

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

かかるフルプログラムy次いで、x標準入力からと整数の2要素ベクトルを印刷します。

仕組み:数学

まず、ガウス整数はダイヤモンドの垂直対角線上に配置され、点Z(x,3y)整数x,y

      + W
     /|\
    / | \
   /  |  \
  /   + X \
 /    |    \
+-----|-----+V
 \    |    /
  \   + Y /
   \  |  /
    \ | /
     \|/
      + Z

図中、WZ¯=3及びWX¯=XY¯=YZ¯=XV¯=YV¯=13。したがって、点の垂直位置が与えられると、次のように最も近いアイゼンシュタイン点を特定できます。

Given a point PWZ¯,{PWX¯the nearest point is WPXY¯the nearest point is VPYZ¯the nearest point is Z

ガウスの点P与えられた場合、まず、Zx軸から離れているダイヤモンドの数(hで表される)によって測定される、どのダイヤモンドP属するかを決定します。hZバツ

h=Py÷3

次に、Zのアイゼンシュタイン座標は

ZバツE=Pバツ+hZyE=2h

今、我々は、セグメントのかを決定Wバツ¯バツY¯YZ¯ Pに属します。このため、次のようにインジケーターwを計算できます。

w=Py×33

w=012YZ¯バツY¯Wバツ¯PZVバツ

PEバツE=Pバツ+h+w2PEyE=2h+w

アイデンティティを使用して h そして w、さらに次のように簡略化できます。

y=Py×3PEバツE=Pバツ+y÷3PEyE=2y÷3

仕組み:コード

0+⌈3÷⍨1 2×⌊⎕×√3
           ⌊⎕×√3   Take the first input (P.y) and calculate y'
   ⌈3÷⍨1 2×       ⍝ Calculate [ceil(y'/3), ceil(2y'/3)]
⎕0+  ⍝ Take the second input(P.x) and calculate [P.x+ceil(y'/3), ceil(2y'/3)]

2

JavaScript(ES6)、112バイト

(a,b,l=b/Math.pow(.75,.5),k=a+l/2,f=Math.floor,x=k-(k=f(k)),y=l-(l=f(l)),z=x+y>1)=>[k+(y+y+z>x+1),l+(x+x+z>y+1)]

ES7は明らかに9バイトをトリムできます。説明:kそして、l最初はに対する浮動小数点ソリューションを表しk+ωl=a+ibます。ただし、座標はユークリッド距離で最も近い整数に丸める必要がありました。私はそのための床を取るkし、lそれらをインクリメントすることに近いポイントにつながるかどうかを判断するために小数部分にいくつかのテストを行い、その後、a+ib


小数部分のテストでは、xが常に.2887または0.577であり、yが常に.1547または.577であるという事実を利用していると思います
-SmileAndNod

@SmileAndNod 3年前?私は本当に思い出せませんが、それはそれほど複雑ではないと思います。ダイヤモンドの最も近い角であるところを探しています。
ニール

2

MATL39 38 35バイト

t|Ekt_w&:2Z^tl2jYP3/*Zeh*!sbw6#YkY)

入力形式は6 + 14*1j(スペースはオプションです)です。出力形式は14 16です。

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

説明

コードは最初に入力を複素数として受け取ります。次に、複雑な平面に十分な大きさの六角形のグリッドを生成し、入力に最も近い点を見つけ、そのアイゼンシュタインの「座標」を返します。

t         % Take input implicitly. This is the Gauss number, say A. Duplicate
|Ek       % Absolute value times two, rounded down
t_        % Duplicate and negate
w&:       % Range. This is one axis of Eisenstein coordinates. This will generate
          % the hexagonal grid big enough
2Z^       % Cartesian power with exponent 2. This gives 2-col 2D array, say B
t         % Duplicate
l         % Push 1
2jYP3/*   % Push 2*j*pi/3
Ze        % Exponential
h         % Concatenate. Gives [1, exp(2*j*pi/3)]
*         % Multiply by B, with broadcast.
!s        % Sum of each row. This is the hexagonal grid as a flattened array, say C
bw        % Bubble up, swap. Stack contains now, bottom to top: B, A, C
6#Yk      % Index of number in C that is closest to A
Y)        % Use as row index into B. Implicitly display

2

Haskell、128バイト

i=fromIntegral;r=[floor,ceiling];a!k=(i a-k)**2;c(a,b)|l<-2*i b/sqrt 3,k<-i a+l/2=snd$minimum[(x k!k+y l!l,(x k,y l))|x<-r,y<-r]

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

入力ガウス整数(a、b)の場合、それをアイゼンシュタイン座標、フロアおよびセルの両方のコンポーネントに変換して、最も近いアイゼンシュタイン整数の4つの候補を取得し、最小距離の1つを見つけて返します。


1

TCL124の 116 106バイト

{{a b f\ int(floor(2*$b/3**.5)) {l "[expr $f+(1-$f%2<($b-$f)*3**.5)]"}} {subst [expr $l+$a-($f+1)/2]\ $l}}

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

これは、@ Neilの3年前の投稿にやや影響を受けています

floor関数は、エッジがベクトル1および ω。この菱形に関して、ガウス整数は、上部(lが偶数の場合)または下部(lが奇数の場合)の垂直バイセクターにあります。これは、左下隅または右上隅のいずれかが許容可能なソリューションになることを意味するため、重要です。左下隅のkを計算し、1つのテストを実行して、ガウス整数が2つの隅を区切る対角線の上または下にあるかどうかを確認します。対角線の上にあるときにkに1を追加し、lについても同様にします。

「対角線dの右下隅と(a、b)を結ぶベクトルvの外積vxdの符号」を使用して、対角線のどちら側にあるかをテストすることにより、10バイトを節約しました。


1

バーレスク、24バイト

pe@3r@2././J2./x/.+CL)R_

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

これがもっと短くなることは確かです。入力として読み取りa b

pe      # Parse input to two ints
@3r@2./ # sqrt(3)/2
./      # Divide b by sqrt(3)/2
J2./    # Duplicate and divide by 2
x/.+    # swap stack around and add to a
CL      # Collect the stack to a list
)R_     # Round to ints

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