Como cualquiera de las dos listas dato se pueden usar para comenzar la intercalación, esto nos sugiere una estrategia de dividir y conquistar que puede comenzar con: intercala(L1, L2, N1, N2, R) :- intercala_primero_lista1(L1, L2, N1, N2, R). intercala(L1, L2, N1, N2, R) :- intercala_primero_lista2(L1, L2, N1, N2, R). Entonces hemos desdoblado el problema en dos casos que cada uno es espejo del otro. Tomemos el primero de los casos y desarrollémoslo: Como lo que se pretende es poner los 'n' primeros elementos de una u otra lista, lo primero que desarrollamos es un predicado n_primeros/4 que tiene el siguiente esqueleto: n_primeros(+entero, +lista, ?lista_prefijo, ?lista_sufijo). donde lista es la lista que hay que partir, y el entero marca la cantidad que irá en lista_prefijo; el resto de la lista irá en lista_sufijo. Por ejemplo: | ?- n_primeros(3, [a,b,c,d,e,f,g,h], X, Xs). X = [a,b,c] Xs = [d,e,f,g,h] Retomamos intercala_primero_lista1/5. La primer cláusula que nos viene a la mente es la reescritura en Prolog del enunciado del problema: intercala_primero_lista1(L1, L2, N1, N2, Z) :- n_primeros(N1, L1, N1_de_L1, Resto_L1), n_primeros(N2, L2, N2_de_L2, Resto_L2), intercala_primero_lista1(Resto_L1, Resto_L2, N1, N2, Y), append(N1_de_L1, N2_de_L2, X), append(X, Y, Z). O sea, que para intercalar primero la lista L1 con la lista L2, lo que hay que hacer es averiguar cuáles son los N1 primeros elementos de L1, y los N2 primeros elementos de L2, concatenarlos y eso debe usarse como primera parte de la lista resultado. El resto de la lista resultado saldrá recursivamente de intercalar primero lo que queda de la lista L1 con lo que queda de la lista L2. Lo más importante aquí es que si comencé intercalando L1, las recursiones sigan intercalando primero L1. De manera análoga en el caso de intercalar primero L2. Nota: Porqué no puedo usar un único predicado para intercalar de ambos lados? Puede aparecer el problema de las relaciones simétricas, que en Prolog lleva a bucles infinitos. Vamos a trabajar ahora sobre el caso base. Se pueden dar dos diferentes situaciones: a) Cuando la cantidad de elementos de las listas es tal que se produce la intercalación de los elementos de la lista 1 y lista 2 una cierta cantidad de veces. En este caso ambas listas se vacían a la vez: intercala_primero_lista1([], [], _, _, []) :- !. Ejemplo: | ?- intercala_primero_lista1([a1,a2,a3,a4], [b1,b2], 2, 1, X). X = [a1,a2,b1,a3,a4,b2] yes b) Cuando se vacía la lista 2, y quedan exactamente los necesarios de la lista 1 para ponerlos al final del resultado intercala_primero_lista1(X, [], N1, _, X) :- n_primeros(N1, X, X, []), !. Ejemplo: | ?- intercala_primero_lista1([a1,a2,a3,a4], [b1], 2, 1, X). X = [a1,a2,b1,a3,a4] yes Entonces lo que hemos hecho hasta ahora con intercala_primero_lista1/5 nos queda: intercala_primero_lista1([], [], _, _, []) :- !. intercala_primero_lista1(X, [], N1, _, X) :- n_primeros(N1, X, X, []), !. intercala_primero_lista1(L1, L2, N1, N2, Z) :- n_primeros(N1, L1, N1_de_L1, Resto_L1), n_primeros(N2, L2, N2_de_L2, Resto_L2), intercala_primero_lista1(Resto_L1, Resto_L2, N1, N2, Y), append(N1_de_L1, N2_de_L2, X), append(X, Y, Z). De manera análoga podemos razonar el caso que se desee intercalar primero la lista 2, lo cual nos lleva al código faltante para completar el ejercicio: intercala_primero_lista2([], [], _, _, []) :- !. intercala_primero_lista2([], X, _, N2, X) :- n_primeros(N2, X, X, []), !. intercala_primero_lista2(L1, L2, N1, N2, Z) :- n_primeros(N1, L1, N1_de_L1, Resto_L1), n_primeros(N2, L2, N2_de_L2, Resto_L2), intercala_primero_lista2(Resto_L1, Resto_L2, N1, N2, Y), append(N2_de_L2, N1_de_L1, X), append(X, Y, Z). Las pruebas que hemos previsto han pasado satisfactoriamente, y por lo tanto lo damos por terminado. EOF ej-03.txt