Membawa sepasang bilangan bulat ke kesetaraan

51

Ini terinspirasi oleh masalah matematika yang saya lihat di suatu tempat di internet tetapi tidak ingat di mana (PEMBARUAN: Masalah aslinya ditemukan pada subreddit teka-teki matematika dengan bukti asalkan itu mungkin, juga lihat posting Math SE ini ), meminta bukti jika proses berikut ini memungkinkan untuk setiap pasangan bilangan bulat sewenang-wenang (dari apa yang saya ingat, itu mungkin untuk setiap pasangan yang diberikan):

Diberikan sepasang bilangan bulat, j dan k, gandakan salah satunya dan tambahkan satu ke yang lain, menghasilkan sepasang bilangan bulat baru, yaitu, (j, k) -> (j + 1, k * 2) atau (j * 2, k +1). Kemudian ulangi proses ini dengan bilangan bulat tersebut, dengan tujuan agar pasangan bilangan bulat sama.

Contoh-contoh yang diberikan ini belum tentu optimal tetapi menunjukkan bagaimana proses ini dapat dilakukan pada bilangan bulat apa pun, positif, negatif atau nol:

(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)

Tantangan

Buat program yang diberi dua bilangan bulat, mengeluarkan daftar langkah-langkah yang diperlukan untuk membuat bilangan bulat itu sama dengan secara berulang menambah satu dan menggandakan yang lainnya

Spesifikasi

  • Solusi tidak harus optimal tetapi harus diselesaikan dalam jumlah langkah terbatas untuk setiap pasangan yang sewenang-wenang
  • Input harus berupa dua bilangan bulat

  • Output dapat berupa output yang masuk akal yang dengan jelas menunjukkan bilangan bulat yang dihasilkan dari setiap langkah, misalnya:

    • string dengan dua pembatas yang berbeda (simbol apa saja, spasi putih, dll), satu untuk setiap bilangan bulat dalam satu pasangan dan satu untuk setiap pasangan
      • mis. input j, k: 2, 5 -> output: 3,10; 6,11; 12,12
    • daftar daftar bilangan bulat
      • mis. input j, k: 2, 5 -> output: [[3, 10], [6, 11], [12, 12]]
  • Jika input adalah pasangan angka yang sama, Anda dapat mengeluarkan apa saja asalkan konsisten dengan jawaban nontrivial lainnya

    • sebagai contoh
      • jika input [2, 5] memiliki output [[3, 10], [6, 11], [12, 12]], yang tidak termasuk pasangan input, maka input [4, 4] seharusnya tidak menghasilkan apa-apa.
      • jika input [2, 5] memiliki output [[2, 5], [3, 10], [6, 11], [12, 12]], yang mencakup pasangan input, maka input [4, 4] harus output [[4, 4]].
  • Metode IO standar berlaku dan lubang standar dilarang

  • Ini adalah kode golf sehingga jawaban terpendek dalam byte menang

JMigst
sumber
13
Ini tantangan pertama yang menyenangkan, BTW. Selamat datang di PPCG!
Arnauld
@Arnauld Terima kasih! Juga terima kasih untuk menunjukkan kesalahan, saya melakukan semua contoh dengan tangan dan benar-benar harus mengimplementasikan solusi sendiri terlebih dahulu
JMigst
Bisakah output terbalik? Misalnya [(12,12),(6,11),(3,10),(2,5)]untuk input (2,5)?
Laikoni
1
@Laikoni Mempertimbangkan semua langkah yang diperlukan masih dikeluarkan, saya pikir tidak apa
JMigst
1
Saya menambahkan ini ke OEIS sebagai A304027 . Pasangan (34,23) tampaknya sangat sulit.
Peter Kagey

Jawaban:

10

JavaScript (ES6), 111 90 83 byte

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

Cobalah online!

Berkomentar

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
Arnauld
sumber
9

Haskell, 70 69 byte

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]]

Cobalah online!

BFS sederhana. Melacak langkah-langkah dalam daftar daftar pasangan.

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)
nimi
sumber
7

Python 3 , 90 74 72 byte

-2 byte terima kasih kepada Dennis .

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)

Cobalah online!

Mengambil input sebagai daftar tunggal .


Tidak disatukan

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
    ) 
ovs
sumber
4

Pyth, 41 byte

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

Coba di sini

Penjelasan

Ini adalah pencarian pertama yang cukup luas. Simpan antrian dari urutan yang mungkin ( J), dan sampai kami mendapatkan pasangan yang cocok, ambil urutan berikutnya, tempelkan pada setiap gerakan yang mungkin, dan letakkan di akhir antrian.
Demi singkatnya, kami mendefinisikan fungsi y(menggunakan ekspresi lambda L) untuk melakukan salah satu gerakan, dan menerapkannya maju dan mundur.

Mnemonik
sumber
4

Jelly , 20 byte

ḃ2d2;@+*¥\
0çṪEɗ1#Ḣç

Cobalah online!

Dennis
sumber
(catatan: ini mengambil daftar tunggal dari daftar 2-elemen, misalnya [[2,5]])
user202729
4

05AB1E , 25 22 20 byte

Mengambil daftar bersarang ganda sebagai input dan menampilkan daftar bergerigi dengan setiap langkah pada satu kedalaman sarang.

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

Cobalah online!

Penjelasan

[                      # 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
Emigna
sumber
4

Retina , 72 byte

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

Cobalah online! Hanya dua kasus uji karena keterbatasan aritmatika unary. Penjelasan:

\d+
*

Konversikan ke unary.

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

Sementara input tidak mengandung sepasang angka yang identik ...

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

... cocokkan dengan pasangan terakhir pada setiap baris ...

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

... dan mengubah garis menjadi dua garis, satu suffix dengan angka pertama bertambah dan kedua berlipat ganda, yang lainnya suffix dengan angka pertama dua kali lipat dan yang kedua bertambah.

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

Ikuti terus dengan pasangan yang cocok.

_+
$.&

Konversi kembali ke desimal. 89 88 byte byte desimal versi aritmatika (bekerja dengan 0 juga):

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

Cobalah online!

Neil
sumber
4

MATL , 24 byte

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

Waktu berjalan adalah acak, tetapi terbatas dengan probabilitas 1.

Kode ini sangat tidak efisien. Input yang membutuhkan lebih dari 4 atau 5 langkah memiliki kemungkinan besar penghentian waktu dalam juru bahasa online.

Cobalah online!

Penjelasan

`         % 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)
Luis Mendo
sumber
3

Stax , 29 26 byte

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

Jalankan dan debug itu

Ini pencarian pertama yang luas. Tampaknya cukup cepat.

Dibutuhkan sepasang integer yang dibungkus ganda. Outputnya adalah daftar nilai yang dipisahkan oleh spasi. Setiap dua nilai mewakili satu pasangan di jalur menuju solusi.

rekursif
sumber
2

Haskell , 95 byte

g s|a:_<-[a|a@((x,y):_)<-s,x==y]=a
g s=g$do a@((x,y):_)<-s;[(x*2,y+1):a,(x+1,y*2):a]
h t=g[[t]]

Cobalah online! Output dalam urutan terbalik, misalnya h(2,5)hasil [(12,12),(6,11),(3,10),(2,5)].

Laikoni
sumber
2

Merah , 142 byte

Mengambil input sebagai blok bersarang ganda dari pasangan bilangan bulat dalam format Merah(2, 5) ->2x5

Mengembalikan hasilnya sebagai daftar pasangan merah , misalnya 2x5 3x10 6x11 12x12. Termasuk pasangan awal.

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]

Cobalah online!

Input yang ketat:

Inputnya adalah dua angka, misalnya 2 5

Merah , 214 byte

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]

Cobalah online!

Penjelasan:

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 
]
Galen Ivanov
sumber