Ordenar fusión
En este desafío, implementará la subrutina de fusión del tipo de fusión. Específicamente, debe crear una función o programa o verbo o similar que tome dos listas, cada una ordenada en orden creciente, y las combine en una lista ordenada en orden creciente. Requisitos:
- Su algoritmo debe tomar una cantidad de tiempo asintóticamente lineal en el tamaño de la entrada. Por favor, deje de dar soluciones O (n ^ 2).
- No puede usar ninguna función incorporada capaz de ordenar una lista, o fusionar una lista, o algo así. Discreción del autor.
- El código debe poder manejar elementos repetidos.
- No te preocupes por las listas vacías.
Ejemplos:
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]
Este es el código de golf , ¡así que gane el código más corto!
b=a;b=b.length
podría duplicar toda la matriza
(y dar como resultado un tiempo O (n ^ 2) si se ejecuta para cada elemento) o duplicar solo la referencia a la matriz (tiempo O (n)). ¿Cuál cuenta?Respuestas:
Rebmu (
3532 caracteres)Prueba
Acerca de
Rebmu es un dialecto de Rebol que permite 'mezclar' el código regular para situaciones que requieren brevedad. Impecable, el código funciona algo así como:
Creo que esto satisface el requisito de O (n) , ya que el bloque hasta se repite tantas veces como la longitud de la entrada (y
reverse
solo cambia el orden del contenedor de los bloques de entrada, no los bloques en sí). Usartake
es quizás una libertad, pero sigue siendo un golpe de eficiencia menor.Rebol (
8375 caracteres)Solo un poquito diferente: en Rebol, las rutas son una expresión más corta que
first
osecond
.a
es el bloque de entrada que contiene los dos bloques:fuente
Soluciones de OP:
Haskell
494440Python
1311051019993Gracias a @Evpok:
fuente
a%b=a++b
después de la coincidencia del patrón principal para manejar listas vacías, que eliminará un par de caracteres.Pitón (79)
Python (95, si no se nos permite devolver un generador)
Itertools es la solución para todos los problemas mundanos.
Bonificación: los dos trabajan en un número arbitrario de listas, y SE PREOCUPAN por las listas vacías (como en, felizmente tomarán 2 listas vacías y devolverán una lista vacía, o tomarán 1 lista vacía y 1 lista no vacía, y devolverán el no vacío. Otra característica adicional de los 2 no cedidos: también se ejecutarán sin argumentos, y solo devolverán una lista vacía).
Sin golf:
fuente
r+=[...]
lugar der.append(...)
(ahorra 4 caracteres cada vez)C - 75
Esto opera en
NULL
matrices terminadas deint *
, aunque funcionaría igualmente bien para punteros a otros tipos al sustituir la función de comparación apropiada para**b < **a
(por ejemplo,strcmp(*b, *a) < 0
).Sin golf:
fuente
Golfscript,
2927302926 byteso
Cómo funciona
El comando
se procesará de la siguiente manera:
El resultado es:
fuente
[1 1 1 ... 2]
y[1 1 1 ... 3]
), ya que comparar las matrices (en lugar de sus primeros elementos) sería muy lento en este caso.J -
4233Versión modificada desde aquí + el comentario de @algorithmshark
k
antepone la cabecera de la matriz derecha a las colas fusionadas de ambas matrices.k~
es lo mismo, pero con las matrices invertidas.(>&{.)
está comparando las cabezas. El código arrojará un error si una de las matrices está vacía, en ese caso solo devolveremos su concatenación,
.fuente
/:~ a,b
es la respuesta prohibida (junto con[:/:~,
), que está buscando la respuesta más corta que no incluye/:
, ¿verdad?m=:k~`k@.(>&{.)`,@.(0=*&#)
ahorra 2 char.k=:(m}.),~0{]
ym=:k~`k@.(>&{.) ::,
. Usamos0{
para lanzar un error cuando la lista está vacía, y luego capturamos ese error y salimos con,
.JavaScript (ES6),
6979 bytesCómo funciona
fuente
<
operador no es válido como lo hace una comparación de cadenas:f([123, 456, 789], [1, 2, 3, 4, 5]) => [1, 123, 2, 3, 4, 456, 5, 789]
[]
y luego convertirla en una cadena requiere tiempo O (n). Hacerlo una vez para todos los n elementos de la matriz lleva O (n ^ 2) tiempo.Pitón
(63) (69)(71)Escribí esto antes de ver los comentarios de OP sobre tiempos de ejecución de otras respuestas, por lo que esta es otra solución que es O (n) en el algoritmo pero no en la implementación.
fuente
return[a.pop(0)]+(a and m(a,b)or b)
Haskell, 35 bytes
Haskell, 30 bytes (no competitivos)
Esta versión no competitiva solo garantiza un tiempo de ejecución lineal si
a
yb
tiene elementos disjuntos; de lo contrario, todavía se ejecuta correctamente, pero puede usar tiempo cuadrático.fuente
PHP
91 9891 bytesedit # 1: Empty
$b
requiere una condición adicional en las llaves (+7).editar # 2: campos de golf menores
editar # 3: segunda versión agregada
muy claro. La mejor parte es el ternario dentro del
array_shift
(que falla si lo intentas sin los rizos)
o
sin golf
prueba
fuente
$a&(!$b|$a[0]<$b[0])?$a:$b
lugar de${$a&(!$b|$a[0]<$b[0])?a:b}
array_shift
parámetro se utiliza como referencia. Tiene que ser una variable; una expresión no funcionará.Go, 124 caracteres
fuente
JavaScript - 133
El mismo tipo de enfoque que los OP.
fuente
perl, 87 caracteres / perl 5.14, 78 + 1 = 79 caracteres
Esta implementación registra las referencias de la matriz de entrada. Aparte de eso, es bastante sencillo: si bien ambas matrices tienen algo, cambie la parte inferior de las dos. Luego, devuelva el bit combinado junto con los bits restantes (solo quedará uno de @ $ x o @ $ y). Perl5 recto, 87 caracteres:
Usando perl 5.14.0 y su nuevo cambio de arrayref: 78 caracteres + 1 penalización de char = 79 caracteres:
fuente
*
en lugar de&&
guardará un byte. Y aún más sisub M{map{shift(!@$x+@$y*($$y[0]<$$x[0])?$y:$x)}map@$_,($x,$y)=@_}
Java: 144
Esto es bastante sencillo. Una función que toma dos matrices y devuelve una, la versión fusionada, golfizada y sin envoltorio de compilación:
Sin golf (con envoltorio ejecutable y compilable):
Ejecuciones de ejemplo:
Cualquier consejo para acortar sería apreciado.
fuente
Scala, 97 bytes
Solución recursiva con O (n). Para acortar el código, a veces se realiza una operación cambiando los 2 parámetros intercambiables, es decir, f (a, b) llama a f (b, a).
Sin golf:
fuente
APL (32)
Explicación:
fuente
LISP, 117 bytes
El algoritmo termina en
n + 1
iteraciones, donden
es la longitud de la lista más corta en la entrada.fuente
PYG (50)
PYG (64, nuevamente, si no se permiten generadores):
Una adaptación de mi respuesta de Python .
fuente
Python - 69 bytes
Si el orden de entrada y salida descendiera, esto podría acortarse a 61 bytes :
Y más abajo a 45 bytes si se permiten generadores:
fuente
pop(0)
se pueden implementar en O (1) y+=
al menos se pueden implementar mejor que O (n) (vea el enlace). Por cierto, su solución usa+=
(es decir,append
yextend
) con tanta frecuencia como la mía. De todos modos, todo eso es una pregunta de implementación (hasta donde yo sé), por lo que en una implementación de Python (ficticia), donde las listas se implementan como listas, mi función es O (n). Finalmente, su pregunta requería que el algoritmo fuera O (n), y el mío es.Perl 6: 53 caracteres
Pasar de cualquiera de
a
ob
tiene el valor más pequeño, hastaa
XORb
(a^b
) es verdadera. Luego devuelva lo que quede, aplanar ([]
) las matrices en la lista (a[],b[]
).Suponiendo que el cambio desde el comienzo de una matriz es O (n), el peor de los casos es dos comparaciones y un cambio por elemento, por lo que el algoritmo es O (n).
fuente
JavaScript (ES5)
908690 byteseditar: (90 -> 86) Se movió el ternario a la condición de bucle for. Idea robada de Dennis.
editar: (86 -> 90) Se eliminó la distribución de matriz a cadena, ya que rompe el requisito de O (n) .
fuente
Mathematica
137135Entrada:
Salida:
Sin golf:
Probablemente podría hacerlo mejor.
fuente
m[a:{x___,y_},b:{___,z_}]:=If[y<z,b~m~a,{x}~m~b~Join~{y}];{}~m~b_=b;
R, 80
La misma solución que en Scala y otros idiomas. No estoy tan seguro de que x [-1] sea O (1).
fuente
Mathematica, 104 bytes
La función anónima almacena la longitud de las dos listas de entrada en las variables
m
yn
, luego, cada iteración delDo
bucleSow
es un elemento de una de las listas que incrementa el contador de esa lista (i
para el primero,k
para el segundo) en uno. Si uno de los contadores excede la longitud de la lista, laIf
instrucción siempre seráSow
el elemento de la otra lista. Después de lasn+m
operaciones, todos los elementos han sido atendidos.Reap
o más bien parte[[2,1]]
de su salida es una lista de elementos en el orden en que han sidoSow
n.No estoy seguro de las partes internas (está accediendo a una parte de una lista, una
O(1)
operación o no), pero los tiempos se veían bastante lineales en mi máquina con respecto a la longitud de la lista de entrada.fuente