I want to get the left and right diagonals of a matrix containing the element with the given column and row indexes.
For example:
rightDiagonal([[1,2,3],[4,5,6],[7,8,9]], 1, 0, Diagonal).
Diagonal = [2,4]
leftDiagonal([[1,2,3],[4,5,6],[7,8,9]], 1, 0, Diagonal).
Diagonal = [4,8]
Thank you.
This is my try:
left_diagonal_left(Board, 0, Column_Index, List, New_List) :-
get_value_from_matrix(Board, Row_Index, Column_Index, Value),
append(List, Value, New_List).
left_diagonal_left(Board, Row_Index, 0, List, New_List) :-
get_value_from_matrix(Board, Row_Index, Column_Index, Value),
append(List, Value, New_List).
left_diagonal_left(Board, Row_Index, Column_Index, List, New_List) :-
get_value_from_matrix(Board, Row_Index, Column_Index, Value),
append(List, Value, New_List),
R = Row_Index - 1,
C = Column_Index - 1,
left_diagonal_left(Board, R, C, New_List, Newer_List).
left_diagonal_right(Board, 6, Column_Index, List, New_List).
left_diagonal_right(Board, Row_Index, 6, List, New_List).
left_diagonal_right(Board, Row_Index, Column_Index, List, New_List) :-
get_value_from_matrix(Board, Row_Index, Column_Index, Value),
append(List, Value, New_List),
R = Row_Index + 1,
C = Column_Index + 1,
left_diagonal_right(Board, R, C, New_List, Newer_List).
left_diagonal(Board, Row_Index, Column_Index, List, Newer_List) :-
left_diagonal_left(Board, Row_Index, Column_Index, List, New_List),
R = Row_Index + 1,
C = Column_Index + 1,
left_diagonal_right(Board, R, C, New_List, Newer_List).
The problem is that the append() fails.
We can make a generic predicate that can walk in both directions (to the left, and to the right).
We basically here need two parameters: the index of the first column, and and the "direction" in which we walk, this is -1 for "right", and 1 for "left".
We can thus implement a predicate diagonal/4 that will generate such diagional.
Basically there are three cases we need to take into account:
the matrix has "no rows", in that case the diagonal is an empty list;
the matrix has at least one row, but the index is too low/high, in that case the diagonal is an empty list as well; and
the matrix has at least one row, and the index is not out of range, in that case we add the element of the first row for the given column, and recursively call the predicate where we shift the column one to the right, or one to the left.
So we can implement this with:
diagonal([], _, _, []).
diagonal([Row|Rest], Col, DCol, Result) :-
( nth0(Col, Row, El)
-> (Result = [El | R2],
Col2 is Col + DCol,
diagonal(Rest, Col2, DCol, R2))
; Result = []).
So now we can obtain diagonals with:
?- diagonal([[4,5,6],[7,8,9]], 1, -1, Diagonal).
Diagonal = [5, 7].
?- diagonal([[1,2,3],[4,5,6],[7,8,9]], 1, -1, Diagonal).
Diagonal = [2, 4].
?- diagonal([[4,5,6],[7,8,9]], 0, 1, Diagonal).
Diagonal = [4, 8].
Of course the above is not yet complete: since in the question, one enters two coordinates. In case we take the right coordinate however, for a coordinate pair (X, Y), this is equivalent to (X+Y, 0). The same for left diagonals: the diagonal containing (X, Y) is the same as the one containing (0, Y-X). Note however that it is possible that X+Y, or Y-X are out of range, so we can first "normalize" the coordinate, but in case the coordinate is "too high", or "too low", we thus will need a to drop a certain number of rows, and each time updating the number until we reach a value that is in range.
So we can implement a predicate that first makes some iterations until it finds a valid index, and then passes control to the diagonal/4 predicate, for example prediagonal/4:
prediagonal([], _, _, []).
prediagonal([Row|Rest], Col, DCol, Result) :-
Col2 is Col + DCol,
( nth0(Col, Row, El)
-> (Result = [El | R2],
diagonal(Rest, Col2, DCol, R2))
; prediagonal(Rest, Col2, DCol, Result)).
So now we can write our left_diagonal/4 and right_diagonal in terms of prediagonal/4:
left_diagonal(M, R, C, Diagonal) :-
Delta is C-R,
prediagonal(M, Delta, 1, Diagonal).
right_diagonal(M, R, C, Diagonal) :-
Delta is R+C,
prediagonal(M, Delta, -1, Diagonal).
this then gives us:
?- right_diagonal([[1,2,3],[4,5,6],[7,8,9]], 1, 0, Diagonal).
Diagonal = [2, 4].
?- left_diagonal([[1,2,3],[4,5,6],[7,8,9]], 1, 0, Diagonal).
Diagonal = [4, 8].
The above is not the most elegant solution. It might be better to "merge" diagonal/4 and prediagonal/4 in one predicate. I leave this as an exercise.
Related
I'm new to prolog, I don't understand much of the language and I had already posted a question about Prolog before. Now I want to obtain, from a list of integers, the numbers in the interval that contains the largest amount of numbers in that list, in other words the maximum range. Example:
maxrange(X,Y,[1,3,2,7,4,5,6,9,8]).
X = 1, Y= 10.
maxrange(1,10,[1,3,2,7,4,5,6,9,8].
True.
maxrange(1,8,[1,3,2,7,4,5,6,9,8].
False.
Lists must contain all numbers between [X,Y) and must be the maximum interval.
Try this code:
maxrange(A, B, List) :-
maxranges(List, Ranges),
member(A-B, Ranges).
maxranges(List, Ranges) :-
sort(List, [Min|Sorted]),
maxranges_loop(Sorted, Min, Min, [], Ranges).
maxranges_loop([], A, B, Ranges, UpdatedRanges) :-
update(Ranges, A, B, UpdatedRanges).
maxranges_loop([X|Xs], A, B, Ranges, UpdatedRanges) :-
Bool is abs(sign(X - (B + 1))),
maxranges_case(Bool, X, Xs, A, B, Ranges, UpdatedRanges).
maxranges_case(0, X, Xs, A, _, Ranges, UpdatedRanges) :-
maxranges_loop(Xs, A, X, Ranges, UpdatedRanges).
maxranges_case(1, X, Xs, A, B, Ranges, UpdatedRanges) :-
maxranges_loop(Xs, X, X, Ranges, NewRanges),
update(NewRanges, A, B, UpdatedRanges).
update([], A, B0, [A-B]) :- B is B0+1.
update([A0-B0|Ranges], A, B, UpdatedRanges) :-
B1 is B+1,
Sign is sign((B1-A)-(B0-A0)),
update_case(Sign, [A0-B0|Ranges], A, B1, UpdatedRanges).
update_case( 0, Ranges, A, B, [A-B|Ranges]).
update_case(+1, _, A, B, [A-B]).
update_case(-1, Ranges, _, _, Ranges).
Examples:
?- maxrange(X, Y, [1,3,2,7,4,5,6,9,8]).
X = 1,
Y = 10.
?- maxrange(1, 10, [1,3,2,7,4,5,6,9,8]).
true.
?- maxrange(1, 8, [1,3,2,7,4,5,6,9,8]).
false.
?- maxrange(A, B, [1,2, 4,5,6,7, 9,10,11, 14,15,16,17]).
A = 4,
B = 8 ;
A = 14,
B = 18.
?- maxranges([1,2, 4,5,6,7, 9,10,11, 14,15,16,17], R).
R = [4-8, 14-18].
EXPLANATION
The predicate update_case/5 updates a list of maximum ranges, with respect to a new range [A..B), written in Prolog as A-B. If its first argument is 0, then the new range [A..B) is added to that list; if its first argument is +1, that list changes to a new list containing only the range [A..B); and, its first argument is -1, then that list is kept unchanged.
?- update_case(0, [14-18], 5, 9, R).
R = [5-9, 14-18].
?- update_case(+1, [14-18], 1, 9, R).
R = [1-9].
?- update_case(-1, [14-18], 3, 7, R).
R = [14-18].
The predicate update/4 updates a list of maximum ranges with respect to a new range [A..B]. First, it transforms the closed range [A..B] into a corresponding right-open range [A..B+1). Then, if that list is empty, the predicate adds the new range to it. Otherwise, the predicate compares the range [A..B+1) with the first range in that list, say [A0..B0). The comparison is made by the expression Sign is sign((B+1-A)-(B0-A0). If both ranges are equal, then Sign is 0; if the first range is bigger than the second, then Sign is +1; and, if the first range is lesser than the second, then Sign is -1. The result of the comparision is used to call the predicate update_case/5.
?- update([], 17, 19, R).
R = [17-20].
?- update([17-20], 11, 13, R). % equal
R = [11-14, 17-20].
?- update([11-14, 17-20], 5, 9, R). % bigger
R = [5-10].
?- update([5-10], 2, 3, R). % lesser
R = [5-10].
The predicate maxranges_loop/5 traverses a sorted list (without duplicates) and finds all ranges that are part of it. For each range found, the list of current maximum ranges is updated with a call to the predicate update/4.
The predicate maxranges/2 is just a wrapper to the predicate maxranges_loop/5, that ensures the list is sorted and does not contain duplicates.
The predicate maxrange/3 call maxranges/2 to get the list of maximum ranges and checks whether the range [A..B) belongs to it.
Do you mean a simple min & max of the list:
list_min_max([H|T], Min, Max) :-
list_min_max_(T, H, H, Min, Max).
list_min_max_([], Min, Max, Min, Max).
list_min_max_([H|T], Min0, Max0, Min, Max) :-
min(H, Min0, Min1),
max(H, Max0, Max1),
list_min_max_(T, Min1, Max1, Min, Max).
Results in swi-prolog:
?- list_min_max([4,9,2,6], Min, Max).
Min = 2,
Max = 9.
I am trying to create a swap function in prolog but I ended up with an infinite loop, I tried to debug it using trace()
An example of this function is swap(4, 3, ["You", "Are", "Awesome", "thank", "You"], SwappedList)
With the output being
["You", "Are", "thank", "Awesome", "You"]
In the trace output, it is showing that the problem is in the delete as it is failing and redoes the split
/* Getting the nth element of the list*/
n_thelement(1, [Head|_], Head).
n_thelement(N, [_|Tail], Item):-
NewN is N-1,
n_thelement(NewN, Tail, Item).
/* Deleting the element of the desired Nth element*/
delete(X, [X|Tail], Tail).
delete(X, [Head|Tail], [Head|Item]):-
delete(X, Tail, Item).
/* Adding the deleted element to the beginning of the list*/
append([], Element, Element).
append([Head], Element, [Head|Element]).
swap(X, X, List, List).
swap(X, Y, List, NList):-
n_thelement(X, List, Num1),
n_thelement(Y, List, Num2),
split(X, List, B1, A1),
delete(Num1, A1, L1),
append([Num2], L1, NList1),
append(B1, NList1, NList2),
split(Y, NList2, B2, A2),
delete(Num2, A2, L2),
append([Num1], L2, NList3),
append(B2, NList3, NList).
split(1, [Head|Tail], Head, Tail).
split(N, [Old_List|New_List], Old_List, New_List):-
NewN is N -1,
split(NewN, _, Old_List, New_List).
If I understand your problem statement correctly, given to indices into a list, M and N such that M < N and M and N are both valid indices into the list, you want to swap the elements at those indices.
I would first make the indices zero-relative instead of 1-relative as that makes the math a little easier.
So, you want to break up the list into 5 pieces, 3 of which are themselves lists of any length and two of which are the list entries to be swapped:
As: The lead-in prefix of the list. It is of length M.
B: The 1st item to be swapped.
Cs: The middle segment of the list. It is of length N - (M+1).
D: The 2nd item to be swapped.
Es: The suffix/remainder of the list. It is of any length.
append/3 is useful for deconstruction and reconstruction of lists, making the actual swap easy. You have 3 cases.
First, the special case of both indices being the same, in which case, there is no work to do:
swap( M, M, Ls, Ls ).
Second, the case of the indices being out of order, in which case we just recursively swap them to put them in order:
swap( M, N, Ls, Rs ) :- M > N, swap(N,M,Ls,Rs).
Third, the general case:
swap( M, N, Ls, Rs ) :- % if the 2 indices differ
M < N, % - and are in order
M >= 0, % - and M is greater than or equal to zero
N >= 0, % - and N is greater than or equal to zero
X is N - (M+1), % - compute the length of the middle segment
length( As, M ), % - construct an empty, unbound list of length M, the length of the prefix
length( Cs, X ), % - and construct an empty, unbound list of that length
append( As, [B|T1], Ls), % - get the prefix (As) and the first item (B) to be swapped
append( Cs, [D|Es], T1), % - get the middle segment (Cs), the second item (D) to be swapped, and the suffix (Es)
append( As, [D|Cs], T2), % - concatenate As, D, and Cs, then...
append( T2, [B|Es], Rs ) % - concatenate that with B and the suffix
. % Easy!
You can define a predicate to replace the i-th item of the list for another:
replace(Index, [Old|Rest], [New|Rest], Old, New) :- Index == 0, !.
replace(Index, [First|Rest], [First|NewRest], Old, New) :-
Index > 0,
Previous is Index - 1,
replace(Previous, Rest, NewRest, Old, New).
Examples:
?- replace(1, [a,b,c,d,e], List1, Old1, x).
List1 = [a, x, c, d, e],
Old1 = b.
?- replace(1, [a,b,c,d,e], List1, Old1, New1).
List1 = [a, New1, c, d, e],
Old1 = b.
?- replace(4, [a,b,c,d,e], List2, Old2, New2).
List2 = [a, b, c, d, New2],
Old2 = e.
Then, using this predicate, you can define:
swap(I, J, OldList, NewList) :-
replace(I, OldList, List, X, Y),
replace(J, List, NewList, Y, X).
Examples:
?- swap(3, 2, ["You", "Are", "Awesome", "thank", "You"], L).
L = ["You", "Are", "thank", "Awesome", "You"].
?- swap(1, 4, [a,b,c,d,e], L).
L = [a, e, c, d, b].
?- swap(0, 3, [a,b,c,d,e], L).
L = [d, b, c, a, e].
?- swap(1, 0, [a,b,c,d,e], L).
L = [b, a, c, d, e].
?- swap(2, 2, [a,b,c,d,e], L).
L = [a, b, c, d, e].
?- swap(3, 9, [a,b,c,d,e], L).
false.
Working on the Bert Bos Puzzle, where I need to print all possible permutations of a sequence (clicks or no clicks) that will turn the whole square red. This will be done by clicking the top row in a sequence of clicks and no clicks. Then, you go to the subsequent row and click squares there to make the first row all red. You progress through the puzzle like this until you turn the whole square red.
So a possible solution to a 4x4 square would be [click, click, no click, no click] on the first row. You dont have to follow the pattern for any of the lines below, just keep flipping until all blocks on the next line are red and continue till all squares are red.
Im trying to write a predicate that tests all possible permutations of ‘click’ and ‘no click’ for the first row of a square of size N. Right now Im trying to go about it by keeping track of the color of the top row after it has been clicked, then using that to say which squares of the second row should be clicked to make the top row all red.
The problem is I cant figure out how to keep track of the colors of the second row that are changed by clicks from the first row, and then how to keep track of clicks from the second row on and how they affect the rest of the rows. Any help would be greatly appreciated.
Here is what I have so far
state(no_click).
state(click).
flip(blue, red).
flip(red, blue).
board_permutations(0,[]):- !.
board_permutations(N, [H|T]) :-
state(H),
N1 is N - 1,
board_permutations(N1, T).
first_row_solutions([], []).
first_row_solutions([H1, H2|T], [FirstRow|SecondRow]):-
H1 = click,
flip(H1,C),
flip(H2,C),
first_row_solutions(H2, FirstRow).
first_row_solutions([H|T], [FRH1, FRH2, FRH3|FRT], [SR1, SR2, SR3|SRT]) :-
H = click,
flip(FRH1, C1),
flip(FRH2, C2),
flip(FRH3, C3),
%flip(SR1, S1), I was thinking I could keep track of the second row colors here
%flip(SR2, S2),
%flip(SR3, S3)
%FlipListRow1 = [C1, C2, C3 | T],
%FlipListRow2 = [S1, S2, S3|T],
first_row_solutions(H, FRH3).
%Possible predicate to handle row 2, 3, 4 etc --> ClickList is what clicks to do on row 3 to make row 2 red, etc
%row_n_solutions(FlipListRow2, ClickList)
generate_board(0, [], _).
generate_board(N, [H|T], ConstantN) :-
generate_row(ConstantN, H),
N =< 12, N >= 1,
N2 is N-1,
generate_board(N2, T, ConstantN).
generate_row(0, []) :- !.
generate_row(N, [H | T]) :-
N =< 12, N >= 1,
N2 is N-1,
H = blue,
generate_row(N2, T).
test(X) :- generate_board(5,X,5).
test1(X) :- solutions([no_click, click, no_click, no_click], X).
#CapelliC has already suggested one possible approach: You can carry along the matrix (using predicate arguments), and use this to always inspect the current state of any surrounding cells.
Complementing this approach, I would also like to point out a different method to approach the whole task: We can consider this puzzle as finding a suitable linear combination of vectors from the finite field GF(2). The number of clicks can be represented as an integer coefficient for each vector.
It only remains to establish a correspondence between board positions and vector indices. We can define such a relation as follows:
n_id_x_y(N, ID, X, Y) :-
ID #= Y*N + X,
N1 #= N - 1,
[X,Y] ins 0..N1.
Example:
?- n_id_x_y(4, 6, X, Y).
X = 2,
Y = 1.
Note that I specified 4 to obtain a mapping that works for 4×4 boards.
This uses CLP(FD) constraints and works in all directions, including for example:
?- n_id_x_y(4, ID, 3, 2).
ID = 11.
Based on this, we can also relate any index to its neighbours, again denoted by their unique indices:
n_id_neighbour(N, ID, NID) :-
n_id_x_y(N, ID, X, Y),
( ( NX #= X - 1, NY #= Y
; NX #= X + 1, NY #= Y
)
; ( NX #= X, NY #= Y - 1
; NX #= X, NY #= Y + 1
)
),
n_id_x_y(N, NID, NX, NY).
Clicking on any board position flips the colour of that position and its defined neighbours. We will use a Boolean vector and let 1 denote that the colour of the position that corresponds to this index is affected:
n_id_vector(N, ID, Vs) :-
V #= N*N,
V1 #= V - 1,
ID in 0..V1,
indomain(ID),
findall(NID, n_id_neighbour(N, ID, NID), Ns),
sort([ID|Ns], IDs),
length(Vs, V),
phrase(ids_vector(IDs, 0), Vs, Zeroes),
maplist(=(0), Zeroes).
ids_vector([], _) --> [].
ids_vector([ID|IDs], Pos0) -->
{ Gap #= ID - Pos0,
Pos #= ID + 1,
length(Zeroes, Gap),
maplist(=(0), Zeroes) },
Zeroes,
[1],
ids_vector(IDs, Pos).
For example, clicking on entry 0-0 affects precisely three other cells, which are indicated by 1:
?- n_id_vector(4, 0, Vs).
Vs = [1, 1, 0, 0, 1, 0, 0, 0, 0|...].
We are now ready to describe what we expect from a solution: A solution consists of a list of coefficients, one for each vector, such that the sum of the scalar products (vector times coefficient for each vector) modulo 2 is equal to (1,1,...,1). This means that the colour of each cell has changed.
n_solution(N, Cs) :-
findall(Vs, n_id_vector(N,_,Vs), Vss),
same_length(Vss, Cs),
Cs ins 0..1,
maplist(flip_cell(Cs), Vss),
label(Cs).
flip_cell(Cs, Ts) :-
scalar_product(Ts, Cs, #=, Sum),
Sum mod 2 #= 1.
Note that in this case, due to the inherent symmetry, there is no need to transpose the matrix.
The fact that we are reasoning over Boolean algebra already entails that the order in which the cells are clicked does not affect the outcome, and also that each of the vectors needs to be used at most once in any solution.
Here are solutions for a 4×4 board:
?- n_solution(4, Cs).
Cs = [0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1] ;
Cs = [0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1] ;
Cs = [0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0] ;
Cs = [0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0] ;
etc.
Each solution indicates precisely which of the cells we must click. For example, the first solution:
Here is one of the longest solutions for this board size:
And this is one of the shortest:
You can of course also apply this approach to other board sizes, such as 7×7:
Or 12×12:
the problem is ; we have a function take 3 argument,
like; func ( [[0, 0, 0, 1, 0], [0, 1, 1, 1, 0], [0, 0, 1, 0, 0],
[0, 0, 1, 0, 0], [0, 0, 0, 1, 0]], (1, 1), X ) the first one is nested list, which is
show 5x5 matrix and 1s means it is full, 0 means empty and,
the second parameter (1,1) our starting point 1st row 1st column,
the 3rd parameter X is ; variable that we will unify with
the points that are accessible from the starting point which is (1,1)
so if asked;
?- func ( [ [0,0,0,1] [0,0,1,0] [0,0,1,1] [0,0,1,0] ], (1,1), X).
X = (1, 1);
X = (1, 2);
X = (1, 3);
X = (2, 2);
X = (3, 2);
X = (4, 1);
X = (4, 2);
false.
when we start from (1,1) we can move up, down, left and right;
since no left and up movement while on (1,1) look right if empty, write it, look down empty write down, go the (1,2) again, move right or left or up or down, and so on.
here the reason why we didn't write the outputs, (2,4) (4,4)
if for example point (2,3) is full and (2,4) is empty
we look that can we go point (2,4) one by one, I mean,
if left , up and down of them is full, we can't go point (2,4) using this point, since they are full.
My solution: get the textbook, sit at the computer, and figure it out for yourself! Simply labelling something as homework doesn't excuse not doing it yourself.
lastly I done it, here is the code;
%returns the nth element from the list
nth([F|_],1,F).
nth([_|R],N,M) :- N > 1, N1 is N-1, nth(R,N1,M).
%returns true if cell is empty: gets the cell value at (StartRow,StartColumn) and returns whether the value is 0
isempty(Maze,StartRow,StartColumn) :- nth(Maze,StartRow,Line),nth(Line,StartColumn,Y), Y == 0.
%returns the head of the list
head([Elem|_],Elem).
%find accessible returns empty list if not in maze size (1 to N for row and column)
findaccessible(Maze, (StartRow,StartColumn), [], _) :- head(Maze,L),length(L,N), (StartColumn > N ; StartRow > N ; StartColumn < 1 ; StartRow < 1).
%find all empty cells and retain them in X. L retains the current found cells in order to avoid returning to visited positions.
findaccessible(Maze, (StartRow,StartColumn), X, L) :-
%if cell is empty, retain position and add it to the list
isempty(Maze,StartRow,StartColumn) -> (union(L,[(StartRow,StartColumn)],L1),X1 = [(StartRow,StartColumn)],
%check right column and if element not visited, find all accessible cells from that point and unify the lists
SR is StartRow, SC is StartColumn+1,(member((SR,SC),L) -> union(X1,[],X2) ; (findaccessible(Maze, (SR,SC), Tmp1, L1), union(X1,Tmp1,X2))),
%check down row and if element not visited, find all accessible cells from that point and unify the lists
SR2 is StartRow+1,SC2 is StartColumn, (member((SR2,SC2),L) -> union(X2,[],X3) ; (findaccessible(Maze, (SR2,SC2), Tmp2, L1), union(X2,Tmp2,X3))),
%check left column and if element not visited, find all accessible cells from that point and unify the lists
SR3 is StartRow, SC3 is StartColumn-1, (member((SR3,SC3),L) -> union(X3,[],X4) ; (findaccessible(Maze, (SR3,SC3), Tmp3, L1), union(X3,Tmp3,X4))),
%check up row and if element not visited, find all accessible cells from that point and unify the lists
SR4 is StartRow-1, SC4 is StartColumn, (member((SR4,SC4),L) -> union(X4,[],X) ; (findaccessible(Maze, (SR4,SC4), Tmp4, L1), union(X4,Tmp4,X)))) ; X = [].
%lists each result
%if no more results return false
results(_,[]) :- fail.
%return the result or return the rest of the results
results(X,[Head|Rest]) :- X = Head ; results(X,Rest).
%accessible predicate that finds all empty accessible cells and then list each of them
accessible(Maze, (StartRow,StartColumn), X) :- findaccessible(Maze, (StartRow,StartColumn), Lst, []), !, results(X,Lst).
%sample test run
%accessible([[0, 0, 0, 1, 0], [0, 1, 1, 1, 0], [0, 0, 1, 0, 0], [0, 0, 1, 0, 0], [0, 0, 0, 1, 0]], (1, 1), X).
hi is there anybody know how can i do the pascal nth row
when i ask for
:? pascal(2,Row).
i get Row=[1,2,1]
??
please help me
Here is the code to compute the nth row.
The first part scans a row, to compute the next row. The first row must be prefixed with a 0, so that the first "1" in the next row is a sum, like the other elements. It recurses on the 2 lists:
pascal_next_row([X],[X]).
pascal_next_row([H,H2|T],[A|B]):-
pascal_next_row([H2|T],B),
A is H + H2.
The second part computes all the rows until the one which was asked. It recurses on N:
pascal(0, [1]) :- !.
pascal(N, R) :-
N1 is N-1,
pascal(N1, R1),
pascal_next_row([0|R1], R).
If you need the full triangle, all you have to do is change the second parameter to handle a list of rows, and collect them:
pascal(0, [[1]]) :- !.
pascal(N, [R, R1 | RN]) :-
N1 is N-1,
pascal(N1, [R1 | RN]),
pascal_next_row([0|R1], R).
This answer to a code golf has the implementation in prolog, just expand the names:
The Pascal Triangle is also known as the Tartaglia Triangle:
sumC([X,Y],[Z]) :- Z is X + Y.
sumC([X,Y|L], Z):- H is X + Y,
sumC([Y|L],L2),
Z = [H|L2].
tartaglia(1,[1]) :- ! .
tartaglia(2,[1,1]) :- !.
tartaglia(N, L) :- Ant is N - 1,
tartaglia(Ant,L2),
sumC(L2,R),
append([1|R],[1],L), !.
Using the helper predicate sumC, you can get it easily:
?- tartaglia(3,R).
R = [1, 2, 1].
?- tartaglia(2,R).
R = [1, 1].
?- tartaglia(1,R).
R = [1].
?- tartaglia(6,R).
R = [1, 5, 10, 10, 5, 1].
As said in my comment. You ask for the nth row. [1,2,1] from your example is the 3rd row.