นำคู่จำนวนเต็มไปสู่ความเท่าเทียมกัน


51

นี่เป็นแรงบันดาลใจจากปัญหาทางคณิตศาสตร์ที่ฉันเห็นที่ไหนสักแห่งบนอินเทอร์เน็ต แต่จำไม่ได้ว่าที่ไหน (อัพเดท: ปัญหาดั้งเดิมที่พบในปริศนาคณิตศาสตร์ subredditพร้อมหลักฐานที่ระบุว่าเป็นไปได้และดูโพสต์คณิตศาสตร์ SE นี้ด้วย ) หลักฐานหากกระบวนการต่อไปนี้เป็นไปได้สำหรับคู่ของจำนวนเต็มใด ๆ (จากสิ่งที่ฉันจำได้มันเป็นไปได้สำหรับคู่ใดก็ตาม):

ให้คู่ของจำนวนเต็ม, j และ k, สองเท่าของพวกเขาและเพิ่มหนึ่งไปยังอีกส่งผลให้คู่ของจำนวนเต็มใหม่คือ (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)

ท้าทาย

สร้างโปรแกรมที่ให้จำนวนเต็มสองจำนวนออกผลลัพธ์รายการขั้นตอนที่จำเป็นเพื่อทำให้จำนวนเต็มเหล่านั้นเท่ากันโดยการเพิ่มทีละหนึ่งซ้ำแล้วซ้ำอีก

ข้อมูลจำเพาะ

  • การแก้ปัญหาไม่จำเป็นต้องดีที่สุด แต่จะต้องแก้ปัญหาในขั้นตอนที่ จำกัด สำหรับคู่ใด ๆ โดยพลการ
  • ข้อมูลที่ป้อนต้องเป็นจำนวนเต็มสองจำนวน

  • ผลลัพธ์อาจเป็นผลลัพธ์ที่สมเหตุสมผลที่แสดงถึงจำนวนเต็มที่เกิดของแต่ละขั้นตอนอย่างชัดเจนตัวอย่างเช่น

    • สตริงที่มีตัวคั่นสองตัวที่แตกต่างกัน (สัญลักษณ์ใด ๆ ช่องว่าง ฯลฯ ) สตริงหนึ่งสำหรับแต่ละจำนวนเต็มในคู่และอีกหนึ่งสำหรับแต่ละคู่
      • เช่นอินพุต 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
นี่เป็นความท้าทายครั้งแรกที่ดี BTW ยินดีต้อนรับสู่ PPCG!
Arnauld

@Arnauld ขอบคุณ! นอกจากนี้ขอขอบคุณที่ชี้ข้อผิดพลาดออกมาฉันทำตัวอย่างทั้งหมดด้วยมือและควรใช้วิธีแก้ปัญหาด้วยตัวเองก่อน
JMigst

เอาต์พุตสามารถกลับด้านได้หรือไม่? เช่น[(12,12),(6,11),(3,10),(2,5)]ใส่(2,5)?
Laikoni

1
@Laikoni พิจารณาทุกขั้นตอนที่จำเป็นยังคงออกมาผมคิดว่ามันเป็นเรื่องดี
JMigst

1
ฉันเพิ่มนี้ไป OEIS เป็นA304027 ทั้งคู่ (34,23) ดูเหมือนจะยากเป็นพิเศษ
Peter Kagey

คำตอบ:


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 3 , 90 74 72 ไบต์

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

ลองออนไลน์!

จะเข้าเป็นรายการเดี่ยว


Ungolfed

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

05AB1E , 25 22 20 ไบต์

รับรายการซ้อนกันสองเท่าเป็นอินพุตและเอาต์พุตรายการแบบขรุขระด้วยแต่ละขั้นตอนที่ความลึกซ้อนหนึ่งระดับ

[ć¤Ë#¤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
_+
$.&

ลองออนไลน์! มีเพียงสองกรณีทดสอบเนื่องจากข้อ จำกัด ของเลขคณิตยูนารี คำอธิบาย:

\d+
*

แปลงเป็นเอก

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

ในขณะที่อินพุตไม่มีตัวเลขที่เหมือนกัน ...

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

... จับคู่คู่สุดท้ายของแต่ละบรรทัด ...

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

... และเปลี่ยนสายเป็นสองบรรทัดหนึ่งต่อท้ายด้วยการเพิ่มจำนวนแรกและสองเท่าสองครั้งต่อท้ายด้วยการเพิ่มจำนวนสองครั้งแรกและสองเพิ่มขึ้น

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

รักษาเส้นด้วยคู่ที่ตรงกัน

_+
$.&

แปลงกลับเป็นทศนิยม 89เวอร์ชันเลขคณิตทศนิยม 88 ไบต์ที่ไม่ได้ลงชื่อ (ใช้ได้กับ 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

Stax , 29 26 ไบต์

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

เรียกใช้และแก้ไขข้อบกพร่อง

มันเป็นการค้นหาแบบกว้างครั้งแรก ดูเหมือนว่าจะเร็วพอสมควร

มันต้องใช้จำนวนเต็มคู่ทวีคูณ เอาต์พุตเป็นรายการที่คั่นด้วยช่องว่าง ทุกสองค่าแสดงถึงคู่หนึ่งในพา ธ ไปยังโซลูชัน



2

สีแดง 142 ไบต์

นำอินพุตเป็นบล็อกซ้อนกันสองเท่าของคู่จำนวนเต็มในรูปแบบของRed(2, 5) ->2x5

ผลตอบแทนเป็นรายการ ot แดง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 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.