Sum of elements in list - Prolog - list

I'm still new to SWI-Prolog and I'm not sure how to do this two questions.
Write a predicate sum_composite(Numbers, Sum) that sum ONLY COMPOSITE NUMBERS of a list of non-negative whole numbers. Example:
?- sumList([1,3,5,2,4,6,8,7],Sum).
Sum=18.
true
Write a predicate maxPrime(List, Min) that given a list of numbers, returns the maximum prime element in the list. Example:
?- maxPrime([1, -4, 7, 4, 7, 9, -2, 3], Max).
Max = 7
true
This is what I have so far:
sum_list([],0). //empty list.
sum_list([First|Tail],Sum) :-
sumlist(Tail, SumTail).

As nearly always in Prolog, you can write predicates on lists using two clauses.
foo(L,R) :-
foo(L,I,R).
foo([],F,F).
foo([H|T],F,R) :-
F2 is f(F,H),
foo(T,F2,R).
With F the current result, F2 the updated result, H the head of the list that far, T the tail of the list, I the initial value, and R the result.
Such patterns use tail recursion with an accumulator (in this case F), this patterns are considered one of the most efficient in Prolog. (middle-recursion or return accumulators increase the call stack and require more bookkeeping).
In case of a sum, this is tranformed into:
sum(L,R) :-
sum(L,0,R).
sum([],F,F).
sum([H|T],F,R) :-
F2 is F+H,
sum(T,F2,R).
I will leave the maxPrime as an exercise, but it fits "nicely" into the above described pattern.

question
Write a predicate composites_sum(NUMBERs, SUM) that sums ONLY COMPOSITE NUMBERS of a list of non-negative whole numbers .
(ed: a "composite" number is an number that is not an "prime" number) .
Example :
?- composites_sum([1,3,5,2,4,6,8,7],Sum) .
Sum = 18 .
true
answer
./src/parts/composites_sum.prolog
composites_sum(NUMBERs0,SUM)
:-
composites(NUMBERs0,NUMBERs) ,
sum(NUMBERs,SUM)
.
./demos/parts/composites_sum.prolog.console
?- composites_sum([1,3,5,2,4,6,8,7],SUM) .
SUM = 18 .
?- composites_sum([1,2,3],SUM) .
SUM = 0 .
?- sum([1,2,3],SUM) .
SUM = 6 .
?- sum([1,2,3,4],SUM) .
SUM = 10 .
?- composites_sum([1,2,3,4],SUM) .
SUM = 4 .
?- composites_sum([],SUM) .
SUM = 0 .
./src/parts/prime.prolog
%! prime(N0)
%
% true if `N0` is an prime number ;
% false if `N0` is not an prime number .
%
% this predicate can be used to generate prime numbers ;
% see the demos for the example using `between` .
/*
If an number is divisible by any other number less than it's sqrt then
the number is not prime ; otherwise it is prime .
*/
:- op(1,'xfy','prime_') .
prime(N0) :- [start] prime_ (N0) .
[start] prime_ (N0)
:-
[init] prime_ (N0)
.
[init] prime_ (N0)
:-
K is floor(sqrt(N0)) ,
[while] prime_ (N0,K)
.
[while] prime_ (_N0,K0)
:-
K0 = 1 ,
! ,
[finish] prime_ (true)
.
[while] prime_ (N0,K0)
:-
0 is mod(N0,K0) , % true if K0 multiplied by some value is N0 .
! ,
[finish] prime_ (false)
.
[while] prime_ (N0,K0)
:-
! ,
K is K0 - 1 ,
[while] prime_ (N0,K)
.
[finish] prime_ (true) .
[finish] prime_ (false) :- false .
./demos/parts/prime__1.prolog.console
?- prime(1) .
true
?- prime(2) .
true
?- prime(3) .
true
?- prime(4) .
false
?- prime(5) .
true
?- prime(7) .
true
./demos/parts/prime__2.prolog.console
?- between(1,1000,N) , prime(N) .
N = 1 ? ;
N = 2 ? ;
N = 3 ? ;
N = 5 ? ;
N = 7 ? ;
N = 11 ? ;
N = 13 ? ;
N = 17 ? ;
N = 19 ? ;
N = 23 ? ;
N = 29 ? ;
N = 31 ? ;
N = 37 ? ;
N = 41 ? ;
N = 43 ? ;
N = 47 ? ;
N = 53 ? ;
N = 59 ? ;
N = 61 ? ;
N = 67 ? ;
N = 71 ? %etcetera.
./src/parts/composites.prolog
%! composites(Xs0,Ys)
%
% `Ys` is those elements of `Xs0` that are not prime .
composites([],[]) :- ! .
composites([X0|Xs],[X0|Ys])
:-
+ prime(X0) ,
! ,
composites(Xs,Ys)
.
composites([_X0|Xs],Ys0)
:-
! ,
composites(Xs,Ys0)
.
./demos/parts/composites.prolog.console
?- composites([1,2,3,4,5,6,7,8,9,10,11,12],Cs) .
Cs = [4,6,8,9,10,12] .
?- composites([1],Cs) .
Cs = [] .
?- composites([],Cs) .
Cs = [] .
./src/parts/sum.prolog
%! sum(Xs,SUM)
%
% calculate the total sum of the items of list `Xs` .
sum(Xs,SUM)
:-
sum(Xs,0,SUM)
.
sum([],SUM0,SUM0) .
sum([X0|Xs],SUM0,SUM)
:-
SUM1 is SUM0 + X0 ,
sum(Xs,SUM1,SUM)
.
./demos/parts/sum.prolog.console
?- sum([1,2,3,4],SUM).
SUM = 10.
?- sum([1,2],SUM).
SUM = 3.
?- sum([1,2,-1],SUM).
SUM = 2.
?- sum([-1],SUM).
SUM = -1.
?- sum([],SUM).
SUM = 0.

Related

Calculating List of positive numbers of a given list in Prolog

I tried resolving it by myself in the following way:
list_of_positives(L1, L2) :-
list_of_positives(L1, L2, []).
list_of_positives([], L, L).
list_of_positives([H|T], L2, L3) :-
( H > 0
-> list_of_positives(T,L2,[H|L3])
; list_of_positives(T,L2,L3)
).
The problem with this solution is that I get as response a reversed list of positive numbers. Can someone help me to find a way to get the list in the "correct order"?
You can solve the problem as follows:
positives([], []).
positives([H|T], P) :-
( H > 0
-> P = [H|R] % desired order!
; P = R),
positives(T, R) .
Example:
?- positives([2,-3,6,-7,1,4,-9], P).
P = [2, 6, 1, 4].
You want to use a difference list, a non-closed, or open list. So, something like this:
positives( [] , [] ) . % An empty list has not positives, and closes the list.
positives( [N|Ns] , [N|Rs] ) :- % For a non-empty list, we prepend N to the result list
N > 0, % - if N is positive
positives(Ns,Rs) % - and recurse down.
. %
positives( [N|Ns] , Rs ) :- % For non-empty lists, we discard N
N =< 0, % - if N is non-positive
positives(Ns,Rs) % - and recurse down.
. %

Prolog - How to count the number of elements in a list that satisfy a specific condition?

for example, if I have a list [1,1,2,3,5,1], I want to count the number of 1's in this list, how would I do that?
I wrote something like:
count([], 0).
count([H|T], N) :-
count(T, X),
( H =:= 1
-> N is X+1
; N is X
),
N > 0.
In this recursion, I want to do if Head equals 1, then the counting + 1, if Head is not 1, then counting stays the same. However, it returns false if I have things that are not 1 in the list. I know the problem is that it'd fail as soon as an element does not satisfy the if statement; and it can never reach the else statement. How do I fix this? Please help!!!!
Try this:
count([],0).
count([1|T],N) :- count(T,N1), N is N1 + 1.
count([X|T],N) :- X \= 1, count(T,N).
Alternative solution, which uses foldl/4 and defines higher order predicate (the one which takes another predicate as a parameter):
count_step(Condition, Item, CurrentCount, NewCount) :-
call(Condition, Item) ->
NewCount is CurrentCount + 1 ;
NewCount = CurrentCount.
count(List, Condition, Count) :-
foldl(count_step(Condition), List, 0, Count).
is_one(Expr) :-
Expr =:= 1.
Usage example:
?- count([0, 2, 3, 0], is_one, Count).
Count = 0.
?- count([1, 2, 3, 1], is_one, Count).
Count = 2.
Another (rather dirty) approach is to use include/3 combined with length/2:
count(List, Condition, Count) :-
include(Condition, List, Filtered),
length(Filtered, Count).
Let’s start with your code and ask some queries!
I added comments on the side showing the result I would have expected...
?- count([0,2,3,0], Count).
false % bad: expected Count = 0
?- count([1,2,3,1], Count).
Count = 2 % ok
?- count([1,2,3], Count).
false % bad: expected Count = 1
If my expectation matches yours, the minimal fix for your code is tiny: just remove the goal N > 0!
count([], 0).
count([H|T], N) :-
count(T, X),
( H =:= 1
-> N is X+1
; N is X
).
Let’s run above queries again:
?- count([0,2,3,0], Count).
Count = 0 % was “false”, now ok
?- count([1,2,3,1], Count).
Count = 2 % was ok, still is ok
?- count([1,2,3], Count).
Count = 1. % was “false”, now ok
The bottom line: your original code failed whenever the last list item was not equal to 1.
Since you've already opted to use (;)/2 - if-then-else, you might find the following variant with if_/3 interesting:
list_1s(L,X) :-
length(L,Len),
list_1s_(L,X,0,Len).
list_1s_([],X,X,0).
list_1s_([Y|Ys],X,Acc0,Len1) :-
if_(Y=1, Acc1 is Acc0+1, Acc1 is Acc0),
Len0 is Len1-1,
list_1s_(Ys,X,Acc1,Len0).
The goal length/2 in the calling predicate list_1s/2 together with the 4th argument of the actual relation list_1s_/4 is used to make sure the result lists are listed in a fair manner if the predicate is called with the first argument being variable. The 3rd argument of list_1s_/4 is an accumulator that's used to count the number of 1s up from zero, in order to make the predicate tail recursive. Consequently the 2nd and 3rd arguments of list_1s_/4 are equal if the list is empty. Now let's see some example queries. In the list to number direction the predicate yields the desired results and succeeds deterministically (it doesn't leave unnecessary choice points open, no need to press ; after the single answer) in doing so:
?- list_1s([],X).
X = 0.
?- list_1s([1,2,3],X).
X = 1.
?- list_1s([1,2,3,1],X).
X = 2.
?- list_1s([0,2,3,0],X).
X = 0.
In the number to list direction there are infinitely many lists for any given number and, as mentioned above, they are listed in a fair manner, that is, all possibilities of lists of length n are listed before moving on to length n+1:
?- list_1s(L,0).
L = [] ; % <- empty list
L = [_G386], % <- length 1
dif(_G386, 1) ;
L = [_G442, _G445], % <- length 2
dif(_G442, 1),
dif(_G445, 1) ;
L = [_G498, _G501, _G504], % <- length 3
dif(_G498, 1),
dif(_G501, 1),
dif(_G504, 1) ;
.
.
.
?- list_1s(L,1).
L = [1] ; % <- length 1
L = [1, _G404], % <- length 2
dif(_G404, 1) ;
L = [_G401, 1], % <- length 2
dif(_G401, 1) ;
L = [1, _G460, _G463], % <- length 3
dif(_G460, 1),
dif(_G463, 1) ;
L = [_G457, 1, _G463], % <- length 3
dif(_G457, 1),
dif(_G463, 1) ;
L = [_G457, _G460, 1], % <- length 3
dif(_G457, 1),
dif(_G460, 1) ;
.
.
.
And the most general query is listing the results in a fair manner as well:
?- list_1s(L,X).
L = [], % <- empty list
X = 0 ;
L = [1], % <- length 1
X = 1 ;
L = [_G413], % <- length 1
X = 0,
dif(_G413, 1) ;
L = [1, 1], % <- length 2
X = 2 ;
L = [1, _G431], % <- length 2
X = 1,
dif(_G431, 1) ;
L = [_G428, 1], % <- length 2
X = 1,
dif(_G428, 1) ;
.
.
.

PROLOG Undefined procedure ERROR (Two parameters recursion)

count([], 0, 0).
count([X|T], M, N) :- 1 is X, count(T, MRec, NRec),
M is MRec, N is NRec+1.
count([X|T], M, N) :- 0 is X, count(T, MRec, NRec),
M is MRec+1, N is NRec.
control_number(L) :- count_digit(L, M, N), 2 is M, 3 is N.
?- control_number([1,1,0,0,1]).
ERROR: count_number/3: Undefined procedure: count/3
Hello everybody, I need help. This code must provide the count of two separate number recursively. However, I cannot provide recursion
with 2 parameters. I guess MRec and NRec is not valid in any way.
Any help will be appreciated. Thanks now...
Here is a more idiomatic rewrite:
count_digits([], 0, 0).
count_digits([1|T], M, N) :-
count_digits(T, M, NRec),
N is NRec+1.
count_digits([0|T], M, N) :-
count_digits(T, MRec, N),
M is MRec+1.
control_number(L) :-
count_digits(L, 2, 3).
This can be improved a lot by using library(clpfd). Maybe someone else will answer.
As already pointed out by #false this predicate is quite a candidate for clpfd. Besides that I added constraints (marked as % <-) to ensure that M and N are greater than 0 in the recursive cases, so Prolog does not continue to search for further solutions once those variables have been reduced to 0.
:- use_module(library(clpfd)).
count_digits([], 0, 0).
count_digits([1|T], M, N) :-
N #> 0, % <-
NRec #= N-1,
count_digits(T, M, NRec).
count_digits([0|T], M, N) :-
M #> 0, % <-
MRec #= M-1,
count_digits(T, MRec, N).
With these minor modifications you can already use count_digits/3 in several ways. For example to ask for all lists with 2 0's and 3 1's:
?- count_digits(L,2,3).
L = [1,1,1,0,0] ? ;
L = [1,1,0,1,0] ? ;
L = [1,1,0,0,1] ? ;
L = [1,0,1,1,0] ? ;
L = [1,0,1,0,1] ? ;
L = [1,0,0,1,1] ? ;
L = [0,1,1,1,0] ? ;
L = [0,1,1,0,1] ? ;
L = [0,1,0,1,1] ? ;
L = [0,0,1,1,1] ? ;
no
Or count the occurrences of 0's and 1's in a given list:
?- count_digits([1,1,0,0,1],M,N).
M = 2,
N = 3
% 1
Or even ask for the number of 0's and 1's in a list containing variables:
?- count_digits([1,0,X,Y],M,N).
M = X = Y = 1,
N = 3 ? ;
M = N = 2,
X = 1,
Y = 0 ? ;
M = N = 2,
X = 0,
Y = 1 ? ;
M = 3,
N = 1,
X = Y = 0
This is quite nice already and one might be content with the predicate as is. It certainly is fine if you intend to use it with control_number/1 as suggested by #false. However it might be worth the time to fool around a little with some other queries. For example the most general query: What lists are there with M 0's and N 1's?
?- count_digits(L,M,N).
L = [],
M = N = 0 ? ;
L = [1],
M = 0,
N = 1 ? ;
L = [1,1],
M = 0,
N = 2 ? ;
L = [1,1,1],
M = 0,
N = 3 ?
...
It is only producing lists that consist of 1's exclusively. That is because the first recursive rule is the one describing the case with the 1 as the first element of the list. So the solutions are coming in an unfair order. What happens with the following query is maybe even somewhat less intuitive: What lists are there with the same (but not fixed) number of 0's and 1's:
?- count_digits(L,M,M).
L = [],
M = 0 ? ;
There is an answer and then the predicate loops. That's not exactly a desirable property. An interesting observation about this query: If one uses it on lists with fixed length the result is actually as expected:
?- length(L,_), count_digits(L,M,M).
L = [],
M = 0 ? ;
L = [1,0],
M = 1 ? ;
L = [0,1],
M = 1 ? ;
L = [1,1,0,0],
M = 2 ? ;
L = [1,0,1,0],
M = 2 ? ;
...
Applying this idea to the previous query yields a fair ordering of the results:
?- length(L,_), count_digits(L,M,N).
L = [],
M = N = 0 ? ;
L = [1],
M = 0,
N = 1 ? ;
L = [0],
M = 1,
N = 0 ? ;
L = [1,1],
M = 0,
N = 2 ? ;
L = [1,0],
M = N = 1 ? ;
...
It certainly would be nice to get these results without having to prefix an auxiliary goal. And looking a little closer at the relation described by count_digits/3 another observation meets the eye: If there are M 0's and N 1's the length of the list is actually fixed, namely to M+N. To put these observations to work one could rename count_digits/3 to list_0s_1s/3 and redefine count_digits/3 to be the calling predicate with the following constraints:
:- use_module(library(clpfd)).
count_digits(L,M,N) :-
X #= M+N,
length(L,X), % L is of length M+N
list_0s_1s(L,M,N).
list_0s_1s([], 0, 0).
list_0s_1s([1|T], M, N) :-
N #> 0,
NRec #= N-1,
list_0s_1s(T, M, NRec).
list_0s_1s([0|T], M, N) :-
M #> 0,
MRec #= M-1,
list_0s_1s(T, MRec, N).
The first three queries above yield the same results as before but these two are now producing results in a fair order without looping:
?- count_digits(L,M,N).
L = [],
M = N = 0 ? ;
L = [1],
M = 0,
N = 1 ? ;
L = [0],
M = 1,
N = 0 ? ;
L = [1,1],
M = 0,
N = 2 ? ;
L = [1,0],
M = N = 1 ?
...
?- count_digits(L,M,M).
L = [],
M = 0 ? ;
L = [1,0],
M = 1 ? ;
L = [0,1],
M = 1 ? ;
L = [1,1,0,0],
M = 2 ? ;
L = [1,0,1,0],
M = 2 ?
...
Two last notes on your predicate control_number/1: Firstly, if you are using is/2 make sure to use it like so:
?- M is 2.
M = 2
% 1
instead of (as used in your definition of control_number/1):
?- 2 is M.
ERROR!!
INSTANTIATION ERROR- in arithmetic: expected bound value
% 1
And secondly, if you intend to use a predicate like control_number/1 to call count_digits/3, don't put goals like M is 2 and N is 3 after the actual call of count_digits/3. That way you are asking for all solutions of count_digits(L,M,N), of which there are infinitely many, and in the subsequent goals you are then filtering out the ones that satisfy your constraints (M is 2 and N is 3). With this ordering of the goals you make sure that control_number/1 does not terminate after producing the finite number of solutions, since infinitely many solution-candidates are produced by the first goal that subsequently fail according to your constraints. Instead, place such constraints first or put them directly as arguments into the goal as posted by #false.
Accumulation parameters is the way to go (you need an auxiliary predicate in order to initialize those parameters):
count(List,C0,C1) :-
count_aux(List,C0,C1,0,0).
count_aux([],C0,C1,C0,C1).
count_aux([0|Rest],C0,C1,PartialC0,PartialC1) :-
IncC0 is PartialC0+1,
!,
count_aux(Rest,C0,C1,IncC0,PartialC1).
count_aux([1|Rest],C0,C1,PartialC0,PartialC1) :-
IncC1 is PartialC1+1,
!,
count_aux(Rest,C0,C1,PartialC0,IncC1).
count_aux([_|Rest],C0,C1,PartialC0,PartialC1) :-
count_aux(Rest,C0,C1,PartialC0,PartialC1).
Note:
You should call count/3, not count_aux/5.
Last two parameters to count_aux/5 are accumulation parameters
initialized to zero.
First clause to count_aux/5 is the base case, where accumulated
parameters are returned.
Last clause to count_aux/5 prevents predicate failure if list items
are not 0 nor 1.
Example:
?- count([1,1,0,0,0,k],A,B).
A = 3,
B = 2.

Prolog : Comparing numbers in a list

I have this block of numbers:
num(1).
num(-2).
num(5).
num(50).
num(-3).
num(87).
I'm supposed to make a function that given a number it is supposed to check if that number is the smallest of that "list" of numbers given above.
ex:
not_smallest(5).
true.
not_smallest(X).
X = 1 ;
X = -2 ;
X = 5 ;
X = 50 ;
X = 87.
What i thought was making a list with the above block of numbers , and comparing a given number to all elements of the list.
But whenever i try to load the .pl doc i get this error:
Syntax error: Operator expected
what i have done so far is this:
%increments the index of a List
incr(X, X1) :-
X1 is X + 1.
%L-list containing "list" of numbers, N - elements of that "list",
I-index , C-number X is going to be compared to, X- number to compare.
nao_menor(X) :-
findall(N, num(N), L),
num(X),
I is 0,
nth0(I, L, C),
X =< C,
incr(I,I).
Here we go:
not_smallest(N) :-
num(N),
\+ \+ (num(M), M < N).
Sample queries as given by the OP:
?- not_smallest(5).
true.
?- not_smallest(X).
X = 1
; X = -2
; X = 5
; X = 50
; X = 87.

How to count the number of 1's surrounding a given element in a 2D list with Haskell?

Suppose I have the following nested list:
list =
[[0, 1, 0],
[1, 9, 1],
[1, 1, 0]]
Assuming you are only given the x and y coordinate of 9. How do I use Haskell code to find out how many 1's surrounds the number 9?
Let me clarify a bit more, assume the number 9 is positioned at (0, 0).
What I am trying to do is this:
int sum = 0;
for(int i = -1; i <= 1; i++){
for(int j = -1; j <= 1; j++){
if(i == 0 || j == 0) continue;
sum += list[i][j];
}
}
The positions surrounding (0,0) are the following coordinates:
(-1, -1) (0, -1) (1, -1)
(-1, 0) (1, 0)
(-1, 1) (0, 1) (1, 1)
list = [[0,1,0],[1,9,1],[1,1,0]]
s x y = sum [list !! j !! i | i <- [x-1..x+1], j <- [y-1..y+1], i /= x || j /= y]
--s 1 1 --> 5
Note that I there is no error correction if the coordinates are at the edge. You could implement this by adding more conditions to the comprehension.
A list of lists isn't the most efficient data structure if things get bigger. You could consider vectors, or a Map (Int,Int) Int (especially if you have many zeros that could be left out).
[Edit]
Here is a slightly faster version:
s x y xss = let snip i zs = take 3 $ drop (i-1) zs
sqr = map (snip x) $ snip y xss
in sum (concat sqr) - sqr !! 1 !! 1
First we "snip out" the 3 x 3 square, then we do all calculations on it. Again, coordinates on the edges would lead to wrong results.
Edit: switched to summing surrounding 8 rather than surrounding 4
How often do you just want the surrounding count for just one entry? If you want it for all the entries, lists still perform fairly well, you just have to look at it holistically.
module Grid where
import Data.List (zipWith4)
-- given a grid A, generate grid B s.t.
-- B(x,y) = A(x-1,y-1) + A(x,y-1) + A(x+1,y-1)
-- + A(x-1,y) + A(x+1,y)
-- + A(x-1,y+1) + A(x,y+1) + A(x+1,y+1)
-- (where undefined indexes are assumed to be 0)
surrsum :: [[Int]] -> [[Int]]
surrsum rs = zipWith3 merge rs ([] : init rs') (tail rs' ++ [[]])
where -- calculate the 3 element sums on each row, so we can reuse them
rs' = flip map rs $ \xs -> zipWith3 add3 xs (0 : xs) (tail xs ++ [0])
add3 a b c = a+b+c
add4 a b c d = a+b+c+d
merge [] _ _ = []
-- add the left cell, right cell, and the 3-element sums above and below (zero-padded)
merge as bs cs = zipWith4 add4 (0 : init as) (tail as ++ [0]) (bs ++ repeat 0) (cs ++ repeat 0)
-- given a grid A, replace entries not equal to 1 with 0
onesOnly :: [[Int]] -> [[Int]]
onesOnly = map . map $ \e -> if e == 1 then 1 else 0
list :: [[Int]]
list = [[0, 1, 0]
,[1, 9, 1]
,[1, 1, 0]]
Now you can drop down to ghci to see it work:
*Grid Control.Monad> mapM_ (putStrLn . unwords . map show) list
0 1 0
1 9 1
1 1 0
*Grid Control.Monad> mapM_ (putStrLn . unwords . map show) $ onesOnly list
0 1 0
1 0 1
1 1 0
*Grid Control.Monad> mapM_ (putStrLn . unwords . map show) . surrsum $ onesOnly list
2 2 2
3 5 2
2 3 2