none
Sort(s) in Small Basic ? RRS feed

  • Question

  • Since there is no built in sort, I was looking for something simple to handle
    a small data file that would be sorted by user name. I tried the bubble sort,
    But for some reason, it does not appear to work. I would like to see better
    sort Subroutines posted if anyone has them. Thanks -

    SORTIT:
    '  "SORTING..."

    For I = ( N - 1 ) To 1

      For J = 0 To ( I - 1 )
       
        IF A[J] <= A[J+1] THEN
           X = A [J]
           A[J] = A[J+1]
           A[J+1] = X
             EndIf
              ENDFOR
            ENDFOR
    Friday, July 24, 2009 5:20 PM

Answers

  • Check the line below (as I copied it from your post above), it looks like the name starts after 9 characters (some extra spaces?):

    8708951     "Bellan"

    Modify this and the read is OK for me.  Also see the version I uploaded FHH117, where the number of spaces is not an issue - you will have to define a format precisely and be sure to stick to it!

    Now the sorting - you have:

    For I = ( N - 1 ) To 1 Step -1
      For J = 0 To ( I - 1 )
        IF A[J] > A[J+1] THEN
          X = A [J]
          A[J] = A[J+1]
          A[J+1] = X
        EndIf
      ENDFOR
    ENDFOR


    The string comparisons 'IF A[J] > A[J+1] THEN' are not happenning (I put a Sound.PlayClickAndWait() inside the if) since SB is not handling these character string comparisons - this is why I did the unicode breakdown for string sorting - slightly modified below from earlier posts to handle identical strings and to be case insensitive - I think this is your only approach with your sorting algorithm or mine.

    Also running J from 0 is wrong, since you are indexing from 1.

    Sub sort
      For i = 1 To Array.GetItemCount(data)-1
        For j = i+1 To Array.GetItemCount(data)
          iVar = Text.ConvertToLowerCase(data[i][var])
          jVar = Text.ConvertToLowerCase(data[j][var])
          iValue = 0
          jValue = 0
          char = 0
          If (iVar <> jVar) Then
            While (iValue = jValue)
              char = char+1
              iValue = Text.GetCharacterCode(Text.GetSubText(iVar,char,1))
              jValue = Text.GetCharacterCode(Text.GetSubText(jVar,char,1))
            EndWhile
            If (jValue < iValue) Then
              store = data[i]
              data [i] = data[j]
              data [j] = store
            EndIf
          EndIf
        EndFor
      EndFor
    EndSub


    • Marked as answer by LaLag Saturday, July 25, 2009 2:36 PM
    • Unmarked as answer by LaLag Saturday, July 25, 2009 4:55 PM
    • Marked as answer by LaLag Saturday, July 25, 2009 9:01 PM
    Friday, July 24, 2009 10:12 PM
    Moderator

All replies


  • For I = ( N - 1 ) To 1
     
    shoud be: For I = ( N - 1 ) To 1 step -1
    Grzesio
    Friday, July 24, 2009 5:24 PM
  • Your sort (bubble sort) is really great and fast for small arrays. For larger ones is not very effective. How large your array is (can be) ?
    Grzesio
    Friday, July 24, 2009 5:41 PM
  • There is some text array sorting in the example below.

    http://social.msdn.microsoft.com/Forums/en-US/smallbasic/thread/9043e6d9-c829-4a07-aaae-367f6085bfba

    Import reference SKR722.

    The relevant sub to sort a string array contact alphabetically using unicode character codes is sortString , the array contact is multi-dimensional using indexes and data dimensions.

    The advantage of using the first dimension of an array to store consecutive indexs 1, 2, 3 etc is that you can then loop though the array easily, accessing the elements.  If they are not indexed, then we can't loop through.

    Friday, July 24, 2009 5:50 PM
    Moderator
  • Here is a sample of the data. The sort should be on the name, not number.
    The I/P File will be around 200, never bigger than 999. CC 1-9 numeric,
    10 Blank, 11 Quote Then name and end Quote.

    427473928 "STEEL"
    397187559 "kenny"
    144972755 "dallas"
    321843818 "JOE"
    399294533 "giants"
    8708951     "Bellan"
    469940490 "reeds"
    105460956 "Biff"
    143191382 "big jay"
    80619770  "gbpcruncher"
    237338816 "BigBoy"
    33097687  "Iron"

    With the above change made to the code, it just flips the input,
    Not sorting it, but inverting the order and losing the last record.
    The above numeric field is a fixed length field.
    • Edited by LaLag Saturday, July 25, 2009 2:57 AM Correction
    Friday, July 24, 2009 5:53 PM
  • Just for demonstrating bubble sort graphically:

    ArraySize=200
    MaxNum=200
    GraphicsWindow.Show()
    GraphicsWindow.Width=ArraySize
    GraphicsWindow.Height=MaxNum
    
    
    For i=1 to ArraySize
      nums[i]=math.GetRandomNumber(MaxNum)
    EndFor
    
    For I = ( ArraySize - 1 ) To 1 Step -1
      For J = 0 To ( I - 1 )
        If nums[J] > nums[J+1] Then
          GraphicsWindow.SetPixel(j,nums[j],"white")
          GraphicsWindow.SetPixel(j+1,nums[j+1],"white")
          X=nums[J]
          nums[J]=nums[J+1]
          nums[J+1]= X
          GraphicsWindow.SetPixel(j,nums[j],"black")
          GraphicsWindow.SetPixel(j+1,nums[j+1],"black")
        EndIf
      EndFor
    EndFor
    
    
    

    Grzesio
    Friday, July 24, 2009 6:04 PM
  • If you set your arrays up as:

    data[1]["IP"] = 427473928
    data[1]["name"] = "STEEL"
    data[2]["IP"] = 397187559
    data[2]["name"] = "kenny"

    etc.

    Then modifying the sample SKR722 you can alphabetically sort on "name" using:

    var = "name"
    sortString()

    Sub sortString
      For i = 1 To Array.GetItemCount(data)-1
        For j = i+1 To Array.GetItemCount(data)
          iVar = data[i][var]
          jVar = data[j][var]
          iValue = 0
          jValue = 0
          char = 0
          While (iValue = jValue)
            char = char+1
            iValue = Text.GetCharacterCode(Text.GetSubText(iVar,char,1))
            jValue = Text.GetCharacterCode(Text.GetSubText(jVar,char,1))
          EndWhile
          If (jValue < iValue) Then
            store = data[i]
           
    data [i] = data[j]
           
    data [j] = store
          EndIf
        EndFor
      EndFor
    EndSub

    Note that indexing arrays complicates things when we add or delete entries from the array.  See SKR722 for use of the following to shuffle array indexes to be contiguous after deletion.

    i = 1
    j = 1
    While (j <= Array.GetItemCount(data))
      If (Array.ContainsIndex(data,i) = "True") Then
        data[j] = data[i]
        If (i <> j) Then
          data[i] = ""
        EndIf
        j = j+1
      EndIf
      i = i+1
    EndWhile


    Friday, July 24, 2009 6:06 PM
    Moderator
  • You don't have to hard code the data as I did in the example.  You can set up the arrays from any source such as text file or input from textwindow.

    The only requirement is that you index contiguously (1, 2, 3 etc) not (1, 4 , 3, 8).

    So you could do the following, or read from a file - if you use a file then you can also write the database to the file so other users can access it:

    While (IP <> "")
      TextWindow.WriteLine("Enter
    IP then name - blank to finish")
     
    IP = TextWindow.Read()
      If (
    IP <> "") Then
        name = TextWindow.Read()
        i = Array.GetItemCount(data)+1
        data[i]["
    IP "] = IP
        data[i]["name"] = name
      EndIf
    EndWhile
    Friday, July 24, 2009 7:03 PM
    Moderator
  • I gather IP is a 9 character number and name is any character string - this shouldn't be a problem.  The logic should be broken down into:

    1] Reading the database
    2] Processing (sorting the database)
    3] Writing the database

    Where the database is just the data stored in your array.  We have covered point 2 in this thread to some extent.

    BTW, if users are not going to edit the database file in any way (the format of the text file is not an issue) then you can directly write and read your array to the database using File.WriteContents(data) and File.ReadContents(data).  This assumes your database it created and modified by some method other than through the text file.

    If the file has some defined format, then you will have to program read and write capabilities to cover points 1 and 3 above.

    Perhaps if you work on what you have (reading and writing the database to a file) and post again with your code published if you have further questions.

    Good luck.
    Friday, July 24, 2009 7:44 PM
    Moderator
  • I got playing with this with files assuming your format posted earlier and in a file called "address.txt" in the SB executing program directory - reading, sorting and then overwriting the file with sorted data.

    Import reference FHH117, note that File operations are commented (4 of them) by the web import to SB - check these are safe then uncomments as required.
    Friday, July 24, 2009 8:40 PM
    Moderator
  • Check the line below (as I copied it from your post above), it looks like the name starts after 9 characters (some extra spaces?):

    8708951     "Bellan"

    Modify this and the read is OK for me.  Also see the version I uploaded FHH117, where the number of spaces is not an issue - you will have to define a format precisely and be sure to stick to it!

    Now the sorting - you have:

    For I = ( N - 1 ) To 1 Step -1
      For J = 0 To ( I - 1 )
        IF A[J] > A[J+1] THEN
          X = A [J]
          A[J] = A[J+1]
          A[J+1] = X
        EndIf
      ENDFOR
    ENDFOR


    The string comparisons 'IF A[J] > A[J+1] THEN' are not happenning (I put a Sound.PlayClickAndWait() inside the if) since SB is not handling these character string comparisons - this is why I did the unicode breakdown for string sorting - slightly modified below from earlier posts to handle identical strings and to be case insensitive - I think this is your only approach with your sorting algorithm or mine.

    Also running J from 0 is wrong, since you are indexing from 1.

    Sub sort
      For i = 1 To Array.GetItemCount(data)-1
        For j = i+1 To Array.GetItemCount(data)
          iVar = Text.ConvertToLowerCase(data[i][var])
          jVar = Text.ConvertToLowerCase(data[j][var])
          iValue = 0
          jValue = 0
          char = 0
          If (iVar <> jVar) Then
            While (iValue = jValue)
              char = char+1
              iValue = Text.GetCharacterCode(Text.GetSubText(iVar,char,1))
              jValue = Text.GetCharacterCode(Text.GetSubText(jVar,char,1))
            EndWhile
            If (jValue < iValue) Then
              store = data[i]
              data [i] = data[j]
              data [j] = store
            EndIf
          EndIf
        EndFor
      EndFor
    EndSub


    • Marked as answer by LaLag Saturday, July 25, 2009 2:36 PM
    • Unmarked as answer by LaLag Saturday, July 25, 2009 4:55 PM
    • Marked as answer by LaLag Saturday, July 25, 2009 9:01 PM
    Friday, July 24, 2009 10:12 PM
    Moderator
  • Obviously, I like your code a lot better than mine. I like the way you got around the fixed field.
    I have figured out how to write the file back with my spacing, so I can error check before I do anything,
    Thanks again for all your help, I have many more questions, but I have taken up way too much of your time already!

    P.S. I found I also needed the SmallBasicLibrary.dll file and Net Framework 3.5 Installed on each computer for the .exe to work!
    • Edited by LaLag Saturday, July 25, 2009 9:03 PM Found Anser about .Exe elsewhere.
    Friday, July 24, 2009 11:02 PM