CITE THIS NOTEBOOK: Solving and visualizing word problems by Wolfram Emerging Leaders Program. Wolfram Community JAN 27 2023.
The Wolfram Emerging Leaders Program is a 4-month long, project-based program designed for gifted high school students to take a deep dive into a topic of their choice. Students work remotely in small groups to take their project from ideation to completion, with the guidance of Wolfram experts. Wolfram Emerging Leaders Program participants are selected from the Wolfram High School Summer Camp, which is open to talented, STEM-oriented students age 17 and under. This essay was written by:
◼
  • Jason Chae
  • ◼
  • Sophie Chen
  • ◼
  • Maya Viswanathan
  • Abstract: In this project, we designed three functions: one that takes a simple word problem and provides an answer to it and two that return visualizations, both of the problem and of the correct answer. The goal of this project is to help elementary school children check their work on word problems and to better understand them by seeing a visualization that uses pictures to clarify how the arithmetic works. The first function figures out what operation needs to be used by searching for words that indicate the appropriate mathematical operation and looking at the order of the words in the problem. After extracting the numbers and doing the computation, the next two functions visualize the solution by displaying images of the object(s) mentioned in the problem and showing the number of objects after performing the operation.

    Introduction

    Word problems are the intersection of math and reading. Reading is necessary to translate the language of words into numbers so that a solution can be found. In 2022, just 36% of US fourth graders were proficient in math while only 33% were proficient in reading [1]. We created the function "WordProblemSolver" to help elementary-age children better understand word problems through visualizations of both the problem and the answer. Calling “WordProblemSolver” with a word problem as the input provides the user with a clear and concise breakdown of all pieces of the given sentence, including a visualization that uses images and labels derived from Wolfram Mathematica GrammarRules that match the objects in the given sentence.

    basicMath

    To start we looked at the steps involved in solving word problems of the type “1 plus 1,” that only have two numbers. From this type of problem we derived a framework to extract the necessary information from a word problem to solve it.
    We created a list of synonyms of the word “plus” to determine if a problem was an addition problem. We also created synonym lists for subtraction and multiplication and manually edited those to only include relevant words or phrases.
    List of plus words and an association directing each plus word to a plus sign, “+“:
    In[]:=
    plus = Synonyms["plus"];​​plus1 = DeleteDuplicates[Flatten[Table[Synonyms[word],{word,plus}]]];​​plusWords = DeleteDuplicates[Flatten[Table[Synonyms[word],{word,plus1}]]];​​plusses=Table["+",Length[plusWords]];​​poperations=AssociationThread[plusWords, plusses];
    List of multiplication words and association of words to multiplication signs, “*”:
    In[]:=
    multiple={"times","multiplied by","each","every","per","such"};​​ms=Table["*",Length[multiple]];​​moperations=AssociationThread[multiple,ms];
    List of subtraction words and association of words to multiplication signs, “-”:
    In[]:=
    subtraction={"minus","take away","takes away","give away","gives away","fewer than","subtract","remain","remains","lose","lost","less than","are left","rest","difference"};​​ss=Table["-",Length[subtraction]];​​soperations=AssociationThread[subtraction,ss];
    List of math words and association of words indicating operation:
    In[]:=
    mathWords=Join[plusWords,multiple,subtraction];​​operations=Join[moperations,poperations,soperations];
    Then we extracted the numbers from the problem using Interpreter’s “SemanticExpression,” which covers numbers in both numerical and word form.
    Extracts numbers for addition problem using numbers in both numerical and word form:
    In[]:=
    myProb="I have two books and five apples. I have 20 pairs of socks. How many total objects do I have?";​​myIntNums=Table[Interpreter["SemanticExpression"][num],{num,TextCases[myProb,"Number"]}]
    Out[]=
    {2,5,20}
    We extracted the operation word to get the operator symbol.
    Extracting operation word using StringCases:
    In[]:=
    myOp=StringCases[myProb," "~~#&/@mathWords~~PunctuationCharacter|" "]
    Out[]=
    { total }
    Using operations to get operator symbol:
    In[]:=
    myOperator=Table[operations[StringDrop[StringDrop[op,-1],1]],{op,myOp}]
    Out[]=
    {+}
    Then we inserted the operator symbol between the numbers and performed the calculation.
    Using Riffle to insert operator symbol:
    In[]:=
    myExp=Riffle[myIntNums,myOperator]
    Out[]=
    {2,+,5,+,20}
    Performing calculation:
    In[]:=
    ToExpression[StringJoin[Table[ToString[n],{n,myExp}]]]
    Out[]=
    27
    We combined all of these steps into the basicMath function.
    In[]:=
    basicMath[problem_String]:=​​Module[{ints=Table[Interpreter["SemanticExpression"][num],{num,TextCases[problem,"Number"]}],op=Table[operations[ToLowerCase[op]],{op,StringCases[problem,#&/@mathWords,IgnoreCaseTrue]}]},​​ToExpression[StringJoin[Table[ToString[n],{n,Riffle[ints,op]}]]]];

    WordProblemSolver[]

    Next, we decided to use a different method to solve word problems with the FixedOrder function, which is a pattern of objects in the particular order entered. For example FixedOrder[GrammarToken["String"], GrammarToken["SemanticNumber"]] will be the pattern of a string followed by a number. We used this to create a pattern for the order of words in a particular kind of word problem so we could identify the problem entered into our function. We made different FixedOrders for each of the four operations we would have our function perform. The WordProblemSolver function takes in a word problem, finds a FixedOrder that matches it, and then returns a list of the variables it gets from the problem. Following are explanations for each of the FixedOrders and the complete WordProblemSolver function.

    Addition

    First, we designed a FixedOrder for addition. We designed it to fit a problem of the form “Alice has 2 cookies and Bob has 3. How many cookies do they have altogether?” First, we created a FixedOrder[] pattern in which we added a GrammarToken[] for each type of word. We also set variables to store the words or numbers that would be needed for the calculation or the visualization.
    In[]:=
    FixedOrder[​​ (* Looks for a string and sets a variable called name1 to be equal to it. This is the name of the first person. *)​​ name1: GrammarToken["String"],​​ (* Looks for the word "has" *)​​ "has",​​ (* Looks for a number next and sets it to be equal to the variable a. This will be the first number added.*)​​ a:GrammarToken["SemanticNumber"]GrammarToken["Quantity"],​​ (* Looks for a string next and sets the variable obj1 to it. This will be the object that is being added (e.g. cookies)*)​​ ob1: GrammarToken["String"],​​ (* Looks for the word "and" *)​​ "and",​​ (* Looks for a string and sets it to be equal to the variable name2. This represents the name of the second person.*)​​ name2: GrammarToken["String"],​​ (* Looks for the word "has" *)​​ "has",​​ (* Looks for a number next and sets it to be equal to the variable b*)​​ b: GrammarToken["SemanticNumber"],​​ (* Looks for the phrase "How many" *)​​ "How many",​​ (* Looks for a string. This would be the object being counted again. *)​​ GrammarToken["String"],​​ (* Looks for the phrase "do they have" *)​​ "do they have",​​ (* Looks for the operator that signifies this is addition (e.g. altogether). The GrammarToken "Infixoperator" is defined below. *)​​ op:GrammarToken["InfixOperator"],​​ (* Looks for a string. However this is an OptionalElement so even if it doesn't find a string, it will still accept the problem as fitting the order *)​​ OptionalElement[GrammarToken["String"]]​​ (*Next, we return a list containing the two names, two numbers, and object as arguments. The next argument is the sum of the numbers, which we get by applying the operator (which we get by mapping the operator word, op, to the symbol that represents it (in this case, plus)) to the numbers a and b. Finally we return the word "addition" so that we can figure out the correct visualization to use.*)​​] :> {name1, IntegerPart[a], ob1, name2, IntegerPart[b], (op /. {"Plus" -> Plus, "Times" -> Times})[IntegerPart[a], IntegerPart[b]], "addition"};
    When, we run WordProblemSolver[] on the word problem, it will return the visualization function of the keywords in the problem.
    In[]:=
    WordProblemSolver["Alice has 2 cookies and Bob has 3. How many cookies do they have altogether?"]
    Out[]=
    {Alice,2,cookies,Bob,3,5,addition}
    We also created another FixedOrder that would work for a more general additional problem. We looked for the important words, the object, numbers, and the operator, but did not identify any other words and only used OptionalElement to accept any other words in the problem. The order of words in this FixedOrder is less specific and so it could be applied to more types of problems. However, it does not recognize the names of the people involved in the problem so the visualization for it would need to be more general and have fewer labels. We did not end up using this FixedOrder in the finished WordProblemSolver function as looking at more specific types of problems resulted in clearer visualizations.
    Creates a more general FixedOrder that looks for two numbers, and the object and an operator between them. This FixedOrder works similarly to the FixedOrder shown above:
    In[]:=
    FixedOrder[​​ OptionalElement[GrammarToken["String"]],​​ a:GrammarToken["SemanticNumber"],​​ obj: GrammarToken["String"],​​ OptionalElement[GrammarToken["String"]],​​ op:GrammarToken["InfixOperator2"],​​ OptionalElement[GrammarToken["String"]],​​ b: GrammarToken["SemanticNumber"],​​ OptionalElement[GrammarToken["String"]]​​ ] :> ​​{IntegerPart[a], obj, IntegerPart[b], (op /. {"Plus" -> Plus, "Times" -> Times, "Minus" -> Minus})[IntegerPart[a], IntegerPart[b]]};
    Running the WordProblemSolver function on a word problem that fits the second fixed order:
    This is the list that the function will return to visualizationAddSub:
    Next, we defined the “InfixOperator”, used earlier in the FixedOrder for an addition word, to be words that indicate that the problem is an addition problem such as “added to” or “altogether”. These words will be mapped to the Plus function.
    Defines InfixOperator to map words signifying addition to the Plus function.

    Multiplication

    The FixedOrder section for multiplication uses the same methodology as for addition. There are individual GrammarTokens that search for particular elements, which the program identifies and assigns to variables accordingly. With these variables, the function is able to return an answer and labels, such as the object being counted.
    When WordProblemSolver[] identifies the words related to multiplication in the word problem, it returns the words that will be needed for the visualization function.
    Example of running WordProblemSolver on a multiplication problem:
    Next, we defined the “InfixOperator” with words indicating that the problem is a multiplication problem such as “per” or “times”. Then these words are mapped to the Times function.
    Defines InfixOperator to map words signifying multiplication to the Times function.

    Subtraction

    We created three FixedOrders for subtraction because unlike addition and multiplication, order matters for subtraction.
    Subtraction question of the format: “Rachel has 17 apples . Rachel gives 9 to Sarah . How many apples does Rachel have now?”
    Subtraction question of the format: “Sarah gets 9 apples from Rachel. Rachel had 17 apples to start. How many apples does Rachel have now?”
    Subtraction question of the format: “Rachel gives 9 apples to Sarah. Rachel had 17 apples to start. How many apples does Rachel have now?”
    Next, we defined the “InfixOperator” with words indicating that the problem is a subtraction problem, such as “takes away”. Then these words are mapped to the Subtract function.
    Defines InfixOperator to map words signifying subtraction to the Subtract function.

    Division

    Next, we created a FixedOrder that would work for division problems. It is designed to work on a problem such as “26 dollars are distributed equally among 13 men. How much money will each person get?” The FixedOrder uses the same structure that was used in the other problems.
    Next, we defined the InfixOperator for division and mapped the words representing division to the Divide function.
    Define the division InfixOperator
    Running WordProblemSolver on the division problem

    Complete Function

    This is the complete WordProblemSolver function.

    Visualization

    Then we created visualizations for the problem. We used an image of the object being counted and made grids with images of that object to show how the number of the objects changed. To start we visualized the problem without the answer. Then we created a separate function to visualize and return the answer.

    Plural to Singular

    When creating visualizations of word problems, we used WebImageSearch to find an image of one instance of an object. For example, in the problem, "Rachel gives 9 apples to Sarah. Rachel had 17 apples to start. How many apples does Rachel have now?" a total of 26 individual apples need to be visualized, 17 for Rachel and 9 for Sarah, meaning that the image of only one apple will be used 26 times. We added the word “one” before the object’s name to make sure that only one instance of the object would be returned. Then we had to singularize the object’s name so that “one apple,” and not “one apples” would be searched. Initially we removed the last character from the object’s name, which only worked for cases where the object’s plural form required an “s.” Then we used WordStem, which worked for most, but not all of the cases. In the end we solved for this by using the information returned by WordData to find the object's singular form.
    Getting WordData information for “apple:”
    Adding the BaseForm option returned the singular, or base, of the object’s name:
    Then we used Part to separate the object’s singular name from the rest of the data:
    Another example of plural to singular:

    Visualizing Addition and Subtraction

    The first visualization function, visualizationAddSub, encompasses both addition and subtraction to visually represent sums and differences .
    visualizationAddSub uses the list of elements from the initial sentence as input and splits them into the objects, and their quantities:
    visualizationAddSubAnswer shows the visualization of the answer to the problem. It takes the same list as visualizationAddSub and shows the answer derived from the word problem:
    In the example below, visualizationAddSub is called with the result of the WordProblemSolver function to represent the two elements of the addition equation :
    In the example below, we run visualizationAddSubAnswer on the same problem to show the result:
    WordProblemSolver uses visualizationAddSub in subtraction equations to show the distinguished values, while also determining the order in which the operation handles them.

    Visualizing Multiplication and Division

    We created two separate functions, visualizationMult and visualizationDiv, to visualize multiplication and division respectively.
    visualizationMult takes a list as input of the first object, the number of first objects per the number of second objects, the second object, the number of second objects, and the final answer, which is the total number of first objects.
    Example of a list returned by WordProblemSolver:
    visualizationMultAnswer shows the visualization of the answer to the problem. It takes the same list as visualizationMult.
    WordProblemSolver uses visualizationMult to visualize the multiplication problem below:
    Next, we created visualization functions for division. Here, the answer and problem are opposite that of multiplication. We show dividers in the answer and not in the problem.
    Next we created visualizations for division. visualizationDiv takes in the list returned by WordProblemSolver and visualizes the total number of objects with no dividers.
    visualizationDivAnswer takes a list as input of the first objects to be divided, the number of first objects, the second object that the first objects will be divided among, the number of second objects, and the final answer, which is the number of first objects per second object.
    An example of visualizationDiv and visualizationDivAnswer being used:

    Visualization Function

    Next, we created an overall visualization function that would use the right visualization based on the last element of the list returned by WordProblemSolver which tells us whether the problem was an addition, multiplication, subtraction, or division problem. The Which[] function allows us to test what the last word is and then return the right visualizations accordingly.
    We used the TabView[] function to create two buttons where one would show the problem visualization and the second would show the answer visualization. This allows kids to first see the visualization of the problem and solve it themselves instead of getting the answer immediately.
    Overall visualization function:
    Here are examples of using the visualization function for problems with all types of operations.

    Website

    Finally, we used CloudDeploy[] to create a website where we could enter a problem and get the answer and visualizations. In order to speed things up in the cloud, we used a stock image for the visualizations instead of finding specific images for the problem online.

    Conclusion

    We created a function that can figure out what kind of problem a simple word problem is in order to use the right operation to solve the problem. We also created functions to visualize the problem before and after it was solved, using images of the objects mentioned in the problem to clarify how to get the answer.

    Future Work

    We would like to expand our project to solve more complicated types of problems. For example, we would like to try working on solving problems with more than two numbers, such as those where three numbers need to be added. We would also like to work on problems that have multiple different operations instead of just one operation, for example problems that involve both addition and subtraction. Additionally, we would like to work on expanding the lists of words that correspond to each operation instead of just using the few most commonly used ones. All of this would help bring us closer to being able to solve any word problem.

    Acknowledgements

    Thank you to our mentor Rory Foulger for all their suggestions and help with this project! Thank you as well to Jeremy Stratton-Smith for introducing us to this problem during Wolfram High School Summer camp and showing us how to use FixedOrder and GrammarRules!

    References

    [1] https://www.nytimes.com/2022/10/24/us/math-reading-scores-pandemic.html?smid=nytcore-ios-share&referringSource=articleShare​
    ​
    ​https://www.wolframcloud.com/env/summer/Portal2022/Data/ExternalSpeakers/2022SummerCamp-jeremy.nb