Portare una coppia di numeri interi all'uguaglianza


51

Questo è stato ispirato da un problema di matematica che ho visto da qualche parte su Internet, ma non ricordo dove (AGGIORNAMENTO: il problema originale è stato riscontrato sugli enigmi matematici subreddit con una prova a condizione che sia possibile, vedi anche questo post di Math SE ), chiedendo di una prova se il seguente processo è possibile per qualsiasi coppia arbitraria di numeri interi (da quello che ricordo, è stato possibile per ogni data coppia):

Data una coppia di numeri interi, j e k, raddoppia uno di essi e aggiungi uno all'altro, risultando in una coppia di nuovi numeri interi, ovvero, (j, k) -> (j + 1, k * 2) o (j * 2, k + 1). Quindi ripetere questo processo con questi numeri interi, con l'obiettivo di avere la coppia di numeri interi uguali.

Questi esempi non sono necessariamente ottimali, ma mostrano come questo processo possa essere eseguito su qualsiasi numero intero, positivo, negativo o zero:

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

Sfida

Creare un programma che ha dato due numeri interi, genera l'elenco dei passaggi necessari per rendere uguali tali numeri interi incrementando ripetutamente uno e raddoppiando l'altro

specificazioni

  • La soluzione non deve essere ottimale ma deve risolvere in un numero finito di passaggi per qualsiasi coppia arbitraria
  • L'input deve essere di due numeri interi

  • L'output può essere qualsiasi output ragionevole che denoti chiaramente gli interi risultanti di ogni passaggio, ad esempio:

    • una stringa con due delimitatori distinti (qualsiasi simbolo, spazio bianco, ecc.), uno per ogni numero intero in una coppia e uno per ogni coppia
      • ad es., input j, k: 2, 5 -> output: 3,10; 6,11; 12,12
    • un elenco di elenchi di numeri interi
      • ad es. input j, k: 2, 5 -> output: [[3, 10], [6, 11], [12, 12]]
  • Se l'input è una coppia di numeri uguali, è possibile generare qualsiasi cosa purché sia ​​coerente con altre risposte non banali

    • per esempio
      • se input [2, 5] ha output [[3, 10], [6, 11], [12, 12]], che non include la coppia di input, allora input [4, 4] non dovrebbe produrre nulla.
      • se input [2, 5] ha output [[2, 5], [3, 10], [6, 11], [12, 12]], che include la coppia di input, quindi input [4, 4] dovrebbe output [[4, 4]].
  • Si applicano metodi IO standard e sono vietate le scappatoie standard

  • Questo è il codice golf, quindi vince la risposta più breve in byte


13
Questa è una bella prima sfida, a proposito. Benvenuti in PPCG!
Arnauld,

@Arnauld Grazie! Inoltre, grazie per aver segnalato l'errore, ho fatto tutti gli esempi a mano e dovrei davvero implementare una soluzione prima io stesso
JMigst

L'uscita può essere al contrario? Ad esempio [(12,12),(6,11),(3,10),(2,5)]per l'input (2,5)?
Laikoni,

1
@Laikoni Considerando che tutti i passaggi richiesti sono ancora in uscita, penso che
vada

1
L'ho aggiunto a OEIS come A304027 . La coppia (34,23) sembra essere particolarmente difficile.
Peter Kagey,

Risposte:


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

Provalo online!

Commentate

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

Provalo online!

Un semplice BFS. Tiene traccia dei passaggi in un elenco di un elenco di coppie.

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

Provalo online!

Prende l'input come un elenco singleton .


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 byte

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

Provalo qui

Spiegazione

Questa è una ricerca piuttosto ampia e semplice. Mantieni una coda di possibili sequenze ( J) e fino a quando non otteniamo una coppia corrispondente, prendi la sequenza successiva, mantieni le mosse possibili e mettile alla fine della coda.
Per brevità, definiamo una funzione y(usando l'espressione lambda L) per eseguire una delle mosse e la applichiamo sia in avanti che al contrario.



4

05AB1E , 25 22 20 byte

Prende un elenco doppiamente nidificato come input e genera un elenco frastagliato con ogni passaggio a una profondità del nido.

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

Provalo online!

Spiegazione

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

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

Provalo online! Solo due casi di test a causa dei limiti dell'aritmetica unaria. Spiegazione:

\d+
*

Converti in unario.

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

Mentre l'input non contiene una coppia di numeri identici ...

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

... abbina l'ultima coppia su ogni riga ...

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

... e trasforma la linea in due righe, una con il primo numero incrementata e la seconda raddoppiata, l'altra con il primo numero raddoppiata e la seconda incrementata.

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

Mantieni la linea con la coppia corrispondente.

_+
$.&

Converti nuovamente in decimale. 89 Versione aritmetica decimale senza segno a 88 byte (funziona anche con 0):

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

Provalo online!


4

MATL , 24 byte

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

Il tempo di esecuzione è casuale, ma è finito con probabilità 1.

Il codice è molto inefficiente. Gli input che richiedono più di 4 o 5 passaggi hanno una grande probabilità di timeout nell'interprete online.

Provalo online!

Spiegazione

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

Esegui ed esegui il debug

È una prima ricerca ampia. Sembra abbastanza veloce.

Ci vuole una coppia di interi doppiamente avvolti in array. L'output è un elenco di valori separato da spazi. Ogni due valori rappresenta una coppia nel percorso della soluzione.


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

Provalo online! Uscite in ordine inverso, ad es . h(2,5)Rese [(12,12),(6,11),(3,10),(2,5)].


2

Rosso , 142 byte

Prende l'input come blocco doppiamente nidificato della coppia di numeri interi nel formato di Red(2, 5) ->2x5

Restituisce il risultato come un elenco di coppie rosse , ad esempio 2x5 3x10 6x11 12x12. Include la coppia iniziale.

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]

Provalo online!

Input rigoroso:

L'input è di due numeri, ad esempio 2 5

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

Provalo online!

Spiegazione:

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 
]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.