非負のものから整数のペアを生成します


25

N入力として負でない整数を取り、2つの整数(負、ゼロまたは正)Xおよびを出力または返すプログラムまたは関数を作成する必要がありYます。

整数は無限に多く存在するため、数学的な意味で使用されます。

実装された関数は全単射でなければなりません。これは、毎回N異なるX Yペアを出力しX Yなければならないことを意味し、すべてのペアはいくつかの入力に対してN出力される必要がありますN

                 ...
    ┌─────┬─────┬────┬────┬────┐
    │-2 -2│-2 -1│-2 0│-2 1│-2 2│
    ├─────┼─────┼────┼────┼────┤
    │-1 -2│-1 -1│-1 0│-1 1│-1 2│
    ├─────┼─────┼────┼────┼────┤
... │0 -2 │0 -1 │0 0 │0 1 │0 2 │ ...
    ├─────┼─────┼────┼────┼────┤
    │1 -2 │1 -1 │1 0 │1 1 │1 2 │
    ├─────┼─────┼────┼────┼────┤
    │2 -2 │2 -1 │2 0 │2 1 │2 2 │
    └─────┴─────┴────┴────┴────┘
                 ...

U VV Uは異なるペアであることに注意してくださいU!=V

詳細

  • 言語が任意の大きな整数をサポートしていない場合は問題ありませんが、アルゴリズムは任意の大きな整数のデータ型で動作するはずです。コードは少なくともの入力値を引き続きサポートする必要があります2^31-1
  • 出力を文字列として印刷または返すことを選択した場合、先頭の0'や+記号は使用できません。それ以外の場合、言語の標準整数表現は問題ありません。

場合は、タスクは非負の整数取っ全単射関数を作ることになりN、出力1の整数X関数であることができるソリューションを

if (input mod 2 == 0) return N/2 else return -(N+1)/2

いくつかの言語で実装されています。この関数はX = 0 -1 1 -2 2...を返しますN = 0 1 2 3 4...


出力内の任意の整数を異なる入力に対して繰り返すことはできますか?たとえば10=>11 12, 9=>10 11、11が繰り返されるため、これは無効ですか?
BrainSteel

1
「全単射」が定義されている限り、「11 12」は「10 11」と同じではなく、したがって有効です。これは、全単射関数が「1つのセットのすべての要素が他のセットの1つの要素とペアになり、他のセットのすべての要素が最初のセットの1つの要素とペアになる関数」として定義されるためですペアになっていない要素。」(en.wikipedia.org/wiki/Bijection)。関数を逆にすると、「11 12」は10を出力し、「10 11」は9を出力します
。– GiantTree

@BrainSteelあなたの例は有効です。(順序付けられた)ペアのみを繰り返すことはできません。GiantTreeは正しいです。質問にさらに説明を追加しました。
-randomra

与えられた言語の整数範囲内の全単射でなければなりませんか、それともすべての整数で動作するはずですか
-flawr

1
@LegionMammalにはタスクの数学的な説明がありました:「全単射関数$ f:N +→Z ^ 2 $を定義する必要があります。– LegionMammal978。」声明のどこかで有益だと思う
ブライアンJ

回答:


15

Pyth、15

u,-HyeGhGjQ2,ZZ

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

u             reduce
                lambda G,H:    [implicit]
  ,-HyeGhG         (H-2*G[-1],G[0])
  jQ2           base(input(),2)
  ,ZZ           (0,0)
              print result     [implicit]

Pythonの翻訳:

g=lambda Z,n:(n-2*Z[1],Z[0])
print reduce(g,binlist(input()),(0,0))

または反復的に:

(x,y)=(0,0)
for b in binlist(input()):
    (x,y)=(b-2*y,x)
print (x,y)

where binlistは、数値をのような数字のリストに変換しbinlist(4) = [1,0,0]ます。

それで、これはどのように機能しますか?私のPythonソリューションのように、数値 2進数を、ベースの負の2の2つのインターリーブされた数値として解釈しますn

2進数はペアx y = b 02 b 2 + 4 b 48 b 6 + b 12 b 3 + 4 b 58 b 7 +

n=b5b4b3b2b1b0
バツy=b02b2+4b48b6+b12b3+4b58b7+

nの最後の桁をまだ処理していない場合、ペアx y ′に対応する$ 1 $、n = b 5 b 4 b 3 b 2 b 1だけ高いすべてのインデックスがあります= b 12 b 3 + 4 b 58 b 7 + b 22 b 4b0n

n=b5b4b3b2b1
バツy=b12b3+4b58b7+b22b4+4b68b8+

が古い値で読み取られると、新しい値を表現できますb0

バツy=b02yバツ

バツyb2yバツbnバツy


MathJaxサポートが無効になっていることに注意してください。説明を読みやすくするために、編集を検討することをお勧めします。
アレックスA.

32

CJam、24 22 21バイト

私の脳は、他のソリューションが使用している数学を理解するのに苦労しています。しかし、私の脳はバイナリを確実に理解しているので、ビット操作に基づいた魂動がここにあります!

li4b2fmd2/z{)(\2b^}%p

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

説明

このアプローチは、入力を各出力番号に1つずつ、2つのインターリーブされたバイナリ値として扱います。それぞれの最下位ビットを除くすべてがマグニチュードをエンコードし、最下位ビットはこのマグニチュードのビット単位の補数を取るかどうかを示します。この実装では、奇数番目のビットは最初の出力番号に対応し(偶数番目のビットは2番目に対応)0、補数を取る信号のLSBに対応します。

例えば、入力が与えられ73、そのバイナリ表現uninterleaving、1001001b生成0 1|0(奇数配置ビット)及び1 0 0|1(偶数配置ビット)。最初の値はの大きさで01b = 1あり、最終値に対して補完する必要が~1 = -2あり、2番目の値は大きさで100b = 4あり、補完するべきではありません。

正確さの非公式なデモンストレーション

2Dグリッドの出力位置に、ゼロからユーザー指定の数値から1を引いた値までの各入力を配置するテストプログラムを作成しました。オンラインで試すこともできます。アルゴリズムのマッピング方法を示すこのプログラムの出力は次の0-99とおりです。

      -8 -7 -6 -5 -4 -3 -2 -1  0  1  2  3  4  5  6  7  8

-8                      92 84 86 94                     
-7                      88 80 82 90                     
-6                      76 68 70 78                     
-5                   96 72 64 66 74 98                  
-4                60 52 28 20 22 30 54 62               
-3                56 48 24 16 18 26 50 58               
-2                44 36 12  4  6 14 38 46               
-1                40 32  8  0  2 10 34 42               
 0                41 33  9  1  3 11 35 43               
 1                45 37 13  5  7 15 39 47               
 2                57 49 25 17 19 27 51 59               
 3                61 53 29 21 23 31 55 63               
 4                   97 73 65 67 75 99                  
 5                      77 69 71 79                     
 6                      89 81 83 91                     
 7                      93 85 87 95                     
 8                                                      

塗りつぶしパターンは少し奇妙に見えますが、実際には全単射です!連続する4のべき乗ごとに、前の辺の長さの2倍の正方形を埋めます。たとえば、アルゴリズムのマッピング方法は0-15次のとおりです。

      -2 -1  0  1  2

-2    12  4  6 14   
-1     8  0  2 10   
 0     9  1  3 11   
 1    13  5  7 15   
 2                  

これにより、次の8x8正方形の中央に4x4正方形が作成され0-63ます。

      -4 -3 -2 -1  0  1  2  3  4

-4    60 52 28 20 22 30 54 62   
-3    56 48 24 16 18 26 50 58   
-2    44 36 12  4  6 14 38 46   
-1    40 32  8  0  2 10 34 42   
 0    41 33  9  1  3 11 35 43   
 1    45 37 13  5  7 15 39 47   
 2    57 49 25 17 19 27 51 59   
 3    61 53 29 21 23 31 55 63   
 4                              

次の16x16正方形の中央に8x8正方形を構成し0-255ます。

         -8  -7  -6  -5  -4  -3  -2  -1   0   1   2   3   4   5   6   7   8

 -8     252 244 220 212 124 116  92  84  86  94 118 126 214 222 246 254    
 -7     248 240 216 208 120 112  88  80  82  90 114 122 210 218 242 250    
 -6     236 228 204 196 108 100  76  68  70  78 102 110 198 206 230 238    
 -5     232 224 200 192 104  96  72  64  66  74  98 106 194 202 226 234    
 -4     188 180 156 148  60  52  28  20  22  30  54  62 150 158 182 190    
 -3     184 176 152 144  56  48  24  16  18  26  50  58 146 154 178 186    
 -2     172 164 140 132  44  36  12   4   6  14  38  46 134 142 166 174    
 -1     168 160 136 128  40  32   8   0   2  10  34  42 130 138 162 170    
  0     169 161 137 129  41  33   9   1   3  11  35  43 131 139 163 171    
  1     173 165 141 133  45  37  13   5   7  15  39  47 135 143 167 175    
  2     185 177 153 145  57  49  25  17  19  27  51  59 147 155 179 187    
  3     189 181 157 149  61  53  29  21  23  31  55  63 151 159 183 191    
  4     233 225 201 193 105  97  73  65  67  75  99 107 195 203 227 235    
  5     237 229 205 197 109 101  77  69  71  79 103 111 199 207 231 239    
  6     249 241 217 209 121 113  89  81  83  91 115 123 211 219 243 251    
  7     253 245 221 213 125 117  93  85  87  95 119 127 215 223 247 255    
  8                                                                        

3
非常に賢い!のli4b2fmd2/代わりにを使用して2バイトを保存できます0li2b+W%2/W%。これにより、同じ整数が得られますが、順序は逆になります。
デニス

@デニスそれも非常に賢いです。そのトリックを使用するように回答を更新しました。ありがとう!
Runer112

12

Python 2、49

編集:ベース-2のより良い1ステップの再帰を使用して49に改善

def f(n):x,y=n and f(n/2)or(0,0);return n%2-2*y,x

これはを使用したPythバージョンreduceです。

編集:バランスのとれた三元からベース-2に切り替えることにより、52に改善されました。

Python 2、52

h=lambda n:n and n%2-2*h(n/4)
lambda n:(h(n),h(n/2))

Python 2、54

h=lambda n:n and-~n%3-1+3*h(n/9)
lambda n:(h(n),h(n/3))

これは、Runer112のソリューションのような数字インターリーブを使用しますが、符号付きバイナリではなくバランスの取れた3進数を使用します。Pythonにはベース変換が組み込まれていないため、コードはそれを再帰的に実装します。

ヘルパー関数h(の3代わりに9)は自然数を取り、それを3進数からバランスの取れた3進数に数字置換で変換します

0 -> 0 
1 -> +1
2 -> -1

したがって、たとえば、ベースで201である19は、バランスのとれた3進数で(-1)(0)(+ 1)、つまり(-1)* 3 ^ 2 +(0)* 3 ^ 1 +(+ 1)* 3 ^ 0 = -8。

バランスの取れた3進法は、すべての整数をエンコードするのに十分であるため、自然数から整数へのマッピングを提供します。

整数のペアにマッピングするには、数字をでインターリーブしますn。そうするために、再帰的なステップとしてではなく、h1桁おきに見ていきます。次に、1つの座標について、でフロア分割してシフトします。n/9n/3n3

以下は、領域[-4,4] ^ 2をカバーする最初の81個の出力です。

0 (0, 0)
1 (1, 0)
2 (-1, 0)
3 (0, 1)
4 (1, 1)
5 (-1, 1)
6 (0, -1)
7 (1, -1)
8 (-1, -1)
9 (3, 0)
10 (4, 0)
11 (2, 0)
12 (3, 1)
13 (4, 1)
14 (2, 1)
15 (3, -1)
16 (4, -1)
17 (2, -1)
18 (-3, 0)
19 (-2, 0)
20 (-4, 0)
21 (-3, 1)
22 (-2, 1)
23 (-4, 1)
24 (-3, -1)
25 (-2, -1)
26 (-4, -1)
27 (0, 3)
28 (1, 3)
29 (-1, 3)
30 (0, 4)
31 (1, 4)
32 (-1, 4)
33 (0, 2)
34 (1, 2)
35 (-1, 2)
36 (3, 3)
37 (4, 3)
38 (2, 3)
39 (3, 4)
40 (4, 4)
41 (2, 4)
42 (3, 2)
43 (4, 2)
44 (2, 2)
45 (-3, 3)
46 (-2, 3)
47 (-4, 3)
48 (-3, 4)
49 (-2, 4)
50 (-4, 4)
51 (-3, 2)
52 (-2, 2)
53 (-4, 2)
54 (0, -3)
55 (1, -3)
56 (-1, -3)
57 (0, -2)
58 (1, -2)
59 (-1, -2)
60 (0, -4)
61 (1, -4)
62 (-1, -4)
63 (3, -3)
64 (4, -3)
65 (2, -3)
66 (3, -2)
67 (4, -2)
68 (2, -2)
69 (3, -4)
70 (4, -4)
71 (2, -4)
72 (-3, -3)
73 (-2, -3)
74 (-4, -3)
75 (-3, -2)
76 (-2, -2)
77 (-4, -2)
78 (-3, -4)
79 (-2, -4)
80 (-4, -4)

非常にきれいですが、クォーターイマジナリーを使用した代替コーディングは長くなりました。

Python 2、63

h=lambda n:n and n%4+2j*h(n/4)
lambda n:(h(n).real,h(n).imag/2)

複雑な変換を扱いにくい言語では、おそらくこれがより良いアプローチでしょう。複素数を出力できれば、次のことができます。

Python 2、38

f=lambda n:n and n%2+n/2%2*1j-2*f(n/4)

1
元のベース-2関数は、平均的なPyth回答を作成します。L&b-%b2*2y/b4,yQy/Q2長さはわずか20バイトです。
デニス

4
@Dennis 15文字のPythソリューションを書きました。
xnor

バランスの取れた三項および四分の一想像。私のお気に入りの拠点の2つ。Base-eのみが続きます。
ブライアンミントン

11

Python 2、98バイト

簡単なアプローチから始めましょう。

def f(N):
 x=a=0;b=2
 while N:x+=1j**b;b+=a<1;a=a or b/2;N-=1;a-=1
 return int(x.real),int(x.imag)

N原点から始まり、2Dグリッド上に長い長方形のスパイラルユニットを形成し、最後のポイントの座標を返します。

関数は全単射です:

  • 十分な長さのスパイラルがあれば、各ポイントをカバーできます
  • 各ポイントは、スパイラルと1回だけ交差します

スパイラルは次のようになります(1からではなく0から始まることを除く)。

ウラムスパイラル


@AlexA。0**0 == 1Pythonで、それはちょうど同じですif a == 0: a = b/2
-grc

クール、説明してくれてありがとう。
アレックスA.

@AlexA。a=a or b/2短いことが判明
-grc

0^0=1pythonだけでなく、すべての数学の@grc 。
デニス

1
@Daenyth 0**0は実際には数学では不定形です
-Sp3000

8

dc、49

[1+2~2*1-*n]sm?dsa8*1+v1-2/dd1+*2/lar-dlmx32P-lmx

これは、グリッド上の負でない整数を次のように配置することから始まります。

..| 
4 | 14
3 |  9 13
2 |  5  8 12
1 |  2  4  7 11
0 |  0  1  3  6 10
Y +-----------------
  X  0  1  2  3  4 ...

グリッド位置が対角線方向にNを大きくしていく方法に注意してください。Y= 0の行には、で与えられる三角の数列が含まれていることに注意してくださいN = X(X+1)/2。これは、+ veの根だけを使用して通常の式を使用して解く2次方程式であるため、Y = 0のときにNからXを決定できます。次は、Nごとに一意の{X、Y}を与える簡単な算術シャッフルです。

これは必要な全単射品質を提供しますが、XとYは負でないだけですが、質問にはすべての整数が必要です。したがって、XとYは((t+1)/2)*((t+1)~2*2-1)可能なすべての整数します。

dc 任意の精度の数値があるため、入力範囲は 2^31-1は問題ありません。また、デフォルトの精度は10進数の0桁であり、ここで必要な動作であるsqrt()およびを切り捨て/ます。

出力:

$ for i in {0..10}; do dc biject.dc <<< $i; echo; done
0 0
0 -1
-1 0
0 1
-1 -1
1 0
0 -2
-1 1
1 -1
-2 0
0 2
$

5

Matlab、54バイト

n=input('')+1;[i,j]=find(spiral(2*n)==n);disp([i,j]-n)

ここで重要なのはspiral、これにより任意のサイズのスパイラルマトリックスが作成されることです。

spiral(3)

返す

ans =

 7     8     9
 6     1     2
 5     4     3

spiral4n2n104n1052.91011n=232


2

Haskell、78 74バイト

(concat[[(x,i-x),(x,x-1-i),(-1-x,x-1-i),(-1-x,i-x)]|i<-[0..],x<-[0..i]]!!)

試運転:

*Main> mapM_ (print . (concat[[(x,i-x),(x,x-1-i),(-1-x,x-1-i),(-1-x,i-x)]|i<-[0..],x<-[0..i]]!!) ) [0..20]
(0,0)
(0,-1)
(-1,-1)
(-1,0)
(0,1)
(0,-2)
(-1,-2)
(-1,1)
(1,0)
(1,-1)
(-2,-1)
(-2,0)
(0,2)
(0,-3)
(-1,-3)
(-1,2)
(1,1)
(1,-2)
(-2,-2)
(-2,1)
(2,0)

仕組み:最初の象限のすべてのペアを次の順序でリストします

  |
 2| #4
  |
 1| #2  #5
  | 
 0| #1  #3  #6
  +---------------
     0   1   2   3 

各ポイントを他の象限にミラーリングして、4つの要素リストのリストを作成します。すべてを1つのリストに連結し、nth要素を取得します。

編集:関数は名前を必要とせず、数学を並べ替えました。式。


do-notation を使用して4バイト節約できます:オンラインで試してください!
13:07に

1

Haskell、50バイト

(0!).succ
l!n=(last$(!).succ:[(,)|odd n])l$div n 2

オンラインそれを試してみてくださいまたはその逆でそれを試してみてください!

非ゴルフ

ntoN2 n = 0 ! (n + 1)

xCounter ! remainingNum
  | odd remainingNum = (xCounter, div remainingNum 2)
  | otherwise        = (xCounter + 1) ! div remainingNum 2

説明

バツyN22バツ2y+11N(!)バツlxCounteryます。

実際の関数fntoN2)は、プロシージャを開始する前に入力をインクリメントすることに注意してください。


1

05AB1E、35バイト

>©DÝʒo®sÖ}àsÅÉʒ®sÖ}à<2÷‚εDÈi2÷ë>2÷(

オンラインでお試しください!またはテストスイートとして

説明

検討する

fNN×Nnバツy
バツ2バツn+12y+1n+1ff1バツy=2バツ2y+11

gN×NZ×Zmnhmhn
hNZn{n2n でもn+12n 奇妙な
fghgfNZ×Z

gf

>©DÝʒo®sÖ}àsÅÉʒ®sÖ}à<2÷‚εDÈi2÷ë>2÷( # Full program

                                    # Implicit input: Integer n
>©                                  # Compute n+1 and save it to the register
  DÝ                                # Duplicate n+1 and push the list [0,...,n+1]
    ʒo®sÖ}                          # Only keep those numbers x so that 2^x divides n+1
          à                         # Get maximum element in the list.
           sÅÉ                      # Swap so that n+1 is on top and push [1,3,5,...,n+1]
              ʒ®sÖ}                 # Only keep those numbers z which divides n+1
                   à<2÷             # Compute y = (z-1)/2
                       ‚            # Push the pair [x,y]
                        ε           # Apply the function h to x (and y):
                           i        # if...
                         DÈ         # x is even
                            2÷      # then compute x/2
                              ë>2÷( # else compute -(x+1)/2
                                    # Implicit output: [h(x),h(y)]

うわー、素敵な説明に賛成。しかし、確かに05AB1EはPythを打ち負かすことができますか?
ASCIIのみ

gf

0

Mathematica、46

SortBy[Tuples[Range[2#]-#,2],Norm][[#]]&[#+1]&

ベクトルを標準に並べ替えてから、n1番目のベクトルを取ります。


0

JavaScript、166 168バイト/文字

他の人が使用しているような長方形のスパイラルを使用する新しいアプローチ。

function f(n){return b=Math,k=b.ceil((b.sqrt(n)-1)/2),t=2*k+1,m=b.pow(t,2),t+=4,m-t>n?(m-=t,m-t>n?(m-=t,m-t>n?[k,k-(m-n-t)]:[-k+(m-n),k]):[-k,-k+(m-n)]):[k-(m-n),-k]}

この回答をMath.SEで使用し、JSに翻訳してUglifyJS を使用し圧縮しました

このアプローチでは、ループを使用せず、スパイラルを作成しません。

fN0Z2

更新:に 保存して2文字を保存しMathましたb

t-=1t+=4f0=f8N00


1)まったく同じ質問を再投稿しても、実際には役に立ちません。2)別の回答をコピーしてから、ゴルフにミニファイターを使用することもできません:)
オプティマイザー

少なくとも、質問で述べられているすべての規則に従い、それは別のアプローチです。また、私は他の人の作品を盗んではいませんが、この答えをどのようにしたかについて言及しています。
ジャイアントツリー

@Optimizer:1)GiantTreeは、元の無効なアプローチに対して3(値する)ダウン票を得たため、再投稿することを提案しました。2)Math.SEから取得したコードはJavaScriptでもないため、ミニファイターでコピーするだけではありません。
デニス

@Dennisの人々は、自分の投票権を撤回することができます。また、コードを最小化するためにミニファイヤを使用することは、実際には推奨されていません。
オプティマイザー

@Optimizer私はコードをゴルフしようとしましたが、コンプレッサーを使用するとより良い結果(より少ない文字)が得られたので、代わりにそれを使用しました。
ジャイアントツリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.