Page 5 of 10 FirstFirst ... 34567 ... LastLast
Results 41 to 50 of 91

Thread: Beginner Programming Challenge #11

  1. #41
    Join Date
    Oct 2006
    Location
    Austin, Texas
    Beans
    2,715

    Re: Beginner Programming Challenge #11

    I felt like playing around with this problem some, I'm not sure that I qualify as a beginner though

    I'm whiting my code out just in case...

    Code:
    
    from operator import add, sub, mul, div, mod
    
    
    class Evaluator:
    
      def __init__(self):
        self.operators = {'+':add, '-':sub, '*':mul, '/':div, '%':mod, '^':pow}
    
      def tokenize(self, expr):
        # Split string into tokens
        # otherwise return expr (assuming it's already a token list)
        if isinstance(expr, str):
          return [x.strip() for x in expr.split()]
        return expr
    
      def evaluate(self, expr, environment={}):
        # Evaluate RPN expression string or token list, return top of stack
        stack = []
        for token in self.tokenize(expr):
          if token in self.operators:
            b = stack.pop()
            a = stack.pop()
            stack.append(self.operators[token](a, b))
          elif token in environment:
            stack.append(environment[token])
          else:
            stack.append(float(token))
        return stack[-1]
    
      def make_function(self, expr, *arguments):
        # Return callable version of some expression, mapping args to "arguments"
        def callback(*args):
          return self.evaluate(expr, dict(zip(arguments, args)))
        return callback
    
      def infix_to_rpn(self, expr):
        # Convert infix expression or token list to rpn token list
        tokens = self.tokenize(expr)
        out = []
        stack = []
        prec_list = '^*/+-%('
        prec = prec_list.index
        for token in tokens:
          if token in prec_list:
            while stack and prec(token) > prec(stack[-1]):
              yield stack.pop()
            stack.append(token)
          elif token == '(':
            stack.append(token)
          elif token == ')':
            while stack[-1] != '(':
              yield stack.pop()
            stack.pop()
          else:
            yield token
        while stack:
          yield stack.pop()
    
    
    ev = Evaluator()
    infix_expr = '( x + x ) + y * 2'
    rpn_expr = ev.infix_to_rpn(infix_expr)
    x2_add_y2 = ev.make_function(rpn_expr, 'x', 'y')
    print x2_add_y2(20, 30)
    
    (it can convert infix to postfix/rpn, also returns callable functions from an rpn expression and an argument list)

  2. #42
    Join Date
    Mar 2009
    Location
    Brazil
    Beans
    475
    Distro
    Ubuntu 12.04 Precise Pangolin

    Re: Beginner Programming Challenge #11

    Here is mine, now fully working (at least I hope so):
    PHP Code:
    import os
    def listfiles
    ():
        
    files = []
        for 
    item in os.listdir("."):
            
    files.append(item)
        for 
    item in range(0len(files)):
            print 
    item"-"files[item]
        return 
    files
    def importfile
    (files):
        try:
            
    file input("Choose a file - ")
            
    filedata open(files[file], "r")
            for 
    line in filedata:
                
    expression line.strip()
            print 
    "The expression is"expression
            
    return expression.split(None)
        
    except:
            print 
    "Not a valid file"
            
    return []
    def isnumber(number):
        try:
            
    float(number)
            return 
    True
        except
    :
            return 
    False
    def calculate
    (operand1operand2operator):
        try:
            if 
    operator == "+":
                return 
    operand1 operand2
            elif operator 
    == "-":
                return 
    operand1 operand2
            elif operator 
    == "*":
                return 
    operand1 operand2
            elif operator 
    == "/" and operand2 != 0:
                return 
    operand1 operand2
            elif operator 
    == "%" and operand2 != 0:
                return 
    operand1 operand2
            elif operator 
    == "^":
                return 
    pow(operand1,operand2)
            else:
                print 
    "Divided by zero"
                
    expression = []
        
    except:
            
    expression = []
    def main(expression):
        
    operators = ["+""-""*""/""%""^"]
        while 
    len(expression) > 1:
            for 
    n in range (0len(expression)):
                if 
    expression[nin operators:
                    if 
    1:
                        
    expression[n] = str(calculate(float(expression[n-2]),float(expression[n-1]),expression[n]))
                        
    del expression[int(n-1)]
                        
    del expression[int(n-2)]
                        break
                    else:
                        print 
    "Too few operands before operator"
                        
    expression = []
                        return
                
    elif not isnumber(expression[n]):
                    print 
    "Unrecognized token"
                    
    expression = []
                    return
                
    elif n == len(expression)-1:
                    print 
    "Too many operands"
                    
    expression = []
                    return
        if 
    len(expression) == and isnumber(expression[0]):
            print 
    expression[0]
        else:
            print 
    "Expression is not valid"
    print "Enter your RPN expression, press o to open file or press q to quit"
    quit False
    while quit == False:
        
    raw_expression raw_input()
        if 
    raw_expression == "q":
            
    quit True
        elif raw_expression 
    == "o":
            
    files listfiles()
            
    expression importfile(files)
            
    main(expression)
        else:
            
    expression raw_expression.split(None)
            
    main(expression
    Might add more operations and features later, tho.

    EDIT: Added a file importer.

    EDIT2: Updated in post #49, now converts to infix.
    Last edited by Marlonsm; April 2nd, 2010 at 07:58 PM.
    Ubuntu User #27453 | Linux User #490358
    "Don't preach Linux, mention it"
    "Linux is not Windows"
    73% of statistics in forums are made up on the spot

  3. #43
    Join Date
    Aug 2007
    Location
    UK
    Beans
    427
    Distro
    Ubuntu UNR

    Re: Beginner Programming Challenge #11

    Not a beginner. Here is an importable module that makes rather heavy use of exceptions in the token classification process.
    Code:
    #! /usr/bin/env python
    
    """Stack based RPN calculator importable as a module."""
    
    
    import operator
    from collections import deque
    
    
    __all__ = ["rpncalc", "StackError", "UnrecognizedTokenError"]
    
    
    class StackError(RuntimeError):
        """Stack was unexpectedly empty or unexpectedly not."""
        pass
    
        
    class UnrecognizedTokenError(RuntimeError):
        """Only numbers and +-*/%^ allowed."""
        pass
    
    
    # Mapping of RPN symbols to the functions that perform the operation.
    oplookup = {
        "+" : operator.add,
        "-" : operator.sub,
        "*" : operator.mul,
        "/" : operator.truediv,
        "%" : operator.mod,
        "^" : operator.pow }
    
    
    def rpncalc(tokens):
        """Performs reverse polish notation calculations, returning the answer.
        
           tokens: A list or tuple of numbers and operators.
    
        """
        stack = deque() # Like list but optimized for stack operations.
        
        for token in tokens:
            try:
                # If it can cast to a float, it's a number.
                stack.append(float(token))
            except ValueError:
                try:
                    op = oplookup[token]
                except KeyError:
                    raise UnrecognizedTokenError("unrecognized token %s" % token)
                try:
                    b, a = (stack.pop(), stack.pop())
                except IndexError:
                    raise StackError("too few operands")
                # Result of computation is pushed onto the stack.
                stack.append(op(a, b))
                
        try:
            a = stack.pop()
        except IndexError:
            raise StackError("too many operators")
        if stack:
            raise StackError("too many operands")
       
        return a
    
    
    # This code runs when not importing as a module.  
    if __name__ == "__main__":
        print "Reverse polish notation calculator. Type 'exit' to finish."
        while 1:
            line = raw_input("> ").strip()
            if not line:
                continue
            if line.lower() == "exit":
                break
            try:
                result = rpncalc(line.split(" "))
            except (ZeroDivisionError, StackError, UnrecognizedTokenError), msg:
                print msg
            else:
                print result
    Last edited by StephenF; April 2nd, 2010 at 12:51 PM. Reason: while(1): -> while 1:

  4. #44
    Join Date
    Nov 2009
    Location
    /dev/null
    Beans
    74

    Re: Beginner Programming Challenge #11

    In Perl.

    No need to judge mine...

    Algorithm..
    1. Put the whole input line into a variable, and convert the variable to the array(@x) with space(s) being a delimiter.
    2. Shift out the 1st element of @x.
    3. If shifted out data in #2 is a number, push it to the last element of another array(@op). If the said data is an operator(+.-,*,/,%,^), pop out the last 2 data from @op and run the specified calculation on them.
    4. The result from #3 is pushed into the last element of @op.
    5. Go to #2 until the data in @x runs out.


    "Static" error check is done by subroutine "err_chk", and "dynamic" error check(divided by 0 and operand/operator sequence problem) is done in sub "calc" along with the calculation.


    Code:
    #!/usr/bin/perl
    
    use warnings;
    use strict;
    
    my (@x, $err);
    
    print "> ";
    while(<>){
      chomp;
      if($_ eq 'q'){                # Quit if 'q'.
        last;
      }
      s/^\s+//;                     # Removing the leading spaces
      s/\s+$//;                     # Removing the trailing spaces
      @x = split(/\s+/,$_);
    
      $err = err_chk(@x);        # call sub for error check. 
      
      ($err ne '') ? print "$err\n" : print calc(@x),"\n";  # if there is an error, print it, otherwise call calc sub for calculation. 
    
      print "> ";
    }
    
    
    sub err_chk {
    
    my ($tmp, $operand, $operator) = ('', -1, 0);           # Legit operation has one more operands than operators.  
    
      foreach (@_){                                         # Error: Counting the operands and oparators to match each other 
        if(/^[0-9][0-9]*$/){                                #        as well as detecting unrecognized operators/operands.
           $operand++;
        }
        elsif(/^\+$/||/^\-$/||/^\*$/||/^\/$/||/^\%$/||/^\^$/){
           $operator++;
        }
        else{
           $tmp = "ERROR: Unrecognized operators/operands: $_";
        }
      }
    
      if( ($tmp eq '') && ($operand > $operator) ){
         $tmp = "ERROR: Too many operands";
      }
      elsif( ($tmp eq '') && ($operand < $operator)){
         $tmp = "ERROR: Too many operators";
      }
    
    
    return $tmp; 
    }
    
    
    sub calc {
    
      my (@op, $a, $b);
      my $tmp = '';
      
      undef(@op);
    
      foreach (@_){ 
    
        if(/\+/||/\-/||/\*/||/\//||/\%/||/\^/ ){
          if(scalar(@op) < 2){
             $tmp = "ERROR: Operands or operators sequence may be wrong"; last;     # Error: Stack must have at least 2 data when the operation is performed.
          }
        }
    
        if(/\+/){                                           ### Addition
             $b = pop(@op); $a = pop(@op); $tmp=$a+$b;      # Add the last 2 elements in the array.
             push(@op, $tmp);                               # Push the result to the tail of the array. 
        }
        elsif(/\-/){                                        # Subtraction
             $b = pop(@op); $a = pop(@op); $tmp=$a-$b;
             push(@op, $tmp); 
        }
        elsif(/\*/){                                        ### Multiplication
             $b = pop(@op); $a = pop(@op); $tmp=$a*$b;
             push(@op, $tmp);
        }
        elsif(/\//){                                        ### Division
             $b = pop(@op); $a = pop(@op);
             if($b eq '0'){
               $tmp = "ERROR: Divide by 0"; last;           # Error: divide by 0 detected. Exit the loop.
             }
             $tmp=$a/$b;
             push(@op, $tmp);
        }
        elsif(/\%/){                                        ### Remainder
             $b = pop(@op); $a = pop(@op);
             if($b eq '0'){
               $tmp = "ERROR: Divide by 0"; last;           # Error: divide by 0 detected. Exit the loop.
             }
             $tmp=$a%$b;
             push(@op, $tmp); 
        }
        elsif(/\^/){                                        ### Power of ...
             $b = pop(@op); $a = pop(@op); $tmp=$a**$b;
             push(@op, $tmp); 
        }
        elsif(/[0-9][0-9]*/){
             push(@op, $_);                                 ### Pushing into the array if it's a number.
        }
     }
    
    return $tmp;                                            # Return the result
    }
    Code:
    TPX30:~/perl> perl rpn
    > 3 4 +
    7
    > 10 3 /
    3.33333333333333
    > 2 5 ^
    32
    > 10 2 %
    0
    > 24 12 3 + 4 % / 6 - 4 * 3 ^
    512
    >          6          5            4         *        -      2   8      /              +
    -13.75
    > 10 2 2 %
    ERROR: Too many operands
    > 10 2 2 % /
    ERROR: Divide by 0
    > 10 + 10
    ERROR: Operands or operators sequence may be wrong
    > 10 10 10 +
    ERROR: Too many operands
    > sdj fh 5 sej 4 5 +
    ERROR: Unrecognized operators/operands: sej
    > 45 6 + / & 4
    ERROR: Unrecognized operators/operands: &
    > + 4 1
    ERROR: Operands or operators sequence may be wrong
    > 4 5a +
    ERROR: Unrecognized operators/operands: 5a
    > 10 2 + -
    ERROR: Too many operators
    > 1 2 + hdf + itu -
    ERROR: Unrecognized operators/operands: itu
    > 2 4 + 1 4
    ERROR: Too many operands
    > 2 4 + - 4
    ERROR: Operands or operators sequence may be wrong
    > 3 4 9 * / % 8
    ERROR: Operands or operators sequence may be wrong
    > q
    TPX30:~/perl>
    Last edited by lostinxlation; April 3rd, 2010 at 07:28 AM.

  5. #45
    Join Date
    Jan 2010
    Beans
    Hidden!
    Distro
    Kubuntu 9.10 Karmic Koala

    Re: Beginner Programming Challenge #11

    OPEN QUESTION:

    I, personally, think it's great that some more experienced coders are posting here. The best way to become a better coder is to look at other people's code, and I would prefer to look at good code than bad code.

    Needless to say, I'm not interested in winning, but getting better. I think most people here would agree.

    That aside, I have a question: Some of the coders are importing the operator module, including functions like pow, add, sub, etc. Why? pow is already in the __builtin__ module, so why import its cousin in operator? And the others? - how do you think they simplify the code?

    Thanks

  6. #46
    Join Date
    Oct 2006
    Location
    Austin, Texas
    Beans
    2,715

    Re: Beginner Programming Challenge #11

    Quote Originally Posted by vik_2010 View Post
    That aside, I have a question: Some of the coders are importing the operator module, including functions like pow, add, sub, etc. Why? pow is already in the __builtin__ module, so why import its cousin in operator? And the others? - how do you think they simplify the code?

    Thanks
    Probably just for uniformity.

    I usually just "from operator import ..." since those functions are so useful and it saves on having to use the '.' operation.

    As far as importing the others, in general, because "add" is a lot less to type than "lambda x, y: x + y" and is visually easier to "parse" with your eyes.

  7. #47
    Join Date
    Aug 2007
    Location
    UK
    Beans
    427
    Distro
    Ubuntu UNR

    Re: Beginner Programming Challenge #11

    Quote Originally Posted by vik_2010 View Post
    I have a question: Some of the coders are importing the operator module, including functions like pow, add, sub, etc. Why? pow is already in the __builtin__ module, so why import its cousin in operator?
    Consistency, although I don't like the idea of clobbering the version of pow residing in the module namespace. It is a separate entity from the ones in the math and operator modules.
    Quote Originally Posted by vik_2010 View Post
    And the others? - how do you think they simplify the code?
    By putting the mathematical operator functions in a lookup table (Python dictionary) they can be defined once and only once, making the code much easier to maintain.

    From:
    If the token is x, then you do y multiple times for where x and y have concrete definitions and lines of code have to be repeated with subtle variations (leading to a copy, paste, modify programming style where errors can creep in).
    To:
    This token appears in the operator lookup table so look up its corresponding mathematical function and use it to perform a calculation using the numbers we have to hand.
    Last edited by StephenF; April 2nd, 2010 at 07:20 PM.

  8. #48
    Join Date
    Apr 2007
    Location
    NorCal
    Beans
    1,149
    Distro
    Ubuntu 10.04 Lucid Lynx

    Re: Beginner Programming Challenge #11

    Quote Originally Posted by vik_2010 View Post
    That aside, I have a question: Some of the coders are importing the operator module, including functions like pow, add, sub, etc. Why? pow is already in the __builtin__ module, so why import its cousin in operator? And the others? - how do you think they simplify the code?
    Instead of having something like this:

    Code:
    if token is "+":
        result = lhs + rhs
    elif token is "-":
        result = lhs - rhs
    ...
    else:
        raise BadSyntax("Unrecognized token")
    You can have something like this:

    Code:
    operators = { "+" : operator.add,
                  "-" : operator.sub,
                  ...
    }
    ...
    try:
        result = operators[token](lhs, rhs)
    except KeyError:
        raise BadSyntax("Unrecognized token")
    This makes it a lot easier to add new operators, as well as cut down on the lines of code and therefore opportunities to make mistakes.
    Last edited by schauerlich; April 2nd, 2010 at 05:47 PM.
    Posting code? Use the [code] or [php] tags.
    I don't care, I'm still free. You can't take the sky from me.

  9. #49
    Join Date
    Mar 2009
    Location
    Brazil
    Beans
    475
    Distro
    Ubuntu 12.04 Precise Pangolin

    Re: Beginner Programming Challenge #11

    Added an infix converter to mine (in Python), the code is kind of big and messy, but I'm very proud of it:

    The infix converter will assume any unrecognized token as a variable, for example, "x y +" will return "x+y".
    PHP Code:
    import os
    def listfiles
    ():   #List files in directory and gives each one a number
        
    files = []
        for 
    item in os.listdir("."):
            
    files.append(item)
        for 
    item in range(0len(files)):
            print 
    item"-"files[item]
        return 
    files
    def importfile
    (files):  #Import file based on number chosen
        
    try:
            
    file input("Choose a file - ")
            
    filedata open(files[file], "r")
            for 
    line in filedata:
                
    expression line.strip()
            print 
    "The expression is"expression
            
    return expression.split(None)
        
    except:
            print 
    "Not a valid file"
            
    return []
    def isnumber(number):  #Check if an item is a number
        
    try:
            
    float(number)
            return 
    True
        except
    :
            return 
    False
    def islist
    (list):     #Check if an item in a list
        
    try:
            list.
    append("")
            return 
    True
        except
    :
            return 
    False
    def listtostring
    (list):   #Converts a list into a string
        
    string str()
        for 
    item in list:
            if 
    islist(item): #If an item is a list, make it a string
                
    string += "( " listtostring(item) + " )"
            
    else:
                
    string += item
        
    return string
    def calculate
    (operand1operand2operator): #Calculate
        
    try:
            if 
    operator == "+":
                return 
    operand1 operand2
            elif operator 
    == "-":
                return 
    operand1 operand2
            elif operator 
    == "*":
                return 
    operand1 operand2
            elif operator 
    == "/" and operand2 != 0:
                return 
    operand1 operand2
            elif operator 
    == "%" and operand2 != 0:
                return 
    operand1 operand2
            elif operator 
    == "^":
                return 
    pow(operand1,operand2)
            else:
                print 
    "Divided by zero"
                
    expression = []
        
    except:
            
    expression = []
    def solveRPN(expression):
        
    operators = ["+""-""*""/""%""^"]
        
    #This variable will hold the position reached by the program so it won't iterate numbers more than once
        
    while len(expression) > 1:
            for 
    n in range (mlen(expression)):
                if 
    expression[nin operators:
                    if 
    1#If there are enough operands before operator, calculate
                        
    expression[n] = str(calculate(float(expression[n-2]),float(expression[n-1]),expression[n]))
                        
    del expression[int(n-1)]
                        
    del expression[int(n-2)]
                        
    -= 2
                        
    break
                    else:
                        print 
    "Too few operands before operator"
                        
    expression = []
                        return
                
    elif not isnumber(expression[n]): #If a token is not an operator, neither a number, stop
                    
    print "Unrecognized token"
                    
    expression = []
                    return
                
    elif n == len(expression)-1#If there are no more operators but there is more then one number, stop
                    
    print "Too many operands"
                    
    expression = []
                    return
                else:
                    
    += 1
        
    if len(expression) == and isnumber(expression[0]): #When the result is found, print it
            
    print expression[0]
        else:
            print 
    "Expression is not valid"
    def converttoinfix(expression): #Same as "solveRPN()" but instead of calculate, just put in order
        
    operators = ["+""-""*""/""%""^"]
        while 
    len(expression) > 1:
            for 
    n in range (0len(expression)):
                if 
    expression[nin operators:
                    if 
    1:
                        
    expression[n] = [expression[n-2], " "expression[n], " "expression[n-1]]
                        
    del expression[int(n-1)]
                        
    del expression[int(n-2)]
                        break
                    else:
                        print 
    "Too few operands before operator"
                        
    expression = []
                        return
                
    elif n == len(expression)-1:
                    print 
    "Too many operands"
                    
    expression = []
                    return
        if 
    len(expression) == 1:
            print 
    listtostring(expression[0]) #Covert to string and print result
        
    else:
            print 
    "Expression is not valid"
    if __name__ == "__main__":
        print 
    "Enter your RPN expression, press o to open file, i to convert to infix or q to quit"
        
    quit False
        
    while quit == False:
            
    raw_expression raw_input("RPN > ")
            if 
    raw_expression == "q":
                
    quit True
            elif raw_expression 
    == "o":
                
    files listfiles()
                
    expression importfile(files)
                
    solveRPN(expression)
            
    elif raw_expression == "i":
                print 
    "Enter an RPN expression or press o to open a file"
                
    raw_expression raw_input("RPN to Infix > ")
                if 
    raw_expression == "o":
                    
    files listfiles()
                    
    expression importfile(files)
                    
    converttoinfix(expression)
                else:
                    
    expression raw_expression.split(None)
                    
    converttoinfix(expression)
            else:
                
    expression raw_expression.split(None)
                
    solveRPN(expression
    Example:
    Code:
    marlon@marlon-Ubuntu:~/Desktop$ python rpn.py
    Enter your RPN expression, press o to open file, i to convert to infix or q to quit
    RPN > 1 2 +
    3.0
    RPN > 1 2 3 + -
    -4.0
    RPN > o
    0 - expression2.txt
    1 - Screenshot.png
    2 - rpn.py
    3 - expression.txt
    4 - Compartilhado.sh
    Choose a file - 0
    The expression is 24 12 3 + 4 % / 6 - 4 * 3 ^
    512.0
    RPN > i
    Enter an RPN expression or press o to open a file
    RPN to Infix > 1 2 +
    1 + 2
    RPN > i
    Enter an RPN expression or press o to open a file
    RPN to Infix > o
    0 - expression2.txt
    1 - Screenshot.png
    2 - rpn.py
    3 - expression.txt
    4 - Compartilhado.sh
    Choose a file - 3
    The expression is 5 1 2 + 4 * + 3 -
    ( 5 + ( ( 1 + 2 ) * 4 ) ) - 3
    RPN > i
    Enter an RPN expression or press o to open a file
    RPN to Infix > x y + z /
    ( x + y ) / z
    RPN > 1 2 &
    Unrecognized token
    RPN > 1 2 3 +
    Too many operands
    RPN > 1 2 + -
    Too few operands before operator
    RPN > q
    marlon@marlon-Ubuntu:~/Desktop$
    EDIT: Now it can also be used as a module and I added an optimization that it won't iterate the whole expression again after making an operation.
    Last edited by Marlonsm; April 10th, 2010 at 11:51 PM.
    Ubuntu User #27453 | Linux User #490358
    "Don't preach Linux, mention it"
    "Linux is not Windows"
    73% of statistics in forums are made up on the spot

  10. #50
    Join Date
    Dec 2006
    Location
    Hogwarts, `UNKNOWN`
    Beans
    Hidden!
    Distro
    Ubuntu 8.10 Intrepid Ibex

    Re: Beginner Programming Challenge #11

    C

    OUTPUT
    Compiled with gcc -Wall -Wextra -pedantic -ansi -lm revpolish.c
    Code:
    amd@amita-pc:~/Programming$ ./a.out 
    Welcome to Post Fix Interpreter. Press q to quit
    
    postfix> 3 4 +
    7.000000
    postfix> 10 3 /
    3.333333
    postfix> 2 5 ^
    32.000000
    postfix> 24 12 3 + 4 % / 6 - 4 * 3 ^
    512.000000
    postfix> 10 + 10
    ERROR: Too less operands
    postfix> 10 10 10 +
    ERROR: Too many operands
    postfix> sald;kas;dk;asdk;as
    ERROR: Invalid Token
    postfix> 45 6 + / & 4 
    ERROR: Too less operands
    postfix> 2 & 4
    ERROR: Invalid Token
    postfix> q   
    
    amd@amita-pc:~/Programming$

    SOURCE CODE
    [ http://pastebin.fosspowered.com/view/35147988 ] (For easier Reading)

    PHP Code:
    #include<stdlib.h>
    #include<string.h>
    #include<stdio.h>
    #include<math.h>

    #define LEN 100

    /* Enumerated Data type to determine whether we are in process of getting a number or decimal or new operand/operator */
    enum State    {OUTINDECIMAL}; 
    enum Sign    {POSITIVENEGATIVE};

    /************************************************LIFO Data Structure using Linked Lists********************************/
    typedef struct Node {
        
    double num;
        
    struct Node *ptr;
    Node;

    typedef struct Stack    {
        
    Node *top;
    Stack;

    /* Initialize a stack to NULL */
    void Stack_Initialize(Stack *s)    {
        
    s->top NULL;
    }

    /* Push an element on to a stack. No need to check for bounds, as the nodes are dynamically created */
    void Stack_Push(Stack *sdouble n)    {
        
    /* Create a new node to store the new value */
        
    Node *prevtop s->top
        
    Node *newnode;
        
    newnode = (Node*)malloc(sizeof(Node));
        
    newnode->num n;
        
    newnode->ptr prevtop/* Point the pointer in the node to the current top of the stack */
        
        
    s->top newnode;    /* Point the top of the stack to the new node */
    }

    /* Pop an element from stack and store it in retnum, if successful return 1, if not return 0 */
    int Stack_Pop(Stack *sdouble *retnum)    {
        
    Node *s->top;
        
        
    /* If the stack top is NULL, that means no data is there in the stack*/
        
    if(s->top == NULL)    {
            return 
    0;    /* Failure to Pop */
        
    }
        
        *
    retnum p->num/* Store the number on top node of srack in retnum */
        
    s->top p->ptr;  /* Now set the new stack top the stack to the node below the top */
        
    free(p); /* Clean up the top node */
        
        
    return 1;    /* Successful */
    }
    /************************************************End of Data Structure********************************/

    /* Safely get a string, and put space in the end of the input string as sentinel element */
    void get_string(char str[])
    {
        
    char *newline;
        
    fgets(strLENstdin);
        
    newline strchr(str'\n');
        *
    newline ' ';
    }

    /* Compute the postfix expression string */
    void compute(char postinp[])    {
        
    int i
        
    double num/* Variable for storing the extracted decimal number */
        
    char ch/* Variable to store each character */
        
    int len/* Length of the string */
        
    enum State n OUT/* Set initial state of whether reading a decimal or not as OUT */
        
    enum Sign sign POSITIVE;
        
    int count_decplaces 0/* Variable to determine number of decimal places, in case of . is detected in string for floating point numbers parsing */
        
    Stack pfstack/* Stack to store operands for postfix evaluation */
        
    double op1op2res/* Variables to hold the operands which are popped out and res is the result stored which is pushed to the stack */
        
    int count_operands 0/* Count number of operands, if zero then output nothing */
        
        
    Stack_Initialize(&pfstack); 
        
        
    len strlen(postinp); 
        
        for(
    i=0i<len; ++i)    {
            
    ch postinp[i];    
            
            
    /* Detect use of - as a negative sign */
            
    if(postinp[i]=='-' && (postinp[i+1] >= '0' && postinp[i+1] <= '9') && sign == POSITIVE && n==OUT)    {
                
    sign NEGATIVE;
                continue;            
            }
            
            
    /* If the character is a numeric type, put it into the current or set as new number */    
            
    if((ch>='0' && ch<='9'))    {
                
    /* If it's a new number in case n is OUT, and not IN or DECIMAL; set the number's first digit place */
                
    if(n==OUT)    {
                    
    num = (int)ch-(int)'0';            
                    
    n=IN;    
                }
                
    /* If in process of reading a number, multiply the current number by 10 and add the new digit */
                /* eg. if we read 123, and now read 4, then 123*10=1230 then 1230+4=1234 */
                
    else if(n==IN)    {
                    
    num *= 10;
                    
    num += (int)ch-(int)'0';            
                }
                
    /* If we are in n = DECIMAL, that is reading a decimal */
                
    else    {
                    
    count_decplaces++; /* Moving in to next decimal place, increment the number of decimal places */
                    
                    /* Divide the digit to the 10th power of the number of decimal places eg. 2 in 3rd decimal place then 0.002 would be added */
                    
    num += ((int)ch-(int)'0')/pow(10count_decplaces); 
                }
            }
            
            
    /* In case a decimal point is detected and it's not illegaly used period(.), i.e. double(.) or so */
            
    else if(ch=='.' && != DECIMAL)    {
                if(
    n==OUT)    {
                    
    num 0.0/* In case if user inputs, .23, then sets num = 0.0 */
                
    }
                
    n=DECIMAL/* Set n as DECIMAL, i.e. it will read as decimal state */
            
    }
            
    /* If we detect ch as any other character which is neither numeric nor single period */
            
    else    {
                
    /* If we are reading the current number, then we finish reading it here */
                
    if(n==IN || n==DECIMAL)    {
                    if(
    sign == NEGATIVE)    {
                        
    num *= -1;
                    }
                    
    sign POSITIVE;
                    
    Stack_Push(&pfstacknum);     
                    
    count_operands++; 
                }
                
    /* Stop reading the number which was being read */
                
    OUT
                
    count_decplaces=0;
                
                
    /* If an operator is detected */
                
    if(ch=='+' || ch=='-' || ch=='*' || ch=='/' || ch=='^')    {
                    
    /*Pop top two elements, from the stack, if successfully popped, then move further */
                    
    if(Stack_Pop(&pfstack, &op1) && Stack_Pop(&pfstack,&op2))    {
                        switch(
    ch)    {
                            
    /* Perform appropraite operation */
                            
    case '+':
                                
    res op2 op1;
                                break;
                            case 
    '-':
                                
    res op2 op1;
                                break;
                            case 
    '*':
                                
    res op2 op1;
                                break;
                            case 
    '/':
                                if(
    op1 == 0)    {
                                    
    printf("ERROR: Divide by zero\n");
                                    return;
                                }
                                
    res op2 op1;
                                break;
                            case 
    '^':
                                
    res pow(op2op1);
                                break;
                        }
                        
    Stack_Push(&pfstackres); /* Push the result onto the stack */
                    
    }
                    
    /* In case there is underflow in the stack, that means there were too many operators for current number of operands */
                    
    else    {
                        
    printf("ERROR: Too less operands\n");
                        return;
                    }
                }
                    
                
    /* ' ' is the seperator between numbers, it has to be noted operators can acts as separators too */
                
    else if(ch==' ')
                    continue;
                
    /* Any other character other than numeric, operator, or ' ' is invalid */
                
    else    {
                    
    printf("ERROR: Invalid Token\n");
                    return;
                    }
                }
                
            }

            
        
    Stack_Pop(&pfstack, &res); /* Pop the (hopefully) last element, this is the result */
        
        /* If an element still remains after the previous popping operations it means, there were excess of operands */
        /* In case of failure of popping, which means successful parsing, res does not change its values during this code */
        
    if(Stack_Pop(&pfstack, &res))    {
            
    printf("ERROR: Too many operands\n");
            return;
        }
        
        
    /* Output nothing if the number of operands is zero */
        
    if(count_operands==0)    {
            return;
        }
        
        
    /* Show the result */
        
    printf("%f\n"res);
        
    }

    int main()
    {
        
    char inp[LEN];
        
        
    printf("Welcome to Post Fix Interpreter. Press q to quit\n\n");
        
        while(
    1)    {
            
    printf("postfix> ");    /* Prompt */
            
    get_string(inp);
            if(
    inp[0] == 'q')
                break;
            
    compute(inp);    /* Evaluate */
        
    }

        
    printf("\n");
        return 
    0;





    The only "problem" is that if an invalid token if AFTER say lack of operands I mean like 45 6 + / & 4, this would exit at the point of that '/' with the too less operands error rather than invalid token as shown to be done, but I dont think it's much of a problem; No?

    EDIT: ~SNIPPED~

    EDIT#2: Added support for Negative numbers, and also works with Decimals. Removed %

    EDIT#3: Please separate tokens by space. There seems to be ambiguity if ane expression such as -2-2+ is used, -2 -2 + works though
    Last edited by Canis familiaris; April 3rd, 2010 at 09:52 AM.

Page 5 of 10 FirstFirst ... 34567 ... LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •