13 svar
374 visningar
Hmowed är nöjd med hjälpen
Hmowed 63
Postad: 30 nov 2021 14:43

Infix to Postfix!

Hej! 

Jag har i uppgift att konvertera en String (expr) från infix till postfix, där (expr) har delats in i tokens som kan vara (nummer, operator och parentes "(" ")"). 

Så här har jag kommit med koden än så länge:

 

List<String> infix2Postfix(List<String> infix) {
List<String> resultPostfix = new ArrayList<>();
Deque<String> s = new ArrayDeque<>();
for (int i = 0; i < infix.size(); i++) {
String tokenValue = infix.get(i);
if ("0-9".contains(tokenValue)){
resultPostfix.add(tokenValue);
}else if (isOperator(tokenValue)){
while (!s.isEmpty() && getPrecedence(tokenValue) <= getPrecedence(s.pop()) && s.pop()!= "("){
resultPostfix.add(s.pop());
s.pop();
}
}

}

return null; //här returnerar jag null för att kunna debugga. 
}

 

 

boolean isOperator (String st) {
switch (st) {
case "^":
case "/":
case "*":
case "+":
case "-":
return true;
default:
return false;
}
}

 


int getPrecedence(String op) { //order of operations
if ("+-".contains(op)) {
return 2;
} else if ("*/".contains(op)) {
return 3;
} else if ("^".contains(op)) {
return 4;
} else {
throw new RuntimeException(OP_NOT_FOUND);
}
}

 

Har ett problem med första metoden infixTopostfix, efter att jag får tokenValue så vill jag kolla om det är ett nummer. Är det ett nummer så vill jag addera det till min Lista. Men, det verkar vara fel där (Då jag får "False" vid debuggning av if-satsen).

Vidare så har jag inte riktigt koll om resten av metod är logisk.

Laguna Online 28637
Postad: 30 nov 2021 17:20

Kan du ordna så koden blir indenterad? Då är den lättare att läsa. Använd kod-verktyget, som ser ut som {}.

Hmowed 63
Postad: 30 nov 2021 17:30 Redigerad: 30 nov 2021 20:01

Så har har jag kommit med koden. Den funkar ganska bra för några tester, men när det kommer till att behandla parenteser och fallet 432så har min kod misslyckats. bifogar tester och vad jag fått vid körning av koden.

i2p("1+10", "1 10 +");
        i2p("1+2+3", "1 2 + 3 +");
        i2p("1+2-3", "1 2 + 3 -");
        i2p("3-2-1", "3 2 - 1 -");
        i2p("1 + 2 * 3", "1 2 3 * +");
        i2p("1 / 2 + 3", "1 2 / 3 +");
        i2p("20/4/2", "20 4 / 2 /");
        i2p("4^3^2", "4 3 2 ^ ^");
        i2p("4^3*2", "4 3 ^ 2 *");
        i2p("(1+2)*3", "1 2 + 3 *");
        i2p("2^(1+1)", "2 1 1 + ^");


[1, 10, +]
true
[1, 2, +, 3, +]
true
[1, 2, +, 3, -]
true
[3, 2, -, 1, -]
true
[1, 2, 3, *, +]
true
[1, 2, /, 3, +]
true
[20, 4, /, 2, /]
true
[4, 3, ^, 2, ^]
false
[4, 3, ^, 2, *]
true
[(, 1, 2, ), 3, *, +]
false
[2, (, 1, ^, 1, ), +]
false

Process finished with exit code 0
List<String> infix2Postfix(List<String> infix) {
        List<String> resultPostfix = new ArrayList<>();
        Deque<String> s = new ArrayDeque<>();

        for (int i = 0; i < infix.size(); i++) {
            String token = infix.get(i);

            if (!isOperator(token)) {  //if token is operand.
                resultPostfix.add(token); //add to postfix list.

            }else if (isOperator(token)){  //if operator 
                while(!s.isEmpty() && getPrecedence(s.peek()) >= getPrecedence(token) && !Objects.equals(s.peek(), "(")){
                    resultPostfix.add(s.peek()); 
                    s.pop();                      
                }
                s.push(token);

            }else if (token.equals("(")){
                s.push(token);

            }else if (token.equals(")")){
                while(!s.isEmpty() && s.peek() != "("){
                    resultPostfix.add(s.peek());
                    s.pop();
                }
                s.pop();
            }
        }
        while (!s.isEmpty()){
            resultPostfix.add(s.peek()); //finally, we add left tokens to list and pop. 
            s.pop();
        }

    return resultPostfix;
    }
Laguna Online 28637
Postad: 30 nov 2021 23:15

Det här var svårare än de flesta programmeringsfrågor, men jag ska försöka lösa det.

Har du gjort algoritmen själv eller läst om den någonstans?

Hmowed 63
Postad: 30 nov 2021 23:38
Laguna skrev:

Det här var svårare än de flesta programmeringsfrågor, men jag ska försöka lösa det.

Har du gjort algoritmen själv eller läst om den någonstans?

Jag har haft en del mindre uppgifter som förberedelse inför denna uppgift. 
Har oxå kollat på den här 

https://youtu.be/vXPL6UavUeA

Laguna Online 28637
Postad: 1 dec 2021 20:23

Det verkar sunt i princip. Jag ser några tveksamheter, men de är inte relevanta för dina testfall. Men jag förstår inte hur parenteser kan hamna i utstacken, man får noggrant gå steg för steg. Har du gjort det?

Vad gäller ^ i fel ordning så får man betrakta en kommande ^ som högre prioritet än den första ^ så fungerar det.

Hmowed 63
Postad: 1 dec 2021 20:52 Redigerad: 1 dec 2021 20:54
Laguna skrev:

Det verkar sunt i princip. Jag ser några tveksamheter, men de är inte relevanta för dina testfall. Men jag förstår inte hur parenteser kan hamna i utstacken, man får noggrant gå steg för steg. Har du gjort det?

Vad gäller ^ i fel ordning så får man betrakta en kommande ^ som högre prioritet än den första ^ så fungerar det.

Yes, i slutet så tänkte jag samma vad det gäller att gå steg för steg.

Koden innehåller många if/else if, men känns lätt att begripa. Tror att man kunde använde while för att släppa if/else if satser. 

Här är koden : 

 

List<String> infix2Postfix(List<String> infix) {
        List<String> resultPostfix = new ArrayList<>();
        Deque<String> s = new ArrayDeque<>();

        for (int i = 0; i < infix.size(); i++) {
            String token = infix.get(i);

            if (token.matches("[0-9]+")) {  //if token is operand.
                resultPostfix.add(token); //add to postfix list.

            } else if (isOperator(token)) {
                if (s.isEmpty() || s.peek().equals("(")) {
                    s.push(token);
                } else if (!s.isEmpty() && (getPrecedence(token) < getPrecedence(s.peek()))) {
                    resultPostfix.add(s.pop());
                    s.push(token);
                } else if (!s.isEmpty() && (getPrecedence(token) > getPrecedence(s.peek()))) {
                    s.push(token);
                } else if (!s.isEmpty() && (getPrecedence(token) == getPrecedence(s.peek()))
                        && (getAssociativity(s.peek()) == Assoc.LEFT)) {
                    resultPostfix.add(s.pop());
                    s.push(token);
                } else if (!s.isEmpty() && (getPrecedence(token) == getPrecedence(s.peek()))
                        && (getAssociativity(s.peek()) == Assoc.RIGHT)) {
                    s.push(token);
                }
            } else if (token.equals("(")) {
                s.push(token);
            } else if (token.equals(")")) {
                if (!s.isEmpty() && !Objects.equals(s.peek(), "(")) {
                    resultPostfix.add(s.pop());
                }
                s.pop();
            }

        }
        while (!s.isEmpty()) {
            resultPostfix.add(s.pop());
        }

        return resultPostfix;
    }

Koden har passerat alla tester förutom ett, bifogar testen också:

 

 // Infix to postfix -----------------------
	
	i2p ("Infix", "Förväntat")
        
	i2p("1+10", "1 10 +");
        i2p("1+2+3", "1 2 + 3 +");
        i2p("1+2-3", "1 2 + 3 -");
        i2p("3-2-1", "3 2 - 1 -");
        i2p("1 + 2 * 3", "1 2 3 * +");
        i2p("1 / 2 + 3", "1 2 / 3 +");
        i2p("20/4/2", "20 4 / 2 /");
        i2p("4^3^2", "4 3 2 ^ ^");
        i2p("4^3*2", "4 3 ^ 2 *");
        i2p("(1+2)*3", "1 2 + 3 *");
        i2p("2^(1+1)", "2 1 1 + ^");
        i2p(" 1 ^ 1 ^ 1 ^ 1  - 1", " 1 1 ^ 1 ^ 1 ^ 1 -"); //False

Resultat när jag körde koden:

[1, 10, +]
true
[1, 2, +, 3, +]
true
[1, 2, +, 3, -]
true
[3, 2, -, 1, -]
true
[1, 2, 3, *, +]
true
[1, 2, /, 3, +]
true
[20, 4, /, 2, /]
true
[4, 3, 2, ^, ^]
true
[4, 3, ^, 2, *]
true
[1, 2, +, 3, *]
true
[2, 1, 1, +, ^]
true
[1, 1, 1, 1, ^, 1, -, ^, ^]
false

Process finished with exit code 0

koden lyckades inte med sista testet. 

Hmowed 63
Postad: 1 dec 2021 21:10
Laguna skrev:

Det verkar sunt i princip. Jag ser några tveksamheter, men de är inte relevanta för dina testfall. Men jag förstår inte hur parenteser kan hamna i utstacken, man får noggrant gå steg för steg. Har du gjort det?

Vad gäller ^ i fel ordning så får man betrakta en kommande ^ som högre prioritet än den första ^ så fungerar det.

Vad det gäller ^, Jaha. Nu fattar jag varför testet gick inte igenom.

Hmowed 63
Postad: 1 dec 2021 21:14

Nu löste det sig, tack för hjälpen. 

List<String> infix2Postfix(List<String> infix) {
        List<String> resultPostfix = new ArrayList<>();
        Deque<String> s = new ArrayDeque<>();

        for (int i = 0; i < infix.size(); i++) {
            String token = infix.get(i);

            if (token.matches("[0-9]+")) {  //if token is operand.
                resultPostfix.add(token); //add to postfix list.

            } else if (isOperator(token)) {
                if (s.isEmpty() || s.peek().equals("(")) {
                    s.push(token);
                } else if (!s.isEmpty() && (getPrecedence(token) < getPrecedence(s.peek()))) {
                    resultPostfix.add(s.pop());
                    s.push(token);
                } else if (!s.isEmpty() && (getPrecedence(token) > getPrecedence(s.peek()))) {
                    s.push(token);
                } else if (!s.isEmpty() && (getPrecedence(token) == getPrecedence(s.peek()))
                        && (getAssociativity(s.peek()) == Assoc.LEFT || token.equals(s.peek()))){
                    resultPostfix.add(s.pop());
                    s.push(token);
                } else if (!s.isEmpty() && (getPrecedence(token) == getPrecedence(s.peek()))
                        && (getAssociativity(s.peek()) == Assoc.RIGHT)) {
                    s.push(token);
                }
            } else if (token.equals("(")) {
                s.push(token);
            } else if (token.equals(")")) {
                if (!s.isEmpty() && !Objects.equals(s.peek(), "(")) {
                    resultPostfix.add(s.pop());
                }
                s.pop();
            }

        }
        while (!s.isEmpty()) {
            resultPostfix.add(s.pop());
        }

        return resultPostfix;
    }
Laguna Online 28637
Postad: 2 dec 2021 09:02

Nu har jag inte tittat så noga på det senaste, men fungerar det med parenteser i flera nivåer, t.ex. 2*(3-(4+7))?

Hmowed 63
Postad: 2 dec 2021 11:56
Laguna skrev:

Nu har jag inte tittat så noga på det senaste, men fungerar det med parenteser i flera nivåer, t.ex. 2*(3-(4+7))?

Ja, det fungerar bra. 

Calculator v 1.0. To exit input bye
> 2*(3-(4+7))
-16.0
> bye

Process finished with exit code 0
Laguna Online 28637
Postad: 2 dec 2021 19:52

Först nu upptäckte jag att du hade en till tråd om precis samma sak.

Hmowed 63
Postad: 2 dec 2021 23:04
Laguna skrev:

Först nu upptäckte jag att du hade en till tråd om precis samma sak.

Ja, försökte att radera en av de. Lyckades inte med det :).

Laguna Online 28637
Postad: 3 dec 2021 08:40

Man kan tala om det i tråden. Jag tänkte jag skulle titta mer efter eventuella buggar, men nu gör jag inte det.

Svara Avbryt
Close