Just another update

This commit is contained in:
Ingy döt Net 2015-02-20 00:35:01 -05:00
parent a25938f123
commit 00a190b0a6
6591 changed files with 94363 additions and 23227 deletions

View file

@ -15,13 +15,13 @@ isOp _ = False
simSYA xs = final ++ [lastStep]
where final = scanl f ([],[],"") xs
lastStep = (\(x,y,_) -> (reverse y ++ x, [], "")) $ last final
f (out,st,_) t | isOp t =
f (out,st,_) t | isOp t =
(reverse (takeWhile testOp st) ++ out
, (t:) $ (dropWhile testOp st), t)
| t == "(" = (out, "(":st, t)
| t == ")" = (reverse (takeWhile (/="(") st) ++ out,
| t == "(" = (out, "(":st, t)
| t == ")" = (reverse (takeWhile (/="(") st) ++ out,
tail $ dropWhile (/="(") st, t)
| True = (t:out, st, t)
| otherwise = (t:out, st, t)
where testOp x = isOp x && (leftAssoc t && prec t == prec x
|| prec t < prec x)

View file

@ -1,6 +1,7 @@
{-# LANGUAGE LambdaCase #-}
import Control.Applicative
import Control.Lens
import Control.Monad
import Control.Monad.Error
import Control.Monad.State
import System.Console.Readline
@ -60,13 +61,11 @@ pushVal n = _1 %= (OutVal n:)
pushParen :: RPNComp ()
pushParen = _2 %= (Paren:)
--Run StateT. `process` is effectively foldM_ with the base case to
--format the output string
--Run StateT
toRPN :: [InToken] -> Either String [OutToken]
toRPN xs = evalStateT (process (return ()) xs) ([],[])
where process st [] = st >> get >>= \(a,b) -> (reverse a++) <$>
(mapM toOut b)
process st (x:xs) = process (st >> processToken x) xs
toRPN xs = evalStateT process ([],[])
where process = mapM_ processToken xs
>> get >>= \(a,b) -> (reverse a++) <$> (mapM toOut b)
toOut :: StackElem -> RPNComp OutToken
toOut (StOp o) = return $ OutOp o
toOut Paren = throwError "Unmatched left parenthesis"

View file

@ -0,0 +1,46 @@
import java.util.Stack;
public class ShuntingYard {
public static void main(String[] args) {
String infix = "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3";
System.out.printf("infix: %s%n", infix);
System.out.printf("postfix: %s%n", infixToPostfix(infix));
}
static String infixToPostfix(String infix) {
final String ops = "-+/*^";
StringBuilder sb = new StringBuilder();
Stack<Integer> s = new Stack<>();
for (String token : infix.split("\\s")) {
char c = token.charAt(0);
int idx = ops.indexOf(c);
if (idx != -1 && token.length() == 1) {
if (s.isEmpty())
s.push(idx);
else {
while (!s.isEmpty()) {
int prec2 = s.peek() / 2;
int prec1 = idx / 2;
if (prec2 > prec1 || (prec2 == prec1 && c != '^'))
sb.append(ops.charAt(s.pop())).append(' ');
else break;
}
s.push(idx);
}
} else if (c == '(') {
s.push(-2);
} else if (c == ')') {
while (s.peek() != -2)
sb.append(ops.charAt(s.pop())).append(' ');
s.pop();
} else {
sb.append(token).append(' ');
}
}
while (!s.isEmpty())
sb.append(ops.charAt(s.pop())).append(' ');
return sb.toString();
}
}

View file

@ -0,0 +1,71 @@
function Stack() {
this.dataStore = [];
this.top = 0;
this.push = push;
this.pop = pop;
this.peek = peek;
this.length = length;
}
function push(element) {
this.dataStore[this.top++] = element;
}
function pop() {
return this.dataStore[--this.top];
}
function peek() {
return this.dataStore[this.top-1];
}
function length() {
return this.top;
}
var infix = "3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3";
infix = infix.replace(/\s+/g, ''); // remove spaces, so infix[i]!=" "
var s = new Stack();
var ops = "-+/*^";
var precedence = {"^":4, "*":3, "/":3, "+":2, "-":2};
var associativity = {"^":"Right", "*":"Left", "/":"Left", "+":"Left", "-":"Left"};
var token;
var postfix = "";
var o1, o2;
for (var i = 0; i < infix.length; i++) {
token = infix[i];
if (token > "0" && token < "9") { // if token is operand (here limited to 0 <= x <= 9)
postfix += token + " ";
}
else if (ops.indexOf(token) != -1) { // if token is an operator
o1 = token;
o2 = s.peek();
while (ops.indexOf(o2)!=-1 && ( // while operator token, o2, on top of the stack
// and o1 is left-associative and its precedence is less than or equal to that of o2
(associativity[o1] == "Left" && (precedence[o1] <= precedence[o2]) ) ||
// the algorithm on wikipedia says: or o1 precedence < o2 precedence, but I think it should be
// or o1 is right-associative and its precedence is less than that of o2
(associativity[o1] == "Right" && (precedence[o1] < precedence[o2]))
)){
postfix += o2 + " "; // add o2 to output queue
s.pop(); // pop o2 of the stack
o2 = s.peek(); // next round
}
s.push(o1); // push o1 onto the stack
}
else if (token == "(") { // if token is left parenthesis
s.push(token); // then push it onto the stack
}
else if (token == ")") { // if token is right parenthesis
while (s.peek() != "("){ // until token at top is (
postfix += s.pop() + " ";
}
s.pop(); // pop (, but not onto the output queue
}
}
while (s.length()>0){
postfix += s.pop() + " ";
}
print(postfix);

View file

@ -1,51 +1,49 @@
use 5.010;
use strict;
use warnings;
my %prec = (
'^' => 4,
'*' => 3,
'/' => 3,
'+' => 2,
'-' => 2,
'(' => 1);
'^' => 4,
'*' => 3,
'/' => 3,
'+' => 2,
'-' => 2,
'(' => 1
);
my %assoc = (
'^' => 'right',
'*' => 'left',
'/' => 'left',
'+' => 'left',
'-' => 'left');
'^' => 'right',
'*' => 'left',
'/' => 'left',
'+' => 'left',
'-' => 'left'
);
sub shunting_yard {
my @inp = split ' ', $_[0];
my @ops;
my @res;
my @inp = split ' ', $_[0];
my @ops;
my @res;
my $report = sub { printf "%25s %-7s %10s %s\n", "@res", "@ops", $_[0], "@inp" };
my $shift = sub { $report->( "shift @_"); push @ops, @_ };
my $reduce = sub { $report->("reduce @_"); push @res, @_ };
my $report = sub { printf "%25s %-7s %10s %s\n", "@res", "@ops", $_[0], "@inp" };
my $shift = sub { $report->("shift @_"); push @ops, @_ };
my $reduce = sub { $report->("reduce @_"); push @res, @_ };
while( @inp ) {
given( shift @inp ) {
when ( /\d/ ) { $reduce->($_) }
when ( '(' ) { $shift->($_) }
when ( ')' ) { while( @ops and "(" ne (my $x = pop @ops) ) { $reduce->( $x ) } }
default {
my $newprec = $prec{$_};
while( @ops ) {
my $oldprec = $prec{$ops[-1]};
last if $newprec > $oldprec;
last if $newprec == $oldprec and $assoc{$_} eq 'right';
$reduce->( pop @ops );
}
$shift->( $_ );
}
}
}
while (@inp) {
my $token = shift @inp;
if ( $token =~ /\d/ ) { $reduce->($token) }
elsif ( $token eq '(' ) { $shift->($token) }
elsif ( $token eq ')' ) {
while ( @ops and "(" ne ( my $x = pop @ops ) ) { $reduce->($x) }
} else {
my $newprec = $prec{$token};
while (@ops) {
my $oldprec = $prec{ $ops[-1] };
last if $newprec > $oldprec;
last if $newprec == $oldprec and $assoc{$token} eq 'right';
$reduce->( pop @ops );
}
$shift->($token);
}
}
$reduce->( pop @ops ) while @ops;
@res;
}
local $, = " ";
say shunting_yard '3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3' ;
print shunting_yard '3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3';

View file

@ -0,0 +1,110 @@
Option Explicit
Option Base 1
Function ShuntingYard(strInfix As String) As String
Dim i As Long, j As Long, token As String, tokenArray() As String
Dim stack() As Variant, queue() As Variant, discard As String
Dim op1 As String, op2 As String
Debug.Print strInfix
' Get tokens
tokenArray = Split(strInfix)
' Initialize array (removed later)
ReDim stack(1)
ReDim queue(1)
' Loop over tokens
Do While 1
i = i + 1
If i - 1 > UBound(tokenArray) Then
Exit Do
Else
token = tokenArray(i - 1) 'i-1 due to Split returning a Base 0
End If
If token = "" Then: Exit Do
' Print
Debug.Print i, token, Join(stack, ","), Join(queue, ",")
' If-loop over tokens (either brackets, operators, or numbers)
If token = "(" Then
stack = push(token, stack)
ElseIf token = ")" Then
While Peek(stack) <> "("
queue = push(pop(stack), queue)
Wend
discard = pop(stack) 'discard "("
ElseIf isOperator(token) Then
op1 = token
Do While (isOperator(Peek(stack)))
' Debug.Print Peek(stack)
op2 = Peek(stack)
If op2 <> "^" And precedence(op1) = precedence(op2) Then
'"^" is the only right-associative operator
queue = push(pop(stack), queue)
ElseIf precedence(op1$) < precedence(op2$) Then
queue = push(pop(stack), queue)
Else
Exit Do
End If
Loop
stack = push(op1, stack)
Else 'number
'actually, wrong operator could end up here, like say %
'If the token is a number, then add it to the output queue.
queue = push(CStr(token), queue)
End If
Loop
While stack(1) <> ""
If Peek(stack) = "(" Then Debug.Print "no matching ')'": End
queue = push(pop(stack), queue)
Wend
' Print final output
ShuntingYard = Join(queue, " ")
Debug.Print "Output:"
Debug.Print ShuntingYard
End Function
'------------------------------------------
Function isOperator(op As String) As Boolean
isOperator = InStr("+-*/^", op) <> 0 And Len(op$) = 1
End Function
Function precedence(op As String) As Integer
If isOperator(op$) Then
precedence = 1 _
- (InStr("+-*/^", op$) <> 0) _
- (InStr("*/^", op$) <> 0) _
- (InStr("^", op$) <> 0)
End If
End Function
'------------------------------------------
Function push(str, stack) As Variant
Dim out() As Variant, i As Long
If Not IsEmpty(stack(1)) Then
out = stack
ReDim Preserve out(1 To UBound(stack) + 1)
out(UBound(out)) = str
Else
ReDim out(1 To 1)
out(1) = str
End If
push = out
End Function
Function pop(stack)
pop = stack(UBound(stack))
If UBound(stack) > 1 Then
ReDim Preserve stack(1 To UBound(stack) - 1)
Else
stack(1) = ""
End If
End Function
Function Peek(stack)
Peek = stack(UBound(stack))
End Function