<?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>thattommyhall.com &#187; RubyQuiz</title>
	<atom:link href="http://www.thattommyhall.com/category/rubyquiz/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.thattommyhall.com</link>
	<description>A Random Walk Through Idea Space</description>
	<lastBuildDate>Tue, 20 Jul 2010 19:13:21 +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>RubyQuiz 148 &#8211; Postfix to Infix</title>
		<link>http://www.thattommyhall.com/2007/12/01/rubyquiz-148-postfix-to-infix/</link>
		<comments>http://www.thattommyhall.com/2007/12/01/rubyquiz-148-postfix-to-infix/#comments</comments>
		<pubDate>Sat, 01 Dec 2007 23:32:05 +0000</pubDate>
		<dc:creator>tom</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[RubyQuiz]]></category>

		<guid isPermaLink="false">http://www.thattommyhall.com/2007/12/01/rubyquiz-148-postfix-to-infix/</guid>
		<description><![CDATA[I have been meaning for some time to tackle the RubyQuiz problems in Python. The one from yesterday (#148) is quite interesting, taking postfix notated expressions and returning an infix version. For example 2 3 5 + * -&#62; 2 * (3 + 5) I spoilt it a bit by reading Reverse Polish Notation on [...]]]></description>
			<content:encoded><![CDATA[<p>I have been meaning for some time to tackle the RubyQuiz problems in Python.</p>
<p>The one from yesterday (#148) is quite interesting, taking postfix notated expressions and returning an infix version.</p>
<p>For example<br />
<strong>2 3 5 + *</strong> -&gt; <strong>2 * (3 + 5)</strong></p>
<p>I spoilt it a bit by reading Reverse Polish Notation on Wikipedia, which gave away how to evaluate the postfix expressions.</p>
<p>Here is my python code to evaluate postfix expressions<br />
<span id="more-28"></span></p>
<pre class="brush: python;">
ops = [&quot;+&quot;,&quot;*&quot;,&quot;/&quot;,&quot;-&quot;]

def evaluate(inputpfs):
    numstack =[]
    opstack = []
    for i in inputpfs.split():
        if i not in ops:
            numstack.append(i)
        else:
            right = numstack.pop()
            left = numstack.pop()
            #print (left + i +  right)
            numstack.append(str(eval(left + i +  right)))
    assert len(numstack) == 1
    return eval(numstack[0])
</pre>
<p>Then I realised all I needed to do was remove eval, add brackets and I would have what I needed.</p>
<pre class="brush: python;">
def bracket(somestring):
    return &quot;(&quot; + somestring + &quot;)&quot;

def post2infix(inputpfs):
    numstack = []
    opstack = []
    resultstr = &quot;&quot;
    for i in inputpfs.split():
        if i not in ops:
            numstack.append(i)
        else:
            right = numstack.pop()
            left = numstack.pop()
            newresult = &quot; &quot;.join([left, i, right])
            newresult = bracket(newresult)
            numstack.append(newresult)
    return numstack[0]
</pre>
<p>Then only printing brackets when you must. If the operation is &#8211; or /; you always need them around the right hand expression, unless is is a plain number as they are not associative. If the operation is +, you never need them. If the operation is * then you need them if you have + or &#8211; in the right hand expression. Note that left is always a plain number as only the top element of the stack is a compound expression</p>
<pre class="brush: python;">
def isnum (somestring):
    return all([i not in somestring for i in ops]) 

def post2infixpp(inputpfs):
    numstack = []
    opstack = []
    resultstr = &quot;&quot;
    for i in inputpfs.split():
        if i not in ops:
            numstack.append(i)
        else:
            right = numstack.pop()
            left = numstack.pop()
            if not isnum(right):
            #if (not all([i not in right for i in ops])):
                if i in [&quot;/&quot;, &quot;-&quot;]:
                    right = bracket(right)
                elif i==&quot;*&quot; and (&quot;-&quot; in right or &quot;+&quot; in right):
                    right = bracket(right)
            newresult = &quot; &quot;.join([left, i, right])
            numstack.append(newresult)
    return numstack[0]
</pre>
<p>A subtle bug means I could not do isnum inline (commented out, line 15 here), I had to add an auxiliary function. Though this way is more comprehensible, I cannot figure out why swapping lines 14 and 15 breaks the code.</p>
<p><strong>Testing</strong>: I know I should have done a bit more error checking in the above functions, but here is the little test sequence I wrote.</p>
<pre class="brush: python;">
eg1 = &quot;2 3 +&quot;
eg2 = &quot;2 3 5 + *&quot;
eg3 = &quot;56 34 213.7 + * 678 -&quot;
egs = [eg1,eg2,eg3]

for i in egs:
    print &quot;*********&quot;
    print i
    print evaluate(i)
    print post2infix(i)
    print post2infixpp(i)
    assert (#evaluate(i) ==
            eval(post2infix(i)) ==
            eval(post2infixpp(i))
           )
</pre>
<p>I had to comment out the evaluate(i) part of the assertion as it failed on eg3 due to some sort of floating point rounding error. I will try and track down why tomorrow.</p>
<pre class="brush: python;">
evaluate(eg3) == 13193.200000000001
eval(post2infixpp(eg3)) == eval(post2infix(eg3)) == 13193.199999999999
</pre>
<p>Get the file <a href="http://www.thattommyhall.com/rubyquiz148.py">Here</a></p>
<p class="facebook"><a href="http://www.facebook.com/share.php?u=http://www.thattommyhall.com/2007/12/01/rubyquiz-148-postfix-to-infix/" target="_blank" title="Share on Facebook">Share on Facebook</a></p>]]></content:encoded>
			<wfw:commentRss>http://www.thattommyhall.com/2007/12/01/rubyquiz-148-postfix-to-infix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
