Suppose I have a list of "base atoms" and a longer atom made up only of those base atoms. repeats are allowed. I whipped up the following code to generate lists of all the atoms which could possibly make up the longer atom. This code seems to work with the exception that it finds many repeats of the same (correct) solutions and I am not sure why?
basics([a, abc, def, aaa]).
candidate(aaaabcaaadef).
join_atoms(Atoms, Atom):- join_atoms( Atoms, '', Atom ) .
join_atoms( [], Atom, Atom ) .
join_atoms( [H|T], AtomAccum, Atom ) :-
atom_concat( AtomAccum, H, UpdatedAtom) ,
join_atoms( T, UpdatedAtom, Atom ) .
split_atoms( C, Atoms ):- split_atoms( C, [], Atoms ) .
split_atoms( '', AtomsAccum, Atoms ) :-
candidate(C) ,
reverse( AtomsAccum, AtomsAccumR ) ,
join_atoms( AtomsAccumR, C ) ,
Atoms = AtomsAccumR .
split_atoms(C, AtomsAccum, Atoms):-
basics( B ) ,
member( SubAtom, B ) ,
sub_atom( C, _, Length, _, SubAtom ) ,
sub_atom( C, Length, _, 0, AtomRest ) ,
split_atoms(AtomRest, [SubAtom|AtomsAccum], Atoms).
main:-
candidate( C ) ,
findall( Atoms, split_atoms(C, Atoms), AllAtoms ) ,
sort( AllAtoms, UniqueAtoms ) ,
write(UniqueAtoms),
nl .
The findall/3 and sort/2 will get all solutions and remove the duplicates, of course. But without those the correct solutions are repeated multiple times.
For example (output truncated)
| ?- split_atoms(aaaabcaaadef, Atoms).
Atoms = [a,a,a,abc,a,a,a,def] ? a
Atoms = [a,a,a,abc,a,a,a,def]
Atoms = [a,a,a,abc,a,a,a,def]
Atoms = [a,a,a,abc,a,a,a,def]
Atoms = [a,a,a,abc,a,a,a,def]
Atoms = [a,a,a,abc,a,a,a,def]
Atoms = [a,a,a,abc,aaa,def]
Atoms = [a,a,a,abc,a,a,a,def]
Atoms = [a,a,a,abc,a,a,a,def]
.
.
.
Can anyone suggest why this is happening? Presumably it is backtracking more than necessary for some reason? Or perhaps my code is unintentionally creating a situation which can be minimized?