So I would love an explanation on the best way to use inString() and get extract specific sections, I know how to do it, but the getting it to work is honestly luck, I rarely get it working exactly how I want it to, which makes it even worse.

So if that is possible anyone, I would greatly appreciate it. Very Happy
(note, this is a crosspost from another topic)

So basically inString finds the starting location of the first substring of a large string that matches a given substring, or 0 if the substring is not found. If you want to find repeated instances, and the last was found at position P, then you want to call the next inString() call with the optional starting position P+1. In other words:


Code:
inString(longstring,substring->P
inString(longstring,substring,P+1->P
inString(longstring,substring,P+1->P
inString(longstring,substring,P+1->P
(repeat ad infinitum)


Or better yet:


Code:
DelVar PRepeat not(P
inString(longstring,substring,P+1->P
If P:Disp "FOUND AT ",P
End
KermMartian wrote:
(note, this is a crosspost from another topic)

So basically inString finds the starting location of the first substring of a large string that matches a given substring, or 0 if the substring is not found. If you want to find repeated instances, and the last was found at position P, then you want to call the next inString() call with the optional starting position P+1. In other words:


Code:
inString(longstring,substring->P
inString(longstring,substring,P+1->P
inString(longstring,substring,P+1->P
inString(longstring,substring,P+1->P
(repeat ad infinitum)


Or better yet:


Code:
DelVar PRepeat not(P
inString(longstring,substring,P+1->P
If P:Disp "FOUND AT ",P
End



I know exactly how it works, but it is a matter of the display(the starting position and the length) especially if it isn't the first in the string.
The code I gave you will find each instance of the substring in the larger string, by changing the starting offset repeatedly, but without requiring you to use sub(). Perhaps I don't understand your question fully.
KermMartian wrote:
The code I gave you will find each instance of the substring in the larger string, by changing the starting offset repeatedly, but without requiring you to use sub(). Perhaps I don't understand your question fully.


Let's say I had a the following string:


Code:
:"KNIGHT/BLACK BELT/THIEF/RED MAGE/WHITE MAGE/BLACK MAGE/"


Now let's say I had a custom menu, just like the one I have on the title screen of FFME, take the X position of when it is selected, and use that number to decide which part of the string to extract and store to another string. The "/" are what the inString() will search for, I just can't seem to get it working every time, in fact, I have got it working once, and I can't seem to do it anymore. :/
In other words, you have :"KNIGHT/BLACK BELT/THIEF/RED MAGE/WHITE MAGE/BLACK MAGE/", you have a value for X, and X can be 0, 1, 2, 3, 4, or 5, correct? 0=KNIGHT, 1=BLACK BELT, ..., 5=BLACK MAGE? Here's how I would do it:


Code:
:{Assume X is already set}
:"KNIGHT/BLACK BELT/THIEF/RED MAGE/WHITE MAGE/BLACK MAGE/->Str0
:DelVar PWhile X
:inString(Str0,"/",P+1->P
:X-1->X
:End
:{Now P+1 is the first letter of the substring we need}
:inString(Str0,"/",P+1->Q
:{Now Q is the letter after the last letter of the substring
:sub(Str0,P+1,Q-P-1
:{Ans now holds the class name, if I did this right}


Now, a small optimization:


Code:
:{Assume X is already set}
:"KNIGHT/BLACK BELT/THIEF/RED MAGE/WHITE MAGE/BLACK MAGE/->Str0
:DelVar PWhile X
:inString(Str0,"/",P+1->P
:X-1->X
:End
:{Now P+1 is the first letter of the substring we need}
:sub(Str0,P+1,{-}P-1+inString(Str0,"/",P+1
:{Ans now holds the class name, if I did this right}

Code:
:"KNIGHT/BLACK BELT/THIEF/RED MAGE/WHITE MAGE/BLACK MAGE/->Str0
:DelVar PWhile X  //waits until X is 0
:inString(Str0,"/",P+1->P Stores the first letter to P, and goes to the next class every loop, looking for the next "/" in the string
:X-1->X decreases X by 1, and causes inString to loop through the classes until X is 0
:End
:sub(Str0,P+1,{-}P-1+inString(Str0,"/",P+1 //Finds the length of the section and sets the length


Now how would I adapt X to use 12, 32, and 52 for 3 possible classes, of course the only 3 in the string in that case.
Your explanation is more or less correct. The loop skills past (X) slashes by decreasing X by one for each slash that it passes. When the loop finishes, the P is on the character directly preceding the first string of the substring we want, so we know P+1 points to the first character that we want. We still need to find out where the end of that substring is, though, because the substrings have different lengths. We could have stored lists of start and end indices, but that's the stupid way out, so we'll do one more inString() to find the slash that terminates the substring we want, so we do an inString starting at P+1 (since we know P is a slash). Since P is a slash, and Q (aka, the result of the final substring) is a slash, the length of the string in between is Q-P-1. Voila!

For those three specific values, you could use {-}1+int(.5sqrt(X))->X. My proof:

X={12,32,52}
sqrt(X)={3.46,5.66,7.21}
0.5sqrt(X)={1.73,2.83,3.61}
int(0.5sqrt(X))={1,2,3}
{-}1+int(0.5sqrt(X))={0,1,2}
KermMartian wrote:
Your explanation is more or less correct. The loop skills past (X) slashes by decreasing X by one for each slash that it passes. When the loop finishes, the P is on the character directly preceding the first string of the substring we want, so we know P+1 points to the first character that we want. We still need to find out where the end of that substring is, though, because the substrings have different lengths. We could have stored lists of start and end indices, but that's the stupid way out, so we'll do one more inString() to find the slash that terminates the substring we want, so we do an inString starting at P+1 (since we know P is a slash). Since P is a slash, and Q (aka, the result of the final substring) is a slash, the length of the string in between is Q-P-1. Voila!


Well I was getting at that pretty much, but I was running out of time and raced to get it finished.

KermMartian wrote:

For those three specific values, you could use {-}1+int(.5sqrt(X))->X. My proof:

X={12,32,52}
sqrt(X)={3.46,5.66,7.21}
0.5sqrt(X)={1.73,2.83,3.61}
int(0.5sqrt(X))={1,2,3}
{-}1+int(0.5sqrt(X))={0,1,2}


Very nice, thank you.
My pleasure. Smile I'm sure Weregoose could find something that shaves a few bytes off that, but I'm happy enough with it. Smile Did you give that a try oncalc yet?
KermMartian wrote:
My pleasure. Smile I'm sure Weregoose could find something that shaves a few bytes off that, but I'm happy enough with it. Smile Did you give that a try oncalc yet?


I did and it works perfectly. Very Happy
Epic winsauce! I'm feeling this is one of our more productive and on-topic topics, then. While we're on the subject, are there more inString(), sub(), length(), etc questions that I could answer?
KermMartian wrote:
Epic winsauce! I'm feeling this is one of our more productive and on-topic topics, then. While we're on the subject, are there more inString(), sub(), length(), etc questions that I could answer?


Nothing off of the top of my head, it was just trying to get a code working, if I can make sure it works for any string if any size, and I remember how this works, I should be good for optimizing some Text() outputs too. Very Happy
The way I wrote that code, it will work well for any string of at least zero characters. Wink How about I give you a coding challenge or two, then? What if I asked you to take my code and make it return, instead of a single class name, a single class name plus the next one, eg "KNIGHT/BLACK BELT" for X=0? Can you then expand your code to replace the slash with a space, such as "KNIGHT BLACK BELT"? There's no particular useful application that I'm considering, but I think that would be good practice for you.
KermMartian wrote:
The way I wrote that code, it will work well for any string of at least zero characters. Wink How about I give you a coding challenge or two, then? What if I asked you to take my code and make it return, instead of a single class name, a single class name plus the next one, eg "KNIGHT/BLACK BELT" for X=0? Can you then expand your code to replace the slash with a space, such as "KNIGHT BLACK BELT"? There's no particular useful application that I'm considering, but I think that would be good practice for you.


I believe I can do that, but one question, do you mean replace the slash with a space on display, or in the string itself?
All the manipulations I was talking about were in the resultant Ans string itself. If you choose to display it as well, that's your prerogative.
KermMartian wrote:
All the manipulations I was talking about were in the resultant Ans string itself. If you choose to display it as well, that's your prerogative.


Ok, I was just curious how you meant it, that can be managed, in fact, that shouldn't be too bad to do.
Just as a general TI-BASIC-y tip, you may want to index when needed into a list; rather than searching through a 'slash' delimited string of 'words' to find the i-th 'word', having a short routine that uses inString to store the locations of those slashes into a list will yield faster code... though again, it really depends on the situation.
rthprog wrote:
Just as a general TI-BASIC-y tip, you may want to index when needed into a list; rather than searching through a 'slash' delimited string of 'words' to find the i-th 'word', having a short routine that uses inString to store the locations of those slashes into a list will yield faster code... though again, it really depends on the situation.


I did that, and I got sick of making a new list, then deleting it afterwards, which also adds on quite a few bytes to the program, which I really am trying not to do. :/
rthprog wrote:
Just as a general TI-BASIC-y tip, you may want to index when needed into a list; rather than searching through a 'slash' delimited string of 'words' to find the i-th 'word', having a short routine that uses inString to store the locations of those slashes into a list will yield faster code... though again, it really depends on the situation.
You'll notice above that I decided against that since it looked like this was a one-time-use situation, but I agree that that would be the best if this operation needed to be repeatedly performed.
  
Register to Join the Conversation
Have your own thoughts to add to this or any other topic? Want to ask a question, offer a suggestion, share your own programs and projects, upload a file to the file archives, get help with calculator and computer programming, or simply chat with like-minded coders and tech and calculator enthusiasts via the site-wide AJAX SAX widget? Registration for a free Cemetech account only takes a minute.

» Go to Registration page
Page 1 of 3
» All times are UTC - 5 Hours
 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

 

Advertisement