<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Algorithms and Stuff &#187; list reverse</title>
	<atom:link href="http://blog.ivank.net/tag/list-reverse/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.ivank.net</link>
	<description>Algorithms and Stuff</description>
	<lastBuildDate>Thu, 14 Mar 2013 18:36:34 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Prolog tutorial &#8211; Matrices</title>
		<link>http://blog.ivank.net/prolog-matrices.html</link>
		<comments>http://blog.ivank.net/prolog-matrices.html#comments</comments>
		<pubDate>Thu, 01 Sep 2011 22:53:15 +0000</pubDate>
		<dc:creator>Ivan Kuckir</dc:creator>
				<category><![CDATA[Prolog]]></category>
		<category><![CDATA[examples]]></category>
		<category><![CDATA[exercises]]></category>
		<category><![CDATA[list reverse]]></category>
		<category><![CDATA[matrices]]></category>
		<category><![CDATA[matrix]]></category>
		<category><![CDATA[matrix operations]]></category>
		<category><![CDATA[matrix transpose]]></category>

		<guid isPermaLink="false">http://blog.ivank.net/?p=229</guid>
		<description><![CDATA[This article can be a guide for solving some problems with Prolog. If you know it&#8217;s syntax, maybe after reading this you will get an idea, how to use this language effectively. Basic matrix operations and functions When solving the exercise below, I firstly wrote predicates like &#8220;encode&#8221;, &#8220;decode&#8221; etc. After that, I wrote those [...]]]></description>
			<content:encoded><![CDATA[<p>This article can be a guide for solving some problems with Prolog. If you know it&#8217;s syntax, maybe after reading this you will get an idea, how to use this language effectively.</p>
<p><span id="more-229"></span></p>
<h2>Basic matrix operations and functions</h2>
<p>When solving the exercise below, I firstly wrote predicates like &#8220;encode&#8221;, &#8220;decode&#8221; etc. After that, I wrote those basic operations, so my approach was &#8220;from the top&#8221; and I thik it&#8217;s the right approach. I decided to move these basic matrix operations from the end to the beginning, to make the code below more clear.</p>
<h3>The list of N characters</h3>
<p>This code creates a list of $n$ characters (zeros). It takes one characters and attach a list of $n-1$ characters to it. A list of zero characters is empty.</p>
<pre class="gc">
% spaces(+Num, -Spaces)
spaces(N, [0|Tail]) :- N > 0, N2 is N-1, spaces(N2, Tail).
spaces(0, []).
</pre>
<h3>Concatenation of two lists</h3>
<p>It uses a simple recursion.  It goes deeply into recursion, and when going back, it ataches the items from the end of $X$ to the head of $Y$.</p>
<pre class="gc">
% concat(+X, +Y, -X.Y)
concat([X| T], L, [X | Rest]) :- concat(T, L, Rest).
concat([], L, L).
</pre>
<h3>List reverse</h3>
<p>This code reverses the list using &#8220;accumulator model&#8221;. Predicate <b>halves</b> has 3 parameters $A, B, C$. I want it to be true, when $C$ is the concatenation of $A^{-1}$ (reversed A) and $B$. So I wrote the rule, that when you take a character from the head of $A$ and put it at the head of $B$, it&#8217;s still true. When interpreter tries to evaluate the $C$, it uses this rule, untill $A$ is empty, then $B$ equals $C$.</p>
<pre class="gc">
% rev(+M, -M2) - reverse of a list
rev(M, M2) :- halves(M, [], M2).
% halves(+A, +B, -C).
halves([X|T], Acc, M2) :- halves(T, [X|Acc], M2).
halves([], X, X).
</pre>
<h3>Checking, if the matrix consists of constant values $X$</h3>
<p>A matrix consists of $X$s, when the first row consists of $X$s and other rows too. The row consists of $X$s, when it&#8217;s first item is $X$ and other items too.</p>
<pre class="gc">
% mcontent(+M, +X) - check if there are only Xs in matrix
mcontent([R|Rest], X) :- rcontent(R, X), rcontent(Rest, X).
mcontent([], _).
rcontent([X|T], X) :- rcontent(T, X).
rcontent([], _).
</pre>
<h3>Matrix transpose</h3>
<p>Transpose of a square matrix only (!!!). Most interesting is the predicate <b>firstCol</b>. When the first row is $[H|T]$, the first item in column is $H$, the first item in &#8220;rest matrix&#8221; is $T$, other items are computed recursively. If you look at it for a moment, you might get an idea, but don&#8217;t look at it for too long.</p>
<pre class="gc">
% trans(+M1, -M2) - transpose of square matrix
% 1. I get first column from Tail and make a first row (NT) from it
% 2. I transpose "smaller matrix" Rest into NRest
% 3. I take T and make it to be a first column of NTail
trans([[H|T] |Tail], [[H|NT] |NTail]) :-
	firstCol(Tail, NT, Rest), trans(Rest, NRest), firstCol(NTail, T, NRest).
trans([], []).
% firstCol(+Matrix, -Column, -Rest)  or  (-Matrix, +Column, +Rest)
firstCol([[H|T] |Tail], [H|Col], [T|Rows]) :- firstCol(Tail, Col, Rows).
firstCol([], [], []).
</pre>
<h2>Exercise #1: Text encoding / decoding</h2>
<p>You have a text and you have to split it into matrices 4&#215;4. Then you have a &#8220;mask matrix&#8221;, you can see only 4 items of the matrix through this mask. Then you can rotate it and see other 4 items, rotate it again etc., after 4 rotations you have seen all the items.</p>
<table>
<tr>
<th>Decoded text</th>
<th>Encoded text</th>
<th>Example of the mask matrix</th>
</tr>
<tr>
<td><code>Hello, how are you?</code></td>
<td>
<pre>H e l l    o u ? _
o , _ h    _ _ _ _
o w _ a    _ _ _ _
r e _ y    _ _ _ _
</pre>
</td>
<td>
<pre>1 1 1 _
_ _ 1 _
_ _ _ _
_ _ _ _
</pre>
</td>
</tr>
</table>
<h3>Encoding</h3>
<p><b>Algorithm:</b> We just take a letter after letter and insert them into empty matrices, until there are no letters left.</p>
<p><b>Input:</b> A list of characters (their ASCII codes in prolog).</p>
<p><b>Output:</b> A list of matrices 4&#215;4.</p>
<p><b>Approach:</b> We create a predicate &#8220;encode&#8221;, which recursively adds matrices into list. Then predicate &#8220;matrix&#8221;, which adds rows into matrix. Predicate &#8220;row&#8221; adds characters into row.</p>
<pre class="gc">
% encode(+ Text, -[Matrices])
encode(Text, [Mat|Tail]) :-	Text \= [], matrix(Text, Mat, 4, Rest), encode(Rest, Tail).
encode([], []).

% matrix(+ Text, -[Rows...], + NumOfRows, -RestOfText])
matrix(Text, [Row|Tail], N, RText) :-
	N \= 1, row(Text, Row, 4, Rest), N2 is N-1, matrix(Rest, Tail, N2, RText).
matrix(Text, [Row], 1, RText) :- row(Text, Row, 4, RText).

% row(+ Text, -[items...], + NumOfItems, -RestOfText])
row([X|Y], [X|Tail], N, RText) :- N > 0, N2 is N-1, row(Y, Tail, N2, RText).
row([], Items, N, []) :- spaces(N, Items).
row(Text, [], 0, Text).
</pre>
<h3>Checking the mask matrix</h3>
<p><b>Algorithm:</b> When the 4&#215;4 mask is correct? We can see, that &#8220;a middle mask&#8221; 2&#215;2 should have only one slot. Other 3 slots should be around it. Every added slot of these 3 slots occupies 3 more places, which are symmetric to it.</p>
<p>When checking the mask, first we chech the middle mask &#8211; there should be exactly one slot. Then we check the border, we should find 3 slots there. For each slot, the places symmetric to it should be empty. </p>
<p>$ middleOK(M) \wedge borderOK(M) \rightarrow maskOK(M) $</p>
<p><b>UPDATE:</b> I found much simpler solution. We just create 3 new copies of the mask. We rotate them 90, 180 and 270 degrees and add them one to another. We should get a matrix of ones.</p>
<p><b>Input:</b> A mask matrix, 0 for empty, 1 for slot.</p>
<p><b>Output:</b> Correct: true / false.</p>
<p><b>Approach:</b> A mask is correct, when rotated copies of it, added one over another, give us a matrix of ones. Matrix is rotated, when it&#8217;s rows are reversed and it&#8217;s transposed.</p>
<pre class="gc">
% maskOK(+M)
maskOK(M) :- rot(M,M2), rot(M2, M3), rot(M3,M4), add(M, M2, M3, M4, Res), mcontent(Res, 1).

% rot(+M, -M2) - rotate clockwards
rot(M, M2) :- rev(M, M1), trans(M1, M2).

% add(+A, +B, +C, +D, -Out) - addition of 4 matrices
add([A1|R1], [A2|R2], [A3|R3], [A4|R4], [A|R] ) :-
	addRow(A1, A2, A3, A4, A), add(R1, R2, R3, R4, R).
add([], [], [], [], []).
addRow([H1|T1], [H2|T2], [H3|T3], [H4|T4], [H|T]) :-
	H is H1+H2+H3+H4, addRow(T1, T2, T3, T4, T).
addRow([], [], [], [], []).
</pre>
<h3>Decoding</h3>
<p><b>Algorithm:</b> We should &#8220;apply&#8221; differently rotated mask on each encoded matrix, then put these pieces one on another and decode the final result.</p>
<p><b>Input:</b> Encoded text (list of matrices), mask matrix.</p>
<p><b>Output:</b> Decoded text (list of characters = ASCII codes)</p>
<p>We can decode input matrix immidiatelly, without using a mask. But let&#8217;s make it more difficult and unneficient! <img src='http://blog.ivank.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><b>Approach:</b> We make 4 differently rotated copies of the mask. We make 4 copies of encoded matrices. We apply masks on these lists of matrices. Then we put the lists of matrices one over another to get the former text. When decoding, we just take each matrix, each row of it, each char from the row, ant put it all into one big list.</p>
<pre class="gc">
% decode(+Code, +Mask, -Text).
decode(C1, M1, Text) :- c(C1, C2), c(C2, C3), c(C3, C4),
	rot(M1, M2), rot(M2, M3), rot(M3, M4),
	apply(C1, M1, O1), apply(C2, M2, O2), apply(C3, M3, O3), apply(C4, M4, O4),
	addMany(O1, O2, O3, O4, O),  % now "C1" should be equal to "O"
	dec(O, Text).

% apply(+Matrices, +Mask, -Masked)
apply([C|Tail], M, [NC|NTail]) :- applyMask(C, M, NC),  apply(Tail, M, NTail).
apply([], _, []).

applyMask([R|Rest], [MR|MRest], [NR|NRest]) :-
	applyRow(R, MR, NR), applyMask(Rest, MRest, NRest).
applyMask([], [], []).

applyRow([_|ITail], [0|MTail], [0|NTail]) :- applyRow(ITail, MTail, NTail).
applyRow([I|ITail], [1|MTail], [I|NTail]) :- applyRow(ITail, MTail, NTail).
applyRow([], [], []).

addMany([A1|R1], [A2|R2], [A3|R3], [A4|R4], [A|R] ) :-
	add(A1, A2, A3, A4, A), addMany(R1, R2, R3, R4, R).
addMany([], [], [], [], []).

% dec(+M, -Text)
dec([M|Rest], Text) :- decMat(M, T), dec(Rest, RT), concat(T, RT, Text).
dec([], []).
decMat([R|Rest], Text) :- decRow(R, T), decMat(Rest, RT), concat(T, RT, Text).
decMat([], []).
decRow([X|T], [X|RT]) :- X>0, decRow(T, RT).
decRow([0|_], []).
decRow([], []).

c(X, Y) :- copy_term(X, Y).
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.ivank.net/prolog-matrices.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
