Come posso generare tutte le combinazioni possibili degli elementi di un elenco?
Ad esempio, data la lista [1,2,3], voglio progettare un predicato con la forma comb([1,2,3], L).
che dovrebbe restituire il seguente risposta per L:
[1]
[2]
[3]
[1,2]
[2,1]
[1,3]
[3,1]
[2,3]
[3,2]
[1,2,3]
[1,3,2]
[2,1,3]
[2,3,1]
[3,1,2]
[3,2,1]
Combinazioni consentite degli elementi di un elenco - Prolog
risposta
Ciò che si richiede riguarda entrambe le combinazioni (selezione di un sottoinsieme) e permutazioni (riorganizzazione dell'ordine) di un elenco.
L'output di esempio implica che la lista vuota non è considerata una soluzione valida, quindi la escluderemo nell'implementazione che segue. Riconsiderare se questa è stata una svista. Anche questa implementazione produce le soluzioni in un ordine diverso rispetto all'output di esempio.
comb(InList,Out) :-
splitSet(InList,_,SubList),
SubList = [_|_], /* disallow empty list */
permute(SubList,Out).
splitSet([ ],[ ],[ ]).
splitSet([H|T],[H|L],R) :-
splitSet(T,L,R).
splitSet([H|T],L,[H|R]) :-
splitSet(T,L,R).
permute([ ],[ ]) :- !.
permute(L,[X|R]) :-
omit(X,L,M),
permute(M,R).
omit(H,[H|T],T).
omit(X,[H|L],[H|R]) :-
omit(X,L,R).
Testato con Amzi! Prolog:
?- comb([1,2,3],L).
L = [3] ;
L = [2] ;
L = [2, 3] ;
L = [3, 2] ;
L = [1] ;
L = [1, 3] ;
L = [3, 1] ;
L = [1, 2] ;
L = [2, 1] ;
L = [1, 2, 3] ;
L = [1, 3, 2] ;
L = [2, 1, 3] ;
L = [2, 3, 1] ;
L = [3, 1, 2] ;
L = [3, 2, 1] ;
no
Suggerimento: Questo è facile da fare se avete scritto un predicato inselt(X,Y,Z)
, che detiene eventuale inserimento di Y
in X
dà Z
:
inselt([E|X], Y, [E|Z]) :- inselt(X,Y,Z).
inselt(X, Y, [Y|X]).
Poi comb/3
possono essere codificati in modo ricorsivo utilizzando inselt/3
.
v'è un predicato predefinito denominato permutazione ...
1 ?- permutation([1,2,3],L).
L = [1, 2, 3] ;
L = [2, 1, 3] ;
L = [2, 3, 1] ;
L = [1, 3, 2] ;
L = [3, 1, 2] ;
L = [3, 2, 1] .
2 ?- listing(permutation).
lists:permutation([], [], []).
lists:permutation([C|A], D, [_|B]) :-
permutation(A, E, B),
select(C, D, E).
lists:permutation(A, B) :-
permutation(A, B, B).
true.
speranza che questo aiuti ..
È sicuramente utile vedere come si può descrivere le permutazioni (+1!). Una caratteristica istruttiva di questo codice è che 'permutation/3' è * not * tail ricorsivo, e che scambiare i due obiettivi tipicamente aumenta il runtime di un ampio margine. È anche elegante e piacevole da guardare, coinvolgendo solo codice puro. Si noti però che l'OP richiede qualcosa di leggermente diverso: la domanda riguarda le permutazioni delle sottosequenze, non necessariamente comprendendo l'intera lista. Dai un'occhiata alla soluzione breve, elegante e pura di @ repeat! – mat
Resta pura definendo comb/2
sulla base di same_length/2
, prefix/2
, foldl/4
e select/3
:
comb(As,Bs) :- same_length(As,Full), Bs = [_|_], prefix(Bs,Full), foldl(select,Bs,As,_).
Ecco la query di esempio proposta dal OP:
?- comb([1,2,3],Xs).
Xs = [1]
; Xs = [2]
; Xs = [3]
; Xs = [1,2]
; Xs = [1,3]
; Xs = [2,1]
; Xs = [2,3]
; Xs = [3,1]
; Xs = [3,2]
; Xs = [1,2,3]
; Xs = [1,3,2]
; Xs = [2,1,3]
; Xs = [2,3,1]
; Xs = [3,1,2]
; Xs = [3,2,1]
; false.
Ok! Ma cosa succede se la lista data come primo argomento contiene duplicati?
?- comb([1,1,2],Xs).
Xs = [1]
; Xs = [1] % (redundant)
; Xs = [2]
; Xs = [1,1]
; Xs = [1,2]
; Xs = [1,1] % (redundant)
; Xs = [1,2] % (redundant)
; Xs = [2,1]
; Xs = [2,1] % (redundant)
; Xs = [1,1,2]
; Xs = [1,2,1]
; Xs = [1,1,2] % (redundant)
; Xs = [1,2,1] % (redundant)
; Xs = [2,1,1]
; Xs = [2,1,1] % (redundant)
; false.
Non proprio! Possiamo sbarazzarci delle risposte ridondanti sopra? Sì, usa semplicemente selectd/3
!
comb(As,Bs) :- same_length(As,Full), Bs = [_|_], prefix(Bs,Full), foldl(selectd,Bs,As,_).
Quindi cerchiamo di eseguire nuovamente sopra di query di nuovo con la migliore attuazione delle comb/2
!
?- comb([1,1,2],Xs).
Xs = [1]
; Xs = [2]
; Xs = [1,1]
; Xs = [1,2]
; Xs = [2,1]
; Xs = [1,1,2]
; Xs = [1,2,1]
; Xs = [2,1,1]
; false.
Ottima soluzione, +1! Spero che presto vedremo una libreria contenente tutti questi predicati elementari puri! 'library (purple)': * Pure Prolog Library (Elementare) *? – mat
- 1. Prolog rimuovi elementi multipli da un elenco
- 2. Get combinazioni uniche di elementi da un elenco di pitone
- 3. Somma degli elementi nell'elenco in Prolog
- 4. Combinazioni possibili di un elenco
- 5. Ordinare un elenco in Prolog
- 6. Prolog: come ottenere tutte le combinazioni
- 7. Intersezione tutte le possibili combinazioni di elementi di elenco
- 8. Applicare una funzione a tutte le combinazioni a coppie degli elementi di elenco in R
- 9. Riproduzione casuale di elementi in un elenco (riordinamento casuale degli elementi di elenco)
- 10. Definizione degli elenchi negli script prolog
- 11. Ottenere tutte le combinazioni possibili da un elenco di numeri
- 12. Clojure: come ottengo un elenco di combinazioni di "coordinate"?
- 13. Moltiplicazione delle combinazioni di un elenco di elenchi in R
- 14. Nidificare gli elementi dell'elenco all'interno degli elementi di un elenco ordinato?
- 15. Haskell: elenco degli elementi con restrizione di classe
- 16. Elementi concatenati di un elenco
- 17. Elenco degli elementi di tipi sono limitati dal typeclass
- 18. Pensare al Prolog e ad Haskell - Generare liste di combinazioni di valori di verità
- 19. Recupera un elenco di elementi correlati di un elenco di elementi in un array di basi
- 20. Genera tutte le combinazioni possibili degli elementi di alcuni vettori (prodotto cartesiano)
- 21. restituisce un elenco di elementi da un elenco in OCaml
- 22. Disattivazione degli avvisi in swi-prolog
- 23. Prolog: articolo singolo vs elenco singolo elemento
- 24. Cerca un elenco di elementi stringa che corrispondono ad un altro elenco di elementi stringa
- 25. Nice & modo universale per convertire Elenco degli elementi da Albero
- 26. Come eliminare l'ultimo elemento da un elenco in Prolog?
- 27. trucchi per elementi mobili all'interno degli elementi di lista
- 28. Come operare sugli elementi di un elenco?
- 29. Formatta tutti gli elementi di un elenco
- 30. Rimozione di elementi da un elenco
[1] non è di solito chiamato una combinazione di [1,2,3]: Sto indovinando questo non è quello che vuoi dire. –