Parsing list of items with DCG? - list

How do you parse string which is list of items f.e.
1,2,3,4
aa,b,ccc,ddd
Currently I do this (and is the comma) :
sub(X,Y) --> req(X), [and], req(Y).
sub(X) --> req(X).
req(on(X,Y)) --> [X,is,on,the,Y],!.
req(on(X,Y)) --> [X,is,on,Y],!.
req(on(X,Y)) --> [X,on,Y],!.
req(isa(X,Y)) --> [X,is,a,Y].
?- phrase(sub(T,U),[box,is,on,the,table, and, box,is,a,object], R).
T = on(box, table),
U = isa(box, object),
R = [].
but in this case sub() have two different heads sub(X) and sub(X,Y) , which messes the higher level.
I did this :
sub([X|Y]) --> req(X), [and], sub(Y).
sub([X]) --> req(X).
which seems to work ... but returns too many results ..??
?- phrase(sub(T),[box,is,on,the,table, and, box,is,a,object, and, apple , is,a,fruit], R).
T = [on(box, table), isa(box, object), isa(apple, fruit)],
R = [] ;
T = [on(box, table), isa(box, object)],
R = [and, apple, is, a, fruit] ;
T = [on(box, table)],
R = [and, box, is, a, object, and, apple, is, a|...].
it should stop at the first results ...!!
ooo i have to reverse the order, right ?
sub([X]) --> req(X).
sub([X|Y]) --> req(X), [and], sub(Y).

With your last definition:
sub([X]) --> req(X).
sub([X|Y]) --> req(X), [and], sub(Y).
The following queries work:
?- phrase(sub(Sub), [box,is,on,the,table, and, box,is,a,object]).
Sub = [on(box, table), isa(box, object)] ;
false.
?- phrase(sub(Sub), [box,is,on,the,table, and, box,is,a,object, and, apple,is,a,fruit]).
Sub = [on(box, table), isa(box, object), isa(apple, fruit)] ;
false.
Note that I only give two arguments to phrase. phrase has a form with two arguments, and one with three arguments. As a beginner, you will almost certainly only want to use the two-argument form. The two-argument form parses the entire list you give it and succeeds only if really everything in the list could be parsed. This is almost certainly what you want as a beginner. The three-argument form allows you to parse only the beginning of a list, then get back the suffix that wasn't parsed. You are not advanced enough to need this.

Related

Prolog how to use if / else in this way?

In Prolog, i want to use an if-else statement in the following way:
lecture(spanish,monday,at8).
lecture(french,monday,at8).
lecture(english,monday,at10).
lecture(german,tuesday,at8).
generatePossibleSchedulesWithTwoLectures(LectureA,LectureB):-
lecture(LectureA,A,X),
lecture(LectureB,B,Y),
%If A of LectureA is equal to B of lectureB -> times must be un-equal
% How to do implement the requirement of the line above here?
As a result, the function should generate schedules with two lectures which are not in the same time slot.
You started by assuming, i want to use an if-else statement in the following way, but the logic of your problem doesn't describe an if-then-else condition. An if-then-else isn't the construct you want to achieve your goal of:
Generate schedules with two lectures which are not in the same time slot
Also, the Prolog if-then-else construct A -> B ; C removes the choice point you are after. For some detail on this, see the answer to, What's the meaning of Prolog operator '->'
What you really want is to say:
A schedule two lectures A & B is valid if Day1 and Time1 are a time slot for A, and Day2 and Time2 are a time slot for B, and time slots Day1-Time1 and Day2-Time2 are different.
If fact, to avoid duplicates and to keep the schedule in chronological order, we can enforce that the "first" time slot is earlier than the second. This translates to:
generate_possible_schedules_with_two_lectures(LectureA, LectureB):-
lecture(LectureA, Day1, Time1),
lecture(LectureB, Day2, Time2),
dif(LectureA, LectureB), % don't schedule the same class
Day1-Time1 #< Day2-Time2 % timeslots in order, and different
We simplify the time slot comparison by forming a term A-B with the day and time. You could do the longer comparison, comparing the day and tie individually, replacing Day1-Time1 #< Day2-Time2 with (Day1 #< Day2 ; Day1 == Day2, Time1 #< Time2). In either case, you get the following results with your data:
?- generate_possible_schedules_with_two_lectures(A, B).
A = spanish,
B = german ;
A = french,
B = german ;
A = english,
B = spanish ;
A = english,
B = french ;
A = english,
B = german ;
false.

Recursively Assigning One List Element to Another in Prolog

This is a homework assignment and my first experience with Prolog. My goal is to create a list of Assignments from a list of people and a list of tasks. If a person has the letter identifier which matches the tasks then that persons ID and the Tasks ID are matched up and placed in a list of Assignments. My function prints out a list but it does not look like it is comparing all the elements. A sample input: schedule([p1,p2,p3],[t1,t2],Result). A sample output would look like [[p1,t1],[p2,t2][p3,t1],[p3,t2]].
What I have so far:
%%
%% person(ID, TASK_CAPABILITIES, AVAILABLE_HOURS)
%%
%% How many hours each person has available and what classes of tasks they
%% are capable of performing.
%%
person(p1, [c,a], 20).
person(p2, [b], 10).
person(p3, [a,b], 15).
person(p4, [c], 30).
%%
%% task(ID, REQUIRED_HOURS, TASK_CLASS)
%%
%% How long each task requires and what class it falls under.
%%
task(t1, a, 5).
task(t2, b, 10).
task(t3, c, 15).
task(t4, c, 10).
task(t5, a, 15).
task(t6, b, 10).
%test arithmetic functions
add(X, Y, Z) :- Z is X + Y.
subtract(X,Y,Z) :- Z is X - Y.
schedule([],[],[]).
schedule(People,
[Task|OtherTasks],
[[PersonId, TaskId]|RestOfAssignments]):-
member(PersonId, People),
person(PersonId, PersonCapabilities,_),
member(TaskId, [Task|OtherTasks]),
task(TaskId, TaskType,_),
member(TaskType, PersonCapabilities),
schedule( _, OtherTasks, RestOfAssignments).
My reasoning behind what I wrote was that the list of People would be compared to each task, then that task would be replaced by the next task and the comparison would repeat. What I see in the trace of this function instead is that the tasks are being removed from the list but are only compared to the first two People. My question is how can I get the schedule function to check the full list of people for each task?
Your problem seems ill specified, and you are simplifying too much... the code should keep into account hours availability as well as memberships. Ignoring this problem, select/3 instead of member/2 could help to model a naive solution:
schedule([],_,[]).
% peek a suitable task for PersonId
schedule([PersonId|People], Tasks, [[PersonId, TaskId]|RestOfAssignments]):-
select(TaskId, Tasks, RestTasks),
person(PersonId, PersonCapabilities,_),
task(TaskId, TaskType,_),
memberchk(TaskType, PersonCapabilities),
schedule(People, RestTasks, RestOfAssignments).
% if no suitable task for PersonId
schedule([_PersonId|People], Tasks, Assignments):-
schedule(People, Tasks, Assignments).
yields these solutions
?- schedule([p1,p2,p3],[t1,t2],Result).
Result = [[p1, t1], [p2, t2]] ;
Result = [[p1, t1], [p3, t2]] ;
Result = [[p1, t1]] ;
Result = [[p2, t2], [p3, t1]] ;
Result = [[p2, t2]] ;
Result = [[p3, t1]] ;
Result = [[p3, t2]] ;
Result = [].

Enumerate list values into a list of dictionaries

I have a list of dictionaries, and I'm trying to assign dictionary key:value pairs based on the values of other other variables in lists. I'd like to assign the "ith" value of each variable list to ith dictionary in block_params_list with the variable name (as a string) as the key. The problem is that while the code appropriately assigns the values (as demonstrated by "pprint(item)"), when the entire enumerate loop is finished, each item in "block_params_list" is equal to the value of the last item.
I'm at a loss to explain this behavior. Can someone help? Thanks!
'''empty list of dictionaries'''
block_params_list = [{}] * 5
'''variable lists to go into the dictionaries'''
ran_iti = [False]*2 + [True]*3
iti_len = [1,2,4,8,16]
trial_cnt = [5,10,15,20,25]
'''the loops'''
param_list= ['iti_len','trial_cnt','ran_iti']#key values, also variable names
for i,item in enumerate(block_params_list):
for param in param_list:
item[param] = eval(param)[i]
pprint(item) #check what each item value is after assignment
pprint(block_params_list) #prints a list of dictionaries that are
#only equal to the very last item assigned
You've hit a common 'gotcha' in Python, on your first line of code:
# Create a list of five empty dictionaries
>>> block_params_list = [{}] * 5
The instruction [{}] * 5 is equivalent to doing this:
>>> d = {}
>>> [d, d, d, d, d]
The list contains five references to the same dictionary. You say "each item in 'block_params_list' is equal to the value of the last item" - that's an illusion, there's effectively only one item in "block_params_list" and you are assigning to it, then looking at it, five times over through five different references to it.
You need to use a loop to create your list, to make sure you create five different dictionaries:
block_params_list = []
for i in range(5):
block_params_list.append({})
or
block_params_list = [{} for i in range(5)]
NB. You can safely do [1] * 5 for a list of numbers, or [True] * 5 for a list of True, or ['A'] * 5 for a list of character 'A'. The distinction is whether you end up changing the list, or whether you change a thing referenced by the list. Top level or second level.
e.g. making a list of numbers, assinging to it does this:
before:
nums = [1] * 3
list_start
entry 0 --> 1
entry 1 --> 1
entry 2 --> 1
list_end
nums[0] = 8
after:
list_start
entry 0 -xx 1
\-> 8
entry 1 --> 1
entry 2 --> 1
list_end
Whereas making a list of dictionaries the way you are doing, and assigning to it, does this:
before:
blocks = [{}] * 3
list_start
entry 0 --> {}
entry 1 --/
entry 2 -/
list_end
first_block = blocks[0]
first_block['test'] = 8
after:
list_start
entry 0 --> {'test':8}
entry 1 --/
entry 2 -/
list_end
In the first example, one of the references in the list has to change. You can't pull a number out of a list and change the number, you can only put a different number in the list.
In the second example, the list itself doesn't change at all, you're assigning to a dictionary referenced by the list. So while it feels like you are updating every element in the list, you really aren't, because the list doesn't "have dictionaries in it", it has references to dictionaries in it.

Prolog: Writing each element of an existing list

I'm trying to do two things. (1) display each element of an existing list, and (2) search a list to display all names that contain that element.
Here are some facts:
classes(hannes, [cs490, cs499, cs413]). % name has this list of classes
classes(tony, [ma330, ma211, ma250]).
classes(nicholas, [cs424, cs570, ma330]).
classes(pj, [ma211, ma250, ma285, cs424]).
classes(inga, [cs285, cs307, cs309]).
classes(christine, [ma285, ma211, ma330]).
classes(lisa, [cs424, cs413, cs490]).
classes(marty, [cs570, cs424]).
And, here is my rule so far:
taking(N,C) :- % student Name N is taking class C
classes(N,Cs),
[C|T] = Cs.
At the moment, I know this only takes the head of the list and displays it. I need to display each item of the list (one line at a time, if easy enough to do, but not important). But, I also need to be able to do it in reverse. If 1 course is queried (ma330), I want it to display all students that have that particular course.
Query example 1:
?- taking(nicholas, Classes).
Classes = [cs424, cs570, ma330] ;
OR
?- taking(nicholas, Classes).
Classes = cs424 ;
Classes = cs570 ;
Classes = ma330 ;
Query example 2:
?- taking(Names, ma330).
Names = tony ;
Names = nicholas ;
Names = christine ;
I'm going to keep searching for a resolution, but if anyone can help, it would be appreciated.
Thank you!!!
Think of that : C is member of Classes.
EDIT OK try this code :
taking(N,C) :- % student Name N is taking class C
classes(N,Cs),
member(C, Cs).

Erlang record item list

For example i have erlang record:
-record(state, {clients
}).
Can i make from clients field list?
That I could keep in client filed as in normal list? And how can i add some values in this list?
Thank you.
Maybe you mean something like:
-module(reclist).
-export([empty_state/0, some_state/0,
add_client/1, del_client/1,
get_clients/1]).
-record(state,
{
clients = [] ::[pos_integer()],
dbname ::char()
}).
empty_state() ->
#state{}.
some_state() ->
#state{
clients = [1,2,3],
dbname = "QA"}.
del_client(Client) ->
S = some_state(),
C = S#state.clients,
S#state{clients = lists:delete(Client, C)}.
add_client(Client) ->
S = some_state(),
C = S#state.clients,
S#state{clients = [Client|C]}.
get_clients(#state{clients = C, dbname = _D}) ->
C.
Test:
1> reclist:empty_state().
{state,[],undefined}
2> reclist:some_state().
{state,[1,2,3],"QA"}
3> reclist:add_client(4).
{state,[4,1,2,3],"QA"}
4> reclist:del_client(2).
{state,[1,3],"QA"}
::[pos_integer()] means that the type of the field is a list of positive integer values, starting from 1; it's the hint for the analysis tool dialyzer, when it performs type checking.
Erlang also allows you use pattern matching on records:
5> reclist:get_clients(reclist:some_state()).
[1,2,3]
Further reading:
Records
Types and Function Specifications
dialyzer(1)
#JUST MY correct OPINION's answer made me remember that I love how Haskell goes about getting the values of the fields in the data type.
Here's a definition of a data type, stolen from Learn You a Haskell for Great Good!, which leverages record syntax:
data Car = Car {company :: String
,model :: String
,year :: Int
} deriving (Show)
It creates functions company, model and year, that lookup fields in the data type. We first make a new car:
ghci> Car "Toyota" "Supra" 2005
Car {company = "Toyota", model = "Supra", year = 2005}
Or, using record syntax (the order of fields doesn't matter):
ghci> Car {model = "Supra", year = 2005, company = "Toyota"}
Car {company = "Toyota", model = "Supra", year = 2005}
ghci> let supra = Car {model = "Supra", year = 2005, company = "Toyota"}
ghci> year supra
2005
We can even use pattern matching:
ghci> let (Car {company = c, model = m, year = y}) = supra
ghci> "This " ++ c ++ " " ++ m ++ " was made in " ++ show y
"This Toyota Supra was made in 2005"
I remember there were attempts to implement something similar to Haskell's record syntax in Erlang, but not sure if they were successful.
Some posts, concerning these attempts:
In Response to "What Sucks About Erlang"
Geeking out with Lisp Flavoured Erlang. However I would ignore parameterized modules here.
It seems that LFE uses macros, which are similar to what provides Scheme (Racket, for instance), when you want to create a new value of some structure:
> (define-struct car (company model year))
> (define supra (make-car "Toyota" "Supra" 2005))
> (car-model supra)
"Supra"
I hope we'll have something close to Haskell record syntax in the future, that would be really practically useful and handy.
Yasir's answer is the correct one, but I'm going to show you WHY it works the way it works so you can understand records a bit better.
Records in Erlang are a hack (and a pretty ugly one). Using the record definition from Yasir's answer...
-record(state,
{
clients = [] ::[pos_integer()],
dbname ::char()
}).
...when you instantiate this with #state{} (as Yasir did in empty_state/0 function), what you really get back is this:
{state, [], undefined}
That is to say your "record" is just a tuple tagged with the name of the record (state in this case) followed by the record's contents. Inside BEAM itself there is no record. It's just another tuple with Erlang data types contained within it. This is the key to understanding how things work (and the limitations of records to boot).
Now when Yasir did this...
add_client(Client) ->
S = some_state(),
C = S#state.clients,
S#state{clients = [Client|C]}.
...the S#state.clients bit translates into code internally that looks like element(2,S). You're using, in other words, standard tuple manipulation functions. S#state.clients is just a symbolic way of saying the same thing, but in a way that lets you know what element 2 actually is. It's syntactic saccharine that's an improvement over keeping track of individual fields in your tuples in an error-prone way.
Now for that last S#state{clients = [Client|C]} bit, I'm not absolutely positive as to what code is generated behind the scenes, but it is likely just straightforward stuff that does the equivalent of {state, [Client|C], element(3,S)}. It:
tags a new tuple with the name of the record (provided as #state),
copies the elements from S (dictated by the S# portion),
except for the clients piece overridden by {clients = [Client|C]}.
All of this magic is done via a preprocessing hack behind the scenes.
Understanding how records work behind the scenes is beneficial both for understanding code written using records as well as for understanding how to use them yourself (not to mention understanding why things that seem to "make sense" don't work with records -- because they don't actually exist down in the abstract machine...yet).
If you are only adding or removing single items from the clients list in the state you could cut down on typing with a macro.
-record(state, {clients = [] }).
-define(AddClientToState(Client,State),
State#state{clients = lists:append([Client], State#state.clients) } ).
-define(RemoveClientFromState(Client,State),
State#state{clients = lists:delete(Client, State#state.clients) } ).
Here is a test escript that demonstrates:
#!/usr/bin/env escript
-record(state, {clients = [] }).
-define(AddClientToState(Client,State),
State#state{clients = lists:append([Client], State#state.clients)} ).
-define(RemoveClientFromState(Client,State),
State#state{clients = lists:delete(Client, State#state.clients)} ).
main(_) ->
%Start with a state with a empty list of clients.
State0 = #state{},
io:format("Empty State: ~p~n",[State0]),
%Add foo to the list
State1 = ?AddClientToState(foo,State0),
io:format("State after adding foo: ~p~n",[State1]),
%Add bar to the list.
State2 = ?AddClientToState(bar,State1),
io:format("State after adding bar: ~p~n",[State2]),
%Add baz to the list.
State3 = ?AddClientToState(baz,State2),
io:format("State after adding baz: ~p~n",[State3]),
%Remove bar from the list.
State4 = ?RemoveClientFromState(bar,State3),
io:format("State after removing bar: ~p~n",[State4]).
Result:
Empty State: {state,[]}
State after adding foo: {state,[foo]}
State after adding bar: {state,[bar,foo]}
State after adding baz: {state,[baz,bar,foo]}
State after removing bar: {state,[baz,foo]}