Page 4 of 4 FirstFirst 1234
Results 61 to 73 of 73

Thread: instr Count

  1. #61
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: instr Count

    Here you have something that can take a very big string and still be fast (the ones by you and penagate keep getting slower and slower with bigger strings much more easily):

    Code:
    Option Explicit
    
    Private Declare Sub RtlMoveMemory Lib "ntdll.dll" (ByRef lpvDest As Any, ByRef lpvSrc As Any, ByVal cbLen As Long)
    'Private Declare Function VarPtrArray Lib "msvbvm50.dll" Alias "VarPtr" (Var() As Any) As Long
    Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Var() As Any) As Long
    
    Private BufStrHeader(5) As Long
    Private BufFindHeader(5) As Long
    Private BufStr() As Integer
    Private BufFind() As Integer
    Private OldStr As Long
    Private OldFind As Long
    Public Sub SisicInitialize()
        BufStrHeader(0) = 1
        BufStrHeader(1) = 2
        BufStrHeader(4) = &H7FFFFFFF
        BufFindHeader(0) = 1
        BufFindHeader(1) = 2
        BufFindHeader(4) = &H7FFFFFFF
        OldStr = 0
        OldFind = 0
    End Sub
    Public Sub SisicTerminate()
        RtlMoveMemory ByVal VarPtrArray(BufStr), 0&, 4
        RtlMoveMemory ByVal VarPtrArray(BufFind), 0&, 4
    End Sub
    Public Function SisicM(pStr As Long, pFind As Long, lenStr As Long, lenFind As Long) As Long
        Dim i As Long
        Dim j As Long
        Dim k As Long
        Dim l As Long
        Dim Flag As Long
        
        If OldStr <> pStr Then
            BufStrHeader(3) = pStr
            RtlMoveMemory ByVal VarPtrArray(BufStr), VarPtr(BufStrHeader(0)), 4
            OldStr = pStr
        End If
        If OldFind <> pFind Then
            BufFindHeader(3) = pFind
            RtlMoveMemory ByVal VarPtrArray(BufFind), VarPtr(BufFindHeader(0)), 4
            OldFind = pFind
        End If
        
        If lenFind = 1 Then
            j = BufFind(0)
            For i = lenStr - 1 To 0 Step -1
                k = BufStr(i)
                If k = j Then SisicM = SisicM + 1
            Next i
        Else
            lenFind = lenFind - 1
            For i = lenStr - 1 To lenFind Step -1
                For j = lenFind To 0 Step -1
                    k = BufFind(j)
                    l = BufStr(i - (lenFind - j))
                    If Not (k = l) Then Flag = 1: Exit For
                Next j
                If Flag = 0 Then SisicM = SisicM + 1 Else Flag = 0
            Next i
        End If
    End Function

    Usage:

    VB Code:
    1. SisicInitialize
    2. Do
    3.     SisicM StrPtr(SEARCHSTRING), StrPtr(KEYWORD), Len(SEARCHSTRING), Len(KEYWORD)
    4. Loop
    5. SisicTerminate

    I haven't even done my main optimizations yet

  2. #62
    Admodistrator |2eM!x's Avatar
    Join Date
    Jan 2005
    Posts
    3,900

    Re: instr Count

    Quote Originally Posted by |2eM!x
    Why couldnt you use isntr to count the number of times a letter or word repeats? Seems the fastest to me..
    god im so retarded..i meant use Split() function..damn i wasted a whole bunch of peopls time posting that.

    Why couldnt you use SPLIT() to count the number of times a letter or word repeats? Seems the fastest to me..

  3. #63
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: instr Count

    It isn't. Split isn't of the fastest functions around. Otherwise we would use it.

  4. #64
    Admodistrator |2eM!x's Avatar
    Join Date
    Jan 2005
    Posts
    3,900

    Re: instr Count

    Okay, i just thought i was crazy smart and the only one to think of it. Nevermind then

  5. #65
    Frenzied Member yrwyddfa's Avatar
    Join Date
    Aug 2001
    Location
    England
    Posts
    1,253

    Re: instr Count

    Quote Originally Posted by Merri
    Here you have something that can take a very big string and still be fast (the ones by you and penagate keep getting slower and slower with bigger strings much more easily):

    Code:
    Option Explicit
    
    Private Declare Sub RtlMoveMemory Lib "ntdll.dll" (ByRef lpvDest As Any, ByRef lpvSrc As Any, ByVal cbLen As Long)
    'Private Declare Function VarPtrArray Lib "msvbvm50.dll" Alias "VarPtr" (Var() As Any) As Long
    Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Var() As Any) As Long
    
    Private BufStrHeader(5) As Long
    Private BufFindHeader(5) As Long
    Private BufStr() As Integer
    Private BufFind() As Integer
    Private OldStr As Long
    Private OldFind As Long
    Public Sub SisicInitialize()
        BufStrHeader(0) = 1
        BufStrHeader(1) = 2
        BufStrHeader(4) = &H7FFFFFFF
        BufFindHeader(0) = 1
        BufFindHeader(1) = 2
        BufFindHeader(4) = &H7FFFFFFF
        OldStr = 0
        OldFind = 0
    End Sub
    Public Sub SisicTerminate()
        RtlMoveMemory ByVal VarPtrArray(BufStr), 0&, 4
        RtlMoveMemory ByVal VarPtrArray(BufFind), 0&, 4
    End Sub
    Public Function SisicM(pStr As Long, pFind As Long, lenStr As Long, lenFind As Long) As Long
        Dim i As Long
        Dim j As Long
        Dim k As Long
        Dim l As Long
        Dim Flag As Long
        
        If OldStr <> pStr Then
            BufStrHeader(3) = pStr
            RtlMoveMemory ByVal VarPtrArray(BufStr), VarPtr(BufStrHeader(0)), 4
            OldStr = pStr
        End If
        If OldFind <> pFind Then
            BufFindHeader(3) = pFind
            RtlMoveMemory ByVal VarPtrArray(BufFind), VarPtr(BufFindHeader(0)), 4
            OldFind = pFind
        End If
        
        If lenFind = 1 Then
            j = BufFind(0)
            For i = lenStr - 1 To 0 Step -1
                k = BufStr(i)
                If k = j Then SisicM = SisicM + 1
            Next i
        Else
            lenFind = lenFind - 1
            For i = lenStr - 1 To lenFind Step -1
                For j = lenFind To 0 Step -1
                    k = BufFind(j)
                    l = BufStr(i - (lenFind - j))
                    If Not (k = l) Then Flag = 1: Exit For
                Next j
                If Flag = 0 Then SisicM = SisicM + 1 Else Flag = 0
            Next i
        End If
    End Function

    Usage:

    VB Code:
    1. SisicInitialize
    2. Do
    3.     SisicM StrPtr(SEARCHSTRING), StrPtr(KEYWORD), Len(SEARCHSTRING), Len(KEYWORD)
    4. Loop
    5. SisicTerminate

    I haven't even done my main optimizations yet
    I think you'll find that your algorithm (which is almost identical to penegates, and mine) has just the same linear performance problem associated with longer strings.
    "As far as the laws of mathematics refer to reality, they are not certain; and as far as they are certain, they do not refer to reality." - Albert Einstein

    It's turtles! And it's all the way down

  6. #66
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: instr Count

    No, because your versions used CopyMemory to copy the whole string in memory from place A to B. This doesn't copy anything, it just moves an array starting point to point to the string and start working from there. If you think about it: is it first faster to copy 50 MB of string data to byte array or start directly handling the 50 MB?

    The algorithm itself was almost identical because I based it on your code. I just wanted to get it working. The next step would be to apply some nice optimizations and probably try adding Boyer-Moore and a support for TextCompare.

  7. #67
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: instr Count

    Here are the "some nice optimizations". Enjoy.

    VB Code:
    1. Public Function SisicM(ByRef pStr As Long, ByRef pFind As Long, ByRef lenStr As Long, ByRef lenFind As Long) As Long
    2.     Dim lngA As Long, lngB As Long, lngC As Long
    3.     Dim intFind As Integer, intStr As Integer
    4.     Dim intFirst As Integer, intLast As Integer, lngCounter As Long, lngFlag As Long
    5.    
    6.     If OldStr <> pStr Then
    7.         BufStrHeader(3) = pStr
    8.         RtlMoveMemory ByVal VarPtrArray(BufStr), VarPtr(BufStrHeader(0)), 4
    9.         OldStr = pStr
    10.     End If
    11.     If OldFind <> pFind Then
    12.         BufFindHeader(3) = pFind
    13.         RtlMoveMemory ByVal VarPtrArray(BufFind), VarPtr(BufFindHeader(0)), 4
    14.         OldFind = pFind
    15.     End If
    16.    
    17.     If lenFind = 1 Then
    18.         intFirst = BufFind(0)
    19.         For lngA = lenStr - 1 To 0 Step -1
    20.             intStr = BufStr(lngA)
    21.             If intFirst = intStr Then lngCounter = lngCounter + 1
    22.         Next lngA
    23.     ElseIf lenFind = 2 Then
    24.         lenFind = 1
    25.         intFirst = BufFind(0)
    26.         intLast = BufFind(lenFind)
    27.         For lngA = lenStr - 1 To lenFind Step -1
    28.             intStr = BufStr(lngA)
    29.             If intLast = intStr Then
    30.                 intStr = BufStr(lngA - lenFind)
    31.                 If intFirst = intStr Then lngCounter = lngCounter + 1: lngA = lngA - lenFind
    32.             End If
    33.         Next lngA
    34.     Else
    35.         lenFind = lenFind - 1
    36.         intFirst = BufFind(0)
    37.         intLast = BufFind(lenFind)
    38.         For lngA = lenStr - 1 To lenFind Step -1
    39.             intStr = BufStr(lngA)
    40.             If intLast = intStr Then
    41.                 intStr = BufStr(lngA - lenFind)
    42.                 If intFirst = intStr Then
    43.                     lngC = lngA - 1
    44.                     For lngB = lenFind - 1 To 1 Step -1
    45.                         intFind = BufFind(lngB)
    46.                         intStr = BufStr(lngC)
    47.                         If Not (intFind = intStr) Then lngFlag = 1: Exit For
    48.                         lngC = lngC - 1
    49.                     Next lngB
    50.                     If lngFlag = 1 Then lngFlag = 0 Else lngCounter = lngCounter + 1: lngA = lngC
    51.                 End If
    52.             End If
    53.         Next lngA
    54.     End If
    55.     SisicM = lngCounter
    56. End Function

    Increases the speed remarkably with longer keywords. Didn't benchmark the difference, I only know it thanks to previous experience.


    Edit Updated variable names ... and a bug in counting two character long keywords.
    Last edited by Merri; Sep 15th, 2005 at 05:52 AM.

  8. #68
    Frenzied Member yrwyddfa's Avatar
    Join Date
    Aug 2001
    Location
    England
    Posts
    1,253

    Re: instr Count

    Hmmm. Pretty good stuff.
    I wouldn't use the Boyer-Moore algorithm, though. This is good for long strings - especially ones that have multiple searches applied.

    But for short ones which are only going to be searched once, then the creation of the distance table make the use of the algorithm inefficient.

    I suppose you could optimise further by having some sort of threshold where the Boyer-Moore would take over . . .

    (BTW - Nice touch avoiding the copy!)
    "As far as the laws of mathematics refer to reality, they are not certain; and as far as they are certain, they do not refer to reality." - Albert Einstein

    It's turtles! And it's all the way down

  9. #69
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: instr Count

    Boyer-Moore for keywords longer than four or five characters might be ok. I also made quickly a InBArrBMCount (ridiculous function name, but oh well) and it gets faster in keywords of that length.

    Edit Oh... and Boyer-Moore for TextCompare is all good starting from three characters long keywords, I guess you can figure out why.
    Last edited by Merri; Sep 15th, 2005 at 08:39 AM.

  10. #70
    Frenzied Member yrwyddfa's Avatar
    Join Date
    Aug 2001
    Location
    England
    Posts
    1,253

    Re: instr Count

    All you need to do now is to slot the algorithm into a fully inherited object hierarchy and you too can lose all of that perfomance
    "As far as the laws of mathematics refer to reality, they are not certain; and as far as they are certain, they do not refer to reality." - Albert Einstein

    It's turtles! And it's all the way down

  11. #71
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: instr Count

    Object Orientated Inheritable ASM would rock!


    ... NOT!

  12. #72
    Frenzied Member yrwyddfa's Avatar
    Join Date
    Aug 2001
    Location
    England
    Posts
    1,253

    Re: instr Count



    I think someone's already tried that. If I recall correctly they called it MSIL . . .
    "As far as the laws of mathematics refer to reality, they are not certain; and as far as they are certain, they do not refer to reality." - Albert Einstein

    It's turtles! And it's all the way down

  13. #73
    VB6, XHTML & CSS hobbyist Merri's Avatar
    Join Date
    Oct 2002
    Location
    Finland
    Posts
    6,654

    Re: instr Count

    I love power failures. They have the magical touch of striking right before you have saved the last major changes you've done. Looks like I won't work out Boyer-Moore after all, doing it the second time today would be bothersome.

Page 4 of 4 FirstFirst 1234

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width