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).
Related
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 ?
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.
find :-
write('Enter File Name: '),
see(File).
seen.
Now the user can input the text file name and read the text file by using see(File) predicate.
But see(File) must follow the format like see('File.txt'), so how can i read a text file base on user input file name?
To capture the input from the user you use the read() predicate:
read(X).
So you can try this:
find :-
write('Enter File Name: '),
read(File),
see(File),
seen.
find:-
write('Enter File Name: '),
read(File),
processFind(File).
processFind(File):-
write('Enter A Name: '),
read(Name),
see(File),
repeat,
read(Term),
processCheck(Term, Name),
seen.
processCheck(end_of_file, _):-
write('Record Not Found'), !.
processCheck(Term, Name):-
Term = Name -> (write('Record Found'), !).
This is correct answer that i had finally get it.
Enter a file name including a single quotation and then go for check whether the name is exist in the file or not.
True will return Record found else record not found.
I'm trying to use a DCG to split a string into two parts separated by spaces. E.g. 'abc def' should give me back "abc" & "def". The program & DCG are below.
main:-
prompt(_, ''),
repeat,
read_line_to_codes(current_input, Codes),
(
Codes = end_of_file
->
true
;
processData(Codes),
fail
).
processData(Codes):-
(
phrase(data(Part1, Part2), Codes)
->
format('~s, ~s\n', [ Part1, Part2 ])
;
format('Didn''t recognize data.\n')
).
data([ P1 | Part1 ], [ P2 | Part2 ]) --> [ P1 | Part1 ], spaces(_), [ P2 | Part2 ].
spaces([ S | S1 ]) --> [ S ], { code_type(S, space) }, (spaces(S1); "").
This works correctly. But I found that having to type [ P1 | Part1 ] & [ P2 | Part2 ] was really verbose. So, I tried replacing all instances of [ P1 | Part1 ] w/ Part1 & likewise w/ [ P2 | Part2 ] in the definition of data, i.e. the following.
data(Part1, Part2) --> Part1, spaces(_), Part2.
That's much easier to type, but that gave me an Arguments are not sufficiently instantiated error. So it looks like an unbound variable isn't automatically interpreted as a list of codes in a DCG. Is there any other way to make this less verbose? My intent is to use DCG's where I would use regular expressions in other programming languages.
Your intuition is correct; the term-expansion procedure for DCGs (at least in SWI-Prolog, but should apply to others) with your modified version of data gives the following:
?- listing(data).
data(A, D, B, F) :-
phrase(A, B, C),
spaces(_, C, E),
phrase(D, E, F).
As you can see, the variable Part1 and Part2 parts of your DCG rule have been interpreted into calls to phrase/3 again, and not lists; you need to explicitly specify that they are lists for them to be treated as such.
I can suggest an alternative version which is more general. Consider the following bunch of DCG rules:
data([A|As]) -->
spaces(_),
chars([X|Xs]),
{atom_codes(A, [X|Xs])},
spaces(_),
data(As).
data([]) --> [].
chars([X|Xs]) --> char(X), !, chars(Xs).
chars([]) --> [].
spaces([X|Xs]) --> space(X), !, spaces(Xs).
spaces([]) --> [].
space(X) --> [X], {code_type(X, space)}.
char(X) --> [X], {\+ code_type(X, space)}.
Take a look at the first clause at the top; the data rule now attempts to match 0-to-many spaces (as many as possible, because of the cut), then one-to-many non-space characters to construct an atom (A) from the codes, then 0-to-many spaces again, then recurses to find more atoms in the string (As). What you end up with is a list of atoms which appeared in the input string without any spaces. You can incorporate this version into your code with the following:
processData(Codes) :-
% convert the list of codes to a list of code lists of words
(phrase(data(AtomList), Codes) ->
% concatenate the atoms into a single one delimited by commas
concat_atom(AtomList, ', ', Atoms),
write_ln(Atoms)
;
format('Didn''t recognize data.\n')
).
This version breaks a string apart with any number of spaces between words, even if they appear at the start and end of the string.
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.