Đưa một cặp số nguyên về bình đẳng


51

Điều này được lấy cảm hứng từ một vấn đề toán học tôi thấy ở đâu đó trên internet nhưng không nhớ là ở đâu (CẬP NHẬT: Vấn đề ban đầu được tìm thấy trên câu đố toán học subreddit với một bằng chứng với điều kiện là có thể, cũng thấy bài đăng Math SE này ), yêu cầu một bằng chứng nếu quy trình sau có thể áp dụng cho bất kỳ cặp số nguyên tùy ý nào (từ những gì tôi nhớ, có thể có cho bất kỳ cặp đã cho nào):

Cho một cặp số nguyên, j và k, nhân đôi một trong số chúng và thêm một số nguyên, kết quả là một cặp số nguyên mới, nghĩa là (j, k) -> (j + 1, k * 2) hoặc (j * 2, k + 1). Sau đó lặp lại quá trình này với các số nguyên đó, với mục tiêu có cặp số nguyên bằng nhau.

Các ví dụ đã cho này không nhất thiết là tối ưu nhưng cho thấy quá trình này có thể được thực hiện trên bất kỳ số nguyên nào, dương, âm hoặc bằng 0:

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

Thử thách

Tạo một chương trình cho hai số nguyên, đưa ra danh sách các bước cần thiết để làm cho các số nguyên đó bằng nhau bằng cách tăng liên tục một số nguyên và nhân đôi số nguyên kia

Thông số kỹ thuật

  • Giải pháp không phải là tối ưu nhưng nó phải giải quyết trong một số bước hữu hạn cho bất kỳ cặp tùy ý nào
  • Đầu vào phải là hai số nguyên

  • Đầu ra có thể là bất kỳ đầu ra hợp lý nào biểu thị rõ ràng các số nguyên kết quả của từng bước, ví dụ:

    • một chuỗi có hai dấu phân cách riêng biệt (bất kỳ ký hiệu, khoảng trắng, v.v.), một cho mỗi số nguyên trong một cặp và một cho mỗi cặp
      • ví dụ: đầu vào j, k: 2, 5 -> đầu ra: 3,10; 6,11; 12,12
    • danh sách các số nguyên
      • ví dụ: đầu vào j, k: 2, 5 -> đầu ra: [[3, 10], [6, 11], [12, 12]]
  • Nếu đầu vào là một cặp số bằng nhau, bạn có thể xuất bất cứ thứ gì miễn là phù hợp với các câu trả lời không cần thiết khác

    • ví dụ
      • nếu đầu vào [2, 5] có đầu ra [[3, 10], [6, 11], [12, 12]], không bao gồm cặp đầu vào, thì đầu vào [4, 4] sẽ không xuất ra gì.
      • nếu đầu vào [2, 5] có đầu ra [[2, 5], [3, 10], [6, 11], [12, 12]], bao gồm cặp đầu vào, thì đầu vào [4, 4] đầu ra [[4, 4]].
  • Các phương pháp IO tiêu chuẩn được áp dụng và các sơ hở tiêu chuẩn bị cấm

  • Đây là mã golf nên câu trả lời ngắn nhất trong byte thắng


13
Đây là một thử thách đầu tiên tốt đẹp, BTW. Chào mừng đến với PPCG!
Arnauld

@Arnauld Cảm ơn bạn! Cũng cảm ơn vì đã chỉ ra lỗi, tôi đã làm tất cả các ví dụ bằng tay và thực sự nên tự mình thực hiện một giải pháp
JMigst

Đầu ra có thể đảo ngược? Ví dụ [(12,12),(6,11),(3,10),(2,5)]cho đầu vào (2,5)?
Laikoni

1
@Laikoni Xem xét tất cả các bước cần thiết vẫn chưa được xuất, tôi nghĩ nó ổn
JMigst

1
Tôi đã thêm cái này vào OEIS là A304027 . Cặp đôi (34,23) dường như đặc biệt khó khăn.
Peter Kagey

Câu trả lời:


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

Hãy thử trực tuyến!

Đã bình luận

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

Hãy thử trực tuyến!

Một BFS đơn giản. Theo dõi các bước trong danh sách các cặp.

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 3 , 90 74 72 byte

-2 byte nhờ 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)

Hãy thử trực tuyến!

Đưa đầu vào như một danh sách đơn .


Ung dung

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

Bình thường, 41 byte

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

Hãy thử nó ở đây

Giải trình

Đây là tìm kiếm đầu tiên khá đơn giản. Giữ một hàng đợi các chuỗi có thể ( J) và cho đến khi chúng ta có được một cặp phù hợp, thực hiện chuỗi tiếp theo, bám vào từng bước di chuyển có thể và đặt chúng vào cuối hàng đợi.
Vì lợi ích của sự ngắn gọn, chúng tôi xác định một hàm y(sử dụng biểu thức lambda L) để thực hiện một trong các động tác và áp dụng cả hai tiến và lùi.



4

05AB1E , 25 22 20 byte

Lấy một danh sách lồng đôi làm đầu vào và đầu ra một danh sách lởm chởm với mỗi bước ở một độ sâu lồng.

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

Hãy thử trực tuyến!

Giải trình

[                      # 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

Võng mạc , 72 byte

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

Hãy thử trực tuyến! Chỉ có hai trường hợp kiểm tra do những hạn chế của số học đơn phương. Giải trình:

\d+
*

Chuyển đổi sang unary.

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

Trong khi đầu vào không chứa một cặp số giống hệt nhau ...

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

... Ghép cặp cuối cùng trên mỗi dòng ...

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

... Và biến dòng thành hai dòng, một dòng có số thứ nhất tăng và số thứ hai tăng gấp đôi, số còn lại có số thứ nhất tăng gấp đôi và số thứ hai tăng.

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

Giữ dòng với cặp phù hợp.

_+
$.&

Chuyển đổi trở lại thập phân. 89 Phiên bản số học thập phân không dấu 88 byte (cũng hoạt động với 0):

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

Hãy thử trực tuyến!


4

MATL , 24 byte

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

Thời gian chạy là ngẫu nhiên, nhưng nó là hữu hạn với xác suất 1.

Mã này rất không hiệu quả. Các đầu vào yêu cầu nhiều hơn 4 hoặc 5 bước có xác suất hết thời gian lớn trong trình thông dịch trực tuyến.

Hãy thử trực tuyến!

Giải trình

`         % 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

Stax , 29 26 byte

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

Chạy và gỡ lỗi nó

Đó là một tìm kiếm đầu tiên. Có vẻ hợp lý nhanh chóng.

Nó cần một cặp số nguyên bao bọc. Đầu ra là một danh sách các giá trị được phân tách bằng dấu cách. Mỗi hai giá trị đại diện cho một cặp trong đường dẫn đến giải pháp.


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

Hãy thử trực tuyến! Đầu ra theo thứ tự ngược lại, ví dụ h(2,5)sản lượng [(12,12),(6,11),(3,10),(2,5)].


2

Màu đỏ , 142 byte

Lấy đầu vào là một khối gấp đôi của cặp số nguyên ở định dạng của Red(2, 5) ->2x5

Trả về kết quả dưới dạng danh sách các cặp màu đỏ chẳng hạn 2x5 3x10 6x11 12x12. Bao gồm các cặp ban đầu.

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]

Hãy thử trực tuyến!

Đầu vào nghiêm ngặt:

Đầu vào là hai số, ví dụ 2 5

Màu đỏ , 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]

Hãy thử trực tuyến!

Giải trình:

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 
]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.