Bringen Sie ein Paar von ganzen Zahlen zur Gleichheit

51

Dies wurde durch ein mathematisches Problem inspiriert, das ich irgendwo im Internet gesehen habe, aber ich erinnere mich nicht, wo (UPDATE: Das ursprüngliche Problem wurde auf den unterditierten mathematischen Rätseln mit einem Beweis gefunden, sofern es möglich ist, siehe auch diesen Math SE-Beitrag ), gefragt ein Beweis, ob das folgende Verfahren für ein beliebiges ganzzahliges Paar möglich ist (soweit ich mich erinnere, war es für ein bestimmtes Paar möglich):

Wenn ein Paar von ganzen Zahlen j und k gegeben ist, verdoppeln Sie eine von ihnen und addieren Sie eine zu der anderen, was zu einem Paar neuer ganzer Zahlen führt, dh (j, k) -> (j + 1, k * 2) oder (j * 2, k + 1). Wiederholen Sie diesen Vorgang dann mit diesen ganzen Zahlen, mit dem Ziel, dass das ganze Zahlenpaar gleich ist.

Diese angegebenen Beispiele sind nicht unbedingt optimal, zeigen jedoch, wie dieser Prozess für alle positiven, negativen oder Nullen von ganzen Zahlen durchgeführt werden kann:

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

Herausforderung

Erstellen Sie ein Programm mit zwei Ganzzahlen, und geben Sie die Liste der Schritte aus, die erforderlich sind, um diese Ganzzahlen durch wiederholtes Inkrementieren und Verdoppeln der beiden Zahlen gleich zu machen

Spezifikationen

  • Die Lösung muss nicht optimal sein, sondern muss für jedes beliebige Paar in einer endlichen Anzahl von Schritten gelöst werden
  • Die Eingabe muss aus zwei ganzen Zahlen bestehen

  • Die Ausgabe kann jede sinnvolle Ausgabe sein, die die resultierenden ganzen Zahlen jedes Schritts eindeutig kennzeichnet, zum Beispiel:

    • eine Zeichenfolge mit zwei unterschiedlichen Trennzeichen (ein beliebiges Symbol, ein Leerzeichen usw.), eines für jede Ganzzahl in einem Paar und eines für jedes Paar
      • zB Eingabe j, k: 2, 5 -> Ausgabe: 3,10; 6,11; 12,12
    • eine Liste von Listen mit ganzen Zahlen
      • zB Eingabe j, k: 2, 5 -> Ausgabe: [[3, 10], [6, 11], [12, 12]]
  • Wenn es sich bei der Eingabe um ein Paar gleicher Zahlen handelt, können Sie alles ausgeben, solange es mit anderen nichttrivialen Antworten übereinstimmt

    • zum Beispiel
      • Wenn Eingang [2, 5] Ausgang [[3, 10], [6, 11], [12, 12]] hat, der das Eingangspaar nicht enthält, sollte Eingang [4, 4] nichts ausgeben.
      • Wenn Eingang [2, 5] Ausgang [[2, 5], [3, 10], [6, 11], [12, 12]] hat, der das Eingangspaar enthält, sollte Eingang [4, 4] Ausgabe [[4, 4]].
  • Es gelten Standard-E / A-Methoden, und Standard-Regelungslücken sind verboten

  • Dies ist Codegolf, also gewinnt die kürzeste Antwort in Bytes

JMigst
quelle
13
Dies ist eine schöne erste Herausforderung, übrigens. Willkommen bei PPCG!
Arnauld
@ Arnauld Danke! Auch danke für den Hinweis auf den Fehler, ich habe alle Beispiele von Hand gemacht und sollte wirklich zuerst selbst eine Lösung implementieren
JMigst
Kann die Ausgabe umgekehrt sein? ZB [(12,12),(6,11),(3,10),(2,5)]zur Eingabe (2,5)?
Laikoni
1
@Laikoni Angesichts der Tatsache, dass noch alle erforderlichen Schritte ausgegeben wurden, finde ich es in Ordnung
JMigst
1
Ich habe dies dem OEIS als A304027 hinzugefügt . Das Paar (34,23) scheint besonders schwierig zu sein.
Peter Kagey

Antworten:

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

Probieren Sie es online!

Kommentiert

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
quelle
9

Haskell, 70 69 Bytes

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

Probieren Sie es online!

Ein einfaches BFS. Verfolgt die Schritte in einer Liste von Paaren.

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

Python 3 , 90 74 72 Bytes

-2 Bytes dank 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)

Probieren Sie es online!

Übernimmt die Eingabe als Singleton-Liste .


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

Pyth, 41 Bytes

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

Probieren Sie es hier aus

Erläuterung

Dies ist eine ziemlich unkomplizierte Breitensuche. Halten Sie eine Reihe möglicher Sequenzen ( J), und bis wir ein passendes Paar erhalten, nehmen Sie die nächste Sequenz, halten Sie sich an alle möglichen Züge und stellen Sie sie an das Ende der Reihe.
Der Kürze halber definieren wir eine Funktion y(unter Verwendung des Lambda-Ausdrucks L), um eine der Bewegungen auszuführen, und wenden sie sowohl vorwärts als auch rückwärts an.

Gedächtnisstütze
quelle
4

Gelee , 20 Bytes

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

Probieren Sie es online!

Dennis
quelle
(Anmerkung: Dies nimmt zum Beispiel eine Singleton-Liste einer 2-Elemente-Liste [[2,5]])
user202729
4

05AB1E , 25 22 20 Bytes

Nimmt eine doppelt verschachtelte Liste als Eingabe und gibt eine gezackte Liste mit jedem Schritt in einer Verschachtelungstiefe aus.

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

Probieren Sie es online!

Erläuterung

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

Netzhaut , 72 Bytes

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

Probieren Sie es online! Nur zwei Testfälle aufgrund der Einschränkungen der unären Arithmetik. Erläuterung:

\d+
*

In Unary konvertieren.

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

Während die Eingabe kein Paar identischer Zahlen enthält ...

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

... finde das letzte Paar in jeder Zeile ...

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

... und die Zeile in zwei Zeilen umwandeln, wobei eine mit der ersten Nummer inkrementiert und die zweite mit der doppelten und die andere mit der ersten Nummer inkrementiert und die zweite mit der doppelten Nummer inkrementiert wird.

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

Halten Sie die Linie mit dem passenden Paar.

_+
$.&

Zurück in Dezimalzahl konvertieren. 89 Vorzeichenlose 88-Byte-Dezimal-Arithmetikversion (funktioniert auch mit 0):

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

Probieren Sie es online!

Neil
quelle
4

MATL , 24 Bytes

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

Die Laufzeit ist zufällig, aber mit Wahrscheinlichkeit 1 endlich.

Der Code ist sehr ineffizient. Bei Eingaben, die mehr als 4 oder 5 Schritte erfordern, besteht eine hohe Wahrscheinlichkeit, dass der Online-Interpreter ein Zeitlimit überschreitet.

Probieren Sie es online!

Erläuterung

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

Stax , 29 26 Bytes

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

Führen Sie es aus und debuggen Sie es

Es ist eine breite erste Suche. Es scheint ziemlich schnell.

Es wird ein doppelt in ein Array eingeschlossenes Paar von ganzen Zahlen benötigt. Die Ausgabe ist eine durch Leerzeichen getrennte Liste von Werten. Jeweils zwei Werte stehen für ein Paar auf dem Weg zur Lösung.

rekursiv
quelle
2

Haskell , 95 Bytes

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

Probieren Sie es online! Ausgänge in umgekehrter Reihenfolge, zB h(2,5)Erträge [(12,12),(6,11),(3,10),(2,5)].

Laikoni
quelle
2

Rot , 142 Bytes

Nimmt die Eingabe als doppelt verschachtelten Block des Ganzzahlpaares im Red -Format (2, 5)->2x5

Gibt das Ergebnis beispielsweise als Liste mit roten Paaren zurück 2x5 3x10 6x11 12x12. Beinhaltet das erste Paar.

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]

Probieren Sie es online!

Strikte Eingabe:

Die Eingabe besteht beispielsweise aus zwei Zahlen 2 5

Rot , 214 Bytes

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]

Probieren Sie es online!

Erläuterung:

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
quelle