Bir çift tamsayı eşitlik getirmek


51

Bu, internette bir yerde gördüğüm bir matematik probleminden ilham almıştı ama nerede olduğunu hatırlamıyorum (GÜNCELLEME: Asıl problem, matematik bilmecesinde subreddit bulundu, bunun mümkün olması kaydıyla, bu Matematik SE gönderisini görmek için) Herhangi bir rasgele tamsayı çifti için (eğer hatırladığım kadarıyla, verilen herhangi bir çift için mümkündü), aşağıdaki işlemin bir kanıtı varsa:

Bir çift tamsayı verilirse, j ve k, bunlardan birini ikiye katlar ve diğerini ekler, böylece bir çift yeni tam sayı elde edilir, yani, (j, k) -> (j + 1, k * 2) veya (j) * 2, k + 1). Ardından, bu sayının tam sayılarla eşit olmasını sağlamak amacıyla bu tam sayılarla tekrarlayın.

Verilen bu örnekler mutlaka en uygun değildir, ancak bu işlemin pozitif, negatif veya sıfır olan herhangi bir tamsayıda nasıl yapılabileceğini gösterir:

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

Meydan okuma

İki tamsayı verilen bir program oluşturun, bu tamsayıları art arda artırarak ve diğerini iki katına çıkararak eşitlemek için gereken adımların listesini çıkarır.

Özellikler

  • Çözümün optimal olması gerekmez, ancak herhangi bir keyfi çift için sınırlı sayıda adımda çözülmesi gerekir.
  • Giriş iki tamsayı olmalıdır

  • Çıktı, her adımın sonuç tam sayılarını açıkça gösteren herhangi bir makul çıktı olabilir, örneğin:

    • iki ayrı sınırlayıcıya sahip bir dize (herhangi bir sembol, boşluk, vb.), bir çiftteki her tam sayı için bir tane ve her bir çift için bir tane
      • örneğin, j girişi, k: 2, 5 -> çıkış: 3,10; 6,11; 12,12
    • tamsayıların listesi
      • örn. giriş j, k: 2, 5 -> çıkış: [[3, 10], [6, 11], [12, 12]]
  • Girdi bir eşit sayılar çiftiyse, diğer önemsiz yanıtlarla tutarlı olduğu sürece herhangi bir şeyi yazdırabilirsiniz.

    • Örneğin
      • [2, 5] girişi [[3, 10], [6, 11], [12, 12]] çıkışına sahipse, giriş çiftini içermiyorsa, giriş [4, 4] hiçbir şey vermemelidir.
      • [2, 5] girişi [[2, 5], [3, 10], [6, 11], [12, 12]] çıkışına sahipse, giriş çiftini içerir, sonra giriş [4, 4]; çıkış [[4, 4]].
  • Standart IO yöntemleri uygulanır ve standart boşluklar yasaklanır

  • Bu kod golf yani bayt cinsinden en kısa cevap kazanır


13
Bu güzel bir ilk zorluk, BTW. PPCG'ye Hoşgeldiniz!
Arnauld,

@Arnauld Teşekkürler! Ayrıca hatayı işaret ettiğim için teşekkür ederim, tüm örnekleri elle yaptım ve gerçekten kendim önce bir çözüm uygulamalıyım
JMigst

Çıkış ters olabilir mi? Örneğin [(12,12),(6,11),(3,10),(2,5)]giriş için (2,5)?
Laikoni

1
@Laikoni Gerekli tüm adımlar hala çıktısı göz önüne alındığında, bunun iyi olduğunu düşünüyorum
JMigst

1
Bunu OEIS'e A304027 olarak ekledim . Çifti (34,23) özellikle zor görünüyor.
Peter Kagey

Yanıtlar:


10

JavaScript (ES6), 111 90 83 bayt

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

Çevrimiçi deneyin!

Yorumlananlar

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 bayt

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

Çevrimiçi deneyin!

Basit bir BFS. Çiftlerin listesindeki adımları izler.

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 bayt

Dennis sayesinde -2 bayt .

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)

Çevrimiçi deneyin!

Tekli bir liste olarak girdi alır .


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 bayt

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

Burada dene

açıklama

Bu oldukça basit bir ilk arama. Olası dizilerin sırasını ( J) tutun ve eşleşen bir çift elde edene kadar, bir sonraki diziyi alın, olası hareketlerin her birine yapıştırarak ve bunları sıranın sonuna koyun.
Kısalık uğruna , hareketlerden birini gerçekleştirmek yiçin bir işlev (lambda ifadesini kullanarak) tanımlarız Lve onu hem ileri hem de geri uygularız.



4

05AB1E , 25 22 20 bayt

Giriş olarak iki kat yuvalanmış bir liste alır ve her adımda bir yuva derinliğinde tırtıklı bir liste çıkarır.

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

Çevrimiçi deneyin!

açıklama

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

Retina , 72 bayt

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

Çevrimiçi deneyin! Unary aritmetik kısıtlamaları nedeniyle sadece iki test olgusu. Açıklama:

\d+
*

Birliğe dönüştür.

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

Girdi aynı çift sayıları içermese de ...

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

... her bir satırdaki son çifti eşleştirin ...

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

... ve çizgiyi, biri ilk rakam artırılmış ve ikinci kat artırılmış, diğeri ilk rakam iki kat artmış ve ikinci art arıtılmış iki satıra çevirin.

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

Çizgiyi eşleşen çiftle tutun.

_+
$.&

Ondalık basamağa dönüştür. 89 88 baytlık işaretsiz ondalık aritmetik sürümü (0 ile de çalışır):

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

Çevrimiçi deneyin!


4

MATL , 24 bayt

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

Çalışma süresi rastgele, ancak olasılık 1 ile sonlu.

Kod çok verimsiz. 4 veya 5 adımdan daha fazla basamak gerektiren girişler, çevrimiçi yorumlayıcıda büyük bir zaman aşımı olasılığına sahiptir.

Çevrimiçi deneyin!

açıklama

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

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

Koş ve hata ayıkla

Bu bir genişlik ilk arama. Oldukça hızlı görünüyor.

İkilik dizi sarılmış bir tamsayı çifti alır. Çıktı, boşlukla ayrılmış bir değerler listesidir. Her iki değer de çözüm yolundaki bir çifti temsil eder.


2

Haskell , 95 bayt

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

Çevrimiçi deneyin! Ters sırayla çıktılar, örneğin h(2,5)verimler [(12,12),(6,11),(3,10),(2,5)].


2

Kırmızı , 142 bayt

Girdiyi, Red formatındaki çiftlerin tam olarak iç içe bir bloğu olarak alır (2, 5)->2x5

Mesela sonucu Kırmızı çiftler listesi olarak döndürür 2x5 3x10 6x11 12x12. İlk çifti içerir.

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]

Çevrimiçi deneyin!

Sıkı giriş:

Giriş iki sayıdır, örneğin 2 5

Kırmızı , 214 bayt

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]

Çevrimiçi deneyin!

Açıklama:

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 
]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.