Reputation: 11
How can I write a a program in prolog to print even and odd numbers between a range?
Sample output:
Enter first number:2
Enter Second number:15
Even numbers:
2
4
6
8
10
12
14
Odd numbers:
1
3
5
7
9
11
13
15
Upvotes: 0
Views: 842
Reputation: 74197
Here's one way to do it:
odds_and_evens( H , H , [H] , [] ) :- % if lo and hi have converged,
0 =\= H rem 2 % and it's odd
. % then park it with the odds and succeed.
odds_and_evens( H , H , [] , [H] ) :- % if lo and hi have conveged,
0 =:= H rem 2 % and it's even
. % then park it with the evens and succeed.
odds_and_evens( L , H, [L|Odds] , Evens ) :- % else... park lo with the odds
L < H, % - if lo is less than hi
0 =\= L rem 2, % - and lo is odd
L1 is L+1, % - increment lo
odds_and_evens(L1, H, Odds, Evens ) % - and recurse down
. %
odds_and_evens( L , H, Odds , [H|Evens] ) :- % else... park lo with the evens
L < H, % - if lo is less than hi
0 =:= L rem 2, % - and lo is even
L1 is L+1, % - incement lo
odds_and_evens(L1, H, Odds, Evens ) % - and recurse down
. % Easy!
But... Prolog has an in-built between/3
that generates a range of integers. And findall/3
finds all the solutions to a query as a list. So one could also — and more succinctly and declaratively! — say:
odds_and_evens( L , H , Odds , Evens ) :-
findall( X , odds( L , H , X ) , Odds ),
findall( X , evens( L , H , X ) , Evens )
.
odds( L , H , N ) :- between(L,H,N), 0 =\= N rem 2 .
evens( L , H , N ) :- between(L,H,N), 0 =:= N rem 2 .
Once you have odds_and_evens/4
defined, you can than do this:
print_odds_and_evens( Lo, Hi ) :-
odds_and_evens(Lo,Hi,Odds,Evens),
write_to_console('Odd Numbers', Odds ),
write_to_console('Even Numbers', Evens )
.
write_to_console(Label, Ns ) :-
write(Label), writeln(':'),
write_to_console(Ns)
,
write_to_console([]) .
write_to_console([N|Ns]) :- writeln(N), write_to_console(Ns).
If that's too much recursion for you, you could also say (cribbing odds/3
and evens/3
from above):
print_odds_and_evens(Lo,Hi) :-
writeln('Odd Numbers:'),
odd(Lo,Hi,N),
writeln(N),
fail
.
print_odds_and_evens(Lo,Hi) :-
writeln('Even Numbers:'),
even(Lo,Hi,N),
writeln(N),
fail
.
print_odds_and_evens(_,_).
odd( L , H , N ) :- between(L,H,N), 0 =\= N rem 2 .
even( L , H , N ) :- between(L,H,N), 0 =:= N rem 2 .
Upvotes: 2
Reputation: 5509
Here is another possible solution:
% range(+Start, +Stop, +Step, -List)
range(Start, Stop, Step, List) :-
( Start > Stop
-> List = []
; List = [Start|Rest],
Next is Start + Step,
range(Next, Stop, Step, Rest) ).
% even_odd_lists(+Lower, +Upper, -EList, -OList)
even_odd_lists(Lower, Upper, EList, OList) :-
FirstEven is Lower + Lower mod 2,
FirstOdd is Lower + (Lower-1) mod 2,
range(FirstEven, Upper, 2, EList),
range(FirstOdd, Upper, 2, OList).
Some sample queries are:
?- range(1, 10, 3, R).
R = [1, 4, 7, 10].
?- range(1, 10, 2, R).
R = [1, 3, 5, 7, 9].
?- range(2, 10, 2, R).
R = [2, 4, 6, 8, 10].
?- even_odd_lists(1, 15, LE, LO).
LE = [2, 4, 6, 8, 10, 12, 14],
LO = [1, 3, 5, 7, 9, 11, 13, 15].
?- even_odd_lists(2, 15, LE, LO).
LE = [2, 4, 6, 8, 10, 12, 14],
LO = [3, 5, 7, 9, 11, 13, 15].
Upvotes: 1
Reputation: 2662
There are several possible solutions. Here a, naive, without using higher order predicates:
print_even_odd(Lower,Upper,[],[]):-
Lower > Upper, !.
print_even_odd(Lower,Upper,Lodd,Leven):-
Res is Lower mod 2,
( Res =:= 0 ->
Leven = [Lower | LE1], LO1 = Lodd ;
Lodd = [Lower | LO1], LE1 = Leven
),
L1 is Lower + 1,
print_even_odd(L1,Upper,LO1,LE1).
?- print_even_odd(1,15,LE,LO).
LE = [1, 3, 5, 7, 9, 11, 13, 15],
LO = [2, 4, 6, 8, 10, 12, 14]
You can write more compact solutions using higher order predicates as sugggested in the comments.
Upvotes: 1
Reputation: 18663
Here is a solution that only uses Prolog ISO standard built-in predicates. It's also a fast solution as it avoid meta-predicates and appending lists:
print_even_odd(Lower, Upper) :-
even_odd(Lower, Upper, Even, Odd),
write('Even: '), write(Even), nl,
write('Odd: '), write(Odd), nl.
even_odd(Lower, Upper, Even, Odd) :-
Lower =< Upper,
( Lower mod 2 =:= 0 ->
even_odd_lists(Lower, Upper, Even, Odd)
; even_odd_lists(Lower, Upper, Odd, Even)
).
even_odd_lists(Upper, Upper, [Upper], []) :-
!.
even_odd_lists(N, Upper, [N| Even], Odd) :-
M is N + 1,
even_odd_lists(M, Upper, Odd, Even).
Sample calls:
| ?- print_even_odd(1, 24).
Even: [2,4,6,8,10,12,14,16,18,20,22,24]
Odd: [1,3,5,7,9,11,13,15,17,19,21,23]
yes
| ?- print_even_odd(2, 24).
Even: [2,4,6,8,10,12,14,16,18,20,22,24]
Odd: [3,5,7,9,11,13,15,17,19,21,23]
yes
| ?- print_even_odd(1, 35).
Even: [2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34]
Odd: [1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35]
yes
Upvotes: 1
Reputation: 24976
Here is an answer based on SWI-Prolog partition/4.
example_1(Odd,Even) :-
numlist(1,15,List),
partition(is_even,List,Even,Odd).
is_even(N) :-
0 is N mod 2.
Example run
?- example_1(Odd,Even).
Odd = [1, 3, 5, 7, 9, 11, 13, 15],
Even = [2, 4, 6, 8, 10, 12, 14].
Here is a variation that puts the support predicate into a Lambda.
example_2(Odd,Even) :-
numlist(1,15,List),
partition([N]>>(0 is N mod 2),List,Even,Odd).
Example run
?- example_2(Odd,Even).
Odd = [1, 3, 5, 7, 9, 11, 13, 15],
Even = [2, 4, 6, 8, 10, 12, 14].
For answers to the other part of your multi-part question about entering the starting and ending values I would suggest using read_string/5.
See:
How to get user console input into a Prolog list (Answer)
Prolog: How to read data from console and store into database. (Answer)
Other Answers
Upvotes: 1