Prolog: Reading input with spaces causes an error - prolog

this is my program
tran('father','otosan').
tran('father','chichiwe').
tran('mother','okasan').
tran('mother','hahawe').
tran('hi','ohayo').
tran('good night','oyasemi').
tran('good bye','sayonara').
tran('do your best','gambaru').
tran('please','onegai').
tran('sorry','gomen').
tran('thank you','aregatto').
tran('cute','kawaii').
eng:- nl,write('enter a word in english: '),read(X),jap(X).
jap(X):- tran(X,Y),write('the word in japanese is '),write(Y),nl,fail.
jap(Z).
:-eng.
I got an error in the words with spaces
how can I solve this problem?

It appears that when inputting words with spaces, you need to surround them with single quotes:
?- ['trans.pl'].
% trans.pl compiled 0.00 sec, 5,432 bytes
true.
?- eng.
enter a word in english: hi.
the word in japanese is ohayo
false.
?- eng.
enter a word in english: 'good bye'.
the word in japanese is sayonara
false.
The reason this is happening is that when you enter hi, Prolog is unifying it to jap(hi). which resolves to ohayo. When you enter good bye, Prolog unifies it to jap(good bye), which will give you an error (Operator Expected). This is why you need to quote your input as 'good bye'. Prolog will then unify it to jap('good bye'), which gives you what you want.

Related

Program in SWI-Prolog

Task:Write to the new file all the lines of the source file that contain the specified string as a fragment, which is entered from the keyboard.
I can't figure out how to compare the lines from the file line by line in the Prolog with the fragment that I entered from the keyboard and output the matching lines to a new file.I will be glad to receive any advice or direction. I can't think straight in the prologue.
f:-
write('Enter the name of the source file:'),
read(SOURFILE),
check_exist(SOURFILE),
open(SOURFILE,read,FROM),
read_line_to_string(FROM,X),writef(" "),
writef(X),
writeln(" "),
write('Enter a substring:'),
read(WR),
close(FROM),
write('Enter the name of the new file:'),
read(NEWFILE),
check_exist(NEWFILE),
name(S,X),
write_to_file(NEWFILE,S).
check_exist(Filename):-exists_file(Filename),!.
check_exist(_):-writeln('There is no such file'),
fail.
write_to_file(Filename,TEXT) :-
open(Filename, write, File),
write(File, TEXT),nl,
writeln('Data recorded successfully'),
close(File).
In SWI-Prolog, you can use predicate sub_string/5 to verify whether a string contains a substring. Thus, to solve your problem, you can do something like this:
copy(From, To, Substring) :-
open(From, read, Input),
open(To, write, Output),
repeat,
read_line_to_string(Input, String),
( String = end_of_file
-> ! % stop reading lines
; sub_string(String, _, _, _, Substring),
writeln(Output, String),
fail ), % backtracks to read next line
close(Input),
close(Output).

How to get the first letter of each word enter by user

Here are the details of my code
name:-read(X),write('Name : '),write(X),nameCode(X).
nameCode(X):-nl, write('Name Code : ').
I would like to take the first 3 letters from each word and display it . What should be added to my code?
Furthermore, the result i get only allows me to enter a single name from user. When i attempt to enter several names(peter jane mary) in the query, it display a syntax message as below
| ?- name.
|: peter jane mary.
* Syntax Error
Below are the results of what i want to print
Name : peter jane mary
Name Code : PJM
1- First the user enters his/her first/middle/last name.
2- It is read.
3- string_chars breaks the string into characters : peter will become p,e,t,e,r
4- getFirstLetter Predicate extracts the first element from the list: from peter we get p.
5- upcase_atom convert lowercase letters to uppercase: p will become P.
6- display the answer using write.
k:-
write('Enter First name: '),nl,
read(FName),nl,
string_chars(FName,N1),
getFirstLetter(N1,L1),
upcase_atom(L1,Str1),
write('Enter Middle name: '),nl,
read(MName),nl,
string_chars(MName,N2),
getFirstLetter(N2,L2),
upcase_atom(L2,Str2),
write('Enter Last name: '),nl,
read(LName),nl,
string_chars(LName,N3),
getFirstLetter(N3,L3),
upcase_atom(L3,Str3),
write(Str1),write(' '),write(Str2),write(' '),write(Str3).
getFirstLetter([H|_],H).
Example:
?-k.
Enter First name:
peter
Enter Middle name:
jane
Enter Last name:
mary
P J M
___
A more challenging task: Remove the first letter from the name.
1- First the user enters his/her first/middle/last name.
2- It is read.
3- string_chars breaks the string into characters : peter will become p,e,t,e,r
4- removeFirstLetter predicate removes the first letter: p,e,t,e,r will become e,t,e,r
5- charstring predicate will convert e,t,e,r to "e","t","e","r", we do this using term_string (this is important for the next
step)
6- atomic_list_concat joins all the separate charaters together: "e","t","e","r" will
become eter
k:-
write('Enter first name: '),nl,
read(FName),nl,
string_chars(FName,N1),
removeFirstLetter(N1,L1),
charstring(L1,String1),
atomic_list_concat( String1 , Cs1),
write('Enter Middle name: '),nl,
read(MidName),nl,
string_chars(MidName,N2),
removeFirstLetter(N2,L2),
charstring(L2,String2),
atomic_list_concat( String2 , Cs2),
write('Enter Last name: '),nl,
read(LName),nl,
string_chars(LName,N3),
removeFirstLetter(N3,L3),
charstring(L3,String3),
atomic_list_concat( String3 , Cs3),
write(Cs1),write(" "),write(Cs2), write(" "),write(Cs3).
charstring([],[]).
charstring([H|T],[H2|L]):-
term_string(H,H2),
charstring(T,L).
removeFirstLetter([_|T],T).
Example:
?-k.
Enter first name:
peter
Enter Middle name:
jane
Enter Last name:
mary
eter ane ary
1true
The built-in predicate read/1 reads in a prolog term, terminated by a full-stop.
"peter jane mary" is not a prolog term, so you get a syntax error. In particular, prolog doesn't know what to do with the blank space between your names.
If you prefer to use comma to separate names, you can get this:
?- read(X), X = ','(A, ','(B,C)).
|: peter,mary,paul.
X = (peter,mary,paul),
A = peter,
B = mary,
C = paul.
The comma is interpreted as a functor (in standard prolog).
Have I replied your question ?

How can i set a newline in a set string in SWI-Prolog?

I have this string:
B='Dogs cats birds and fish'.
and i need it to appear in the format bellow:
Dogs,
cats,
birds,
and fish
Is there any possible way for this to happen?
I tried nlas in:
B='Dogs,nl, cats,nl, birds,nl, and fish'.
and \n as in:
B='Dogs,\n, cats,\n, birds,\n, and fish'.
to no avail
B='Dogs cats birds and fish'.
you should split the string as a list, and then iterate the list and write.
In Prolog, nl is a Predicate, is can not be used like \n,
print_s([]).
print_s([H|L]):-
write(H),
nl,
print_s(L).
print_s(['Dogs,', 'cats,', 'birds', 'and fish']).
The new line character works, you should use write/1 [swi-doc] to print the string to the console, like:
?- write('Dogs,\ncats,\nbirds,\nand fish').
Dogs,
cats,
birds,
and fish
true.
?- B = 'Dogs,\ncats,\nbirds,\nand fish', write(B).
Dogs,
cats,
birds,
and fish
B = 'Dogs,\ncats,\nbirds,\nand fish'.
If you unify a variable, the Prolog will print that variable as a string literal, not the content of the string.

GNU Prolog: Strange characters

I am new to using GNU Prolog.
Given the following facts:
theme(cafe).
role(manager).
role(boss).
role(coworker).
numberOfCharacters(theme(cafe), 3).
charactersRole(numberCharacters(theme(cafe), 3), role('boss'), role('manager'), role('çoworker')).
When I query:
charactersRole(numberCharacters(theme('cafe'), 3), role(X), role(Y), role(Z)).
It returns some of the values correctly, while one value contains ç in place of normal character 'c'.
X = boss
Y = manager
Z = 'çoworker'
Thanks! :)
role('çoworker')
You have cedilla right here, which gets misrepresented by two characters, usually by not being unicode-aware. This is not a Prolog issue.
ç are U+00C3 U+00A7 in Unicode
And ç is
U+00E7 LATIN SMALL LETTER C WITH CEDILLA
UTF-8: 0xC3 0xA7
That's what you're getting by outputting an UTF-8 2-byte character into non-UTF8-aware LATIN1 terminal.

Prolog wildcard for completing a string

I am currently stuck on a prolog problem.
So far I have:
film(Title) :- movie(Title,_,_). (Where 'movie(T,_,_,)' is a reference to my database)
namesearch(Title, Firstword) :- film(Title), contains_term(Firstword, Title).
It is hard to explain what I need help on, but basically is there a wildcard I can use to search for all films starting with a specific word, for example, if I were to search for all films beginning with the word "The".
Is there a wildcard which would allow me to input as such: namesearch(X,'The*') ?
I have tried using the asterisk like this and it does not work,
Thank your for your help
It all depends how the title is represented.
Atom
If it is represented as an atom, you need sub_atom(Atom, Before, Length, After, Sub_atom)
?- Title = 'The Third Man', sub_atom(Title, 0, _, _, 'The').
Title = 'The Third Man'.
List of codes
If it is a list of codes which is called a string in Prologs in Edinburgh tradition, you can either "hard code" it with append/3 or you might use Definite Clause Grammars for general patterns.
?- set_prolog_flag(double_quotes,codes).
true.
?- append("The",_, Pattern), Title = "The Third Man", Pattern = Title.
Pattern = Title, Title = [84,104,101,32,84,104,105,114,100|...].
?- Title = "The Third Man", phrase(("The",...), Title).
Title = [84,104,101,32,84,104,105,114,100|...]
; false.
Note that 84 is the character code of T etc.
phrase/2 is "the entry" to grammars. See dcg for more. Above used the following definition:
... --> [] | [_], ... .
List of characters
Similar to list of codes, list of characters provide a more readable representation that has still the advantages of being compatible with list predicates and Definite Clause Grammars:
?- set_prolog_flag(double_quotes,chars).
true.
?- append("The",_, Pattern), Title = "The Third Man", Pattern = Title.
Pattern = Title, Title = ['T',h,e,' ','T',h,i,r,d|...].
?- Title = "The Third Man", phrase(("The",...), Title).
Title = ['T',h,e,' ','T',h,i,r,d|...]
; false.
See also this answer.

Resources