I'm doing a Prolog project for uni that's based on the Kakuro game.
I'm having trouble with the predicate spaces_puzzle/2 that does the following:
Receives the Puzzle in the form of a list of lists that represents each file of the puzzle:
[[[sum_vertical, sum_horizontal], P11, P12, [sum_vertical, sum_horizontal],P13, P14...],
[[sum_vertical, sum_horizontal], P21, P22, P23, P24, ...],
[[sum_vertical, sum_horizontal], P31, P32, P33, P34, P35 ...],
...]
and returns a list like this [space(sum_horizontal, [P11,P12]), space(sum_horizontal, [P13,P14]), space(sum_horizontal, [P21,P22,P23,P24]) ...]
I was thinking of using a maplist with a predicate that I have already defined as spaces_in_file/3 which will read a list like [[sum_vertical, sum_horizontal], P11, P12, [sum_vertical, sum_horizontal],P13, P14...] and output in the wanted formatting: [space(sum_horizontal, [P11,P12]), space(sum_horizontal, [P13,P14])...]
I don't understand the syntax for the predicate. The "Goal" I want is the spaces_in_file/3. spaces_in_file(H_V, File, Spaces) is a simple bagof where H_V is a character that says which of the sums I should use, File is the file I want to check for the spaces, and Spaces is my output.
So should it be something like this:
spaces_puzzle(Puzzle, Spaces):-
maplist(spaces_in_file(h, File, Spaces), Puzzle, File)
I want my file to be one of the lists of the Puzzle. I can't seem to get the syntax right.
For now I just want the correct Result for the files, I can easily adapt to get the columns with the transpose/2 predicate which is suggested by the professors.
Appreciate any advice!
maplist/N takes a functor and some lists, and checks whether for each element in each list, the predicate named as that functor and with arguments from those lists, is true (you can fix some arguments by adding them to the functor), so e.g:
maplist( append, [[1], [1, 2], [1, 2, 3]], [[2, 4], [5], [6, 7]], List).
is equivalent to the conjunction
append( [1], [2, 4], _A1 ), List = [ _A1 | _T1 ],
append( [1, 2], [5], _A2 ), _T1 = [ _A2 | _T2 ],
append( [1, 2, 3], [6, 7], _A3 ), _T2 = [ _A3 | _T3 ], _T3 = [].
which will return:
%% List = [ _A1, _A2, _A3 ]
List = [[1, 2, 4], [1, 2, 5], [1, 2, 3, 6, 7]].
Your predicate spaces_in_file takes three arguments, H_V, Line and Spaces, you can do a maplist by fixing H_V and then giving Line and Spaces to maplist as arguments, i.e:
maplist( spaces_in_file(h), Lines, Spaces)
Related
I try to create an emergency system to find people on time and those late.
so my list now looks like:
[ [patient(204,4,2),patient(203,3,2)] , [patient(303,7,3),patient(302,6,3)] , [patient(404,12,4) ,patient(403,11,4)] , [patient(504,16,5),patient(503,15,5)] ]
I want for each list to find those on time using the following function (score):
(consultation time) * (index of patient) + (2nd argument of patient predicate)
consultation time is constant:
example :
consultTime(15)
For this exemple i have to get something like :
[ [4 , 18] , [37, 51] , [72, 86] , [106, 120] ]
the problem is with the indices how can i preserve the same index as with a normal list i.e.:
[ [0, 1], [2, 3], [4, 5] ]
I'm sorry, i didn't find a good question for my problem.
the problem is with the indices how can i preserve the same index as with a normal list i.e.:
[ [0, 1], [2, 3], [4, 5] ]
Pass a counter in at the start of each list, use it to count through the elements, then return how far it got. Pass that value in to start the count for the next list:
% process a single list, just showing the counter
process([], C, C, []).
process([P1|P1s], Count, CountTo, [Count|P2s]) :-
succ(Count, Next),
process(P1s, Next, CountTo, P2s).
% for the list of lists
test([], _, []).
test([L1|L1s], CountFrom, [L2|L2s]) :-
process(L1, CountFrom, CountTo, L2),
test(L1s, CountTo, L2s).
e.g.
?- _Patients = [
[patient(204,4,2), patient(203,3,2)],
[patient(303,7,3), patient(302,6,3)],
[patient(404,12,4), patient(403,11,4)],
[patient(504,16,5), patient(503,15,5)]
],
test(_Patients, 0, Ps).
Ps = [[0, 1], [2, 3], [4, 5], [6, 7]]
I am trying to write a predicate which reverses all rows in a matrix using Prolog.
For instance the matrix [ [1,2,3], [4,5,6], [7,8,9] ] should become [ [3,2,1], [6,5,4], [9,8,7] ].
My attempt so far is :
reverseRows([[H|T]|_],X):-reverse([H|T],X).
which reverses only the first row. How can I change the above to work for all rows ? Any assistance is welcome.
The simplest solution is to use the predicate maplist/3.
?- maplist(reverse, [[1,2,3], [4,5,6], [7,8,9]], Reversed).
Reversed = [[3, 2, 1], [6, 5, 4], [9, 8, 7]].
Other possible solution is:
reverse_rows([], []).
reverse_rows([Xs|Xss], [Ys|Yss]) :-
reverse(Xs, Ys),
reverse_rows(Xss, Yss).
Example:
?- reverse_rows([[1,2,3], [4,5,6], [7,8,9]], Reversed).
Reversed = [[3, 2, 1], [6, 5, 4], [9, 8, 7]].
I have the following code:
pair_list([X,Y],[[X,Y]]).
pair_list([E,Z|X],[K|Y]):- [E,Z]==K, pair_list(X,Y).
When I run it, it gives correct output for
?- pair_list([1, 2, 3, 4, 5, 6], [[1, 2], [3, 4], [5, 6]]).
true ;
but when I run
?- pair_list([1,2, 3, 4, 5, 6], X).
I just get false.
My question is why don't I get X=[[1, 2], [3, 4], [5, 6]]
You are almost there: all you need to do is moving [E,Z] into the head, eliminating K:
pair_list([X,Y],[[X,Y]]).
pair_list([E,Z|X],[[E,Z]|Y]) :- pair_list(X,Y).
Demo 1.
Note that the base clause can be replaced with one based on empty lists:
pair_list([], []).
pair_list([E,Z|X],[[E,Z]|Y]) :- pair_list(X,Y).
Demo 2.
Also note that your program is not going to work with a list that has an odd number of items. In order to fix this, add a separate base clause that handles a list with a single item either by dropping the item, making a pair with some fixed atom, or doing something else that you find useful in this case.
I want to sort the sublists of a list which contains integers eliminating the duplicates. Example:
[1, 2, [4, 1, 4], 3, 6, [7, 10, 1, 3, 9], 5, [1, 1, 1], 7]
=>>>
[1, 2, [1, 4], 3, 6, [1, 3, 7, 9, 10], 5, [1], 7].
I know that i have to work with functor s(but i didn't really get it).
Here is my code : (the (insert+sorting) function works in a simple list of integers,but don't work here. i'm getting red false everytime)
insert(E,[],[E]).
insert(E,[H|T],[H|L]):-
E>H,
insert(E,T,L).
insert(E,[H|T],[H|T]):-
E=H,
!.
insert(E,[H|T],[E|[H|T]]):-
E<H,
!.
sort([],[]).
sort([i(H)|T],L):-
sort(T,L1),
insert(i(H),L1,L).
You could try a solution like this, it uses the the sort/2 predicate to sort sublists:
sort_sublists([], []).
sort_sublists([X|Xs], List) :-
(integer(X) ->
List = [X | List1]
;
sort(X, Sorted),
List = [Sorted | List1]
),
sort_sublists(Xs, List1).
Example call:
?- set_prolog_flag(answer_write_options,[max_depth(0)]).
true.
?- sort_sublists([1, 2, [4, 1, 4], 3, 6, [7, 10, 1, 3, 9], 5, [1, 1, 1], 7], X).
X = [1,2,[1,4],3,6,[1,3,7,9,10],5,[1],7].
#Eduard Adrian it's hard to answer in comments, so first thing you need to do is to remove duplicates from the nested lists.
Here i tried that and you can see different cases that you need to handle. One example:(Head of your list can be a list but it's tail will be empty this happends if last element of your list is a list) in that case you need to define another predicate which will match your recursive call.
Once you have removed duplicates you can use simple sorting algorithm but you have to check if the head is a list then you sort innner list first and place it to the same place otherwise call sort predicate.
As you asked how check if an element is_list or integer, for that you can always use built-in because those predicates you can't write by yourself.
Let us consider lists such as L=[[7,3,4],9,[4,5],[1,3,5],4] where components could be lists or atoms. How to produce this type of permutation results:
R = [[7, 3, 4], 9, [4, 5], [1, 3, 5], 4]
R = [[7, 4, 3], 9, [5, 4], [1, 3, 5], 4]
R = [[7, 4, 3], 9, [4, 5], [1, 5, 3], 4]
....
In fact, we would like to have all the possible permutations of the sub-lists of L while the atom should remain unchanged.
I wrote a classical predicate permutation(OriginalList,PermutedList), and an allperm predicate that apply the maplist function to this permutation predicate:
permutation([],[]).
permutation(L,[T|Q]) :-
select(T,L,L1),
permutation(L1,Q).
/*L is the list to permute, R the result*/
allperm(L,R) :-
maplist(permutation,L,R).
It functions only in the special case where L is composed of lists and doesn't function when L is heterogeneous (atoms and lists).
Could you provide hints or elements of solution to do the right permutation?
The following modification should do:
permutation(X,X).
permutation(L,[T|Q]) :-
dif(L,[T|Q]),
select(T,L,L1),
permutation(L1,Q).
allperm(L,R) :-
maplist(permutation,L,R).
We extend the “identity” permutation to any Prolog term (first clause of permutation) and disallow it in the second clause (which can only be applied to lists anyway).