My quick Scheme code:<br><br>But some notes first:<br>1) Might've rewritten functions already defined<br>2) I'm aware of it's inefficiency as repeated calls to _minus-last_ goes through the list repeatedly<br>3) I represented strings as list as I haven't had any experience with Scheme strings yet.<br>
<br>The code:<br><br>(define (last lst)<br> (cond<br> [(empty? lst) empty]<br> [(empty? (rest lst)) (first lst)]<br> [else (last (rest lst))]))<br><br>(define (minus-last lst)<br> (cond<br> [(empty? lst) empty]<br>
[(empty? (rest lst)) empty]<br> [else (cons (first lst)<br> (minus-last (rest lst)))]))<br><br>(define (lcs lst1 lst2)<br> (local ((define last_lst1 (last lst1))<br> (define last_lst2 (last lst2))<br>
<br> (define (compute_length)<br> (cond<br> [(or (= (length lst1) 0)<br> (= (length lst2) 0))<br> 0]<br> [(equal? last_lst1 last_lst2) (+ 1 (lcs (minus-last lst1)<br>
(minus-last lst2)))]<br> [else (max (lcs (minus-last lst1) lst2)<br> (lcs lst1 (minus-last lst2)))])))<br> (compute_length)))<br>
<br>
>You've been told, but the reality is that syntactically tail recursive<br>
>functions can be written using looping constructs, but not generally<br>
>recursive ones.<br><br>That's enlightening. Thanks.<br><br>>What you have is a generally recursive algorithm. It's possible to write<br>
>this iteratively, but not possible to write it without a stack of some<br>>sort. What you could do to make it iterative is use an explicit stack<br>>onto which you pushed the pending values while you calculated the next<br>
>recursion level, and once you're done you just pop off the stack, apply,<br>>and keep going through the loop.<br>
><br>>But that's a bad idea.<br>
><br>>A really, really bad idea.<br><br>I'm actually implementing this in Java. I'm just "pseudocoding" in Scheme, to gain a grasp on the algorithm. Using an explicit stack won't really reduce my runtime right? My bad. I hit a dead end. Thanks for the insight anyway.<br>
<br><div class="gmail_quote">On Sun, Apr 4, 2010 at 12:52 PM, Synx <span dir="ltr"><<a href="mailto:plt@synx.us.to">plt@synx.us.to</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="im"><br>
Andrei Estioco wrote:<br>
> Hello everyone.<br>
><br>
> I've been told that syntactically recursive functions can be written as<br>
> (while or for) loops.<br>
<br>
</div>You've been told, but the reality is that syntactically tail recursive<br>
functions can be written using looping constructs, but not generally<br>
recursive ones.<br>
<div class="im"><br>
> Consider the LCSlength(s1, s2) function (pseudocode):<br>
><br>
> LCSlength(s1, s2){<br>
> :: length(s1) == 0 OR length(s2) == 0, 0<br>
> :: last(s1) == last(s2), 1 + LCSlength(minus-last(s1), minus-last(s2))<br>
> :: else max(LCSlength(minus-last(s1), s2), LCSlength(s1,<br>
> minus-last(s2)))<br>
> }<br>
<br>
</div>Might be better if you used scheme pseudocode<br>
<br>
<br>
(define (minus l)<br>
; what's this supposed to do?<br>
l)<br>
<br>
(define (lcs-length s1 s2)<br>
(cond<br>
((or (null? s1) (null? s2))<br>
0)<br>
((= (car s1) (car s2))<br>
(+ 1 (lcs-length (minus (cdr s1)) (minus (cdr s2)))))<br>
(else<br>
(max (lcs-length (minus (cdr s1)) (cdr s2))<br>
(lcs-length (cdr s1) (minus (cdr s2)))))))<br>
<br>
...because that code actually compiles! :3<br>
<div class="im"><br>
> I can write this method iteratively but only up to the second condition.<br>
<br>
</div>What you have is a generally recursive algorithm. It's possible to write<br>
this iteratively, but not possible to write it without a stack of some<br>
sort. What you could do to make it iterative is use an explicit stack<br>
onto which you pushed the pending values while you calculated the next<br>
recursion level, and once you're done you just pop off the stack, apply,<br>
and keep going through the loop.<br>
<br>
But that's a bad idea.<br>
<br>
A really, really bad idea.<br>
<br>
Because scheme is *really* good at doing exactly that automatically. The<br>
way to get scheme to manage a stack for you, and ensure that only what<br>
is needed is on it at any given point is to just write the procedure<br>
recursively, and forget about any explicit stack yourself.<br>
<div class="im"><br>
> Iteration, it seems to me, is very linear...<br>
<br>
</div>I don't generally consider "branching" style algorithms to be iteration,<br>
even though it is possible to implement them with only iteration<br>
constructs and an explicit stack. That might be a matter of opinion<br>
though. It's probably more accurate if you referred to things as tail<br>
recursive and uh... not tail-recursive, because linear doesn't really<br>
specify anything about the nature of the algorithm. Any<br>
Turing-compatible algorithm is going to be "linear" whether<br>
tail-recursive or not.<br>
_________________________________________________<br>
For list-related administrative tasks:<br>
<a href="http://list.cs.brown.edu/mailman/listinfo/plt-scheme" target="_blank">http://list.cs.brown.edu/mailman/listinfo/plt-scheme</a><br>
</blockquote></div><br><br clear="all"><br>-- <br>Chad Estioco<br>BS Computer Science (ongoing)<br>University of the Philippines-Diliman<br>==============================<br><a href="http://www.skytreader.net">http://www.skytreader.net</a><br>