I have the following facts
%exam(Student,Subject)
exam(student1,subject1).
exam(student2,subject1).
exam(student3,subject1).
exam(student1,subject2).
exam(student3,subject2).
exam(student1,subject3).
I want to find the subjects of a student and put them in a list
Subjects(Student,[H|T]):-
exam(Student,Subject),
\\+Subject=H,
H = Subject,
Subjects(Student,T).
I can't figure out what the base case should be !
\+ Subject = H means, "can't prove that" Subject can be unified with H.
But since H starts out uninstantiated, it can always be unified with Subject, so that goal will always fail.
Also, to see whether Subject was previously found, you'd have to check its membership in a list of previously found values. That means, carrying around an additional argument from call to call, which would start as [], adding newly found subject into it, and making the next call with the updated list.
As long as you can find a new fact, you add it to this accumulating list, and continue; but if you couldn't find a new fact, you should stop. That will be your base case. It'll be easier to code with auxiliary predicates each performing its separate task (like can_find_new_subject( Student, ListSeenSoFar, Subject) etc.).
subjects(Student, L):- search_subjects(Student, [], L).
search_subjects(Student, Seen, L):-
find_new_subject(Student, Seen, Subj)
search_subjects(Student, [Subj|Seen], L).
search_subjects(Student, Seen, L):-
\+ find_new_subject(Student, Seen, Subj),
... .
find_new_subject( ......
....
The drawback to this setup is that it will be quadratic. You can't make it linear without the extra-logical facilities like assert, or using a built-in findall and the like.
Related
I'm not fully sure how to word my question, so sorry for the rough title.
I am trying to create a pattern that can identify variable names with the following restraints:
Must begin with a letter
First letter may be followed by any combination of letters, numbers, and hyphens
First letter may be followed with nothing
The variable name must not be entirely X's ([xX]+ is a seperate identifier in this grammar)
So for example, these would all be valid:
Avariable123
Bee-keeper
Y
E-3
But the following would not be valid:
XXXX
X
3variable
5
I am able to meet the first three requirements with my current identifier, but I am really struggling to change it so that it doesn't pick up variables that are entirely the letter X.
Here is what I have so far: [a-z][a-z0-9\-]* {return (NAME);}
Can anyone suggest a way of editing this to avoid variables that are made up of just the letter X?
The easiest way to handle that sort of requirement is to have one pattern which matches the exceptional string and another pattern, which comes afterwards in the file, which matches all the strings:
[xX]+ { /* matches all-x tokens */ }
[[:alpha:]][[:alnum:]-]* { /* handle identifiers */ }
This works because lex (and almost all lex derivatives) select the first match if two patterns match the same longest token.
Of course, you need to know what you want to do with the exceptional symbol. If you just want to accept it as some token type, there's no problem; you just do that. If, on the other hand, the intention was to break it into subtokens, perhaps individual letters, then you'll have to use yyless(), and you might want to switch to a new lexing state in order to avoid repeatedly matching the same long sequence of Xs. But maybe that doesn't matter in your case.
See the flex manual for more details and examples.
I have different commands my program is reading in (i.e., print, count, min, max, etc.). These words can also include a number at the end of them (i.e., print3, count1, min2, max6, etc.). I'm trying to figure out a way to extract the command and the number so that I can use both in my code.
I'm struggling to figure out a way to find the last element in the string in order to extract it, in Smalltalk.
You didn't told which incarnation of Smalltalk you use, so I will explain what I would do in Pharo, that is the one I'm familiar with.
As someone that is playing with Pharo a few months at most, I can tell you the sheer amount of classes and methods available can feel overpowering at first, but the environment actually makes easy to find things. For example, when you know the exact input and output you want, but doesn't know if a method already exists somewhere, or its name, the Finder actually allow you to search by giving a example. You can open it in the world menu, as shown bellow:
By default it seeks selectors (method names) matching your input terms:
But this default is not what we need right now, so you must change the option in the upper right box to "Examples", and type in the search field a example of the input, followed by the output you want, both separated by a ".". The input example I used was the string 'max6', followed by the desired result, the number 6. Pharo then gives me a list of methods that match that:
To get what would return us the text part, you can make a new search, changing the example output from number 6 to the string 'max':
Fortunately there is several built-in methods matching the description of your problem.
There are more elegant ways, I suppose, but you can make use of the fact that String>>#asNumber only parses the part it can recognize. So you can do
'print31' reversed asNumber asString reversed asNumber
to give you 31. That only works if there actually is a number at the end.
This is one of those cases where we can presume the input data has a specific form, ie, the only numbers appear at the end of the string, and you want all those numbers. In that case it's not too hard to do, really, just:
numText := 'Kalahari78' select: [ :each | each isDigit ].
num := numText asInteger. "78"
To get the rest of the string without the digits, you can just use this:
'Kalahari78' withoutTrailingDigits. "Kalahari"6
As some of the Pharo "OGs" pointed out, you can take a look at the String class (just type CMD-Return, type in String, hit Return) and you will find an amazing number of methods for all kinds of things. Usually you can get some ideas from those. But then there are times when you really just need an answer!
I'm new to ANTL4 and I can't seem to figure out how to get lexer actions to perform properly.
I have a code snippet that looks for input text:
SIZE10 : [a-zA-Z]* {getText().length() <= 10}?
I would expect that it does not match any combinations of letters that are over 10 letters long, however what this does is treat a 10+ letter string as two different tokens, instead of just nullifying the whole set of 10+ letters. How can I get this action to nullify the whole set of letters?
In addition, where can I go to see all the different token functions I can use (other than getText())? The documentation about lexer actions is really poor. In general, I'm having a hard time figuring out what resources can give me a definitive list of everything in the language. Even an entry point into the source code for me to read would be good at this point. The documentation is too general/basic for me.
EDIT: I've figured out how to send a RuntimeException, but I don't know where to get the elements needed for a proper RecognitionException.
The predicate in a rule directs the parsing process in a way that allows to match only partial input (like in your case) or essentially switch off a part of the grammar depending on certain conditions. In your case the SIZE10 rule is matched until the predicate returns false. Everything up to this event is then returned as a match for SIZE10. After that lexing continues at the point it ended for the previous token and if that is again a letter it will again match SIZE10 as long as the predicate says it is correct. That's a bit different than what you would expect (e.g. using the predicate as an all or nothing switch).
However, if you instead want to match the full set of letters first and then check if the length is <= 10 you can do this in a listener. You can hook into the exitSIZE10() event and reject the match by throwing a recognition exception.
For the usable functions in your actions see the API documentation for ANTLR. For instance here is the one for Token which shows you other possibilities beside getText(). In your action, consider the context you have. In a lexer rule you deal with a Token, hence getText() etc. work on the token. In a parser rule you have a ParserContext instead, which also has a getText() function but that works differently (collecting all child contexts text into a comma separated list).
I have a house with rooms that are defined with connections for when you can go from one room to another eg.
connection(garage,sidehall).
connection(sidehall,kitchen).
connection(kitchen,diningroom).
canget(X,Y):-connection(X,Y).
canget(X,Y):-connection(X,_),
write('player goes from '),write(X),write(' to '),write(Y),nl,
canget(_,Y).
Im trying to figure out how make it so the player can only get from one room to another when they have a specific item, such as you can only be in the kitchen when items = gloves.
canget(X,Y,Item):-connection(X,Y,Item),canbein(Y,Item).
canget(X,Y,Item):-connection(X,Somewhere,Item),canbein(Somewhere,Item),canget(Somewhere,Y,Item).
tried defining canbein with:
canbein(kitchen):- item(sword).
canbein(sidehall):- item(hat).
but that doesnt work!
Have defined my items as such, not sure if this is right either:
item(gloves,sword,helm,cheese).
Basically, have i declared my item values correctly?
How can i use the specific item value to make canget x to y false?
Thank you!
Well, I see a few problems with your code. Firstly, you call canbein with two arguments (from canget predicate). However, canbein is defined as single-argument predicate. Therefore, the call always fails as no canbein/2 predicate exists.
I suggest the following modification:
canbein(kitchen, sword).
canbein(sidehall, hat).
Than, the item definition is not required. Let's think about what happens during the unification of
canget(X,Y,Item) :- connection(X,Y,Item), canbein(Y,Item).
Let's assume the following setting X=sidehall, Y=kitchen, Item==sword. This predicate should be OK. Assuming the conection predicate is OK, prolog tries to find canbein(Y, Item) i.e. canbein(kitchen, sword) and it succeeds.
On the contrary, if the Item is different the unification fails, hence it works as expected.
The second problem is the item predicate. By your definition, it expects 4 arguments. That's nonsense, of course. You should declare it like
item(gloves).
item(sword).
item(helm).
item(cheese).
However, I don't think this predicate is necessary at all. Just to be clear, try to call item(X) and obtain all results (the four declared). Try it with the prior definition - what should you even ask for?
I hope it helps :)
I am new to Prolog and therefore need help with the following task.
I have the programm:
do(save) :- save_bal(bad).
do(act) :- save_bal(good), inc(good).
do(comb) :- save_bal(good), inc(bad).
save_bal(good) :- savMoney(X), depPeople(Y), Min is Y * 1000, X >= Min.
save_bal(bad) :- not(save_bal(good)).
inc(good) :- earn(Z), depPeople(Y), MinE is 3000 + Y * 400, Z >= MinE.
inc(bad) :- not(inc(good)).
savMoney(30000).
earn(60000).
depPeople(4).
My task is to rewrite this programm, so the numbers 30000, 60000 and 4 is set by a user input. How can I do this?
I tried:
:- read(A), savMoney(A).
:- read(B), earn(B).
:- read(C), depPeople(C).
But that won't work.
Can someone point me in the right direction?
Thanks in advance!
Prolog is an homoiconic language, then the first step you should take is to declare which predicate are data, and which are (just to say) logic constraints on the data.
Then, add near top of file (just a stylistic hint) the declarations
:- dynamic(savMoney/1).
:- dynamic(earn/1).
:- dynamic(depPeople/1).
then you can add a service predicate, say user_update_store/1, like
user_update_store(Entry) :-
AccessValueCurr =.. [Entry, ValueCurr],
(retract(AccessValueCurr) -> true ; ValueCurr = 0),
format('enter value for ~s (current is ~w):', [Entry, ValueCurr]),
read(NewValue),
% validate it's a number etc...
StoreNewValue =.. [Entry, NewValue],
assertz(StoreNewValue).
now you can start your user interface:
?- maplist(user_udpdate_store, [savMoney,earn,depPeople]).
this code should work for every (ISO compliant) Prolog. Note: I didn't tested it...
HTH
CapelliC provided an excellent (better) answer while I was busy typing away at this monstrosity. In fact, I didn't end up addressing the question in your title, because you were passing parameters just fine. Instead I wrote about assertz/1 and retract/1. However, I taught myself a fair amount while composing it and you might also find it informative.
In your example code, we have 3 facts declared with the predicates savMoney/1, earn/1, depPeople/1'. We then have a number of rules that determine values based on these facts. A rule is of the form :- ., and which I sometimes read to myself as "<head> is true if <body> is true". We can think of a fact as a rule of the form :- true, e.g.,savMoney(30000) :- true.`, which we might read as "30000 is savMoney if true is true", and true is true or we're all screwed. (BTW, is 'savMoney' short for saved money?)
A directive is of the form :- <body>.. It is like a rule that must be tested in order for the program (or world) to be true (this is more evocative than accurate, because, as you've seen, when a directive fails the whole program-world is not false, we just get a warning). When we consult a prolog file, we add new rules and facts to our program-world, and these can even be impossible nonsense statements like a :- \+ a. "a is true if not-a is true"1. That contradiction will cause cause a stack overflow if you query ?- a., but the program will load just fine. However, directives have to be evaluated and settled while the program loads in the order they are encountered:
This program will throw a stack overflow error when the interpreter consults it.
a :- \+ a.
:- a.
This program will throw an undefined procedure error, because it is being directed to prove a before a has been entered into the database.
:- a.
a :- \+ a.
When we have a directive like :- read(A), savMoney(A)., it's not saying "read the value of user input into A and then set saveMoney to A". Instead, it's saying something more like, "if this program is loaded, then A is a value read in from user input and A is savMoney." Suppose you run the program and enter 100 at the first prompt (the plain prompt is |). What happens?
prolog unifies the variable A with 100.
prolog tries to prove savMoney(100).
it replies Warning: Goal (directive) failed: user:(read(_G2072),savMoney(_G2072)).
This is because, while savMoney(30000) is true, savMoney(100) is not. A directive does not assert the contents of its body, it only tells prolog to prove those contents.
What you are trying to do is allow the user to assert a previously unknown fact into the database. As indicated by mbratch, this requires using the predicate assertz/12. However, predicted that be changed during run-time are differentiated from standard predicates.
If you try to define a reestablished predicate in a program, you'll get an error. E.g., consult a file consisting of the following declaration:
length(2, y).
You'll receive an error:
ERROR: /Users/aporiac/myprolog/swi/studies/test.pl:18:
No permission to modify static procedure `length/2'
Defined at /opt/local/lib/swipl-6.2.6/boot/init.pl:2708
This tells us that 'length/2' is static and that it is already defined in init.pl file at line 2708.
The same happens if you try to assert a static predicate with assertz/1. You can try this by querying assertz(savMoney(100)) in swipl. In order to add new facts or rules about a predicate, we have to declare the predicate to be dynamic.
This is accomplished with dynamic/1. To assure that prolog knows which of our predicates are to be counted as dynamic, we give it a directive like so3:
:- dynamic savMoney/1.
If you've added that to your file (before you define the predicate), you can then query ?- assertz(savMoney(100)). to add the new fact to the database. Now, if you query ?- savMoney(X), you'll get
X = 30000;
X = 100.
There are now two possible values for X, because we've added another fact to the database.
Of course, in your case, you don't want to keep adding values to savMoney/1, you want to be able to update and replace the value.
That calls for retract/1 (If you think there's a chance that more than one occurrence the asserted predicate could get added at some point, then you can use retractall/1 to clear all instances). Now we can write a rule like the following:
set_saved(Amount) :-
retract( savMoney(_) ),
assertz( savMoney(Amount) ).
set_saved(Amount) is true if savMoney(_) can be retracted and removed from the database and the new fact savMoney(Amount) can be asserted.
I've just seen that CapelliC has provided a simple input interface, and a much more concise solution to the problem, but here's my version of your example program in case it might be informative. (I didn't actually get around to adding the prompt and input, but querying, e.g., ?- set_saved(100), does what you'd expect).
:- dynamic [ savMoney/1,
earn/1,
depPeople/1 ].
do(save) :- save_bal(bad).
do(act) :- save_bal(good), inc(good).
do(comb) :- save_bal(good), inc(bad).
save_bal(good) :- savMoney(X), depPeople(Y), Min is Y * 1000, X >= Min.
save_bal(bad) :- not(save_bal(good)).
inc(good) :- earn(Z), depPeople(Y), MinE is 3000 + Y * 400, Z >= MinE.
inc(bad) :- not(inc(good)).
savMoney(30000).
earn(60000).
depPeople(4).
set_saved(Amount) :-
retract( savMoney(_) ),
assertz( savMoney(Amount) ).
set_earned(Amount) :-
retract( earn(_) ),
assertz( earn(Amount) ).
set_people_in_department(Number) :-
retract( depPeople(_) ),
assertz( depPeople(Number) ).
report([Saved, Earned, People]) :-
Saved = savMoney(_) , Saved,
Earned = earn(_) , Earned,
People = depPeople(_), People.
\+/1 is the standard negation operator in swi-prolog and not/1 is depreciated.
assert/1 is equivalent to, and depreciated in favor of, assertz/1. asserta/1 asserts the fact or clause as the first instance of the predicate at hand, while assertz/1 asserts it as the last. (Cf. the manual section on the Database).
Of course, this goes against the interpretation of the directive I suggested before. My interpretation fits when you're using 'normal' predicates in a directive. But, most often, we see directives used for special predicates like in module declarations (:- module(name, [<list of exported predicates>]) or module imports (:- use_module([<list of modules>])).