Estoy intentando crear un programa que tome una lista y escriba todos sus elementos en líneas separadas en un grupo de elementos N por línea.

P.ej. consultas del usuario print(3,[a,s,d,t,s,t]).

Prolog escribe:

asd
tst

Me quedé atrapado en el punto donde el programa enumera los primeros elementos (N) pero no pasa a la siguiente línea. ¿Podría alguien ayudarme a señalar mi error?

print(N,[H|T]):-
    N>=1,
    write(H),
    N1 is N-1,
    print(N1,T),
    nl,
    print(N,T).
1
Lenka 21 ene. 2018 a las 12:40

3 respuestas

La mejor respuesta

Necesita dos números, ya que debe comenzar desde N en cada nueva línea. Además, dos casos base (final de línea, final de lista).

print(N,L):-
  print(N,N,L).

print(N,I,[H|T]):-
  ( I >= 1 ->
    write(H),
    I1 is I-1,
    print(N,I1,T)
  ; nl,
    print(N,N,[H|T]) ).
print(_,_,[]).
1
Tomas By 21 ene. 2018 a las 11:37

Aquí hay otro enfoque usando length/2 y append/3. Es transparente, pero creo que es un poco duro en comparación con la solución de Tomás.

print_substring([]).
print_substring([H|T]) :-
    write(H),
    print_substring(T).

print_substrings(N, L) :-
    length(S, N),
    (   append(S, R, L)
    ->  print_substring(S), nl,
        print_substrings(N, R)
    ;   print_substring(L), nl
    ).

Lo que resulta en:

| ?-  print_substrings(3, [a,b,c,d,e]).
abc
de

yes
| ?-

NOTA: Cuando elige nombres para variables o predicados, es bueno evitar nombres muy genéricos, como print. print resulta ser un predicado de biblioteca en algunos Prólogos, por lo que crear un predicado de ese nombre en su propio código puede generar un conflicto.

1
lurker 21 ene. 2018 a las 19:02

Puede dividir su código en dos partes. La primera función print/2, es la API, y print/3 será su función principal.

print/2 tomará un número entero y una lista de átomos y llamará print/3.

print(N, L) :-
  print(N, L, []).

print/3 y print/2 son prácticamente iguales, excepto que print/3 tomará un Buffer (como lista) en el último argumento:

% if our list of atom is empty
% we just print Buf content and stop
print(_, [], Buf) :- 
  reverse(Buf, Atoms),
  atom_string(Atoms, String),
  format("~s~n", [String]).

% if our list of atom contain an head and tail
% we check if length of Buf is equal to N
print(N, [H|T], Buf) :-
  length(Buf, N), 
    % if its the case, we print our Buf and use
    % the rest of list of atoms
    reverse(Buf,Atoms), 
    atom_string(Atoms, String),
    format("~s~n", [String]), 
    print(N, [H|T])
  ;
    % else we take the head and concate it
    % with Buf.
    print(N, T, [H|Buf]).

Puede probar este código con la swipl intérprete.

?- [myprint].
?- print((3,[a,s,f,t,s,t]).
asf
tst
?- print(4,[a,s,f,t,s,t]).
asft
st
0
Mathieu Kerjouan 21 ene. 2018 a las 11:27