Advertisement
beelzebielsk

prefixToPostfix.js

Feb 21st, 2018
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // An array of arguments for each case.
  2. // Each case's arguments is also an array.
  3. /*
  4. let testCases = [
  5.     ["*34".split('')],   // 34*  
  6.     ["+1*23".split('')], // 123*+
  7.     ["+12".split('')],   // 12+  
  8.     ["+1**23/14".split('')], // 123*14/*+
  9. ]
  10. */
  11.  
  12. /* This is just some stuff I made so that I wouldn't have to use
  13.  * Hackerrank's testing. Don't worry about this testing stuff.
  14.  */
  15. let testCases = [
  16.     [
  17.         [
  18.             "*34",   // 34*  
  19.             "+1*23", // 123*+
  20.             "+12",   // 12+  
  21.             "+1**23/14", // 123*14/*+
  22.         ],
  23.     ],
  24. ]
  25.  
  26. /* This is just some stuff I made so that I wouldn't have to use
  27.  * Hackerrank's testing. Don't worry about this testing stuff.
  28.  */
  29. function testFunction(func, cases) {
  30.     let caller = args => (
  31.         { "input" : args, "output" : func.apply(null, args) }
  32.     );
  33.     return cases.map(caller);
  34. }
  35.  
  36. function isOperation(string) {
  37.     return (string === '+' ||
  38.             string === '-' ||
  39.             string === '*' ||
  40.             string === '+');
  41. }
  42.  
  43. function isNumber(string) {
  44.     return !isNaN(string);
  45. }
  46.  
  47.  
  48. /* This is the solution that worked. Much easier.
  49.  * - An empty token list is not valid. There has to be something.
  50.  * - There are operators: '*', '+', '/', '-'.
  51.  * - There are numbers, which are single digits.
  52.  * - Every operator is binary: it has two operands. Those operands are
  53.  *   valid prefix expressions.
  54.  * - A valid prefix expression is either:
  55.  *   - A number
  56.  *   - Operator expression expression.
  57.  * - Returns:
  58.  *   - a tree representing the expression parsed out from the tokens
  59.  *   - the tokens that were unparsed.
  60.  * This actually gets a lot easier when you make the function simpler
  61.  * and allow numbers to be valid parsable expressions.
  62.  *
  63.  * This function is basically a code definition of the prefix
  64.  * expression language.
  65.  */
  66. function expressionToTree(tokens) {
  67.     if (tokens.length === 0) {
  68.         throw Error("Empty token list invalid.");
  69.     }
  70.     if (isNumber(tokens[0])) {
  71.         return [tokens[0], tokens.slice(1)];
  72.     } else {
  73.         let leftChild, rightChild, tokensLeft;
  74.         let operation = tokens[0];
  75.         tokensLeft = tokens.slice(1);
  76.         [leftChild, tokensLeft] = expressionToTree(tokensLeft);
  77.         [rightChild, tokensLeft] = expressionToTree(tokensLeft);
  78.         return [[operation, leftChild, rightChild], tokensLeft];
  79.     }
  80. }
  81.  
  82. /* It's actually a very straightforward change to turn
  83.  * expressionToTree directly into a prefix-to-postfix converter:
  84.  * instead of trees, return the correct postfix expression that's
  85.  * equivalent to the prefix expression. That's what this function is,
  86.  * the return statement for the case of operations has been modified,
  87.  * and that's it.
  88.  */
  89. function prefixExpressionToPostfixExpression(tokens) {
  90.     if (tokens.length === 0) {
  91.         throw Error("Empty token list invalid.");
  92.     }
  93.     if (isNumber(tokens[0])) {
  94.         return [tokens[0], tokens.slice(1)];
  95.     } else {
  96.         let leftChild, rightChild, tokensLeft;
  97.         let operation = tokens[0];
  98.         tokensLeft = tokens.slice(1);
  99.         [leftChild, tokensLeft] =
  100.             prefixExpressionToPostfixExpression(tokensLeft);
  101.         [rightChild, tokensLeft] =
  102.             prefixExpressionToPostfixExpression(tokensLeft);
  103.         return [leftChild + rightChild + operation, tokensLeft];
  104.     }
  105. }
  106.  
  107. function prefixToPostfix(prefixes) {
  108.     return prefixes.map(prefix => (
  109.         prefixExpressionToPostfixExpression(prefix.split(''))[0]));
  110. }
  111.  
  112. testFunction(prefixToPostfix, testCases).forEach((result, index) => {
  113.     console.log(`Case ${index}:` + '-'.repeat(40));
  114.     console.log('Input:', result.input);
  115.     console.log('Output:', result.output)
  116. });
  117.  
  118. /* This was my original attempt. Much more complicated and difficult,
  119.  * and it seems this was the case because I wasn't willing to let
  120.  * numbers be valid prefix expressions. While the question might not
  121.  * give me a number, my code doesn't have to reflect that.
  122.  *
  123.  * This was an problem where the more general version was easier.
  124.  *
  125. function expressionToTree(tokens) {
  126.     let operation = tokens[0];
  127.     console.log("Original tokens:", tokens);
  128.     console.log("Token[0]:", tokens[0]);
  129.     console.log("Token[1]:", tokens[1]);
  130.     console.log("Token[2]:", tokens[2]);
  131.     console.log("Remaining Tokens:", tokens.slice(3));
  132.  
  133.     //if (tokens.length === 0) return [[], []];
  134.     if ((isOperation(tokens[0])) && isNumber(tokens[1]) && isNumber(tokens[2])) {
  135.         console.log("Left Child:", tokens[1]);
  136.         console.log("Right Child:", tokens[2]);
  137.         console.log("Remaining Tokens", tokens.slice(3));
  138.         console.log("--------------------");
  139.         return [[operation, tokens[1], tokens[2]], tokens.slice(3)];
  140.     }
  141.     else if (isOperation(tokens[0]) && isNumber(tokens[1])) {
  142.         let leftChild, remainingTokens, rightChild;
  143.         leftChild = tokens[1];
  144.         remainingTokens = tokens.slice(2);
  145.         [rightChild, remainingTokens] = expressionToTree(remainingTokens);
  146.         console.log("Left Child:", leftChild);
  147.         console.log("Right Child:", rightChild);
  148.         console.log("Remaining Tokens:", remainingTokens);
  149.         console.log("--------------------");
  150.         return [[operation, leftChild, rightChild], remainingTokens];
  151.     }
  152.     else if (isOperation(tokens[0]) && isOperation(tokens[1])) {
  153.         let leftChild, remainingTokens, rightChild;
  154.         [leftChild, remainingTokens] = expressionToTree(tokens.slice(1));
  155.         [rightChild, remainingTokens] = expressionToTree(remainingTokens);
  156.         console.log("Left Child:", leftChild);
  157.         console.log("Right Child:", rightChild);
  158.         console.log("Remaining Tokens:", remainingTokens);
  159.         console.log("--------------------");
  160.         return [[operation, leftChild, rightChild], remainingTokens];
  161.     }
  162. }
  163. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement