1

Edit: Solved it by first turning the String into a list with string_chars/2. Still not sure why that was needed. I thought strings were already char lists in prologs mind.

Not the best at prolog but I have to use it for this task. I want to write a predicate that will remove characters from a string untill the string is an palindrome. I have palindrome/1, which seems to work correctly.

I've tried this:

predicate(String):-
    palindrome(String).
predicate(String):-
    select(_, String, NewString), % Idea: Removing a character from String will give NewString
    predicate(NewString).

So something like predicate("addal") should give true, but gives me false.

In fact, adding some break-points in the code, like writing "Reached" at different points in the program shows that the program fails at select(_, String, NewString)

Why doesn't select/3 work? The idea is to just remove a random character.

Edit: Its a palindrome, not an anagram like i said at first.

da1g
  • 107
  • 2
  • 7
  • `I want to write a predicate that will remove characters from a string until the string is an anagram.` Which characters, the start, middle, end? How many characters? 1, 2 any number of them. If all of the characters but one character is removed then it is always an anagram. – Guy Coder Mar 24 '19 at 00:45
  • @GuyCoder I meant to say palindrome, not anagram. It should remove any 1 character at any index in the string. I thought that if you say "remove 1 char from S" prolog will try every possible way to remove 1 char. – da1g Mar 24 '19 at 00:48
  • "Still not sure why that was needed." I suggest you read the documentation. Then you'd know why it was needed. But the bottom line is, Prologs are different. It is not just "Prolog". – User9213 Mar 24 '19 at 07:41

2 Answers2

2

To make your program work on any modern Prolog including SWI:

:- set_prolog_flag(double_quotes, chars).

Explicit conversion qua atom_chars/2 or string_chars/2 makes your program unnecessarily moded. That is, you will always have to provide a full string say "abc". With strings as character lists, this means [a,b,c] which in turn can be generalized to [a,X,c] or any term that has [a,b,c] as an instance. There is no way how you can generalize SWI's strings in such a manner.

Such generalizations are extremely useful in Prolog. You lose a lot if you give up on them.

false
  • 10,264
  • 13
  • 101
  • 209
1

It really depends on the Prolog you are using. This is why it doesn't hurt to show exactly what you did.

$ gprolog
Compiled Jul 15 2018, 03:47:56 with gcc
By Daniel Diaz
Copyright (C) 1999-2018 Daniel Diaz
| ?- select(X, "foo", Rest).

Rest = [111,111]
X = 102 ? ;

Rest = [102,111]
X = 111 ? ;

Rest = [102,111]
X = 111 ? ;

no
| ?- 

$ swipl
Welcome to SWI-Prolog (threaded, 64 bits, version 8.1.3-26-g30498cd0a)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).

?- select(X, "foo", Rest).
false.

?- string_codes("foo", Codes), select(X, Codes, Rest).
Codes = [102, 111, 111],
X = 102,
Rest = [111, 111] ;
Codes = [102, 111, 111],
X = 111,
Rest = [102, 111] ;
Codes = [102, 111, 111],
X = 111,
Rest = [102, 111].

In "normal" Prolog, "this is a list of character codes". In SWI-Prolog, "this is a string" and it is not a list, it is an atomic thingy that represents a string. You need to convert it to a list.

User9213
  • 1,316
  • 6
  • 12