How do I math and get result for each text line?

0 favourites
  • 14 posts
From the Asset Store
Change delay, create new lines, "backspace" the text
  • Hey guys i use a text (Text1) with details...


    Example 1





    So i want to use a button and another text (Text2) to calculate and give me the result for each line above.

    So when i hit "Result" button to have this:




    Any help?


    Example 2


    Text 1:




    Text 2:





    Example 3


    Text 1:




    Text 2:





  • I think you'll need to parse the equation using nested tokenat expressions for each operator... Not sure if there is a better way to do it. Also not sure how to break out parentheses.

  • I know that need to use tokenat, something... but don't know the right code. :)

  • You would only need to parse the questions if you are letting the user create questions. if you are supplying the questions, then you can just as easily supply the answers:

    QuestionText = "5+5|2+1|3+3|4-2|3*2|10/5"

    AnswerText = "10|3|6|2|6|2"

    r = int(Random(6))

    quest = tokenAt(QuestionText,r,"|")

    ans = tokenAt(AnswerText,r,"|")

  • Thank you for your reply, but I don't want to use any auto-answer.

  • are the user's providing the questions? or is it random? how are you going to avoid duplicate questions? How complex will the questions get?

    the next thing I would try is to randomly pick the numbers and the sign (+ - / *) (unless that is chosen by the player). Then you can construct the question text and calculate the answer.

  • Look this is not about question-answer game.

    I give some results like the examples.

    Lets say in our example this is manually.

    So basically i care to calculate each line of text of whatever number i have each time.

    No any random or any different way.

    Each time, read from line 0 until the last line of Text 1.

    2 texts only.

    Text 1 is for the numbers

    and Text 2 is for result for each line of Text 1.

    Whatever way, on start of layout with a for system, a button, whatever.

    Hope to make sense now. Thanks!

  • By the sounds of it you just want an app that can give your the answers to general mathematical expressions. There's a lot of subtleties to consider here, while it may seem simple it isn't. A general purpose solution to this problem involves multiple complicated steps that humans do unconsciously:

    1. Turn a list of characters into a list of words (Scan)
    2. Turn a list of words into a tree representing the expression (Parse)
    3. Calculate each branch of the tree recursively until you get the result (Interpret)

    For example:

    1. 1,2, ,+, ,4, ,*, ,2
    2. 12,+,4,*,2
    3. (add 12 (multiply 4 2)) = (add 12 8) = 20

    This area of programming is referred to as expression parsing, and while it's not the hardest thing it's quite theory heavy. I do remember somebody producing an expression parser using the eventsheet system awhile back, it was quite complicated...

    There are 2 "cheats" solutions to this. The first is to have 2 text inputs for values, and a dropdown with a list of operators that a user can select. While it obviously doesn't match up to your examples it is very simple to implement. The second is to just evaluate each line of text as JavaScript, this is also super simple but allows your users to run arbitrary code. You could run a quick check over each letter and only evaluate it if it matches safe characters ( 0-9, +, -, /, * ).

    For an intermediate solution you could create something that does the Scan, Parse and Interpret steps but uses a simpler format such as reverse polish(RP) notation 2 4 * 12 + or S-expressions (add 12 (multiply 2 4)). RP is the easiest as it is linear, not recursive, but is confusing for most people to write. S-expressions are easier to write but again aren't what people are used to writing. Both bypass the issue of operator precedence ( is 12 + 4 * 2 the same as (12 + 4) * 2 or 12 + (4 * 2) ) which is one of the more complicated issues around parsing.

    For an advanced solution I would recommend reading up on Recursive Descent parsers or Pratt parsers.

  • Thank you for your help! :)

  • Parsing is a matter of converting text to a list of tokens, and verifying there were no syntax errors. Actually I've found the error checking to be the more involved part.

    Anyways here's my two cents on top of what has been mentioned. I'd go this route:

    1. Convert text to a list of tokens. Basically numbers and operators (+-*/).

    2. Convert the list of tokens from infix notation to reverse polish notation (RPN) using:

    That will eliminate the parenthesis and make it much simpler to calculate the result. An expression tree is another option but the code to do so in Construct will be more involved.

    3. Evaluate the RPN expression to get the result.

    Here's the current way I've gone about it. 61 fairly organized events although I can see shaving that down further. Handles decimal numbers, the five math operations (+-*/^), parenthesis and negation.

    Older stuff:

    106 events. Same capabilities as the one above. The approach is fairly different. Error checking is done by looking at neighboring tokens to see if it makes sense.

    70 events with a similar error checking method. Doesn't have ^ but it lets you write expressions like you do on paper with some variables. ex: 2(3), 4x+5y, etc...

    You can also just use the browser.execjs() expression to evaluate the expression. The main disadvantage of that is the user can run any js with it. Not really an ideal situation. You could use a complicated regex expression to verify it only contains stuff you want, or maybe there's other approaches. The second disadvantage is you lose the ability to show good error messages if a bad expression is written.

  • R0J0hound

    Thanks a lot my friend!!! :)

  • I've looked at the shunting yard algorithm in the past, but never actually implemented it. Most of the stuff I've looked at has been for generating ASTs for programming languages, which it isn't suited for. While the algorithms are quite different conceptually it's similar to how pratt parsing deals with precedence, but using explicit stacks instead of the call-stack.

    When working with recursive descent and a mathematical expression you don't really need to create the tree nodes, you can just evaluate each node as you reach it and return the value instead. Avoids the type limitations in construct.

  • I agree, the shunting yard algorithm, and reverse polish notation wouldn't be suitable for anything beyond expressions. I've found recursive decent to be awkward and abstract when dealing with precedence, could be just me though. I'm not sure what class of parser I currently utilize falls under but if I wanted to generate a ast I've used the following which I'll drop for reference. It looks similar to the shunting yard algo.

    There are pros and cons to different methods for sure. A lot comes down to personal preference. The method I used seems to make it fairly easy to change up the syntax rules and add stuff. Here i added some math functions and 2d vector types to the expression. Along with type checking, but the error messages could be nicer.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • It's not just you, I totally agree about standard recursive descent. The way that precedence is decided by the control flow makes it feel quite inflexible, and you have to read a lot of code to actually understand the operator ordering.

    I've got a couple of personal projects on the go involving Pratt parsers, which are a variant on the operator precedence parser you link. The first being a JS parser written in JS and the second being a language prototype called Radiance(private repo. ATM) that compiles to JS.

    This is basically the core part of the Pratt parser logic...

    function parse (tokens, precedence) {
    	let next_token = tokens.lookahead();
    	let parselet = prefix_parselets.get(next_token);
    	if (parselet == null) {
    		throw UnexpectedToken(next_token);
    	let left = parselet.use(tokens);
    	while ( precedence < get_precedence( tokens.lookahead() ) ) {
    		let next_token = tokens.lookahead();
    		let parselet = mixfix_parselets.get(next_token);
    		left = parselet.use(left, tokens);
    	return left;

    It's quite flexible, you can do complex operators with multiple sub expression and non-standard precedence rules. Also changing the precedence is as simple as changing 1 number, which is nice.

    I find your parser experiments pretty impressive, it's obviously possible to implement such things using the event sheet but the type limitations must be pretty frustrating at times. Getting good error messages can require a fair bit of work, I think one of the most important parts is including an easy to understand location in the message. Some languages actually ascii diagrams of source code with arrows to the problem parts now... which is pretty nuts!

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)