Tests failing on Acronym exercise

Hi,

I’ve got this code:

abbreviate(Sentence, Acronym) :-
    split_string(Sentence, "- ", " \t\n", PhraseList),
    maplist(remove_non_alphanumeric, PhraseList, CleanList),
    maplist(first_char, CleanList, AcronymList),
    atomic_list_concat(AcronymList, AcronymString),
    upcase_atom(AcronymString, Acronym).

remove_non_alphanumeric(String, CleanString) :-
    atom_chars(String, Chars),
    include(alpha_numeric_char, Chars, AlphaNumericChars),
    atom_chars(CleanString, AlphaNumericChars).

alpha_numeric_char(Char) :-
    char_type(Char, alpha);
    char_type(Char, digit).

first_char(String, Char) :-
    atom_chars(String, [Char|_]).

When I test it interactively it works. However when I run the test, it fails with errors similar to:

ERROR: 
    [[ EXCEPTION while printing message url('/mnt/exercism-iteration/acronym_tests.plt':9)
       with arguments []:
       raised: type_error(text,url('/mnt/exercism-iteration/acronym_tests.plt':9))
    ]]
:
	test basic: failed

I’m completely new to Prolog but do have lots of experience with other programming likes like Python. Thanks in advance for your help on this.

Hi, @deji.

In case you’re still having trouble with this, the explanation for the failed test is very simple. The solution you posted returns an atom, not a string:

?- ["acronym.pl"].
true.

?- abbreviate("domain name server", A), atom(A).
A = 'DNS'.

?- abbreviate("domain name server", A), string(A).
false.

Notice the “single” quotes ('') around the acronym (or rather, the initialism in this case). A string in Prolog is only ever represented with “double” quotes ("").

Atoms are typically not allowed to begin with uppercase letters, unless you “quote” them as above. Quoted atoms can even contain spaces:

?- [user].
|: 'Winnie the Pooh'(bear).
|: ^D
true.

?- 'Winnie the Pooh'(What).
What = bear.

As you may have figured out already, the abbreviate predicate needs to unify the acronym with a string representation:

  % . . .    
  upcase_atom(AcronymString, AcronymAtom),  % <//  result is an atom
  atom_string(AcronymAtom, Acronym).        % <//  result is a string

Sorry that no one had answered this post so far. Hopefully, you or anyone else stumbling across this find help in it :slight_smile:

  • At first, I will provide a general hint about the issue of your code
  • Then I provide an explanation about the difference of strings and atoms in prolog
  • Last but not least the solution to your problem

The issue is in your code

Your tests fail, because of type differences. The tests expects a string as an output but your tests provide atoms.

What are the two different types here?
It may seem confusing for a beginner but an atom in prolog is mostly marked with single quotes. Strings are iirc marked as text surrounded by double quotes.

atoms

In prolog an atom is an identifier that has no further inherent meaning in itself.
If you have a fact like

fruit(apple).

You’ll find that you can query either of these

?- fruit(X), X == 'apple'.
X = apple.

?- fruit(X), X == apple.
X = apple.

The single quotes would become important if you want to treat numbers as atoms or if the atom contains whitespace or if it starts with uppercase letters.
Examples

  • abc
  • ‘xyz’
  • ‘Abc’
  • ‘six words treated as one atom’
  • ‘7’

strings
Strings are always surrounded by double quotes. They can be thought of as a list of unicodes representing some text encoding which is per defaulted treated as UTF-8.
Putting :- set_prolog_flag(double_quotes, chars). at the start of a prolog file will treat any strings in your file as a list of characters allowing you to do list operations on them.

Also most string operations work by replacing the string with a char list.
For example from your code

split_string(Sentence, "- ", " \t\n", PhraseList),

would produce the same result as

split_string(Sentence, ['-', ' '], [' ', '\t', '\n'], PhraseList)

The big confusion comes from the fact that most string operations have some equivalent for atoms.

About your program

So if you change the last line in abbreviate/2

upcase_atom(AcronymString, Acronym).

with

    upcase_atom(AcronymString, AcronymAtom),
	atom_string(AcronymAtom, Acronym).

8 out of the 9 tests pass. The rest of your logic seems to have an issue with treating a single hyphen in the string

"Something - I made up from thin air"