Unire due elenchi ordinati


14

Unisci ordinamento

In questa sfida, implementerai la subroutine di unione dell'ordinamento di tipo merge. In particolare, è necessario creare una funzione o programma o verbo o simile che accetta due elenchi, ognuno ordinato in ordine crescente e li combina in un elenco ordinato in ordine crescente. Requisiti:

- L'algoritmo deve richiedere una quantità di tempo asintoticamente lineare nella dimensione dell'input. Per favore, smetti di dare O (n ^ 2) soluzioni.

  • Non è possibile utilizzare alcuna funzione integrata in grado di ordinare un elenco, unire un elenco o qualcosa del genere. Discrezione dell'autore.
  • Il codice dovrebbe essere in grado di gestire elementi ripetuti.
  • Non preoccuparti per gli elenchi vuoti.

Esempi:

merge([1],[0,2,3,4])
[0,1,2,3,4]

merge([1,5,10,17,19],[2,5,9,11,13,20])
[1, 2, 5, 5, 9, 10, 11, 13, 17, 19, 20]

Questo è , quindi può vincere il codice più corto!


Dobbiamo gestire elementi ripetuti all'interno di un elenco o solo tra i due elenchi?
Keith Randall,

Diciamo entrambi. L'idea è che dovresti essere in grado di usarlo per fare un ordinamento.
isaacg

È kosher intasare gli array di input?
skibrianski

3
Non sono sicuro di come interpretare l' algoritmo debba richiedere un tempo asintoticamente lineare . Gli algoritmi non richiedono tempo, le implementazioni lo fanno. Il tempo di esecuzione della mia risposta Golfscript è O (spaventoso) con l'interprete Ruby, ma il Golfscript Tester online si comporta molto meglio e potrebbe in effetti essere lineare (nessun modo reale di dire senza il codice sorgente però). Il mio punto è: b=a;b=b.lengthpotrebbe duplicare l'intero array a(e dare come risultato O (n ^ 2) se eseguito per ogni elemento) o duplicare solo il riferimento all'array (O (n) time). Quale conta?
Dennis,

1
Immagino che in casi come questi, fai del tuo meglio per capirlo, ma se onestamente non puoi dirlo, puoi presumere che le cose funzionino bene, come la seconda alternativa che hai menzionato. Puoi presumere che l'interprete funzioni bene se la tua lingua non ha un interprete standard.
isaacg

Risposte:


8

Rebmu ( 35 32 caratteri)

u[iG^aNXa[rvA]apGtkFaM?fA]apGscA

Test

>> rebmu/args [u[iG^aNXa[rvA]apGtkFaM?fA]apGscA] [[1 5 10 17 19] [2 5 9 11 13 20]] 
== [1 2 5 5 9 10 11 13 17 19 20]

>> rebmu/args [u[iG^aNXa[rvA]apGtkFaM?fA]apGscA] [[2 5 9 11 13 20] [1 5 10 17 19]] 
== [1 2 5 5 9 10 11 13 17 19 20]

Di

Rebmu è un dialetto di Rebol che consente il "mushing" del codice normale per situazioni che richiedono brevità. Unmushed, il codice funziona in qualche modo come:

u [                     ; until
    i g^ a nx a [       ; if greater? args next args
       rv a             ; reverse args
    ]                   ; (we want the block containing the next value first)

    ap g tk f a         ; append output take first args
    m? f a              ; empty? first args
]                       ; (first block is now empty)

ap g sc a               ; append output second args
                        ; (add the remainder of the second)

Credo che questo soddisfi il requisito O (n) in quanto il blocco fino a quando non è al massimo in loop quante volte la lunghezza dell'input (e l' reverseunico cambia l'ordine del contenitore dei blocchi di input, non i blocchi stessi). utilizzandotake è forse una libertà, ma è ancora un piccolo colpo di efficienza.

Rebol ( 83 75 caratteri)

Solo un po 'diverso: in Rebol, i percorsi sono un'espressione più breve di firsto second. aè il blocco di input contenente i due blocchi:

until[if a/2/1 < a/1/1[reverse a]append o:[]take a/1 tail? a/1]append o a/2

5

Le soluzioni di OP:

Haskell 49 44 40

k@(p:r)%l@(q:s)|p>=q=q:k%s|0<1=l%k
a%_=a

Python 131 105 101 99 93

Grazie a @Evpok:

f=lambda u,v:v and(v[-1]<u[-1]and f(v,u)or[b.append(a)for a,b in[(v.pop(),f(u,v))]]and b)or u

1
È possibile scrivere a%b=a++bdopo la corrispondenza del modello principale per gestire elenchi vuoti, che raseranno un paio di caratteri.
swish

la soluzione Haskell non fallisce se il primo elenco si esaurisce per primo?
John Dvorak,

Se guardi la prima funzione, chiama ricorsivamente la funzione con la lista abbreviata come secondo argomento e la lista allungata come primo argomento, oppure scambia gli argomenti. Pertanto, il primo argomento non si riduce mai. Dal momento che dall'OP non inizia a svuotarsi, non si svuoterà mai.
isaacg,

4

Python (79)

from itertools import*
def m(*a):
 while any(a):yield min(compress(a,a)).pop(0)

Python (95, se non ci è permesso di restituire un generatore)

from itertools import*
def m(*a):
 r=[]
 while any(a):r+=[min(compress(a,a)).pop(0)]
 return r

Itertools è la soluzione per tutti i problemi del mondo.

Bonus: entrambi funzionano su un numero arbitrario di elenchi e si preoccupano degli elenchi vuoti (come in, prenderanno felicemente 2 elenchi vuoti e restituiranno un elenco vuoto o prenderanno 1 elenco vuoto e 1 elenco non vuoto, e restituiranno quello non vuoto. Un'altra caratteristica aggiunta dei 2 non ceduti: funzioneranno anche senza argomenti e restituiranno solo un elenco vuoto.)

Ungolfed:

from itertools import *  # Import all items from itertools
def m(*a):               # Define the function m, that takes any number of arguments, 
                         #  and stores those arguments in list a
    r=[]                 # Create an empty list r                         
    while any(a):        # While any element in a returns True as value:
        b=compress(a,a)  # Remove any element from a that isn't True (empty lists)
                         #  The example in the official documentation is this one:
                         #  compress('ABCDEF', [1,0,1,0,1,1]) --> A C E F
        c=min(b)         # Sort the lists by first value, and take the first one of these.
        d=c.pop(0)       # Take the first element from c
        r.append(d)      # Append this first element to r
    return r             # Gives back r

Nelle tue soluzioni senza generatore, usa r+=[...]invece di r.append(...)(salva 4 caratteri ogni volta)
hlt

Non intendo alcuna offesa in questo senso, ma se la tua risposta contiene codice in una lingua che è solo un'altra lingua con modifiche fatte appositamente per il golf, lo ridimensionerò. È un peccato, le risposte in vero pitone sono buone.
undergroundmonorail

Se li dividi in post diversi, voterò su quello di Python.
undergroundmonorail

4
@undergroundmonorail Declassate tutte le risposte di GolfScript?
Evpok,

1
@Evpok Ora che lo dici, potresti anche buttarlo su meta e vedere cosa hanno da dire lì.
Aprıʇǝɥʇuʎs

3

C - 75

Questo funziona su NULLarray terminati di int *, sebbene funzionerebbe ugualmente bene per puntatori ad altri tipi sostituendo la funzione di confronto appropriata per **b < **a(ad esempio, strcmp(*b, *a) < 0).

void m(int**a,int**b,int**c){while(*a||*b)*c++=!*a||*b&&**b<**a?*b++:*a++;}

Ungolfed:

void merge(int **a, int **b, int **c)
{
    while(*a || *b)
        *c++ = !*a || *b && **b < **a
            ? *b++
            : *a++;
}

3

Golfscript, 29 27 30 29 26 byte

~{.0=@.0=@<{}{\}if(@@.}do;~]p

o

~{.0=@.0=@>{\}*(@@.}do;~]p

Come funziona

Il comando

golfscript merge.gs <<< '[2 3] [1 4]'

verrà elaborato come segue:

~            # Interpret the input string.
             #
             # STACK: [2 3] [1 4]
{            #
    .@=0.@=0 # Duplicate the two topmost arrays of the stack and extract their first 
             # elements. This reverses the original order of the first copy.
             #
             # STACK: [1 4] [2 3] 2 1
             #
    >        # Check if the respective first elements of the arrays are ordered.
             #
             # STACK: [1 4] [2 3] 1
             #
    {\}*     # If they are not, swap the arrays. This brings the array with the smallest
             # element to the top of the stack.
             #
             # STACK: [2 3] [1 4]
             #
    (@@      # Shift the first element of the array on top of the stack and rotate it
             # behind the arrays.
             #
             # STACK: 1 [2 3] [4]
             #
    .        # Duplicate the topmost array.
             #
             # STACK: 1 [2 3] [4] [4]
             #
}do          # Repeat this process if the array is non-empty.
             #
             # STACK: 1 [2 3] [4] -> 1 2 [4] [3] -> 1 2 3 [4] []
             #
;~           # Delete the empty array from the stack and dump the non-empty array.
             #
             # STACK: 1 2 3 4
             #
]p           # Combine all elements on the stack into a single array, the to a string and
             # print.

L'output è:

[1 2 3 4]

La duplicazione di array in pila lo rende O (n ^ 2)?
swish

@swish: non sono un informatico, ma direi che dipende dall'implementazione. Se l'interprete duplica effettivamente l'intero array, credo che lo faccia.
Dennis,

La versione precedente era O (n ^ 2) per array molto simili (ad esempio, [1 1 1 ... 2]e [1 1 1 ... 3]), poiché il confronto degli array (anziché i loro primi elementi) sarebbe molto lento in questo caso.
Dennis,

Le uniche operazioni dell'array che avvengono nella nuova versione sono la duplicazione, lo scambio e la rotazione nello stack. Poiché gli array duplicati vengono utilizzati solo per estrarre singoli elementi e testare gli array per non vuoto (entrambe le operazioni distruttive in Golfscript), il codice sopra può essere eseguito in tempo O (n) (duplicando, scambiando e ruotando i riferimenti al array). Le prestazioni effettive dipendono dall'interprete.
Dennis,

2

J - 42 33

Versione modificata da qui + il commento di @algorithmshark

k=:(m}.),~0{]
m=:k~`k@.(>&{.) ::,

kantepone il capo dell'array giusto alle code unite di entrambi gli array. k~è lo stesso, ma con array capovolti. (>&{.)sta confrontando le teste. Il codice genererà un errore se uno degli array è vuoto, in tal caso restituiamo solo la loro concatenazione ,.


Presumo che dato che /:~ a,bè la risposta proibita (insieme a [:/:~,), che stai sparando per la risposta più breve che non include /:, giusto?
Dane,

Sottolineerò che la domanda afferma: "Non preoccuparti di elenchi vuoti".
Dane,

@Dane Il test di vuoto necessario per interrompere la ricorsione.
swish

m=:k~`k@.(>&{.)`,@.(0=*&#)salva 2 caratteri.
algoritmo

In effetti, puoi portare tutto a 33 caratteri: k=:(m}.),~0{]e m=:k~`k@.(>&{.) ::,. Usiamo 0{per lanciare un errore quando l'elenco è vuoto, quindi catturiamo quell'errore e usciamo con ,.
algoritmo

2

JavaScript (ES6), 69 79 byte

f=(a,b,c=[])=>(x=a[0]<b[0]?a:b).length?f(a,b,c.concat(x.shift())):c.concat(a,b)

Come funziona

f = (a, b, c = []) =>          // `f' is a function that takes arguments `a', `b' and `c' -
                               // `c' defaults to `[]' - which returns the following
                               // expression:
                               //
 (x = a[0] < b[0] ? a : b)     // Store the array among `a' and `b' with the smaller first 
                               // element in `x'.
                               //
 .length ?                     // If it's non-empty,
                               //
  f(a, b, c.concat(x.shift())) // append the first element of array `x' to array `c' and run
                               // `f' again;
                               //
  : c.concat(a,b)              // otherwise, append the arrays `a' and `b' to `c'.
                               //
)

Il confronto delle matrici con l' <operatore non è valido in quanto esegue un confronto di stringhe:f([123, 456, 789], [1, 2, 3, 4, 5]) => [1, 123, 2, 3, 4, 456, 5, 789]
nderscore

@nderscore: giusto. Non avrebbe funzionato comunque, dal momento che il confronto di tutti gli array potrebbe non essere O (n). Lo stesso sembra essere vero per il test di non vuoto, che deve convertire l'intero array in una stringa.
Dennis,

Sì, non sono sicuro di quale sia il big-o per la conversione del tipo di stringa array->.
nderscore,

1
Concatenare un array con []e quindi convertirlo in una stringa richiede tempo O (n). Farlo una volta per tutti gli n elementi dell'array richiede O (n ^ 2) tempo.
Dennis,

Ha senso. Fatto.
nderscore,

2

Python (63) (69) (71)

def m(a,b):
 if a[0]>b[0]:a,b=b,a
 return[a.pop(0)]+(m(a,b)if a else b)

Ho scritto questo prima di vedere i commenti di OP sui runtime di altre risposte, quindi questa è un'altra soluzione che è O (n) in algoritmo ma non implementazione.


Quali algoritmi hanno estratti dalla parte anteriore delle matrici come O (1)? Quali algoritmi hanno i confronti di elenco prendono O (1)? Inoltre, puoi giocare a golf cambiando ... se ... altro ... in ... e ... o ...
isaacg

@isaacg Spara, mi ero dimenticato delle ripetizioni forse facendo il confronto della lista O (n). Quindi, ho eliminato quell'ottimizzazione per altri 6 personaggi. È possibile estrarre e aggiungere in primo piano in O (1) in un elenco collegato. Non vedo come puoi fare ... e ... o ... giocare bene restituendo il valore.
xnor

OK, ora vedo come fare ... e ... o ..., ma non salva i caratteri a causa delle parentesi necessarie. return[a.pop(0)]+(a and m(a,b)or b)
xnor

@isaacg: per estrarre la parte anteriore di una matrice in O (1), basta aumentare il puntatore della matrice in modo tale che punti al secondo elemento e rilasci la memoria consumata dal primo elemento.
Wrzlprmft,

@Wrzlprmft Non sono riuscito a far funzionare il trucco dell'array perché entrambi gli elementi dell'array vengono valutati indipendentemente dal valore booleano, che genera un errore quando l'elenco è vuoto. C'è un modo breve per creare un "array pigro"?
xnor

2

Haskell, 35 byte

a#b@(c:d)|a<[c]=b#a|0<1=c:a#d
a#_=a

Haskell, 30 byte (non concorrenti)

Questa versione non competitiva garantisce un runtime lineare solo se ae bpresenta elementi disgiunti; altrimenti funziona ancora correttamente ma può usare il tempo quadratico.

a#b|a<b=b#a|c:d<-b=c:a#d
a#_=a

2

PHP 91 98 91 byte

modifica # 1: Vuoto $brichiede una condizione aggiuntiva tra parentesi graffe (+7).
modifica n. 2: golf minori
modifica n. 3: aggiunta seconda versione

abbastanza diretto. La parte più bella è il ternario all'interno del array_shift
(che fallisce se lo provi senza i ricci)

function m($a,$b){for($c=[];$a|$b;)$c[]=array_shift(${$a&(!$b|$a[0]<$b[0])?a:b});return$c;}

o

function m($a,$b){for($c=[];$a|$b;)$c[]=array_shift(${$a?!$b|$a[0]<$b[0]?a:b:b});return$c;}

ungolfed

function m($a,$b)
{
    $c=[];
    while($a||$b)
    {
        $c[] = array_shift(${
            $a&&(!$b||$a[0]<$b[0])
                ?a
                :b
        });
#       echo '<br>', outA($a), ' / ', outA($b) , ' -> ', outA($c);
    }
    return $c;
}

test

$cases = array (
    [1],[0,2,3,4], [0,1,2,3,4],
    [1,5,10,17,19],[2,5,9,11,13,20], [1, 2, 5, 5, 9, 10, 11, 13, 17, 19, 20],
    [1,2,3],[], [1,2,3],
    [],[4,5,6], [4,5,6],
);
function outA($a) { return '['. implode(',',$a). ']'; }
echo '<table border=1><tr><th>A</th><th>B</th><th>expected</th><th>actual result</th></tr>';
while ($cases)
{
    $a = array_shift($cases);
    $b = array_shift($cases);
#   echo '<hr>', outA($a), ' / ', outA($b) , ' -> ', outA($c);
    $expect = array_shift($cases);
    $result=m($a,$b);
    echo '<tr><td>',outA($a),'</td><td>',outA($b),'</td><td>', outA($expect), '</td><td>', outA($result),'</td></tr>';
}
echo '</table>';

Non riuscivo a capire perché non lo $a&(!$b|$a[0]<$b[0])?$a:$b${$a&(!$b|$a[0]<$b[0])?a:b}
rendessi

1
@ JörgHülsermann Il array_shiftparametro viene utilizzato come riferimento. Deve essere una variabile; un'espressione non funzionerà.
Tito

1

Vai, 124 caratteri

func m(a,b[]int)(r[]int){for len(a)>0{if len(b)==0||a[0]>b[0]{a,b=b,a}else{r=append(r,a[0]);a=a[1:]}};return append(r,b...)}

1

JavaScript - 133

function m(a,b){c=[];for(i=j=0;i<a.length&j<b.length;)c.push(a[i]<b[j]?a[i++]:b[j++]);return c.concat(a.slice(i)).concat(b.slice(j))}

Stesso tipo di approccio degli OP.


1

perl, 87 caratteri / perl 5.14, 78 + 1 = 79 caratteri

Questa implementazione limita i riferimenti dell'array di input. A parte questo, è piuttosto semplice: mentre entrambi gli array hanno qualcosa, spostarsi dalla parte inferiore delle due. Quindi restituisce il bit unito unito a tutti i bit rimanenti (rimarrà solo uno di @ $ x o @ $ y). Straight-up perl5, 87 caratteri:

sub M{($x,$y,@o)=@_;push@o,$$x[0]>$$y[0]?shift@$y:shift@$x while@$x&&@$y;@o,@$x,@$y}

Usando il perl 5.14.0 e il suo nuovo turno di arrayref: 78 caratteri + 1 penalità di carattere = 79 caratteri:

sub M{($x,$y,@o)=@_;push@o,shift($$x[0]>$$y[0]?$y:$x)while@$x&&@$y;@o,@$x,@$y}

*invece di &&salverà un byte. E ancora di più sesub M{map{shift(!@$x+@$y*($$y[0]<$$x[0])?$y:$x)}map@$_,($x,$y)=@_}
user2846289

@VadimR, wow. bel lavoro. Vai avanti e pubblicalo se vuoi - non avrei mai pensato di fare il doppio trucco della mappa invece di spingere su un array.
skibrianski

1

Java: 144

Questo è piuttosto semplice. Una funzione che accetta due array e ne restituisce uno, la versione unita, golfizzata e senza wrapper di compilazione:

int[]m(int[]a,int[]b){int A=a.length,B=b.length,i,j;int[]c=new int[A+B];for(i=j=0;i+j<A+B;c[i+j]=j==B||i<A&&a[i]<b[j]?a[i++]:b[j++]);return c;}

Ungolfed (con wrapper compilabile e eseguibile):

class M{
    public static void main(String[]args){
        int[]a=new int[args[0].split(",").length];
        int i=0;
        for(String arg:args[0].split(","))
            a[i++]=Integer.valueOf(arg);
        int[]b=new int[args[1].split(",").length];
        int j=0;
        for(String arg:args[1].split(","))
            b[j++]=Integer.valueOf(arg);
        int[]c=(new M()).m(a,b);
        for(int d:c)
            System.out.printf(" %d",d);
        System.out.println();
    }
    int[]m(int[]a,int[]b){
        int A=a.length,B=b.length,i,j;
        int[]c=new int[A+B];
        for(i=j=0;i+j<A+B;c[i+j]=j==B||i<A&&a[i]<b[j]?a[i++]:b[j++]);
        return c;
    }
}

Esecuzioni di esempio:

$ javac M.java
$ java M 10,11,12 0,1,2,20,30
 0 1 2 10 11 12 20 30
$ java M 10,11,12,25,26 0,1,2,20,30
 0 1 2 10 11 12 20 25 26 30

Eventuali suggerimenti per accorciare sarebbero apprezzati.


1

Scala, 97 byte

Soluzione ricorsiva con O (n). Per abbreviare il codice, a volte un'operazione viene eseguita commutando i 2 parametri intercambiabili, ovvero f (a, b) chiama f (b, a).

type L=List[Int];def f(a:L,b:L):L=if(a==Nil)b else if(a(0)<=b(0))a(0)::f(a.drop(1),b) else f(b,a)

Ungolfed:

type L=List[Int]

def f(a:L, b:L) : L =
  if (a == Nil)
    b 
  else 
    if (a(0) <= b(0))
      a(0) :: f(a.drop(1), b) 
    else
      f(b,a)

Eccezione se a non è vuoto, ma b è vuoto
Dan Osipov,

1

APL (32)

{⍺⍵∊⍨⊂⍬:⍺,⍵⋄g[⍋g←⊃¨⍺⍵],⊃∇/1↓¨⍺⍵}

Spiegazione:

{⍺⍵∊⍨⊂⍬                               if one or both of the arrays are empty
        :⍺,⍵                           then return the concatenation of the arrays
             ⋄g[⍋g←⊃¨⍺⍵]              otherwise return the sorted first elements of both arrays
                          ,⊃∇/        followed by the result of running the function with
                               1↓¨⍺⍵}  both arrays minus their first element

1

LISP, 117 byte

L'algoritmo termina in n + 1iterazioni, dove nè la lunghezza dell'elenco più breve in input.

(defun o(a b)(let((c(car a))(d(car b)))(if(null a)b(if(null b)a(if(< c d)(cons c(o(cdr a)b))(cons d(o a(cdr b))))))))

0

PYG (50)

def m(*a):
 while An(a):yield Mn(ItCo(a,a)).pop(0)

PYG (di nuovo 64, se non sono consentiti generatori.):

def m(*a):
 r=[]
 while An(a):r+=[(Mn(ItCo(a,a)).pop(0)]
 return r

Un adattamento della mia risposta Python .


0

Python - 69 byte

def m(A,B):
    C=[]
    while A and B:C+=[[A,B][A>B].pop(0)]
    return C+A+B

Se l'ordine di input e output scendesse, questo potrebbe essere ridotto a 61 byte :

def m(A,B):
    C=[]
    while A+B:C+=[[A,B][A<B].pop(0)]
    return C

E più in basso fino a 45 byte se i generatori sono ammessi:

def m(A,B):
    while A+B:yield[A,B][A<B].pop(0)

Questo non è sicuramente O (n). .pop (0) e + = sono entrambe operazioni O (n) eseguite O (n) volte.
isaacg

Fino ad ora non sapevo nemmeno che le liste non fossero implementate come liste in Python e anche allora pop(0)possono essere implementate in O (1) e +=almeno possono essere implementate meglio di O (n) (vedi il link). A proposito, la tua soluzione usa +=(cioè, appende extend) tutte le volte che la mia. Comunque, tutto ciò che è una domanda di implementazione (per quanto ne so), quindi in un'implementazione (fittizia) di Python, in cui gli elenchi sono implementati come elenchi, la mia funzione è O (n). Alla fine la tua domanda richiedeva che l' algoritmo fosse O (n), e il mio lo è.
Wrzlprmft,

In realtà, aggiungere ed estendere sono implementati diversamente in Python rispetto a + =. + = crea un nuovo elenco, mentre .append e .extend ne modificano uno esistente.
isaacg

0

Perl 6: 53 caratteri

sub M(\a,\b){{shift a[0]>b[0]??b!!a}...{a^b},a[],b[]}

Passa dal valore più piccolo ao bha il valore più piccolo, fino a quando aXOR b( a^b) è true. Quindi restituisce tutto ciò che rimane, appiattendo ( []) le matrici nell'elenco ( a[],b[]).

Supponendo che lo spostamento dall'inizio di un array sia O (n), il caso peggiore è due confronti e uno spostamento per elemento, quindi l'algoritmo è O (n).


0

JavaScript (ES5) 90 86 90 byte

function f(a,b){for(o=[];(x=a[0]<b[0]?a:b).length;)o.push(x.shift());return o.concat(a,b)}

edit: (90 -> 86) Spostato il ternario nella condizione di ciclo for. Idea rubata a Dennis.

edit: (86 -> 90) Array rimosso per il cast delle stringhe, poiché infrange il requisito O (n) .


0

Mathematica, 137 135

m[a_,b_]:=(l=a;Do[Do[If[b[[f]]<=l[[s]],(l=Insert[l,b[[f]],s];Break[]),If[s==Length@l,l=l~Append~b[[f]]]],{s,Length@l}],{f,Length@b}];l)

Ingresso:

m[{2,2,4,6,7,11},{1,2,3,3,3,3,7}]

Produzione:

{1, 2, 2, 2, 3, 3, 3, 3, 4, 6, 7, 7, 11}

Ungolfed:

mergeList[a_, b_] := (
    list = a;
    Do[
        Do[(
            If[
                b[[f]] <= list[[s]],
                (list = Insert[list, b[[f]], s]; Break[]),
                If[
                    s == Length@list,
                    list = list~Append~b[[f]]
                ]
        ]),
        {s, Length@list}
    ],
    {f, Length@b}
    ];
    list
)

Probabilmente potrebbe fare di meglio.


m[a:{x___,y_},b:{___,z_}]:=If[y<z,b~m~a,{x}~m~b~Join~{y}];{}~m~b_=b;
alephalpha,

0

R, 80

Stessa soluzione di Scala e di altre lingue. Non sono così sicuro che x [-1] sia O (1).

f=function(a,b)if(length(a)){if(a[1]<=b[1])c(a[1],f(a[-1],b))else f(b,a)}else b

0

Mathematica, 104 byte

Reap[{m,n}=Length/@{##};i=k=1;Do[If[k>n||TrueQ[#[[i]]<#2[[k]]],Sow@#[[i++]],Sow@#2[[k++]]],n+m]][[2,1]]&

Funzione anonima, memorizza la lunghezza dei due elenchi di input nelle variabili me n, quindi ogni iterazione del Doloop Sowè un elemento di uno degli elenchi che incrementano il contatore per quell'elenco ( iper il primo, kper il secondo) di uno. Se uno dei contatori supera la lunghezza dell'elenco, l' Ifistruzione sarà sempre Sowl'elemento dell'altro elenco. Dopo le n+moperazioni, tutti gli elementi sono stati curati.Reapo meglio, parte [[2,1]]del suo output è un elenco di elementi nell'ordine in cui sono statiSow n.

Non sono sicuro degli interni (l'accesso a una parte di una lista è O(1)un'operazione o meno), ma i tempi sembravano abbastanza lineari sulla mia macchina rispetto alla lunghezza della lista di input.

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.