How to replace x and y in a string with * and a integer or only an integer depending on a character

Morten Eyrich shared this question 2 years ago
Answered

I have a string - for example "2x + 3y + 4 = 0" or "x + 3y + 4 = 0".

And I would like to replace "x" and "y" with "*" and an integer (if there is an integer before it) or just an integer (if there isn't any integer before it).


I guess that I then need to first split the string into a list that contain each single character in the string.

And then get GeoGebra to check which character there is before x and y. And depending on that replace the letter with either "*" and an integer (if there is an integer before it) or just an integer (if there isn't any integer before it).

And then combine each element on the list to a string.


My question: How can I do this ?

Best Answer
photo

I have found another more simple way to do what I want:


First define these 5 variables:


T = "2x + 3y + 4"


T_{After substitution} = ""


ValueOfString__{After substitution} = 0


x_0 = 1

y_0 = 5


Create a button and write the following under its Click Script:

SetValue[ T_{After substitution}, ReplaceAll[ ReplaceAll[ T, "x", "x_0" ], "y", "y_0" ] ] ]

ParseToNumber[ ValueOfString__{After substitution}, T_{After substitution} ]


When the button click script have been run, the value of ValueOfString__{After substitution} changes to 21.

Comments (10)

photo
1

Check out Split(), ReplaceAll() and the UnicodeXXX commands


https://wiki.geogebra.org/e...

photo
1

A basic idea is to first replace any "<digit><variable>" by "<digit>*<value>", and finally replace any "<variable>" by "<value>".

The first solution attached constructs a list starting with the original string, followed by all the search strings and corresponding replacement strings. Then the Iteration command is used to work through this list, doing all the replacements one after another. The second solution does basically the same but also uses brackets when a replacement value is a negative number (see reasoning below).

The question is what syntax guarantees the original string has, and - assuming that the final string is supposed to be evaluated again be GeoGebra - whether this basic solution is sufficient to produce a string that would evaluate correctly under the given syntax guarantees. A simple example: What if there is white space between a number literal and the following x (or y)? Should the replacement also contain "*" then? Or maybe it would suffice to just add brackets if the replacement value is negative, because in (all?) other cases GeoGebra will interpret the white space as multplication anyway.

Generally, if there are only weak syntax guarantees that would require handling a lot of special cases, then I wouldn't try to accomplish the replacement with GeoGebra commands but do this in JavaScript.

photo
1

Thanks a lot.Regarding space before x or y.

That option can be avoided in two ways:

1) By creating a text object where you insert an empty box and insert the used text string variable in that and let the whole text object be in LaTex mode. And then split this string into 1-legth strings in a list.

2) Delete all space elements on the list with 1-length strings before letting GeoGebra to check the character before "x" and "y" on the 1-length string-list.

photo
1

To make it work in my own GeoGebra-applet, I need to understand your script.

Could you please explain how your nice script for "l2" and "StringReplaced2" works in detail in your "replaceXY2.ggb" ?

photo
1

strX and strY are simply the replacement strings for x and y. I used those separate string variables, so it's easier to modifiy (like the brackets for negative numbers) without having to fiddle with the definition of l1.

The list l1 is simply the string list of prefixes that require a "*" when a following "x" or "y" is substituted. Not that important to have those in an extra list (because it's just a sequence of numbers), but it allows for easy tweaking (e.g. in case there will be other prefixes who also require a "*" substitution) without having to fiddle with the details of l2.

The definition of l2 is a bit longish, but not very complicated. It creates four string lists and flattens them into one long list. The first element of l2 is just the orgininal string. The next elements come from Zip({s + "x", s + "*" + strX}, s, l1) which creates all the seach and replacement strings for "x" that contain "*". (The Zip command there lets s run through the list l1 with the relevant prefixes, and constructs the search string s+"x" and the corresponding replacement string s+"*"+strX.) The next elements are constructed the same way, just for "y". And the remaiing elemnts of l2 are the basic search and replacement strings for "x" and "y", and also a dummy at the end, which only serves to make the definition of StringReplaced2 more readible (see below). All in all, l2 looks like this

l2 = {<original string>, <search string 1>, <replacement string 1>, ..., <search string n>, <replacement string n>, <dummy string>}

where the replacements are in the order they are about to be performed later.

Now to StringReplaced2. Before diving into the details of how it works, let's quickly describe what it does. StringReplaced2 uses l2 as a starting point and iterates over it. Each iteration is a list starting a modified version of the original string (some string replacements already applied), followed by the still unused search and replacement strings and the dummy. To make a small example: If l2 were {"abcba", "a", "A", "b", "B", ""} then the first iteration would produce {"AbcbA", "b", "B", ""}, and the second (and final) iteration would produce {"ABcBA", ""}.

Now let's look at the How. To understand the syntax of the Iteration command: The third parameter (here {l2}) is the list of starting values (in this case l2 is the only starting value), the second parameter (I just named it L for "list") is the variable representing the current iteration, the first parameter is the expression describing what's done in each iteration, and it is quite simple here: ReplaceAll(Element(L, 1), Element(L, 2), Element(L, 3)) uses the 2nd and 3rd element (search and replacement string) and applies a string representation on the first element. Then Append(..., Take(L, 4)) puts the resulting string in a list and appends the list all the remaining elements of L (starting at the 4th element, i.e., all search and replacement strings that aren't applied yet). After Length(l2) / 2 - 1 iterations (4th parameter of the Iteration command) the iteration is finished, and the resulting list contains only two elements (the original string with all replacements applied, and the dummy) from which the first element is taken to get the final string.

The only purpose of the dummy string is that Take(L, 4) doesn't result in Undefined in the last iteration. It's easily doable without the dummy, e.g. by replacing Take(L, 4) by If(Length(L)>3,Take(L, 4),{}) (and adjusting the term for the number of iterations), but I opted for a bit more readability.


I hope that clears things up. Generally, Iteration is a very powerful command. Used this way, it's allows to perform operations that are easily describable in "procedural programming" but are otherwise difficult (or tedious) to describe in "functional programming".

photo
1

Thank you VERY much for your detailed explanation ! :)

photo
photo
1

you can replace x with "*" and an integer, then take from second if the first is * , then replace +* with +, then -* with -, then ** with * , etc

photo
1

I have found another more simple way to do what I want:


First define these 5 variables:


T = "2x + 3y + 4"


T_{After substitution} = ""


ValueOfString__{After substitution} = 0


x_0 = 1

y_0 = 5


Create a button and write the following under its Click Script:

SetValue[ T_{After substitution}, ReplaceAll[ ReplaceAll[ T, "x", "x_0" ], "y", "y_0" ] ] ]

ParseToNumber[ ValueOfString__{After substitution}, T_{After substitution} ]


When the button click script have been run, the value of ValueOfString__{After substitution} changes to 21.

photo
1

I think this will work too and is simpler

SetValue[ T_{After substitution}, ReplaceAll[ ReplaceAll[ T, "x", x_0+"" ], "y", y_0+"" ] ] ]

photo
photo
1

I thought you wanted "2*1+3*5+4"

for 21 you can do T = "2x + 3y + 4" , f(x,y)=x+y , parsetofunction(f,T) , f(x0,y0)

© 2023 International GeoGebra Institute