Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Are sub-strings strings?
#11
(12-26-2025, 05:15 PM)bplus Wrote: +1 Steve for doing a real timed test.

So looks like Mem stuff doesn't cut the time down in this case, like with Circle Fill timed experiments.

Too much other stuff going on behind the scenes for the mem to be quicker in this case, with this code.  ASC is a plenty fast operator and does 10,000,000 swaps in 0.05 seconds here.  I think that's more than fast enough for all my needs, and it's certainly much simpler to write and maintain, and understand.  

Somehow it seems people tend to forget that in QB64, we can use ASC on the left hand side of the equal sign just as easily as we can on the right.  Wink
Reply
#12
Yeah, exactly—that’s why I used the word 'yet' in that post. I haven’t benchmarked it for speed yet. The ASC solution is definitely much better, no doubt about it. Whenever I see _MEM, I just think, 'Hey, you fast beast!' Well, okay, maybe not always. So, do we have a candidate for a new fast function here? Thanks for sharing. The _MEM function is crying in a corner now...  Wink


Reply
#13
It's all quite complicated. If I understand correctly, certain characters in a new string need to be rearranged. Why not do it like this?

String strWort is reversed, and strZahl is rearranged.

PS: And that's grammatically correct too: Spiessbraten. Damn!  Tongue
Code: (Select All)

'Jetzt ist es auch grammatikalisch korrekt: Spiessbraten, nicht SpiessBraten
strWortNeu = "S" + Right$(strWort, 5) + "b" + Right$(Left$(strWort, 6), 5)
Print strWortNeu

Code: (Select All)

Option _Explicit

Dim As String strWort, strWortNeu, strZahl, strZahlNeu

strWort = "Bratenspiess"
strZahl = "12345678"

Print Left$(strWort, 6)
Print Right$(strWort, 6)
Print
strWortNeu = Right$(strWort, 6) + Left$(strWort, 6)
Print strWortNeu

Print
Print strZahl
strZahlNeu = Left$(strZahl, 1) + Mid$(strZahl, 6, 1) + Mid$(strZahl, 3, 1) + Mid$(strZahl, 8, 1)
Print
Print strZahlNeu

End
Reply
#14
I totally forgot ASC can be used that way.  Cool.

- Dav

Find my programs here in Dav's QB64 Corner
Reply
#15
Yes it can be done in one-line but it is ugly because it is 5 section formula that you have to manually plug in values for the positions of the 2 chars to swap.

Code: (Select All)
T$ = "12345678"

' testing function to see if building correct swappings
t1$ = swapChar$(T$, 3, 6)
Print t1$ ' 12645378 check
t2$ = swapChar$(T$, 1, 8)
Print t2$ ' 82345671 check
t3$ = swapChar$(T$, 4, 5)
Print t3$ ' 12354678   check

' error 9 is past the length of s$
t4$ = swapChar$(T$, 4, 9)
Print t4$ ' no error just moved 4 to the end not terrible result  ! good enough

'to do this in one line   say: swap 2 and 5 as Phil had it
'T$ = Mid$(T$, 1, p1 - 1) + Mid$(T$, p2, 1) + Mid$(T$, p1 + 1, (p2 - 1) - (p1 + 1) + 1) + Mid$(T$, p1, 1) + Mid$(T$, p2 + 1)
' since p1 = 2: p2 = 5 substitute back in: 2 for p1 and 5 for p2

' OK one-liner manual substitution p1 = 2 and p2 = 5
T$ = Mid$(T$, 1, 2 - 1) + Mid$(T$, 5, 1) + Mid$(T$, 2 + 1, (5 - 1) - (2 + 1) + 1) + Mid$(T$, 2, 1) + Mid$(T$, 5 + 1)
Print T$ 'it woiked :)

'test swapChar$ function
Function swapChar$ (S$, p1, p2)
    If p1 > p2 Then Swap p1, p2 'ha!
    swapChar$ = Mid$(S$, 1, p1 - 1) + Mid$(S$, p2, 1) + Mid$(S$, p1 + 1, (p2 - 1) - (p1 + 1) + 1) + Mid$(S$, p1, 1) + Mid$(S$, p2 + 1)
End Function

Well that is too extreme of a thinker. If I were Phil, I would stick to what he had. Smile
  724  855  599  923  575  468  400  206  147  564  878  823  652  556 bxor cross forever
Reply
#16
For those that like a nice _MEM version of this, let me introduce the following little code snippet for you guys:

Code: (Select All)
$Console:Only
Dim As String a1, n1
a1 = "ABCDEFGHIJ" 'some strings we can swap
n1 = "1234567890"

Print a1, n1
SteveSwap a1, 2, n1, 2, 3
Print a1, n1

'some time testing
limit1 = 10000
limit2 = 1000

t1# = Timer
For i = 1 To limit1
For j = 1 To limit2
SteveSwap a1, 2, n1, 2, 3
Next
Next
t2# = Timer
Print Using "###.##### seconds with SteveSwap"; t2# - t1#


Sub SteveSwap (s1 As String, pos1 As Long, s2 As String, pos2 As Long, length As Long)
$Checking:Off
Static As _MEM m1, m2, m3
m1 = _Mem(_Offset(s1), Len(s1)): m2 = _Mem(_Offset(s2), Len(s2))
If m3.SIZE = 0 Then m3 = _MemNew(1000) 'note to make this large enough so it's always large enough to handle your strings
_MemCopy m1, m1.OFFSET + pos1 - 1, length To m3, m3.OFFSET
_MemCopy m2, m2.OFFSET + pos2 - 1, length To m1, m1.OFFSET + pos1 - 1
_MemCopy m3, m3.OFFSET, length To m2, m2.OFFSET + pos2 - 1
_MemFree m1
_MemFree m2
$Checking:On
End Sub

Now note that I engineered this a little different from what we had before. I figured, "Hey! Why the heck isn't this as versatile as possible for us?"

Well, NOW IT IS!!

Now we send it two strings (or one string referenced twice, if we so desire), and we sent it the positions we want swapped, *and* we send it the length we want swapped.

So in this case, my two strings are:
"ABCDEFGHIJ"
"1234567890"

And I tell it I want to swap the first string, second position with the second string, second position, for three characters. And that's what it does. The "BCD" changes places with the "234".

And it does this quickly... 10,000,000 times in 0.2 seconds on my laptop.

And how would this compare with the AscSwap?? AscSwap takes 0.05 seconds, but that's *per character*. Since this is moving 3 characters, I would assume 0.15 seconds would be as good as it would be, and probably slower due to looping overhead.

But *this* can do any length of string with the swap.... and from initial testing, it doesn't drop in performance very much. 7 characters perform the same as 3 characters, so no real increase in time required. I haven't bothered to test it with some long strings to see how much of a hit it would take with a few hundred characters being swapped from one string to another, as I just don't think I'd ever have any use for such large swaps like this.

And *YES*, you can swap the same string, if you desire. Nothing to prevent you from doing so, if you want.



Now, with all the highlights mentioned, let me add some nice "WOAH THERE SON!!" warnings.

Since this is supposed to be nice and quick, with speed and performance as its key note, I added *ZERO* error checking here. In fact, I turned $CHECKING:OFF completely. So you, as the end user, would have to make certain that the parameters you pass are within bounds, and that you're not overlapping segments. You start passing it values that don't work, it *will blow up on you*. Your computer will melt and turn into swiss cheese and when you come crying over it, I'll just laugh and say... "Well... did you read my whole post and the warning at the end of it?" Big Grin

So... don't send this bad strings, bad parameters, and such things.

And... It could *still* end up returning you false data at some point. Chances are it won't, but it *COULD*. This works with the unsafe _MEM method with variable length strings. Variable length strings *can* move in memory at any time. The actual chance however of this moving inside such a small loop, is reasonably small and inconsequential to me. I don't see why doing this type of action would trigger any sort of memory movement or whatnot, but if one were to have something on an ON TIMER event, or perhaps even a background process kick in suddenly, the strings *could* move after we took a look at where they were in memory, and then we'd be swapping data with random junk.

I don't personally *think* it's likely to happen, and I'd toss it into one of my personal programs under the assumption that it'd be safe to do so, but then again I'm not coding nuclear launch codes for the space shuttle or anything. Just be aware of the possible glitch, in case it does happen at some point for you.
Reply
#17
Just for fun, and maybe someone else already did this (I'm late tot the party)...

Code: (Select All)
Dim Shared t$
t$ = "Pete's Tremendous. Steve's Amazing.": Print t$
swapx Mid$(t$, 8, 10), Mid$(t$, 28, 7)
Print t$
Print
t$ = "My apple is green. Your tomatoe is red.": Print t$
swapx Mid$(t$, 4, 5), Mid$(t$, 25, 7)
Print t$

Sub swapx (b$, a$)
    i = Len(t$) - (InStr(t$, a$) - 1 + Len(a$))
    j = InStr(t$, b$) - 1
    k = j + Len(b$) + 1
    temp1$ = Mid$(t$, 1, j) + a$
    temp2$ = Mid$(Mid$(t$, k), 1, Len(Mid$(t$, k)) - Len(a$) - i) + b$
    t$ = temp1$ + temp2$ + Mid$(t$, Len(temp1$) + Len(temp2$) + 1)
End Sub

Like I said, just for fun, because it isn't bullet proof. Since it uses INSTR() we can thuck fings up by working with sentences that have replacement parts repeated in the sentence. In other words, INSTR() would always pick the first occurrence, even if that's not the one your wanted swapped in the sentence.

Now if you were okay with not making the sub-strings, as you called them, hard coded, you could DIM shared the variables used to determine those sub-strings and write the algorithm differently. Like I said, this was fun, because I decided to see if I could come up with anything using those hard coded values, and I sorta did.

Pete

Oh, and swap that first sentence back before Steve and I sue your ASCII!
Reply
#18
I think the old Basic fighters are really getting old!  Tongue

Code: (Select All)

'ABCDEFGHIJ und 1234567890 tauschen die Plaetze: BCD und 234
'26. Dez. 2026

Option _Explicit

Dim As String strBuchstaben, strZahlen, strTeilbuchstaben, strTeilzahlen
Dim As String strNeuBuchstaben, strNeuZahlen

strBuchstaben = "ABCDEFGHIJ"
strZahlen = "1234567890"

Print strBuchstaben
Print strZahlen

Print
strTeilbuchstaben = Mid$(strBuchstaben, 2, 3)
Print strTeilbuchstaben
strTeilzahlen = Mid$(strZahlen, 2, 3)
Print strTeilzahlen

Print
strNeuBuchstaben = Left$(strBuchstaben, 1) + strTeilzahlen + Mid$(strBuchstaben, 5)
Print strNeuBuchstaben

Print
strNeuZahlen = Left$(strZahlen, 1) + strTeilbuchstaben + Mid$(strZahlen, 5)
Print strNeuZahlen

End

[Image: Old-Basic-Kaempfer2025-12-26-234033.jpg]
Reply
#19
(12-26-2025, 10:42 PM)Kernelpanic Wrote: I think the old Basic fighters are really getting old!  Tongue

Code: (Select All)

'ABCDEFGHIJ und 1234567890 tauschen die Plaetze: BCD und 234
'26. Dez. 2026

Option _Explicit

Dim As String strBuchstaben, strZahlen, strTeilbuchstaben, strTeilzahlen
Dim As String strNeuBuchstaben, strNeuZahlen

strBuchstaben = "ABCDEFGHIJ"
strZahlen = "1234567890"

Print strBuchstaben
Print strZahlen

Print
strTeilbuchstaben = Mid$(strBuchstaben, 2, 3)
Print strTeilbuchstaben
strTeilzahlen = Mid$(strZahlen, 2, 3)
Print strTeilzahlen

Print
strNeuBuchstaben = Left$(strBuchstaben, 1) + strTeilzahlen + Mid$(strBuchstaben, 5)
Print strNeuBuchstaben

Print
strNeuZahlen = Left$(strZahlen, 1) + strTeilbuchstaben + Mid$(strZahlen, 5)
Print strNeuZahlen

End

[Image: Old-Basic-Kaempfer2025-12-26-234033.jpg]

@Kernalpanic   Sure, that works, but it works *slow*.  Run it a few thousand times and see how long it takes to separate strings and then add them back together like that.  I was showing you a nice fast way to do this (with a few careful limitations).  Using strings like this is simply inherently sloooow due to the internals and use of temp strings and string clean up and sting copying and all sorts of stuff like that going on behind the scene.  Wink
Reply
#20
Quote:@Kernalpanic   Sure, that works, but it works *slow*.  Run it a few thousand times and see how long it takes to separate strings and then add them back together like that.  I was showing you a nice fast way to do this (with a few careful limitations).  Using strings like this is simply inherently sloooow due to the internals and use of temp strings and string clean up and sting copying and all sorts of stuff like that going on behind the scene.  [Image: wink.png]
Yes, if there are more changes than one need two files, I think so and have to put them in a loop. The crucial question, however, is whether the same positions should always be swapped between the two files. For example:

1st file: Letters
2nd file: Numbers
The positions 2, 3, 4 in the letters should always be swapped with positions 6, 7, 8 in the numbers. Only then does a loop make sense. Is there using _Mem$ faster than using instructions from QB? When using _Mem$, one have to write to memory and then read it back.

But if the positions to be swapped alternate between letters and numbers, then the user has to intervene, and then one can forget about the time. - Or one need a third file from which the changing positions can be read. It's all very complicated.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Print strings with accents and special chars Ikerkaz 8 669 12-20-2025, 09:28 PM
Last Post: TempodiBasic

Forum Jump:


Users browsing this thread: