<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress/2.0.10" -->
<rss version="2.0" 
	xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
	<title>Comments on: 99 Lisp Prolog Erlang problems</title>
	<link>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/</link>
	<description>A diary of madness</description>
	<pubDate>Wed, 07 Jan 2009 20:38:26 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.0.10</generator>

	<item>
		<title>by: dda</title>
		<link>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2562</link>
		<pubDate>Tue, 23 Jan 2007 14:40:20 +0000</pubDate>
		<guid>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2562</guid>
					<description>*The* &lt;a href="http://www.rubycentral.com/book/" rel="nofollow"&gt;Ruby book&lt;/a&gt;</description>
		<content:encoded><![CDATA[<p>*The* <a href="http://www.rubycentral.com/book/" rel="nofollow">Ruby book</a>
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Christian</title>
		<link>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2561</link>
		<pubDate>Mon, 22 Jan 2007 11:39:56 +0000</pubDate>
		<guid>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2561</guid>
					<description>I would like to learn some Ruby. What resource do you recommend?</description>
		<content:encoded><![CDATA[<p>I would like to learn some Ruby. What resource do you recommend?
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Christian</title>
		<link>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2560</link>
		<pubDate>Thu, 18 Jan 2007 12:33:17 +0000</pubDate>
		<guid>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2560</guid>
					<description>My last comment was about &lt;b&gt;P07&lt;/b&gt;.</description>
		<content:encoded><![CDATA[<p>My last comment was about <b>P07</b>.
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Christian</title>
		<link>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2559</link>
		<pubDate>Thu, 18 Jan 2007 12:32:47 +0000</pubDate>
		<guid>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2559</guid>
					<description>I said
&lt;blockquote&gt;
But it is unfortunate that the non tail-recursive call implies T instead of H…
&lt;/blockquote&gt;
but this is wrong. T may be shorter than H, in which case it was fortunate! The time complexity here does not depend on the number of the items which are not lists but on the whole structure as well (it is a tree, actually, because we deal with lists of lists, in general).</description>
		<content:encoded><![CDATA[<p>I said</p>
<blockquote><p>
But it is unfortunate that the non tail-recursive call implies T instead of H…
</p></blockquote>
<p>but this is wrong. T may be shorter than H, in which case it was fortunate! The time complexity here does not depend on the number of the items which are not lists but on the whole structure as well (it is a tree, actually, because we deal with lists of lists, in general).
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Christian</title>
		<link>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2558</link>
		<pubDate>Thu, 18 Jan 2007 12:28:54 +0000</pubDate>
		<guid>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2558</guid>
					<description>&lt;b&gt;P06&lt;/b&gt;
Your solution is the simplest one but not the most efficient, I believe, since you construct the reversed list of the input. I have been thinking a little and came up with a different approach, that keeps the memory usage to a small constant plus the space of the input if the garbage collector is quick enough or if the input is big enough. The idea consists in splitting the input list. If there are an odd number of items, the middle item is discarded. The run-time do not rebuild individual items (just change some pointers) and the garbage collector will discover that the head of first half of the initial list is no more accessible during the splitting. If the list is big enough, it will trigger a collection. Then the two parts of the list are matched against each other, thus relying, as you do, on the run-time environment for that task. The first half of the input list is reversed by the splitting, so matching is immediate:
&lt;blockquote&gt;
palindrome(L) -&#62; are_equal(split(L)).

split(L) -&#62;
    Length=ninety:length(L),
    case Length rem 2 of
      0 -&#62; split(even,Length div 2,[],L);
      1 -&#62; split(odd,Length div 2,[],L)
    end.

split(even,0,RevFstHalf,SecHalf) -&#62; {RevFstHalf,SecHalf};
split(odd,0,RevFstHalf,[_&#124;SecHalf]) -&#62; {RevFstHalf,SecHalf};
split(Mode,HalfLen,Left,[Item&#124;Right]) -&#62; split(Mode,HalfLen-1,[Item&#124;Left],Right).

are_equal({L,L}) when list(L) -&#62; yes;
are_equal(_) -&#62; no.
&lt;/blockquote&gt;
It would seem that the time complexity (counting a constant for each item traverses) is greater than in your solution, because I compute the length of the input list first and because we do not take into account the cost of the matching. But if we do, it is in fact the same because in your solution, the input list, of, say, N items, is reversed, which costs N, then the matching also costs N, thus total is 2N. In my code, the length computation costs N, then the half list is build at the cost of [N/2], then the matching costs [N/2], so total is 2N as well. What do you think?

&lt;b&gt;P07&lt;/b&gt;

Why is there a flatten/2 in your code? I am learning Erlang, so I have a question: is the guard predicate &lt;b&gt;is_list/1&lt;/b&gt; or &lt;b&gt;list/1&lt;/b&gt;? There is a source of inefficience with your solution:
&lt;blockquote&gt;
do_flatten([H&#124;T], Tail) -&#62; [H&#124;do_flatten(T, Tail)];
&lt;/blockquote&gt;
This is not a tail-recursive call, i.e. it is not compiled as a loop, so the size of the BEAM stack will grow in proportion to the number of items in the input list from the item which is not a list, until the end. If all items in the input list are lists, no problem, the stack usage will remain reasonable, since the other clause contains a tail recursive call and one which is not. But it is unfortunate that the non tail-recursive call implies T instead of H... So I propose a little modification to solve these two sources of inefficience at once:

flatten(List) -&#62; reverse(rev_flatten([],List)).

rev_flatten(Acc,[]) -&#62; Acc;
rev_flatten(Acc,[Item&#124;Items]) when list(Item) -&#62; rev_flatten(rev_flatten(Acc,Item),Items);
rev_flatten(Acc,[Item&#124;Items]) -&#62; rev_flatten([Item&#124;Acc],Items).


&lt;b&gt;P08&lt;/b&gt;
Your solution is complex (three parameters) and inefficient because it relies on flatten/1, which is not constant stack space (despite my efforts). There is a direct and fully tail recursive solution:
&lt;blockquote&gt;
compress(List) -&#62; compress([],List).

compress(Acc,[]) -&#62; reverse(Acc);
compress([Item&#124;Acc],[Item&#124;Items]) -&#62; compress([Item&#124;Acc],Items);  % Skip item
compress(Acc,[Other&#124;Items]) -&#62; compress([Other&#124;Acc],Items).
&lt;/blockquote&gt;
This is something I like about Erlang and Prolog: non-linear patterns, i.e. patterns with repeated variables.

&lt;b&gt;P09&lt;/b&gt;
Again, your solution is very complex (didn't check it fully) and not efficient (relies on flatten/1. Here is a better one
&lt;blockquote&gt;
pack(L) -&#62; pack([],L).

pack(Acc,[]) -&#62; reverse(Acc);
pack([[Item&#124;Same]&#124;Others],[Item&#124;Items]) -&#62; pack([[Item,Item&#124;Same]&#124;Others],Items);
pack(Acc,[Item&#124;Items]) -&#62; pack([[Item]&#124;Acc],Items).
&lt;/blockquote&gt;
Again, tail-recursivity and non-linear patterns are our best friends.

&lt;b&gt;P10&lt;/b&gt;
Your code is incredibly complex, I did not even bother checking it, sorry, because I have a tiny and efficient solution for you:
&lt;blockquote&gt;
encode(L) -&#62; encode([],pack(fun (X) -&#62; X end,[],L)).
   
encode(Codes,[]) -&#62; Codes;
encode(Codes,[[Item&#124;Items]&#124;Lists]) -&#62; 
encode([{ninety:length(Items)+1,Item}&#124;Codes],Lists).
&lt;/blockquote&gt;
You wonder what is this pack/3 function, thanks for asking:) The question requires to reuse pack, but I realized that pack/1 is reversing the accumulator and I need here the elements in the order of the accumulaor (which is the reversed order with respect to the input). So, instead of duplicating the code of pack/2 I instead rewrote pack/2 into a pack/3 as follows:
&lt;blockquote&gt;
pack(L) -&#62; pack(fun (X) -&#62; reverse(X) end,[],L).

pack(Finalize,Acc,[]) -&#62; Finalize(Acc);
pack(Finalize,[[Item&#124;Same]&#124;Others],[Item&#124;Items]) -&#62;
    pack(Finalize,[[Item,Item&#124;Same]&#124;Others],Items);
pack(Finalize,Acc,[Item&#124;Items]) -&#62;pack(Finalize,[[Item]&#124;Acc],Items).
&lt;/blockquote&gt;
Notice the extra first parameter which is the function to apply to the accumulator when we are done. This makes pack/3 a higher-order function, which is a cool name:) All this to be able to parameterize what we do to the accumulator at the end. Here, in pack/1, we want to reverse it, hence
&lt;blockquote&gt;
fun (X) -&#62; reverse(X) end
&lt;/blockquote&gt;

Now, in encode/2, we do &lt;b&gt;not&lt;/b&gt; want to reverse it, thus
&lt;blockquote&gt;
fun (X) -&#62; X end
&lt;/blockquote&gt;&lt;blockquote&gt;
which is the identity function. 

By the way, ninety:length/1 is what you called ninety:len/1, obviously.

Tell me what you think of this and I will come back for the rest. Note that dispite my professoral tone, I often make mistakes, so disbelief is very welcome:)&lt;/blockquote&gt;</description>
		<content:encoded><![CDATA[<p><b>P06</b><br />
Your solution is the simplest one but not the most efficient, I believe, since you construct the reversed list of the input. I have been thinking a little and came up with a different approach, that keeps the memory usage to a small constant plus the space of the input if the garbage collector is quick enough or if the input is big enough. The idea consists in splitting the input list. If there are an odd number of items, the middle item is discarded. The run-time do not rebuild individual items (just change some pointers) and the garbage collector will discover that the head of first half of the initial list is no more accessible during the splitting. If the list is big enough, it will trigger a collection. Then the two parts of the list are matched against each other, thus relying, as you do, on the run-time environment for that task. The first half of the input list is reversed by the splitting, so matching is immediate:</p>
<blockquote><p>
palindrome(L) -&gt; are_equal(split(L)).</p>
<p>split(L) -&gt;<br />
    Length=ninety:length(L),<br />
    case Length rem 2 of<br />
      0 -&gt; split(even,Length div 2,[],L);<br />
      1 -&gt; split(odd,Length div 2,[],L)<br />
    end.</p>
<p>split(even,0,RevFstHalf,SecHalf) -&gt; {RevFstHalf,SecHalf};<br />
split(odd,0,RevFstHalf,[_|SecHalf]) -&gt; {RevFstHalf,SecHalf};<br />
split(Mode,HalfLen,Left,[Item|Right]) -&gt; split(Mode,HalfLen-1,[Item|Left],Right).</p>
<p>are_equal({L,L}) when list(L) -&gt; yes;<br />
are_equal(_) -&gt; no.
</p></blockquote>
<p>It would seem that the time complexity (counting a constant for each item traverses) is greater than in your solution, because I compute the length of the input list first and because we do not take into account the cost of the matching. But if we do, it is in fact the same because in your solution, the input list, of, say, N items, is reversed, which costs N, then the matching also costs N, thus total is 2N. In my code, the length computation costs N, then the half list is build at the cost of [N/2], then the matching costs [N/2], so total is 2N as well. What do you think?</p>
<p><b>P07</b></p>
<p>Why is there a flatten/2 in your code? I am learning Erlang, so I have a question: is the guard predicate <b>is_list/1</b> or <b>list/1</b>? There is a source of inefficience with your solution:</p>
<blockquote><p>
do_flatten([H|T], Tail) -&gt; [H|do_flatten(T, Tail)];
</p></blockquote>
<p>This is not a tail-recursive call, i.e. it is not compiled as a loop, so the size of the BEAM stack will grow in proportion to the number of items in the input list from the item which is not a list, until the end. If all items in the input list are lists, no problem, the stack usage will remain reasonable, since the other clause contains a tail recursive call and one which is not. But it is unfortunate that the non tail-recursive call implies T instead of H&#8230; So I propose a little modification to solve these two sources of inefficience at once:</p>
<p>flatten(List) -&gt; reverse(rev_flatten([],List)).</p>
<p>rev_flatten(Acc,[]) -&gt; Acc;<br />
rev_flatten(Acc,[Item|Items]) when list(Item) -&gt; rev_flatten(rev_flatten(Acc,Item),Items);<br />
rev_flatten(Acc,[Item|Items]) -&gt; rev_flatten([Item|Acc],Items).</p>
<p><b>P08</b><br />
Your solution is complex (three parameters) and inefficient because it relies on flatten/1, which is not constant stack space (despite my efforts). There is a direct and fully tail recursive solution:</p>
<blockquote><p>
compress(List) -&gt; compress([],List).</p>
<p>compress(Acc,[]) -&gt; reverse(Acc);<br />
compress([Item|Acc],[Item|Items]) -&gt; compress([Item|Acc],Items);  % Skip item<br />
compress(Acc,[Other|Items]) -&gt; compress([Other|Acc],Items).
</p></blockquote>
<p>This is something I like about Erlang and Prolog: non-linear patterns, i.e. patterns with repeated variables.</p>
<p><b>P09</b><br />
Again, your solution is very complex (didn&#8217;t check it fully) and not efficient (relies on flatten/1. Here is a better one</p>
<blockquote><p>
pack(L) -&gt; pack([],L).</p>
<p>pack(Acc,[]) -&gt; reverse(Acc);<br />
pack([[Item|Same]|Others],[Item|Items]) -&gt; pack([[Item,Item|Same]|Others],Items);<br />
pack(Acc,[Item|Items]) -&gt; pack([[Item]|Acc],Items).
</p></blockquote>
<p>Again, tail-recursivity and non-linear patterns are our best friends.</p>
<p><b>P10</b><br />
Your code is incredibly complex, I did not even bother checking it, sorry, because I have a tiny and efficient solution for you:</p>
<blockquote><p>
encode(L) -&gt; encode([],pack(fun (X) -&gt; X end,[],L)).</p>
<p>encode(Codes,[]) -&gt; Codes;<br />
encode(Codes,[[Item|Items]|Lists]) -&gt;<br />
encode([{ninety:length(Items)+1,Item}|Codes],Lists).
</p></blockquote>
<p>You wonder what is this pack/3 function, thanks for asking:) The question requires to reuse pack, but I realized that pack/1 is reversing the accumulator and I need here the elements in the order of the accumulaor (which is the reversed order with respect to the input). So, instead of duplicating the code of pack/2 I instead rewrote pack/2 into a pack/3 as follows:</p>
<blockquote><p>
pack(L) -&gt; pack(fun (X) -&gt; reverse(X) end,[],L).</p>
<p>pack(Finalize,Acc,[]) -&gt; Finalize(Acc);<br />
pack(Finalize,[[Item|Same]|Others],[Item|Items]) -&gt;<br />
    pack(Finalize,[[Item,Item|Same]|Others],Items);<br />
pack(Finalize,Acc,[Item|Items]) -&gt;pack(Finalize,[[Item]|Acc],Items).
</p></blockquote>
<p>Notice the extra first parameter which is the function to apply to the accumulator when we are done. This makes pack/3 a higher-order function, which is a cool name:) All this to be able to parameterize what we do to the accumulator at the end. Here, in pack/1, we want to reverse it, hence</p>
<blockquote><p>
fun (X) -&gt; reverse(X) end
</p></blockquote>
<p>Now, in encode/2, we do <b>not</b> want to reverse it, thus</p>
<blockquote><p>
fun (X) -&gt; X end
</p></blockquote>
<blockquote><p>
which is the identity function. </p>
<p>By the way, ninety:length/1 is what you called ninety:len/1, obviously.</p>
<p>Tell me what you think of this and I will come back for the rest. Note that dispite my professoral tone, I often make mistakes, so disbelief is very welcome:)</p></blockquote>
]]></content:encoded>
				</item>
	<item>
		<title>by: Christian</title>
		<link>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2557</link>
		<pubDate>Thu, 18 Jan 2007 11:08:50 +0000</pubDate>
		<guid>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2557</guid>
					<description>I haven't finished yet, but here are my comments and code.

&lt;b&gt;P01&lt;/b&gt;
The problem with your solution is that it returns the empty list when the input is the empty list, but also when the last element of a non-empty list is the empty list... In the first case, there should be an error, i.e. either a user-defined exception or a VM-level exception. If I understand the philosophy of Erlang, I would write
&lt;blockquote&gt;
mylast([Item&#124;Items]) -&#62; mylast(Items,Item).
&lt;/blockquote&gt;

&lt;b&gt;P02&lt;/b&gt;
The English is broken in the question and the example is different from the Prolog version. In LISP, it seems the output is the list of the two last elements, whereas in Prolog it is indeed the last element which is the "result". I assume the latter interpretation, as you did. You have the same problem as with &lt;b&gt;P01&lt;/b&gt;. So I would rather write
&lt;blockquote&gt;
mybutlast([A,B&#124;Items]) -&#62; mybutlast(Items,A,B).
&lt;/blockquote&gt;

&lt;b&gt;P03&lt;/b&gt;
Since the only possible error here is for index to be out of range, I would not bother to return an error, so the logic of the application is not obscured by the logic of errors (since there is only one possible here). It is unusual for me, but it seems this is the Erlang way, don't you agree? But there is a logical error you do not avoid here, which happens when the index is negative. Also, if you decrement the index you don't need another index. So I wrote:
&lt;blockquote&gt;
element_at([Item&#124;Items],N) when N &#62; 0 -&#62;
     element_at__([Item&#124;Items],N).
element_at__([Item&#124;_],1)   -&#62; Item;
element_at__([_&#124;Items],N) -&#62; element_at__(Items,N-1).
&lt;/blockquote&gt;

[I will submit this comment now to check whether the HTML is fine, and if so, resume.]</description>
		<content:encoded><![CDATA[<p>I haven&#8217;t finished yet, but here are my comments and code.</p>
<p><b>P01</b><br />
The problem with your solution is that it returns the empty list when the input is the empty list, but also when the last element of a non-empty list is the empty list&#8230; In the first case, there should be an error, i.e. either a user-defined exception or a VM-level exception. If I understand the philosophy of Erlang, I would write</p>
<blockquote><p>
mylast([Item|Items]) -&gt; mylast(Items,Item).
</p></blockquote>
<p><b>P02</b><br />
The English is broken in the question and the example is different from the Prolog version. In LISP, it seems the output is the list of the two last elements, whereas in Prolog it is indeed the last element which is the &#8220;result&#8221;. I assume the latter interpretation, as you did. You have the same problem as with <b>P01</b>. So I would rather write</p>
<blockquote><p>
mybutlast([A,B|Items]) -&gt; mybutlast(Items,A,B).
</p></blockquote>
<p><b>P03</b><br />
Since the only possible error here is for index to be out of range, I would not bother to return an error, so the logic of the application is not obscured by the logic of errors (since there is only one possible here). It is unusual for me, but it seems this is the Erlang way, don&#8217;t you agree? But there is a logical error you do not avoid here, which happens when the index is negative. Also, if you decrement the index you don&#8217;t need another index. So I wrote:</p>
<blockquote><p>
element_at([Item|Items],N) when N &gt; 0 -&gt;<br />
     element_at__([Item|Items],N).<br />
element_at__([Item|_],1)   -&gt; Item;<br />
element_at__([_|Items],N) -&gt; element_at__(Items,N-1).
</p></blockquote>
<p>[I will submit this comment now to check whether the HTML is fine, and if so, resume.]
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: dda</title>
		<link>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2556</link>
		<pubDate>Wed, 17 Jan 2007 19:26:45 +0000</pubDate>
		<guid>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2556</guid>
					<description>&lt;strong&gt;P20&lt;/strong&gt; solved in &lt;strong&gt;P16&lt;/strong&gt;

&lt;strong&gt;P21&lt;/strong&gt;
insertAt(Elem, Liste, Position) -&#62; insertAt(Liste, 1, Position, Elem, []).
insertAt([], _, _, Elem, Acc) -&#62; reverse(Acc);
insertAt([H&#124;T], Current, Current, Elem, Acc) -&#62; flatten(reverse([T, H, Elem&#124;Acc]));
insertAt([H&#124;T], Current, N, Elem, Acc) -&#62;
&#160;&#160;insertAt(T, Current+1, N, Elem, [H&#124;Acc]).

&lt;strong&gt;P22&lt;/strong&gt;
range(Start, End) -&#62;
&#160;&#160;if
&#160;&#160;&#160;Start == End -&#62; [Start];
&#160;&#160;&#160;Start &#62; End -&#62; {error, "Start &#62; End"};
&#160;&#160;&#160;Start  range(Start, End, [])
&#160;&#160;end.
range(End, End, Acc) -&#62; reverse([End&#124;Acc]);
range(Start, End, Acc) -&#62;
&#160;&#160;range(Start+1, End, [Start&#124;Acc]).

&lt;strong&gt;P23&lt;/strong&gt;
rndSelect(Liste, Len) -&#62; rndSelect(Liste, Len, []).
rndSelect([], _, Acc) -&#62; reverse(Acc);
rndSelect(Liste, 0, Acc) -&#62; reverse(Acc);
rndSelect(Liste, N, Acc) -&#62;
&#160;&#160;L=len(Liste),
&#160;&#160;Rnd=random:uniform(L),
&#160;&#160;[NewListe, Number]=extract(Liste, 1, Rnd, []),
&#160;&#160;rndSelect(NewListe, N-1, [Number&#124;Acc]).

extract([H&#124;T], Current, Current, Acc) -&#62; [flatten(reverse([T&#124;Acc])), H];
extract([H&#124;T], Current, N, Acc) -&#62;
&#160;&#160;extract(T, Current+1, N, [H&#124;Acc]).

&lt;strong&gt;P24&lt;/strong&gt;
lottoSelect(N, Max) -&#62;
&#160;&#160;rndSelect(range(1,Max),N).

&lt;strong&gt;P25&lt;/strong&gt;
rndPermu(Liste) -&#62; rndSelect(Liste, len(Liste)).
</description>
		<content:encoded><![CDATA[<p><strong>P20</strong> solved in <strong>P16</strong></p>
<p><strong>P21</strong><br />
insertAt(Elem, Liste, Position) -&gt; insertAt(Liste, 1, Position, Elem, []).<br />
insertAt([], _, _, Elem, Acc) -&gt; reverse(Acc);<br />
insertAt([H|T], Current, Current, Elem, Acc) -&gt; flatten(reverse([T, H, Elem|Acc]));<br />
insertAt([H|T], Current, N, Elem, Acc) -&gt;<br />
&nbsp;&nbsp;insertAt(T, Current+1, N, Elem, [H|Acc]).</p>
<p><strong>P22</strong><br />
range(Start, End) -&gt;<br />
&nbsp;&nbsp;if<br />
&nbsp;&nbsp;&nbsp;Start == End -&gt; [Start];<br />
&nbsp;&nbsp;&nbsp;Start &gt; End -&gt; {error, &#8220;Start &gt; End&#8221;};<br />
&nbsp;&nbsp;&nbsp;Start  range(Start, End, [])<br />
&nbsp;&nbsp;end.<br />
range(End, End, Acc) -&gt; reverse([End|Acc]);<br />
range(Start, End, Acc) -&gt;<br />
&nbsp;&nbsp;range(Start+1, End, [Start|Acc]).</p>
<p><strong>P23</strong><br />
rndSelect(Liste, Len) -&gt; rndSelect(Liste, Len, []).<br />
rndSelect([], _, Acc) -&gt; reverse(Acc);<br />
rndSelect(Liste, 0, Acc) -&gt; reverse(Acc);<br />
rndSelect(Liste, N, Acc) -&gt;<br />
&nbsp;&nbsp;L=len(Liste),<br />
&nbsp;&nbsp;Rnd=random:uniform(L),<br />
&nbsp;&nbsp;[NewListe, Number]=extract(Liste, 1, Rnd, []),<br />
&nbsp;&nbsp;rndSelect(NewListe, N-1, [Number|Acc]).</p>
<p>extract([H|T], Current, Current, Acc) -&gt; [flatten(reverse([T|Acc])), H];<br />
extract([H|T], Current, N, Acc) -&gt;<br />
&nbsp;&nbsp;extract(T, Current+1, N, [H|Acc]).</p>
<p><strong>P24</strong><br />
lottoSelect(N, Max) -&gt;<br />
&nbsp;&nbsp;rndSelect(range(1,Max),N).</p>
<p><strong>P25</strong><br />
rndPermu(Liste) -&gt; rndSelect(Liste, len(Liste)).
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: dda</title>
		<link>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2555</link>
		<pubDate>Wed, 17 Jan 2007 17:23:17 +0000</pubDate>
		<guid>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2555</guid>
					<description>&lt;strong&gt;P01&lt;/strong&gt;
mylast(A) -&#62; mylast(A,[]).
mylast([],B) -&#62; B;
mylast([H&#124;T],A) -&#62;
&#160;&#160;mylast(T,H).

&lt;strong&gt;P02&lt;/strong&gt;
mybutlast(A) -&#62; mybutlast(A, [], []).
mybutlast([], A, B) -&#62; A;
mybutlast([H&#124;T], A, B) -&#62;
&#160;&#160;mybutlast(T, B, H).

&lt;strong&gt;P03&lt;/strong&gt;
kthelem(A, N) -&#62; kthelem(A, 1, N).
kthelem([], _, _) -&#62; {error, out_of_range};
kthelem([H&#124;T], Current, Current) -&#62; H;
kthelem([H&#124;T], Current, N) -&#62;
&#160;&#160;kthelem(T, Current+1, N).

&lt;strong&gt;P04&lt;/strong&gt;
len(A) -&#62; len(A, 0).
len([], Len) -&#62; Len;
len([H&#124;T], Len) -&#62; len(T, Len+1).

&lt;strong&gt;P05&lt;/strong&gt;
reverse([]) -&#62; [];
reverse([H&#124;T]) -&#62; reverse(T,[H]).
reverse([], L) -&#62; L;
reverse([H&#124;T], L) -&#62;
&#160;&#160;reverse(T, [H&#124;L]).

&lt;strong&gt;P06&lt;/strong&gt;
palindrome(A) -&#62;
&#160;&#160;B=reverse(A),
&#160;&#160;case A of
&#160;&#160;&#160;B -&#62; true;
&#160;&#160;&#160;_ -&#62; false
&#160;&#160;end.

&lt;strong&gt;P07&lt;/strong&gt;
&lt;em&gt;I had difficulties with this one, and ended up getting a hint or three from lists:flatten/1's source code :-( &lt;/em&gt;
flatten(List) when is_list(List) -&#62;
&#160;&#160;&#160;&#160;do_flatten(List, []).
flatten(List, Tail) when is_list(List), is_list(Tail) -&#62;
&#160;&#160;&#160;&#160;do_flatten(List, Tail).
do_flatten([H&#124;T], Tail) when is_list(H) -&#62;
&#160;&#160;&#160;&#160;do_flatten(H, do_flatten(T, Tail));
do_flatten([H&#124;T], Tail) -&#62;
&#160;&#160;&#160;&#160;[H&#124;do_flatten(T, Tail)];
do_flatten([], Tail) -&#62;
&#160;&#160;&#160;&#160;Tail.

&lt;strong&gt;P08&lt;/strong&gt;
compress(A) -&#62; compress(A, [], []).
compress([], L, _) -&#62; flatten(L);
compress([H&#124;T], L, H) -&#62; compress(T, L, H);
compress([H&#124;T], L, X) -&#62; compress(T, [L,H], H).

&lt;strong&gt;P09&lt;/strong&gt;
pack(A) -&#62; pack(A,[],[],[]).
pack([], X, Liste, Acc) -&#62; reverse([flatten([Acc,X])&#124;Liste]);
pack([H&#124;T], H, Liste,Acc) -&#62;
&#160;&#160;pack(T, H, Liste, [H,Acc]);
pack([H&#124;T], [], Liste, Acc) -&#62;
&#160;&#160;pack(T, H, Liste, [H]);
pack([H&#124;T], X, Liste, []) -&#62;
&#160;&#160;pack(T, H, [[X]&#124;Liste], []);
pack([H&#124;T], X, Liste, Acc) -&#62;
&#160;&#160;pack(T, H, [flatten([Acc,X])&#124;Liste], []).

&lt;strong&gt;P10&lt;/strong&gt;
runlen(A) -&#62; runlen(A,[],[],[]).
runlen([], X, Liste, Acc) -&#62; 
&#160;&#160;runlengths([flatten([Acc,X])&#124;Liste],[]);
runlen([H&#124;T], H, Liste,Acc) -&#62;
&#160;&#160;runlen(T, H, Liste, [H,Acc]);
runlen([H&#124;T], [], Liste, Acc) -&#62;
&#160;&#160;runlen(T, H, Liste, [H]);
runlen([H&#124;T], X, Liste, []) -&#62;
&#160;&#160;runlen(T, H, [[X]&#124;Liste], []);
runlen([H&#124;T], X, Liste, Acc) -&#62;
&#160;&#160;runlen(T, H, [flatten([Acc,X])&#124;Liste], []).
%% Compute sums
runlengths([],Acc) -&#62; Acc;
runlengths([H&#124;T],Acc) -&#62;
&#160;&#160;[Elem&#124;_]=H,
&#160;&#160;runlengths(T,[[len(H), Elem]&#124;Acc]).

&lt;strong&gt;P11&lt;/strong&gt;
runlen2(A) -&#62; runlen2(A,[],[],[]).
runlen2([], X, Liste, Acc) -&#62; 
&#160;&#160;io:format("list looks like: ~p~n",[lists:reverse([flatten([Acc,X])&#124;Liste])]),
&#160;&#160;runlengths2([flatten([Acc,X])&#124;Liste],[]);
runlen2([H&#124;T], H, Liste,Acc) -&#62;
&#160;&#160;runlen2(T, H, Liste, [H,Acc]);
runlen2([H&#124;T], [], Liste, Acc) -&#62;
&#160;&#160;runlen2(T, H, Liste, [H]);
runlen2([H&#124;T], X, Liste, []) -&#62;
&#160;&#160;runlen2(T, H, [[X]&#124;Liste], []);
runlen2([H&#124;T], X, Liste, Acc) -&#62;
&#160;&#160;runlen2(T, H, [flatten([Acc,X])&#124;Liste], []).
%% Compute sums
runlengths2([],Acc) -&#62; Acc;
runlengths2([H&#124;T],Acc) -&#62;
&#160;&#160;[Elem&#124;_]=H,
&#160;&#160;Len=len(H),
&#160;&#160;case Len of
&#160;&#160;&#160;&#160;1 -&#62; runlengths2(T,[[Elem]&#124;Acc]);
&#160;&#160;&#160;&#160;_ -&#62; runlengths2(T,[[len(H), Elem]&#124;Acc])
&#160;&#160;end.

&lt;strong&gt;P12&lt;/strong&gt;
decoderunlength(A) -&#62; decoderunlength(A, []).
decoderunlength([], Acc) -&#62; reverse(Acc);
decoderunlength([H&#124;T], Acc) -&#62;
&#160;&#160;Len=len(H),
&#160;&#160;case Len of
&#160;&#160;&#160;&#160;1 -&#62; decoderunlength(T, [H&#124;Acc]);
&#160;&#160;&#160;&#160;_ -&#62; decoderunlength(T, [deflate(H)&#124;Acc])
&#160;&#160;end.

deflate([Len, Elem]) -&#62; deflate(Elem, 1, Len, [Elem]).
deflate(Elem, Current, Current, Liste) -&#62; Liste;
deflate(Elem, Current, Len, Liste) -&#62;
&#160;&#160;deflate(Elem, Current+1, Len, [Elem&#124;Liste]).

&lt;strong&gt;P14&lt;/strong&gt;
dupli(A) -&#62; dupli(A, []).
dupli([], Acc) -&#62; reverse(Acc);
dupli([H&#124;T], Acc) -&#62;
&#160;&#160;dupli(T, [H,H&#124;Acc]).

&lt;strong&gt;P15&lt;/strong&gt;
repli(A, Times) -&#62; repli(A, Times, []).
repli([], Times, Acc) -&#62; reverse(flatten(Acc));
repli([H&#124;T], Times, Acc) -&#62;
&#160;&#160;repli(T, Times, [deflate([Times, H])&#124;Acc]).

&lt;strong&gt;P16&lt;/strong&gt;
%% I had first misunderstood the problem and wrote a routine
%% that drops the nth element only
drop(A, N) -&#62; drop(A, 1, N, []).
drop([], _, _, Acc) -&#62; reverse(Acc);
drop([H&#124;T], Current, Current, Acc) -&#62; flatten(reverse([T&#124;Acc]));
drop([H&#124;T], Current, N, Acc) -&#62;
&#160;&#160;drop(T, Current+1, N, [H&#124;Acc]).

%% And now the correct solution
dropnth(A, N) -&#62; dropnth(A, 1, N, []).
dropnth([], _, _, Acc) -&#62; reverse(Acc);
dropnth([H&#124;T], Current, Current, Acc) -&#62;
&#160;&#160;dropnth(T, 1, Current, Acc);
dropnth([H&#124;T], Current, N, Acc) -&#62;
&#160;&#160;dropnth(T, Current+1, N, [H&#124;Acc]).

&lt;strong&gt;P17&lt;/strong&gt;
split(A, Len) -&#62; split(A, 1, Len, []).
split([], _, _, Acc) -&#62; reverse(Acc);
split([H&#124;T], Current, Current, Acc) -&#62; [reverse([H&#124;Acc])&#124;[T]];
split([H&#124;T], Current, Len, Acc) -&#62;
&#160;&#160;split(T, Current+1, Len, [H&#124;Acc]).

&lt;strong&gt;P18&lt;/strong&gt;
slice(A, Start, End) when Start &#62; End -&#62;
&#160;&#160;{error, start_point_greater_than_endpoint};
slice(A, 0, End) -&#62;
&#160;&#160;{error, start_point_is_null};
slice(A, Start, End) -&#62; slice(A, 1, Start, End, []).
slice([], End, Start, End, Acc) -&#62; reverse(Acc);
slice([H&#124;T], End, Start, End, Acc) -&#62; reverse([H&#124;Acc]);
slice([H&#124;T], Start, Start, End, Acc) -&#62;
&#160;&#160;slice(T, Start+1, Start, End, [H&#124;Acc]);
slice([H&#124;T], Current, Start, End, _) when Current 
&#160;&#160;slice(T, Current+1, Start, End, []);
slice([H&#124;T], Current, Start, End, Acc) -&#62;
&#160;&#160;slice(T, Current+1, Start, End, [H&#124;Acc]).

&lt;strong&gt;P19&lt;/strong&gt;
lrot(A, N) -&#62; lrot(A, 1, N, []).
lrot([], _, _, Acc) -&#62; {error};
lrot([H&#124;T], Current, Current, Acc) -&#62;
&#160;&#160;flatten([T&#124;reverse([H&#124;Acc])]);
lrot([H&#124;T], Current, N, Acc) -&#62;
&#160;&#160;lrot(T, Current+1, N, [H&#124;Acc]).
</description>
		<content:encoded><![CDATA[<p><strong>P01</strong><br />
mylast(A) -&gt; mylast(A,[]).<br />
mylast([],B) -&gt; B;<br />
mylast([H|T],A) -&gt;<br />
&nbsp;&nbsp;mylast(T,H).</p>
<p><strong>P02</strong><br />
mybutlast(A) -&gt; mybutlast(A, [], []).<br />
mybutlast([], A, B) -&gt; A;<br />
mybutlast([H|T], A, B) -&gt;<br />
&nbsp;&nbsp;mybutlast(T, B, H).</p>
<p><strong>P03</strong><br />
kthelem(A, N) -&gt; kthelem(A, 1, N).<br />
kthelem([], _, _) -&gt; {error, out_of_range};<br />
kthelem([H|T], Current, Current) -&gt; H;<br />
kthelem([H|T], Current, N) -&gt;<br />
&nbsp;&nbsp;kthelem(T, Current+1, N).</p>
<p><strong>P04</strong><br />
len(A) -&gt; len(A, 0).<br />
len([], Len) -&gt; Len;<br />
len([H|T], Len) -&gt; len(T, Len+1).</p>
<p><strong>P05</strong><br />
reverse([]) -&gt; [];<br />
reverse([H|T]) -&gt; reverse(T,[H]).<br />
reverse([], L) -&gt; L;<br />
reverse([H|T], L) -&gt;<br />
&nbsp;&nbsp;reverse(T, [H|L]).</p>
<p><strong>P06</strong><br />
palindrome(A) -&gt;<br />
&nbsp;&nbsp;B=reverse(A),<br />
&nbsp;&nbsp;case A of<br />
&nbsp;&nbsp;&nbsp;B -&gt; true;<br />
&nbsp;&nbsp;&nbsp;_ -&gt; false<br />
&nbsp;&nbsp;end.</p>
<p><strong>P07</strong><br />
<em>I had difficulties with this one, and ended up getting a hint or three from lists:flatten/1&#8217;s source code <img src='http://www.sungnyemun.org/wordpress/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' />  </em><br />
flatten(List) when is_list(List) -&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;do_flatten(List, []).<br />
flatten(List, Tail) when is_list(List), is_list(Tail) -&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;do_flatten(List, Tail).<br />
do_flatten([H|T], Tail) when is_list(H) -&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;do_flatten(H, do_flatten(T, Tail));<br />
do_flatten([H|T], Tail) -&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;[H|do_flatten(T, Tail)];<br />
do_flatten([], Tail) -&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;Tail.</p>
<p><strong>P08</strong><br />
compress(A) -&gt; compress(A, [], []).<br />
compress([], L, _) -&gt; flatten(L);<br />
compress([H|T], L, H) -&gt; compress(T, L, H);<br />
compress([H|T], L, X) -&gt; compress(T, [L,H], H).</p>
<p><strong>P09</strong><br />
pack(A) -&gt; pack(A,[],[],[]).<br />
pack([], X, Liste, Acc) -&gt; reverse([flatten([Acc,X])|Liste]);<br />
pack([H|T], H, Liste,Acc) -&gt;<br />
&nbsp;&nbsp;pack(T, H, Liste, [H,Acc]);<br />
pack([H|T], [], Liste, Acc) -&gt;<br />
&nbsp;&nbsp;pack(T, H, Liste, [H]);<br />
pack([H|T], X, Liste, []) -&gt;<br />
&nbsp;&nbsp;pack(T, H, [[X]|Liste], []);<br />
pack([H|T], X, Liste, Acc) -&gt;<br />
&nbsp;&nbsp;pack(T, H, [flatten([Acc,X])|Liste], []).</p>
<p><strong>P10</strong><br />
runlen(A) -&gt; runlen(A,[],[],[]).<br />
runlen([], X, Liste, Acc) -&gt;<br />
&nbsp;&nbsp;runlengths([flatten([Acc,X])|Liste],[]);<br />
runlen([H|T], H, Liste,Acc) -&gt;<br />
&nbsp;&nbsp;runlen(T, H, Liste, [H,Acc]);<br />
runlen([H|T], [], Liste, Acc) -&gt;<br />
&nbsp;&nbsp;runlen(T, H, Liste, [H]);<br />
runlen([H|T], X, Liste, []) -&gt;<br />
&nbsp;&nbsp;runlen(T, H, [[X]|Liste], []);<br />
runlen([H|T], X, Liste, Acc) -&gt;<br />
&nbsp;&nbsp;runlen(T, H, [flatten([Acc,X])|Liste], []).<br />
%% Compute sums<br />
runlengths([],Acc) -&gt; Acc;<br />
runlengths([H|T],Acc) -&gt;<br />
&nbsp;&nbsp;[Elem|_]=H,<br />
&nbsp;&nbsp;runlengths(T,[[len(H), Elem]|Acc]).</p>
<p><strong>P11</strong><br />
runlen2(A) -&gt; runlen2(A,[],[],[]).<br />
runlen2([], X, Liste, Acc) -&gt;<br />
&nbsp;&nbsp;io:format(&#8221;list looks like: ~p~n&#8221;,[lists:reverse([flatten([Acc,X])|Liste])]),<br />
&nbsp;&nbsp;runlengths2([flatten([Acc,X])|Liste],[]);<br />
runlen2([H|T], H, Liste,Acc) -&gt;<br />
&nbsp;&nbsp;runlen2(T, H, Liste, [H,Acc]);<br />
runlen2([H|T], [], Liste, Acc) -&gt;<br />
&nbsp;&nbsp;runlen2(T, H, Liste, [H]);<br />
runlen2([H|T], X, Liste, []) -&gt;<br />
&nbsp;&nbsp;runlen2(T, H, [[X]|Liste], []);<br />
runlen2([H|T], X, Liste, Acc) -&gt;<br />
&nbsp;&nbsp;runlen2(T, H, [flatten([Acc,X])|Liste], []).<br />
%% Compute sums<br />
runlengths2([],Acc) -&gt; Acc;<br />
runlengths2([H|T],Acc) -&gt;<br />
&nbsp;&nbsp;[Elem|_]=H,<br />
&nbsp;&nbsp;Len=len(H),<br />
&nbsp;&nbsp;case Len of<br />
&nbsp;&nbsp;&nbsp;&nbsp;1 -&gt; runlengths2(T,[[Elem]|Acc]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;_ -&gt; runlengths2(T,[[len(H), Elem]|Acc])<br />
&nbsp;&nbsp;end.</p>
<p><strong>P12</strong><br />
decoderunlength(A) -&gt; decoderunlength(A, []).<br />
decoderunlength([], Acc) -&gt; reverse(Acc);<br />
decoderunlength([H|T], Acc) -&gt;<br />
&nbsp;&nbsp;Len=len(H),<br />
&nbsp;&nbsp;case Len of<br />
&nbsp;&nbsp;&nbsp;&nbsp;1 -&gt; decoderunlength(T, [H|Acc]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;_ -&gt; decoderunlength(T, [deflate(H)|Acc])<br />
&nbsp;&nbsp;end.</p>
<p>deflate([Len, Elem]) -&gt; deflate(Elem, 1, Len, [Elem]).<br />
deflate(Elem, Current, Current, Liste) -&gt; Liste;<br />
deflate(Elem, Current, Len, Liste) -&gt;<br />
&nbsp;&nbsp;deflate(Elem, Current+1, Len, [Elem|Liste]).</p>
<p><strong>P14</strong><br />
dupli(A) -&gt; dupli(A, []).<br />
dupli([], Acc) -&gt; reverse(Acc);<br />
dupli([H|T], Acc) -&gt;<br />
&nbsp;&nbsp;dupli(T, [H,H|Acc]).</p>
<p><strong>P15</strong><br />
repli(A, Times) -&gt; repli(A, Times, []).<br />
repli([], Times, Acc) -&gt; reverse(flatten(Acc));<br />
repli([H|T], Times, Acc) -&gt;<br />
&nbsp;&nbsp;repli(T, Times, [deflate([Times, H])|Acc]).</p>
<p><strong>P16</strong><br />
%% I had first misunderstood the problem and wrote a routine<br />
%% that drops the nth element only<br />
drop(A, N) -&gt; drop(A, 1, N, []).<br />
drop([], _, _, Acc) -&gt; reverse(Acc);<br />
drop([H|T], Current, Current, Acc) -&gt; flatten(reverse([T|Acc]));<br />
drop([H|T], Current, N, Acc) -&gt;<br />
&nbsp;&nbsp;drop(T, Current+1, N, [H|Acc]).</p>
<p>%% And now the correct solution<br />
dropnth(A, N) -&gt; dropnth(A, 1, N, []).<br />
dropnth([], _, _, Acc) -&gt; reverse(Acc);<br />
dropnth([H|T], Current, Current, Acc) -&gt;<br />
&nbsp;&nbsp;dropnth(T, 1, Current, Acc);<br />
dropnth([H|T], Current, N, Acc) -&gt;<br />
&nbsp;&nbsp;dropnth(T, Current+1, N, [H|Acc]).</p>
<p><strong>P17</strong><br />
split(A, Len) -&gt; split(A, 1, Len, []).<br />
split([], _, _, Acc) -&gt; reverse(Acc);<br />
split([H|T], Current, Current, Acc) -&gt; [reverse([H|Acc])|[T]];<br />
split([H|T], Current, Len, Acc) -&gt;<br />
&nbsp;&nbsp;split(T, Current+1, Len, [H|Acc]).</p>
<p><strong>P18</strong><br />
slice(A, Start, End) when Start &gt; End -&gt;<br />
&nbsp;&nbsp;{error, start_point_greater_than_endpoint};<br />
slice(A, 0, End) -&gt;<br />
&nbsp;&nbsp;{error, start_point_is_null};<br />
slice(A, Start, End) -&gt; slice(A, 1, Start, End, []).<br />
slice([], End, Start, End, Acc) -&gt; reverse(Acc);<br />
slice([H|T], End, Start, End, Acc) -&gt; reverse([H|Acc]);<br />
slice([H|T], Start, Start, End, Acc) -&gt;<br />
&nbsp;&nbsp;slice(T, Start+1, Start, End, [H|Acc]);<br />
slice([H|T], Current, Start, End, _) when Current<br />
&nbsp;&nbsp;slice(T, Current+1, Start, End, []);<br />
slice([H|T], Current, Start, End, Acc) -&gt;<br />
&nbsp;&nbsp;slice(T, Current+1, Start, End, [H|Acc]).</p>
<p><strong>P19</strong><br />
lrot(A, N) -&gt; lrot(A, 1, N, []).<br />
lrot([], _, _, Acc) -&gt; {error};<br />
lrot([H|T], Current, Current, Acc) -&gt;<br />
&nbsp;&nbsp;flatten([T|reverse([H|Acc])]);<br />
lrot([H|T], Current, N, Acc) -&gt;<br />
&nbsp;&nbsp;lrot(T, Current+1, N, [H|Acc]).
</p>
]]></content:encoded>
				</item>
	<item>
		<title>by: Christian</title>
		<link>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2554</link>
		<pubDate>Wed, 17 Jan 2007 16:45:04 +0000</pubDate>
		<guid>http://www.sungnyemun.org/wordpress/2007/01/14/99-lisp-prolog-erlang-problems/#comment-2554</guid>
					<description>A good source of exercises, indeed! I will try in Erlang and Prolog too.

Maybe you can post a solution from time to time, so we can compare? There are many solutions sometimes, the simpler ones not being tail-recursive or too greedy in memory.</description>
		<content:encoded><![CDATA[<p>A good source of exercises, indeed! I will try in Erlang and Prolog too.</p>
<p>Maybe you can post a solution from time to time, so we can compare? There are many solutions sometimes, the simpler ones not being tail-recursive or too greedy in memory.
</p>
]]></content:encoded>
				</item>
</channel>
</rss>
