2013-11-21 15 views
6

Voglio creare una regola in prolog che controlli se c'è un numero ripetuto in una lista.Controllare se tutti i numeri in una lista sono diversi in prolog

Ad esempio:

  • per [1,2,3,4] tornerà true.
  • per [1,2,3,3] tornerà false perché il 3 si ripete

sono arrivato fino a questa regola, ma non funziona

Different([]). 
Different([H|T]):- 
    Member(H,T), 
    Different(T). 

Tutte le idee?

+3

Che tipo di sintassi Prolog è quello? – false

risposta

-3

Questo non è molto efficiente, ma per ogni numero è possibile controllare se viene visualizzato di nuovo più tardi. In questo modo:

Different([H|T]):- 
    CheckSingle(H, [T]), 
    Different([T]). 

Checksingle(_,[]). 

Checksingle(Elem, [H, T]):- 
    Elem != H, 
    Checksingle(Elem, [T]). 
+3

-1 per non provare la propria risposta. I predicati devono iniziare con un carattere minuscolo. – kay

4

Il modo più semplice per verificare che tutti i membri della lista sono unici è quello di ordinare la lista e verificare che la lunghezza della lista ordinata è pari della lunghezza della lista originale.

different(X) :- 
    sort(X, Sorted), 
    length(X, OriginalLength), 
    length(Sorted, SortedLength), 
    OriginalLength == SortedLength. 

La soluzione non funziona a causa della sintassi sbagliata (fatti e predicati non dovrebbero iniziare con una lettera maiuscola) e un errore logico. Elenco è unico se testa H non un membro di una coda T di un elenco e coda T è unico:

different([]). 
different([H|T]):- 
    \+member(H,T), 
    different(T). 
9

una definizione compatto potrebbe essere

all_diff(L) :- \+ (select(X,L,R), memberchk(X,R)). 

cioè tutti gli elementi sono diversi se non possiamo sbirciare e trovarlo nel resto ...

modificare

efficienza (marginalmente) migliorare Let: è inutile per verificare se X è membro della sottolista prefisso, quindi:

all_diff(L) :- \+ (append(_,[X|R],L), memberchk(X,R)). 
0

Un modo pulito mi è venuto in mente è la seguente:

Se tutti i membri di una lista sono diverse l'una dall'altra, quindi se dico a prolog di scegliere tutte le coppie (I,J) tali che I,J sono membri della lista e anche I è uguale a J, quindi per ogni elemento della lista sarà solo in grado di trovare una coppia, che è l'elemento con se stesso.

Pertanto, se siamo in grado di mettere tutte queste coppie in una lista, la lunghezza di questa lista dovrebbe essere della stessa lunghezza della lista originale.

Ecco il mio codice di prologo:

all_diff(L) :- 
     findall((I,J), (member(I, L), member(J, L), I == J), List), 
     length(L, SupposedLength), 
     length(List, CheckThis), 
     SupposedLength == CheckThis. 
+0

Nota: questo potrebbe non essere efficiente come le altre risposte considerando il runtime, ma per gli studenti di Programmazione logica come me, è vietato usare l'operatore ** not ** ('' \ + ''), e ho avuto per trovare un modo che non lo usa. – TheNotMe

+1

'all_dif ([X, Y]), X = Y' ha successo errato – false

4

Se tutti i numeri in tale elenco sono interi, e se l'implementazione Prolog offre , non c'è bisogno di scrivere nuovi predicati della propria --- sufficiente utilizzare il predefinito predicato all_different/1!

:- use_module(library(clpfd)). 

uso Esempio:

 
?- all_different([1,2,3,4]). 
true. 

?- all_different([1,2,3,3]). 
false. 
-1

della regola prevista nel la domanda è molto vicino ad una risposta corretta con l'utilizzo della libreria minimo. Ecco una versione di lavoro che ha richiesto solo un cambiamento, l'aggiunta di \ + in terza fila:

uniqueList([]). 
uniqueList([H|T]):- 
    \+(member(H,T)), 
    uniqueList(T). 

Spiegazione del codice per i principianti Prolog: Il membro (H, L) controlli predicato se elemento H è un membro della lista L. \ + è la funzione di negazione del Prolog, in modo che il codice di cui sopra ammonta a:

uniqueList([H|T]) returns true if: (H doesn't have a copy in T) and uniqueList(T) 

considerando che il codice da parte del richiedente originale non ha funzionato perché è stato pari a:

uniqueList([H|T]) returns true if: (H has a copy in T) and uniqueList(T) 

* Ho rinominato Different() in uniqueList() perché legge meglio. La convenzione è di riservare lettere maiuscole per variabili.

+0

Per downvoter: Se la mia soluzione è sbagliata, per favore, indicatela, i casi con cui ho provato funzionavano. – Fadeway

1

Molto semplice risposta ...

il codice:

unique([]). unique([_,[]]). unique([H|T]):-not(member(H,T)),unique(T).

Test:

?-unique([1,2,3,4]). true. ?-unique([1,2,3,3]). false. ?-unique([a,b,12,d]). true ?-unique([a,b,a]). false

Problemi correlati