Skip to content

Commit d81b544

Browse files
committed
Small tweaks to the text and code
Don't need to have a duplicate copy of Stack in this folder
1 parent fa073ec commit d81b544

File tree

8 files changed

+128
-208
lines changed

8 files changed

+128
-208
lines changed

README.markdown

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ Bad sorting algorithms (don't use these!):
9191

9292
- [Greatest Common Divisor (GCD)](GCD/). Special bonus: the least common multiple.
9393
- [Permutations and Combinations](Combinatorics/). Get your combinatorics on!
94+
- [Shunting Yard Algorithm](Shunting Yard/). Convert infix expressions to postfix.
9495
- Statistics
9596

9697
### Machine learning

Shunting Yard/README.markdown

Lines changed: 27 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
11
# Shunting Yard Algorithm
22

3-
Any mathematical expression that we write is expressed in a notation known as Infix Notation.
3+
Any mathematical expression that we write is expressed in a notation known as *infix notation*.
44

55
For example:
66

77
**A + B * C**
88

9-
In the above expression the operator is placed between operands hence the expression is said to be in Infix form.
10-
If you think about it any expression that you write on a piece of paper will always be in infix form. This is what we humans understand.
9+
In the above expression the operator is placed between operands, hence the expression is said to be in *infix* form. If you think about it, any expression that you write on a piece of paper will always be in infix form. This is what we humans understand.
1110

12-
Now, think about the way the above expression is evaluated, you would first multiply B and C then add the result to A. This is because multiplication has
13-
higher precedence than addition. We humans can easily understand the precedence of operators, but a machine needs to be given instructions about each operator. If you were to
14-
write an algorithm that parsed and evaluated the infix notation you will realize that it's a tedious process. You'd have to parse the expression
15-
multiple times to know what operation to perform first. As the number of operators increase so does the complexity.
11+
When the above expression is evaluated, you would first multiply **B** and **C**, and then add the result to **A**. This is because multiplication has higher precedence than addition. We humans can easily understand the precedence of operators, but a machine needs to be given instructions about each operator.
1612

17-
## Postfix notations / Reverse Polish Notation
13+
If you were to write an algorithm that parsed and evaluated the infix notation you will realize that it's a tedious process. You'd have to parse the expression multiple times to know what operation to perform first. As the number of operators increase so does the complexity.
1814

19-
An expression when represented in postfix form will not have any brackets and neither will you have to worry about scanning for operator precedence. This makes it easy for the computer to evaluate
20-
expressions since the order in which the operator need to be applied is fixed.
15+
## Postfix notations / Reverse Polish Notation
2116

22-
For example:
17+
In postfix notation, also known as Reverse Polish Notation or RPN, the operators come after the corresponding operands. Here is the postfix representation of the example from the previous section:
2318

2419
**A B C * +**
2520

26-
The above is the postfix representation of the example in the previous section. The operators come after the corresponding operands.
21+
An expression when represented in postfix form will not have any brackets and neither will you have to worry about scanning for operator precedence. This makes it easy for the computer to evaluate expressions, since the order in which the operators need to be applied is fixed.
2722

2823
### Evaluating a postfix expression
2924

@@ -33,12 +28,11 @@ A stack is used to evaluate a postfix expression. Here is the pseudocode:
3328
2. If the token is an operand, push it into the stack
3429
3. If the token is a binary operator,
3530
1. Pop the two top most operands from the stack
36-
2. Apply the binary operator with thetwo operands
31+
2. Apply the binary operator to the two operands
3732
3. Push the result into the stack
38-
4. Finally, the value of the whole postfix
39-
expression remains in the stack
33+
4. Finally, the value of the whole postfix expression remains in the stack
4034

41-
Using the above psuedocode the evaluation on the stack would be as follows:
35+
Using the above pseudocode, the evaluation on the stack would be as follows:
4236

4337
| Expression | Stack |
4438
| ------------- | --------|
@@ -51,34 +45,36 @@ Using the above psuedocode the evaluation on the stack would be as follows:
5145

5246
Where **D = B * C** and **E = A + D.**
5347

54-
As seen above a postfix operation is relatively easy to evaluate as the order in which the operators need to be applied is predecided.
48+
As seen above, a postfix operation is relatively easy to evaluate as the order in which the operators need to be applied is pre-decided.
5549

56-
## Shunting yard algorithm
50+
## Dijkstra's shunting yard algorithm
5751

58-
The Shunting yard algorithm was invented by Edsger Dijkstra to convert an infix expression to postfix. Many calculators use this algorithm to convert the expression being entered to postfix form.
52+
The shunting yard algorithm was invented by Edsger Dijkstra to convert an infix expression to postfix. Many calculators use this algorithm to convert the expression being entered to postfix form.
5953

6054
Here is the psedocode of the algorithm:
6155

62-
1. For all the input tokens
56+
1. For all the input tokens:
6357
1. Read the next token
6458
2. If token is an operator (x)
6559
1. While there is an operator (y) at the top of the operators stack and either (x) is left-associative and its precedence is less or equal to that of (y), or (x) is right-associative and its precedence is less than (y)
6660
1. Pop (y) from the stack
6761
2. Add (y) output buffer
6862
2. Push (x) on the stack
69-
3. Else If token is left parenthesis, then push it on the stack
70-
4. Else If token is a right parenthesis
63+
3. Else if token is left parenthesis, then push it on the stack
64+
4. Else if token is a right parenthesis
7165
1. Until the top token (from the stack) is left parenthesis, pop from the stack to the output buffer
7266
2. Also pop the left parenthesis but don’t include it in the output buffer
7367
7. Else add token to output buffer
7468
2. While there are still operator tokens in the stack, pop them to output
7569

7670
### How does it work
7771

78-
Let's take a small example and see how the psuedocode works.
72+
Let's take a small example and see how the pseudocode works.
7973

8074
**4 + 4 * 2 / ( 1 - 5 )**
8175

76+
The following table describes the precedence and the associativity for each operator. The same values are used in the algorithm.
77+
8278
| Operator | Precedence | Associativity |
8379
| ---------| -------------| ----------------|
8480
| ^ | 10 | Right |
@@ -87,25 +83,28 @@ Let's take a small example and see how the psuedocode works.
8783
| + | 0 | Left |
8884
| - | 0 | Left |
8985

90-
The above table describes the precedence and the associativity for each operator. The same values are used in the algorithm.
86+
Here we go:
9187

9288
| Token | Action | Output | Operator stack |
9389
|-------|---------------------------------------------|-------------------|----------------|
94-
| 3 | Add token to output | 4 | |
90+
| 4 | Add token to output | 4 | |
9591
| + | Push token to stack | 4 | + |
9692
| 4 | Add token to output | 4 4 | + |
9793
| * | Push token to stack | 4 4 | * + |
9894
| 2 | Add token to output | 4 4 2 | * + |
99-
| / | * Pop stack to output * Push token to stack | 4 4 2 * | / + |
95+
| / | Pop stack to output, Push token to stack | 4 4 2 * | / + |
10096
| ( | Push token to stack | 4 4 2 * | ( / + |
10197
| 1 | Add token to output | 4 4 2 * 1 | ( / + |
10298
| - | Push token to stack | 4 4 2 * 1 | - ( / + |
10399
| 5 | Add token to output | 4 4 2 * 1 5 | - ( / + |
104-
| ) | * Pop stack to output * Pop stack | 4 4 2 * 1 5 - | / + |
100+
| ) | Pop stack to output, Pop stack | 4 4 2 * 1 5 - | / + |
105101
| end | Pop entire stack to output | 4 4 2 * 1 5 - / + | |
106102

103+
We end up with the postfix expression:
104+
105+
** 4 4 2 * 1 5 - / + **
107106

108-
# See Also
107+
# See also
109108

110109
[Shunting yard algorithm on Wikipedia](https://en.wikipedia.org/wiki/Shunting-yard_algorithm)
111110

Shunting Yard/Shunting Yard.playground/Contents.swift renamed to Shunting Yard/ShuntingYard.playground/Contents.swift

Lines changed: 26 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
//: Playground - noun: a place where people can play
22

3-
import Foundation
4-
53
internal enum OperatorAssociativity {
64
case LeftAssociative
75
case RightAssociative
@@ -54,19 +52,18 @@ public enum TokenType: CustomStringConvertible {
5452
}
5553

5654
public struct OperatorToken: CustomStringConvertible {
57-
58-
var operatorType: OperatorType
55+
let operatorType: OperatorType
5956

6057
init(operatorType: OperatorType) {
6158
self.operatorType = operatorType
6259
}
6360

64-
var precedance: Int {
61+
var precedence: Int {
6562
switch operatorType {
6663
case .Add, .Subtract:
6764
return 0
6865
case .Divide, .Multiply, .Percent:
69-
return 5;
66+
return 5
7067
case .Exponent:
7168
return 10
7269
}
@@ -87,22 +84,15 @@ public struct OperatorToken: CustomStringConvertible {
8784
}
8885

8986
func <=(left: OperatorToken, right: OperatorToken) -> Bool {
90-
if left.precedance <= right.precedance {
91-
return true
92-
}
93-
return false
87+
return left.precedence <= right.precedence
9488
}
9589

9690
func <(left: OperatorToken, right: OperatorToken) -> Bool {
97-
if left.precedance < right.precedance {
98-
return true
99-
}
100-
return false
91+
return left.precedence < right.precedence
10192
}
10293

10394
public struct Token: CustomStringConvertible {
104-
105-
var tokenType: TokenType
95+
let tokenType: TokenType
10696

10797
init(tokenType: TokenType) {
10898
self.tokenType = tokenType
@@ -136,9 +126,9 @@ public struct Token: CustomStringConvertible {
136126

137127
var operatorToken: OperatorToken? {
138128
switch tokenType {
139-
case .Operator(let operatorToken):
129+
case .Operator(let operatorToken):
140130
return operatorToken
141-
default:
131+
default:
142132
return nil
143133
}
144134
}
@@ -149,8 +139,7 @@ public struct Token: CustomStringConvertible {
149139
}
150140

151141
public class InfixExpressionBuilder {
152-
153-
private var expression = Array<Token>()
142+
private var expression = [Token]()
154143

155144
public func addOperator(operatorType: OperatorType) -> InfixExpressionBuilder {
156145
expression.append(Token(operatorType: operatorType))
@@ -172,66 +161,62 @@ public class InfixExpressionBuilder {
172161
return self
173162
}
174163

175-
public func build() -> Array<Token> {
164+
public func build() -> [Token] {
176165
// Maybe do some validation here
177166
return expression
178167
}
179168
}
180169

181170
// This returns the result of the shunting yard algorithm
182-
public func reversePolishNotation(expression: Array<Token>) -> String {
183-
171+
public func reversePolishNotation(expression: [Token]) -> String {
172+
184173
var tokenStack = Stack<Token>()
185174
var reversePolishNotation = [Token]()
186175

187176
for token in expression {
188177
switch token.tokenType {
189178
case .Operand(_):
190179
reversePolishNotation.append(token)
191-
break
180+
192181
case .OpenBracket:
193182
tokenStack.push(token)
194-
break
183+
195184
case .CloseBracket:
196-
while tokenStack.count > 0 {
197-
if let tempToken = tokenStack.pop() where !tempToken.isOpenBracket {
198-
reversePolishNotation.append(tempToken)
199-
} else {
200-
break
201-
}
185+
while tokenStack.count > 0, let tempToken = tokenStack.pop() where !tempToken.isOpenBracket {
186+
reversePolishNotation.append(tempToken)
202187
}
203-
break
188+
204189
case .Operator(let operatorToken):
205-
206190
for tempToken in tokenStack.generate() {
207191
if !tempToken.isOperator {
208192
break
209193
}
210194

211195
if let tempOperatorToken = tempToken.operatorToken {
212-
213196
if operatorToken.associativity == .LeftAssociative && operatorToken <= tempOperatorToken
214197
|| operatorToken.associativity == .RightAssociative && operatorToken < tempOperatorToken {
215-
216198
reversePolishNotation.append(tokenStack.pop()!)
217199
} else {
218200
break
219201
}
220202
}
221203
}
222-
223204
tokenStack.push(token)
224-
break
225205
}
226206
}
227207

228208
while tokenStack.count > 0 {
229209
reversePolishNotation.append(tokenStack.pop()!)
230210
}
231211

232-
return reversePolishNotation.map({token in
233-
return token.description
234-
}).joinWithSeparator(" ")
212+
return reversePolishNotation.map({token in token.description}).joinWithSeparator(" ")
235213
}
236214

237-
print(reversePolishNotation(InfixExpressionBuilder().addOperand(3).addOperator(.Add).addOperand(4).addOperator(.Multiply).addOperand(2).addOperator(.Divide).addOpenBracket().addOperand(1).addOperator(.Subtract).addOperand(5).addCloseBracket().addOperator(.Exponent).addOperand(2).addOperator(.Exponent).addOperand(3).build()))
215+
216+
// Simple demo
217+
218+
let expr = InfixExpressionBuilder().addOperand(3).addOperator(.Add).addOperand(4).addOperator(.Multiply).addOperand(2).addOperator(.Divide).addOpenBracket().addOperand(1).addOperator(.Subtract).addOperand(5).addCloseBracket().addOperator(.Exponent).addOperand(2).addOperator(.Exponent).addOperand(3).build()
219+
220+
print(expr.description)
221+
print(reversePolishNotation(expr))
222+

0 commit comments

Comments
 (0)