整数のペアを等しくする


51

これは、インターネット上の数学の問題Iの鋸どこかに触発されましたが、どこ覚えていない(UPDATE:元の問題がで発見された数学の謎のsubredditことが可能であることを提供する証拠と、も参照この数学SEポストを)、を求めると整数の任意のペアに対して次のプロセスが可能かどうかの証拠(私が覚えていることから、任意のペアに対して可能だった):

整数のペアjとkが与えられ、それらの1つを2倍にして、1つをもう1つに加算し、新しい整数のペア、つまり(j、k)->(j + 1、k * 2)または(j * 2、k + 1)。次に、整数のペアを等しくする目的で、これらの整数でこのプロセスを繰り返します。

これらの例は必ずしも最適ではありませんが、正、負、またはゼロの整数でこのプロセスを実行する方法を示しています。

(2, 5) -> (3, 10) -> (6, 11) -> (12, 12)

(5, 6) -> (6, 12) -> (7, 24) -> (14, 25) -> (28, 26) -> (56, 27) -> (112, 28) -> (113, 56) -> (226, 57) -> (227, 114) -> (228, 228)

(0, 2) -> (1, 4) -> (2, 5) -> (3, 10) -> (6, 11) -> (12, 12)

(-4, 0) -> (-3, 0) -> (-2, 0) -> (-1, 0) -> (0, 0)

(3, -1) -> (6, 0) -> (12, 1) -> (13, 2) -> (14, 4) -> (15, 8) -> (16, 16)

(-4, -3) -> (-8, -2) -> (-16, -1) -> (-32, 0) -> (-31, 0) -> ... -> (0, 0)

チャレンジ

2つの整数を指定したプログラムを作成し、一方を繰り返しインクリメントし、他方を倍増することにより、それらの整数を等しくするために必要なステップのリストを出力します

仕様書

  • 解決策は最適である必要はありませんが、任意のペアに対して有限数のステップで解決する必要があります
  • 入力は2つの整数でなければなりません

  • 出力は、各ステップの結果の整数を明確に示す合理的な出力である場合があります。例:

    • 2つの個別の区切り文字(任意の記号、空白など)を含む文字列。1つはペアの各整数に、もう1つは各ペアに
      • たとえば、入力j、k:2、5->出力:3,10; 6,11; 12,12
    • 整数のリストのリスト
      • 例:入力j、k:2、5->出力:[[3、10]、[6、11]、[12、12]]
  • 入力が等しい数値のペアである場合、他の重要な答えと一致する限り、何でも出力できます

    • 例えば
      • 入力[2、5]の出力[[3、10]、[6、11]、[12、12]]に入力ペアが含まれていない場合、入力[4、4]は何も出力しません。
      • 入力[2、5]に出力[[2、5]、[3、10]、[6、11]、[12、12]]があり、入力ペアが含まれている場合、入力[4、4]は出力[[4、4]]。
  • 標準のIOメソッドが適用され、標準の抜け穴が禁止されています

  • これはコードゴルフなので、バイト単位の最短回答が勝ちます


13
これは素晴らしい最初の挑戦です、ところで。PPCGへようこそ!
アーナウルド

@Arnauldありがとうございます!また、エラーを指摘してくれてありがとう、私はすべての例を手作業で行い、最初に自分で解決策を実際に実装する必要があります
-JMigst

出力を逆にすることはできますか?たとえば[(12,12),(6,11),(3,10),(2,5)]、入力用(2,5)
ライコニ

1
@Laikoni必要なすべての手順がまだ出力されていることを考えると、私はそれがうまくいくと思う
-JMigst

1
これをA304027としてOEISに追加しました。ペア(34,23)は特に難しいようです。
ピーターカゲイ

回答:


10

JavaScript(ES6)、111 90 83バイト

f=(a,b,p=q=[],u=[...p,[a,b]])=>a-b?f(...(q=[[a*2,b+1,u],[a+1,b*2,u],...q]).pop()):u

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

コメント済み

f = (                       // f = recursive function taking:
  a, b,                     //   (a, b) = input integers
  p =                       //   p[] = current path
  q = [],                   //   q[] = queue
  u = [...p, [a, b]]        //   u[] = updated path with [a, b] appended to it
) =>                        //
  a - b ?                   // if a is not yet equal to b:
    f(...                   //   recursive call, using spread syntax:
      (q = [                //     prepend the next 2 possible moves in the queue:
        [a * 2, b + 1, u],  //       a * 2, b + 1
        [a + 1, b * 2, u],  //       a + 1, b * 2
        ...q                //
      ]).pop()              //     use the move on the top of the queue
    )                       //   end of recursive call
  :                         // else:
    u                       //   success: return the (updated) path

9

Haskell、70 69バイト

f(w@((i,j):_):r)|i==j=w|1<2=f$r++[(i+1,j*2):w,(i*2,j+1):w]
g x=f[[x]]

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

シンプルなBFS。ペアのリストのリスト内のステップを追跡します。

g x=f[[x]]                -- start with a single list where the only
                          -- step is the starting pair
f (w@((i,j):_):r) =       -- let w be the first list of steps
                          --     (i,j) the last pair of the first list of steps
                                       ('last' as in last operated on. As we store
                                        the steps in reverse order it's the
                                        first element in the list)
                          --     r all other lists of steps
   i==j=w                 -- if i==j stop and return the first list
   1<2= f                 -- else make a recursive call
          r++             -- where the new input list is r followed by
                          -- the first list extended one time by
          [(i+1,j*2):w,         (i+1,j*2) and one time by
             (i*2,j+1):w]       (i*2,j+1)

7

Pythonの390の 74 72バイト

Dennisのおかげで-2バイト。

def f(a,*x):j,k=a[0];return(j==k)*a or f(*x,[(2*j,k+1)]+a,[(j+1,2*k)]+a)

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

入力をシングルトンリストとして受け取ります


非ゴルフ

def f(a,*x):              # function taking at least one argument
                          # a is the first argument, all other are stored in x
  j, k = a[0]             # get the newest values of the current path
  return (j==k)*a         # if j is equal to k return the current path
                  or      # else ...
   f(                     # continue ...
     *x,                  # with the remaining paths ...
     [(2*j,k+1)]+a        # and split the current path ...
     [(j+1,2*k)]+a        # in two new ones
    ) 

4

Pyth、41バイト

J]]QL,hhb*2ebWt{KehJ=J+tJm+hJ]d,yK_y_K)hJ

ここで試してみてください

説明

これは非常に簡単な幅優先検索です。可能なシーケンスのキュー(J)を保持し、一致するペアを取得するまで、次のシーケンスを取得し、可能性のある各動きに固執して、キューの最後に配置します。
簡潔にするために、いずれかの移動を実行する関数をy(ラムダ式を使用してL)定義し、前方および後方の両方に適用します。



4

05AB1E25 22 20バイト

二重にネストされたリストを入力として受け取り、各ステップを1つのネストの深さにしたジャグリストを出力します。

[ć¤Ë#¤xs>R‚ø`R‚s¸sâ«

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

説明

[                      # start a loop
 ć                     # extract the first element of the current list (current path)
  ¤Ë#                  # break if all elements in the head are equal
     ¤xs>              # duplicate one copy of the head and increment another
         R             # reverse the incremented copy
          ‚ø           # zip them together
            `R‚        # reverse the tail of the zipped list
               s¸sâ    # cartesian product with the rest of the current path
                   «   # append to the list of all current paths

4

網膜、72バイト

\d+
*
/\b(_+),\1\b/^+%`(_+),(_+)$
$&;_$&$2¶$=;$1$&_
G`\b(_+),\1\b
_+
$.&

オンラインでお試しください!単項演算の制限による2つのテストケースのみ。説明:

\d+
*

単項に変換します。

/\b(_+),\1\b/^+

入力には同じ数字のペアが含まれていませんが...

%`(_+),(_+)%

...各行の最後のペアを照合する...

$&;_$&$2¶$=;$1$&_

...その行を2行に変更します。1行目は最初の数字が追加され、2つ目が2倍になり、もう1つは最初の数字が2倍になり2つ目が増えます。

G`\b(_+),\1\b

一致するペアの行を保持します。

_+
$.&

10進数に戻します。89 88バイトの符号なし10進数演算バージョン(0でも動作):

/\b(\d+),\1\b/^+%`(\d+),(\d+)$
$&;$.(_$1*),$.(2*$2*)¶$=;$.(2*$1*),$.(_$2*
G`\b(\d+),\1\b

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


4

MATL、24バイト

`vxG1r/q:"tt1rEk(+]td0=~

実行時間はランダムですが、確率1で有限です。

コードは非常に非効率的です。4つまたは5つ以上のステップを必要とする入力は、オンラインインタープリターでタイムアウトする可能性が高くなります。

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

説明

`         % Do...while
  vx      %   Concatenate stack and delete. This clears the stack from contents
          %   of previous iterations   
  G       %   Push input
  1       %   Push 1
  r       %   Push random number uniformly distributed on (0,1)
  /       %   Divide
  q       %   Subtract 1. The result is a random number, t, that has nonzero
          %   probability of being arbitrarily large. Specifically, t is in
          %   the interval (0,1) with probability 1/2; in (1,2) with probability
          %   1/6; ... in (k,k+1) with probability 1/((k+1)*(k+2).
  :       %   Range [1 2 ... floor(t)]
  "       %   For each (that is: do thw following floor(t) times)
    tt    %     Duplicate twice
    1     %     Push 1
    rEk   %     Random number in (0,1), times 2, round down. This produces a 
          %     number i that equals 0 or 1 with probability 1/2
    (     %     Write 1 at entry i. So if the top of the stack is [a b], this
          %     transforms it into either [1 b] or [a 1]
    +     %     Add, element-wise. This gives either [a+1 2*b] or [2*a b+1] 
  ]       %   End for each
  td      %   Duplicate, consecutive difference between the two entries
  0=~     %   Is it not zero? If so, the do...while loop continues with a new
          %   iteration. Normally the code 0=~ could be omitted, because a
          %   nonzero consecutive difference is truthy. But for large t the
          %   numbers a, b may have gone to infinity, and then the consecutive
          %   difference gives NaN
          % End do...while (implicit). Display (implicit)

3

スタックス29 26 バイト

ä⌠|Tô&cm♂NV↓↔╗╣¢♠╜╒█¡Φ≈ñY@

実行してデバッグする

これは幅の広い最初の検索です。かなり速いようです。

二重に配列された整数のペアを取ります。出力は、スペースで区切られた値のリストです。2つの値ごとに、ソリューションへのパス内の1つのペアが表されます。



2

、142バイト

入力をRedの形式の整数のペアの二重にネストされたブロックとして受け取ります(2, 5)->2x5

結果を、たとえば赤のペアのリストとして返します2x5 3x10 6x11 12x12。最初のペアが含まれます。

func[c][a: copy[]foreach d c[l: last d if l/1 = l/2[return d]do replace/all{%+ 1x0 * 1x2
%* 2x1 + 0x1}"%""append/only a append copy d l "]f a]

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

厳密な入力:

入力は、たとえば、2つの数字です 2 5

、214バイト

func[a b][g: func[c][a: copy[]foreach d c[l: last d if l/1 = l/2[return d]append/only a append copy d l + 1x0 * 1x2
append/only a append copy d l * 2x1 + 0x1]g a]c: copy[]insert/only c reduce[do rejoin[a 'x b]]g c]

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

説明:

f: func[a b][                 
g: func[c][                                   ; recursive helper function
  a: copy[]                                   ; an empty block
  foreach d c[                                ; for each block of the input 
    l: last d                                 ; take the last pair
    if l/1 = l/2[return d]                    ; if the numbers are equal, return the block 
    append/only a append copy d l + 1x0 * 1x2 ; in place of each block append two blocks
    append/only a append copy d l * 2x1 + 0x1 ; (j+1, k*2) and (j*2, k+1)
  ]                                           ; using Red's arithmetic on pairs
  g a                                         ; calls the function anew
]
c: copy[]insert/only c reduce[do rejoin[a 'x b]]; prepares a nested block from the input
g c                                           ; calls the recursive function 
]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.