Search code examples
prologswi-prolog

Problems with prolog list matching


I am a prolog beginner. I am trying to build a word generator for a made up language to test my prolog capabilities. Here is my code:

generic_consonant(
    ['ሀ', 'ለ', 'ሐ', 'መ', 'ረ', 'ሰ',
    'ቀ', 'በ', 'ተ', 'ኀ', 'ነ', 'ከ', 
    'ꬣ', 'ጠ', '፷', 'ጸ', 'ዂ', 'ፈ', 
    'ፐ', 'ዱ', 'ዳ', 'ዴ', 'ዶ']).

vowel(['ቈ', 'ቊ', 'ቋ', 'ቌ', 'ቍ', 'ኋ', 'ኊ']).

nasal_consonant(['ጙ', 'ዷ', 'ድ', 'ዲ', 'ደ']).

uvular_consonant(['ሠ', 'ወ', 'ዐ', 'ዘ', 'ጙ']).

syllablegen(1, Syllable) :-
    uvular_consonant(Uvular), vowel(Vowel),
    random(0, 7, VowelIndex), random(0, 5, UvularIndex),
    nth0(UvularIndex, Uvular, UvularChar), 
    nth0(VowelIndex, Vowel, VowelChar),

    Syllable = [UvularChar, VowelChar].

syllablegen(2, Syllable) :-
    generic_consonant(Consonant), uvular_consonant(Uvular), vowel(Vowel),
    random(0, 23, ConsonantIndex), 
    random(0, 7, VowelIndex), 
    random(0, 5, UvularIndex),
    nth0(ConsonantIndex, Consonant, ConsonantChar), 
    nth0(UvularIndex, Uvular, UvularChar), 
    nth0(VowelIndex, Vowel, VowelChar),

    Syllable = [ConsonantChar, UvularChar, VowelChar].

wordgen([], _).
wordgen(SyllableNums, Word) :-
    SyllableNums = [Head|Tail],
    syllablegen(Head, Syllable),
    append(Word, Syllable, NewWord),
    wordgen(Tail, NewWord).

All the syllablegen predicates are working when I call "syllablegen(1, X)." and "syllablegen(2, X).", but a problem occurs when I am calling wordgen and it gives me an unexpected output which is this:

?- wordgen([1, 2],  X).
X = [] ;
X = [_2898] ;
X = [_2898, _2910] ;
X = [_2898, _2910, _2922] ;
X = [_2898, _2910, _2922, _2934]

The behavior I was expecting was an output like this:

?- wordgen([1, 2],  X).
X = [ዐ,ኊ,ለ,ዐ,ቌ] ;

or a derivative of it as randomness exists in this program.

I been working on this for past few hours and I just cannot figure it out for the life of me. Any help would be greatly appreciated.


Solution

  • There are two small things to fix in wordgen/2. First, change the order of the arguments to append/3 (append(A,B,C) succeeds if C is the concatenation of A and B). Second, fix the second argument to the empty list in the first clause.

    wordgen([], []).
    wordgen(SyllableNums, Word) :-
        SyllableNums = [Head|Tail],
        syllablegen(Head, Syllable),
        append(Syllable, NewWord, Word),
        wordgen(Tail, NewWord).