Author Topic: Top 10 Algorythm  (Read 5699 times)

0 Members and 1 Guest are viewing this topic.

Offline Dimster

  • Forum Resident
  • Posts: 500
    • View Profile
Top 10 Algorythm
« on: November 03, 2019, 11:25:30 am »
I have a very simple routine coded to get top 3 scores and names. It opens and closes the same data file multiple times. Pretty simple routine but as the data file gets larger its taking a little more time to display the results. Not that worried about it but was looking for suggestions on improving the coding. Here is a mainstay of the routine.
Code: QB64: [Select]
  1. 'SORTING FOR THE TOP 3 (INCLUDING TIES)
  2.  
  3. ' Assume a sequential data file with Name$ and Score
  4. ' Assume the file has been open as file #1
  5.     INPUT #1, Name$, Score
  6.     IF Score > HighScore1 AND Name$ <> HighName1$ THEN
  7.         HighScore1 = Score
  8.         HighName1$ = Name$
  9.     END IF
  10. 'open
  11.     INPUT #1, Name$, Score
  12.     IF Score > HighScore2 AND Score < HighScore1 THEN
  13.         HighScore2 = Score
  14.         HighName2$ = Name$
  15.     END IF
  16. 'open
  17.  
  18.     INPUT #1, Name$, Score
  19.     IF Score > HighScore3 AND Score < HighScore1 AND Score < HighScore2 THEN
  20.         HighScore3 = Score
  21.         HighName3$ = Name$
  22.     END IF
  23. 'open
  24.  
  25.     INPUT #1, Name$, Score
  26.     IF Score = HighScore1 AND Name$ <> HighName1$ THEN
  27.         HighScore2 = Score
  28.         HighName2$ = Name$
  29.     END IF
  30.     IF Score = HighScore2 AND Name$ <> HighName2$ THEN
  31.         HighScore3 = Score
  32.         HighName3$ = Name$
  33.     END IF
  34.  

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Top 10 Algorythm
« Reply #1 on: November 03, 2019, 11:43:04 am »
Wouldn’t the easiest way just be to open the file once, read the information into an array, and then toss it into a simple sorting routine?
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Petr

  • Forum Resident
  • Posts: 1720
  • The best code is the DNA of the hops.
    • View Profile
Re: Top 10 Algorythm
« Reply #2 on: November 03, 2019, 01:11:21 pm »
I also tried to write something on this topic:

Code: QB64: [Select]
  1. 'add and sort name and score to txt file: (based on principle, that score is not negative value)
  2.  
  3. file$ = "Score.txt"
  4. nfile$ = "Score2.txt"
  5. TYPE Score
  6.     N AS STRING
  7.     S AS INTEGER
  8. REDIM S(0) AS Score
  9.  
  10. INPUT "Insert name (string), score (number)"; n$, nr
  11. OPEN "i", ch, file$
  12.  
  13.     INPUT #ch, S(row).N, S(row).S
  14.     row = row + 1
  15.     REDIM _PRESERVE S(row) AS Score
  16. S(row).N = n$: S(row).S = nr 'in last position in array are new values from input
  17.  
  18. PRINT "Previous order:"
  19. FOR t = LBOUND(S) TO UBOUND(S)
  20.     PRINT S(t).N, S(t).S
  21.  
  22. PRINT "New order:"
  23.  
  24. 'search first, maximal value, then write it to new array, set it in array to mimnimal value (-9999) and again search maximum value
  25. REDIM NOrd(row) AS Score 'NOrd = New Order array
  26.  
  27. FOR complet = 0 TO row
  28.     maximum = -9999
  29.     FOR t = LBOUND(S) TO UBOUND(S)
  30.         IF maximum < S(t).S THEN maximum = S(t).S: i = t
  31.     NEXT
  32.     'we have maximal value. Write it to new array NOrd:
  33.     NOrd(complet).N = S(i).N
  34.     NOrd(complet).S = S(i).S
  35.     S(i).S = -9999
  36.  
  37. FOR t = LBOUND(nord) TO UBOUND(nord)
  38.     PRINT NOrd(t).N, NOrd(t).S
  39.  
  40. 'write sorted values to new text file:
  41. OPEN "o", ch, nfile$
  42. FOR t = LBOUND(nord) TO UBOUND(nord)
  43.     PRINT #ch, NOrd(t).N, NOrd(t).S
  44.  
« Last Edit: November 03, 2019, 01:18:10 pm by Petr »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Top 10 Algorythm
« Reply #3 on: November 03, 2019, 04:24:36 pm »
Hi Dimster

about your goal here my way to get this
Code: QB64: [Select]
  1. ' Goal:
  2. REM  to get top 3 scores and names.
  3. REM It opens and closes the same data file multiple times.
  4. REM as the data file gets larger its taking a little more time to display the results.
  5.  
  6. ' Materials:
  7. REM a text file with in sequence a name of gamer and the score got
  8.  
  9. TYPE Reco
  10.     Gname AS STRING
  11.     Score AS INTEGER
  12.  
  13. DIM top3(0 TO 3) AS Reco
  14. SCREEN _NEWIMAGE(600, 480, 32)
  15. COLOR _RGBA32(0, 127, 127, 255), _RGBA32(0, 0, 0, 255)
  16. _PRINTSTRING (10, 20), "start reading file text"
  17.  
  18. OPEN "Score.txt" FOR INPUT AS #1
  19.     INPUT #1, top3(0).Gname, top3(0).Score
  20.     ' for output during elaboration of data file
  21.     _PRINTSTRING (200, 40), top3(0).Gname + " " + STR$(top3(0).Score)
  22.     _PRINTSTRING (200, 60), top3(1).Gname + " " + STR$(top3(1).Score)
  23.     _PRINTSTRING (200, 90), top3(2).Gname + " " + STR$(top3(2).Score)
  24.     _PRINTSTRING (200, 120), top3(3).Gname + " " + STR$(top3(3).Score)
  25.     _DELAY 1
  26.     CLS
  27.     ' end of verbose output ;-)
  28.     IF top3(0).Score > top3(1).Score THEN
  29.         top3(3).Score = top3(2).Score
  30.         top3(3).Gname = top3(2).Gname
  31.         top3(2).Score = top3(1).Score
  32.         top3(2).Gname = top3(1).Gname
  33.         top3(1).Score = top3(0).Score
  34.         top3(1).Gname = top3(0).Gname
  35.     ELSEIF top3(0).Score > top3(2).Score THEN
  36.         top3(3).Score = top3(2).Score
  37.         top3(3).Gname = top3(2).Gname
  38.         top3(2).Score = top3(0).Score
  39.         top3(2).Gname = top3(0).Gname
  40.     ELSEIF top3(0).Score > top3(3).Score THEN
  41.         top3(3).Score = top3(0).Score
  42.         top3(3).Gname = top3(0).Gname
  43.     END IF
  44. _PRINTSTRING (10, 40), " Name   Score"
  45. _PRINTSTRING (10, 60), top3(1).Gname + " " + STR$(top3(1).Score)
  46. _PRINTSTRING (10, 90), top3(2).Gname + " " + STR$(top3(2).Score)
  47. _PRINTSTRING (10, 120), top3(3).Gname + " " + STR$(top3(3).Score)
  48.  
  49.  

using UDT

  [ You are not allowed to view this attachment ]  

but it is not necessary, you can use also 2 parallel arrays like here


Code: QB64: [Select]
  1. ' Goal:
  2. REM  to get top 3 scores and names.
  3. REM It opens and closes the same data file multiple times.
  4. REM as the data file gets larger its taking a little more time to display the results.
  5.  
  6. ' Materials:
  7. REM a text file with in sequence a name of gamer and the score got
  8.  
  9. CONST One = 1, Two = 2, Three = 3, Zero = 0
  10. DIM top3(Zero TO Three) AS INTEGER, top3Name(Zero TO Three) AS STRING
  11. SCREEN _NEWIMAGE(600, 480, 32)
  12. COLOR _RGBA32(0, 127, 127, 255), _RGBA32(0, 0, 0, 255)
  13. _PRINTSTRING (10, 20), "start reading file text"
  14.  
  15. OPEN "Score.txt" FOR INPUT AS #1
  16.     INPUT #1, top3Name(Zero), top3(Zero)
  17.     ' for output during elaboration of data file
  18.     _PRINTSTRING (200, 40), top3Name(Zero) + " " + STR$(top3(Zero))
  19.     _PRINTSTRING (200, 60), top3Name(One) + " " + STR$(top3(One))
  20.     _PRINTSTRING (200, 90), top3Name(Two) + " " + STR$(top3(Two))
  21.     _PRINTSTRING (200, 120), top3Name(Three) + " " + STR$(top3(Three))
  22.     _DELAY 1
  23.     CLS
  24.     ' end of verbose output ;-)
  25.     IF top3(zero0) > top3(One) THEN
  26.         top3(Three) = top3(Two)
  27.         top3Name(Three) = top3Name(Two)
  28.         top3(Two) = top3(One)
  29.         top3Name(Two) = top3Name(One)
  30.         top3(One) = top3(Zero)
  31.         top3Name(One) = top3Name(Zero)
  32.     ELSEIF top3(Zero) > top3(Two) THEN
  33.         top3(Three) = top3(Two)
  34.         top3Name(Three) = top3Name(Two)
  35.         top3(Two) = top3(Zero)
  36.         top3Name(Two) = top3Name(Zero)
  37.     ELSEIF top3(Zero) > top3(Three) THEN
  38.         top3(Three) = top3(Zero)
  39.         top3Name(Three) = top3Name(Zero)
  40.     END IF
  41. _PRINTSTRING (10, 40), " Name   Score"
  42. _PRINTSTRING (10, 60), top3Name(One) + " " + STR$(top3(One))
  43. _PRINTSTRING (10, 90), top3Name(Two) + " " + STR$(top3(Two))
  44. _PRINTSTRING (10, 120), top3Name(Three) + " " + STR$(top3(Three))
  45.  
  46.  

so reading one time the file you can make top three in one shot!

Thanks Petr for Score.txt that I have used for my example.

IMHO the method showed by Petr let you read how many records you want and extract the three top .
IMHO excellent the method suggested by Steve that let you have a list in RAM to order for any parameter do you like to use. (also for this method do you need of UBOUND for adjourning the upper limit of the array for all data of the file.
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Top 10 Algorythm
« Reply #4 on: November 03, 2019, 07:33:43 pm »
and my 2 cents from tool box, load and sort array at same time:
Code: QB64: [Select]
  1. _TITLE "Load and sort to array at same time" 'B+ 2019-10-26
  2. '2019-10-27 edited 2x with Steve's improvements thanks Steve!
  3. ' 2019-11-03 mod for name score data file
  4. TYPE dat
  5.     n AS STRING
  6.     s AS INTEGER
  7. DIM d(1 TO 100) AS dat 'dimensioned to something known to be > data lines
  8. OPEN "name_score.dat" FOR INPUT AS #1
  9. WHILE EOF(1) = 0
  10.     INPUT #1, N$, s
  11.     IF _TRIM$(N$) <> "" THEN
  12.         i = i + 1
  13.         PRINT N$, s
  14.         FOR j = 1 TO i - 1
  15.             IF s > d(j).s THEN
  16.                 FOR k = i TO j + 1 STEP -1
  17.                     d(k) = d(k - 1)
  18.                 NEXT
  19.                 EXIT FOR
  20.             END IF
  21.         NEXT
  22.         d(j).s = s: d(j).n = N$
  23.     END IF
  24. PRINT: PRINT " and sorted while loading array:"
  25. FOR j = 1 TO i
  26.     IF j < 4 THEN PRINT "Top"; j, d(j).n, d(j).s ELSE PRINT , d(j).n, d(j).s
  27.  
 [ You are not allowed to view this attachment ]  

EDIT: cut 4 lines
« Last Edit: November 03, 2019, 09:24:23 pm by bplus »

Offline Qwerkey

  • Forum Resident
  • Posts: 755
    • View Profile
Re: Top 10 Algorythm
« Reply #5 on: November 04, 2019, 04:38:10 am »
I have nothing to add on sort routines.  But the correct spelling is "algorithm" - even you peculiar Americans spell it this way(?).  It is easy to confuse the spelling because of the word "rhythm" (a six-letter word with no vowels, although of course the y is acting as the vowel).

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Top 10 Algorythm
« Reply #6 on: November 04, 2019, 06:09:39 am »
and my 2 cents from tool box, load and sort array at same time:
Code: QB64: [Select]
  1. _TITLE "Load and sort to array at same time" 'B+ 2019-10-26
  2. '2019-10-27 edited 2x with Steve's improvements thanks Steve!
  3. ' 2019-11-03 mod for name score data file
  4. TYPE dat
  5.     n AS STRING
  6.     s AS INTEGER
  7. DIM d(1 TO 100) AS dat 'dimensioned to something known to be > data lines
  8. OPEN "name_score.dat" FOR INPUT AS #1
  9. WHILE EOF(1) = 0
  10.     INPUT #1, N$, s
  11.     IF _TRIM$(N$) <> "" THEN
  12.         i = i + 1
  13.         PRINT N$, s
  14.         FOR j = 1 TO i - 1
  15.             IF s > d(j).s THEN
  16.                 FOR k = i TO j + 1 STEP -1
  17.                     d(k) = d(k - 1)
  18.                 NEXT
  19.                 EXIT FOR
  20.             END IF
  21.         NEXT
  22.         d(j).s = s: d(j).n = N$
  23.     END IF
  24. PRINT: PRINT " and sorted while loading array:"
  25. FOR j = 1 TO i
  26.     IF j < 4 THEN PRINT "Top"; j, d(j).n, d(j).s ELSE PRINT , d(j).n, d(j).s
  27.  

Here's the only reason why I don't usually advocate the "load and sort" method:

Code: QB64: [Select]
  1. CONST limit = 20000 'number of items to load and sort
  2.  
  3. DIM Array(limit) AS INTEGER
  4. DIM n(limit) AS INTEGER
  5. m = _MEM(Array())
  6. OPEN "temp.txt" FOR OUTPUT AS #1
  7. FOR i = 0 TO limit 'print a ton of entries
  8.     PRINT #1, RND * 10000
  9.  
  10.  
  11.  
  12.  
  13. OPEN "temp.txt" FOR INPUT AS #1
  14.  
  15. t## = TIMER
  16.  
  17. FOR i = 0 TO limit
  18.     INPUT #1, num
  19.     FOR j = 0 TO i - 1
  20.         IF num < n(j) THEN
  21.             FOR k = i TO j + 1 STEP -1
  22.                 n(k) = n(k - 1)
  23.             NEXT
  24.             EXIT FOR
  25.         END IF
  26.     NEXT
  27.     n(j) = num
  28. t1## = TIMER
  29.  
  30. PRINT USING "###.### seconds to load and sort together"; t1## - t##
  31.  
  32. t2## = TIMER
  33. OPEN "temp.txt" FOR INPUT AS #1
  34. FOR i = 0 TO limit
  35.     INPUT #1, Array(i)
  36. Sort m
  37. t3## = TIMER
  38. PRINT USING "###.### seconds to load and then sort"; t3## - t2##
  39.  
  40. FOR i = 0 TO limit STEP limit / 20 'and we'll print a selection of the data so we can compare results.
  41.     PRINT i, n(i), Array(i)
  42.     IF n(i) <> Array(i) THEN SLEEP
  43.  
  44.  
  45. SUB Sort (m AS _MEM)
  46.     $IF 64BIT THEN
  47.         DIM ES AS _INTEGER64, EC AS _INTEGER64
  48.     $ELSE
  49.         DIM ES AS LONG, EC AS LONG
  50.     $END IF
  51.  
  52.     IF NOT m.TYPE AND 65536 THEN EXIT SUB 'We won't work without an array
  53.     IF m.TYPE AND 1024 THEN DataType = 10
  54.     IF m.TYPE AND 1 THEN DataType = DataType + 1
  55.     IF m.TYPE AND 2 THEN DataType = DataType + 2
  56.     IF m.TYPE AND 4 THEN IF m.TYPE AND 128 THEN DataType = DataType + 4 ELSE DataType = 3
  57.     IF m.TYPE AND 8 THEN IF m.TYPE AND 128 THEN DataType = DataType + 8 ELSE DataType = 5
  58.     IF m.TYPE AND 32 THEN DataType = 6
  59.     IF m.TYPE AND 512 THEN DataType = 7
  60.  
  61.     'Convert our offset data over to something we can work with
  62.     DIM m1 AS _MEM: m1 = _MEMNEW(LEN(ES))
  63.     _MEMPUT m1, m1.OFFSET, m.ELEMENTSIZE: _MEMGET m1, m1.OFFSET, ES 'Element Size
  64.     _MEMPUT m1, m1.OFFSET, m.SIZE: _MEMGET m1, m1.OFFSET, EC 'Element Count will temporily hold the WHOLE array size
  65.     _MEMFREE m1
  66.  
  67.     EC = EC / ES - 1 'Now we take the whole element size / the size of the elements and get our actual element count.  We subtract 1 so our arrays start at 0 and not 1.
  68.     'And work with it!
  69.     DIM o AS _OFFSET, o1 AS _OFFSET, counter AS _UNSIGNED LONG
  70.  
  71.     SELECT CASE DataType
  72.         CASE 1 'BYTE
  73.             DIM temp1(-128 TO 127) AS _UNSIGNED LONG
  74.             DIM t1 AS _BYTE
  75.             i = 0
  76.             DO
  77.                 _MEMGET m, m.OFFSET + i, t1
  78.                 temp1(t1) = temp1(t1) + 1
  79.                 i = i + 1
  80.             LOOP UNTIL i > EC
  81.             i1 = -128
  82.             DO
  83.                 DO UNTIL temp1(i1) = 0
  84.                     _MEMPUT m, m.OFFSET + counter, i1 AS _BYTE
  85.                     counter = counter + 1
  86.                     temp1(i1) = temp1(i1) - 1
  87.                     IF counter > EC THEN EXIT SUB
  88.                 LOOP
  89.                 i1 = i1 + 1
  90.             LOOP UNTIL i1 > 127
  91.         CASE 2: 'INTEGER
  92.             DIM temp2(-32768 TO 32767) AS _UNSIGNED LONG
  93.             DIM t2 AS INTEGER
  94.             i = 0
  95.             DO
  96.                 _MEMGET m, m.OFFSET + i * 2, t2
  97.                 temp2(t2) = temp2(t2) + 1
  98.                 i = i + 1
  99.             LOOP UNTIL i > EC
  100.             i1 = -32768
  101.             DO
  102.                 DO UNTIL temp2(i1) = 0
  103.                     _MEMPUT m, m.OFFSET + counter * 2, i1 AS INTEGER
  104.                     counter = counter + 1
  105.                     temp2(i1) = temp2(i1) - 1
  106.                     IF counter > EC THEN EXIT SUB
  107.                 LOOP
  108.                 i1 = i1 + 1
  109.             LOOP UNTIL i1 > 32767
  110.         CASE 3 'SINGLE
  111.             DIM T3a AS SINGLE, T3b AS SINGLE
  112.             gap = EC
  113.             DO
  114.                 gap = 10 * gap \ 13
  115.                 IF gap < 1 THEN gap = 1
  116.                 i = 0
  117.                 swapped = 0
  118.                 DO
  119.                     o = m.OFFSET + i * 4
  120.                     o1 = m.OFFSET + (i + gap) * 4
  121.                     IF _MEMGET(m, o, SINGLE) > _MEMGET(m, o1, SINGLE) THEN
  122.                         _MEMGET m, o1, T3a
  123.                         _MEMGET m, o, T3b
  124.                         _MEMPUT m, o1, T3b
  125.                         _MEMPUT m, o, T3a
  126.                         swapped = -1
  127.                     END IF
  128.                     i = i + 1
  129.                 LOOP UNTIL i + gap > EC
  130.             LOOP UNTIL gap = 1 AND swapped = 0
  131.         CASE 4 'LONG
  132.             DIM T4a AS LONG, T4b AS LONG
  133.             gap = EC
  134.             DO
  135.                 gap = 10 * gap \ 13
  136.                 IF gap < 1 THEN gap = 1
  137.                 i = 0
  138.                 swapped = 0
  139.                 DO
  140.                     o = m.OFFSET + i * 4
  141.                     o1 = m.OFFSET + (i + gap) * 4
  142.                     IF _MEMGET(m, o, LONG) > _MEMGET(m, o1, LONG) THEN
  143.                         _MEMGET m, o1, T4a
  144.                         _MEMGET m, o, T4b
  145.                         _MEMPUT m, o1, T4b
  146.                         _MEMPUT m, o, T4a
  147.                         swapped = -1
  148.                     END IF
  149.                     i = i + 1
  150.                 LOOP UNTIL i + gap > EC
  151.             LOOP UNTIL gap = 1 AND swapped = 0
  152.         CASE 5 'DOUBLE
  153.             DIM T5a AS DOUBLE, T5b AS DOUBLE
  154.             gap = EC
  155.             DO
  156.                 gap = 10 * gap \ 13
  157.                 IF gap < 1 THEN gap = 1
  158.                 i = 0
  159.                 swapped = 0
  160.                 DO
  161.                     o = m.OFFSET + i * 8
  162.                     o1 = m.OFFSET + (i + gap) * 8
  163.                     IF _MEMGET(m, o, DOUBLE) > _MEMGET(m, o1, DOUBLE) THEN
  164.                         _MEMGET m, o1, T5a
  165.                         _MEMGET m, o, T5b
  166.                         _MEMPUT m, o1, T5b
  167.                         _MEMPUT m, o, T5a
  168.                         swapped = -1
  169.                     END IF
  170.                     i = i + 1
  171.                 LOOP UNTIL i + gap > EC
  172.             LOOP UNTIL gap = 1 AND swapped = 0
  173.         CASE 6 ' _FLOAT
  174.             DIM T6a AS _FLOAT, T6b AS _FLOAT
  175.             gap = EC
  176.             DO
  177.                 gap = 10 * gap \ 13
  178.                 IF gap < 1 THEN gap = 1
  179.                 i = 0
  180.                 swapped = 0
  181.                 DO
  182.                     o = m.OFFSET + i * 32
  183.                     o1 = m.OFFSET + (i + gap) * 32
  184.                     IF _MEMGET(m, o, _FLOAT) > _MEMGET(m, o1, _FLOAT) THEN
  185.                         _MEMGET m, o1, T6a
  186.                         _MEMGET m, o, T6b
  187.                         _MEMPUT m, o1, T6b
  188.                         _MEMPUT m, o, T6a
  189.                         swapped = -1
  190.                     END IF
  191.                     i = i + 1
  192.                 LOOP UNTIL i + gap > EC
  193.             LOOP UNTIL gap = 1 AND swapped = 0
  194.         CASE 7 'String
  195.             DIM T7a AS STRING, T7b AS STRING, T7c AS STRING
  196.             T7a = SPACE$(ES): T7b = SPACE$(ES): T7c = SPACE$(ES)
  197.             gap = EC
  198.             DO
  199.                 gap = INT(gap / 1.247330950103979)
  200.                 IF gap < 1 THEN gap = 1
  201.                 i = 0
  202.                 swapped = 0
  203.                 DO
  204.                     o = m.OFFSET + i * ES
  205.                     o1 = m.OFFSET + (i + gap) * ES
  206.                     _MEMGET m, o, T7a
  207.                     _MEMGET m, o1, T7b
  208.                     IF T7a > T7b THEN
  209.                         T7c = T7b
  210.                         _MEMPUT m, o1, T7a
  211.                         _MEMPUT m, o, T7c
  212.                         swapped = -1
  213.                     END IF
  214.                     i = i + 1
  215.                 LOOP UNTIL i + gap > EC
  216.             LOOP UNTIL gap = 1 AND swapped = false
  217.         CASE 8 '_INTEGER64
  218.             DIM T8a AS _INTEGER64, T8b AS _INTEGER64
  219.             gap = EC
  220.             DO
  221.                 gap = 10 * gap \ 13
  222.                 IF gap < 1 THEN gap = 1
  223.                 i = 0
  224.                 swapped = 0
  225.                 DO
  226.                     o = m.OFFSET + i * 8
  227.                     o1 = m.OFFSET + (i + gap) * 8
  228.                     IF _MEMGET(m, o, _INTEGER64) > _MEMGET(m, o1, _INTEGER64) THEN
  229.                         _MEMGET m, o1, T8a
  230.                         _MEMGET m, o, T8b
  231.                         _MEMPUT m, o1, T8b
  232.                         _MEMPUT m, o, T8a
  233.                         swapped = -1
  234.                     END IF
  235.                     i = i + 1
  236.                 LOOP UNTIL i + gap > EC
  237.             LOOP UNTIL gap = 1 AND swapped = 0
  238.         CASE 11: '_UNSIGNED _BYTE
  239.             DIM temp11(0 TO 255) AS _UNSIGNED LONG
  240.             DIM t11 AS _UNSIGNED _BYTE
  241.             i = 0
  242.             DO
  243.                 _MEMGET m, m.OFFSET + i, t11
  244.                 temp11(t11) = temp11(t11) + 1
  245.                 i = i + 1
  246.             LOOP UNTIL i > EC
  247.             i1 = 0
  248.             DO
  249.                 DO UNTIL temp11(i1) = 0
  250.                     _MEMPUT m, m.OFFSET + counter, i1 AS _UNSIGNED _BYTE
  251.                     counter = counter + 1
  252.                     temp11(i1) = temp11(i1) - 1
  253.                     IF counter > EC THEN EXIT SUB
  254.                 LOOP
  255.                 i1 = i1 + 1
  256.             LOOP UNTIL i1 > 255
  257.         CASE 12 '_UNSIGNED INTEGER
  258.             DIM temp12(0 TO 65535) AS _UNSIGNED LONG
  259.             DIM t12 AS _UNSIGNED INTEGER
  260.             i = 0
  261.             DO
  262.                 _MEMGET m, m.OFFSET + i * 2, t12
  263.                 temp12(t12) = temp12(t12) + 1
  264.                 i = i + 1
  265.             LOOP UNTIL i > EC
  266.             i1 = 0
  267.             DO
  268.                 DO UNTIL temp12(i1) = 0
  269.                     _MEMPUT m, m.OFFSET + counter * 2, i1 AS _UNSIGNED INTEGER
  270.                     counter = counter + 1
  271.                     temp12(i1) = temp12(i1) - 1
  272.                     IF counter > EC THEN EXIT SUB
  273.                 LOOP
  274.                 i1 = i1 + 1
  275.             LOOP UNTIL i1 > 65535
  276.         CASE 14 '_UNSIGNED LONG
  277.             DIM T14a AS _UNSIGNED LONG, T14b AS _UNSIGNED LONG
  278.             gap = EC
  279.             DO
  280.                 gap = 10 * gap \ 13
  281.                 IF gap < 1 THEN gap = 1
  282.                 i = 0
  283.                 swapped = 0
  284.                 DO
  285.                     o = m.OFFSET + i * 4
  286.                     o1 = m.OFFSET + (i + gap) * 4
  287.                     IF _MEMGET(m, o, _UNSIGNED LONG) > _MEMGET(m, o1, _UNSIGNED LONG) THEN
  288.                         _MEMGET m, o1, T14a
  289.                         _MEMGET m, o, T14b
  290.                         _MEMPUT m, o1, T14b
  291.                         _MEMPUT m, o, T14a
  292.                         swapped = -1
  293.                     END IF
  294.                     i = i + 1
  295.                 LOOP UNTIL i + gap > EC
  296.             LOOP UNTIL gap = 1 AND swapped = 0
  297.         CASE 18: '_UNSIGNED _INTEGER64
  298.             DIM T18a AS _UNSIGNED _INTEGER64, T18b AS _UNSIGNED _INTEGER64
  299.             gap = EC
  300.             DO
  301.                 gap = 10 * gap \ 13
  302.                 IF gap < 1 THEN gap = 1
  303.                 i = 0
  304.                 swapped = 0
  305.                 DO
  306.                     o = m.OFFSET + i * 8
  307.                     o1 = m.OFFSET + (i + gap) * 8
  308.                     IF _MEMGET(m, o, _UNSIGNED _INTEGER64) > _MEMGET(m, o1, _UNSIGNED _INTEGER64) THEN
  309.                         _MEMGET m, o1, T18a
  310.                         _MEMGET m, o, T18b
  311.                         _MEMPUT m, o1, T18b
  312.                         _MEMPUT m, o, T18a
  313.                         swapped = -1
  314.                     END IF
  315.                     i = i + 1
  316.                 LOOP UNTIL i + gap > EC
  317.             LOOP UNTIL gap = 1 AND swapped = 0
  318.     END SELECT
  319.  

Even with integer values and a fairly smallish data set (only 20,000 items), the load and sort method takes 5 seconds to run on my machine.  Loading then sorting takes about 0.6 seconds...

Now, part of the issue here is with opening the file for INPUT, which is slower than heck to process.  If we replace it with opening the file for BINARY access and using LINE INPUT and VAL, we change the times to  4.5 seconds and 0.15 seconds like so:

Code: QB64: [Select]
  1. CONST limit = 20000 'number of items to load and sort
  2.  
  3. DIM Array(limit) AS INTEGER
  4. DIM n(limit) AS INTEGER
  5. m = _MEM(Array())
  6. OPEN "temp.txt" FOR OUTPUT AS #1
  7. FOR i = 0 TO limit 'print a ton of entries
  8.     PRINT #1, RND * 10000
  9.  
  10.  
  11.  
  12.  
  13. OPEN "temp.txt" FOR BINARY AS #1
  14.  
  15. t## = TIMER
  16.  
  17. FOR i = 0 TO limit
  18.     LINE INPUT #1, temp$
  19.     num = VAL(temp$)
  20.     FOR j = 0 TO i - 1
  21.         IF num < n(j) THEN
  22.             FOR k = i TO j + 1 STEP -1
  23.                 n(k) = n(k - 1)
  24.             NEXT
  25.             EXIT FOR
  26.         END IF
  27.     NEXT
  28.     n(j) = num
  29. t1## = TIMER
  30.  
  31. PRINT USING "###.### seconds to load and sort together"; t1## - t##
  32.  
  33. t2## = TIMER
  34. OPEN "temp.txt" FOR BINARY AS #1
  35. FOR i = 0 TO limit
  36.     LINE INPUT #1, temp$
  37.     Array(i) = VAL(temp$)
  38. Sort m
  39. t3## = TIMER
  40. PRINT USING "###.### seconds to load and then sort"; t3## - t2##
  41.  
  42. FOR i = 0 TO limit STEP limit / 20 'and we'll print a selection of the data so we can compare results.
  43.     PRINT i, n(i), Array(i)
  44.     IF n(i) <> Array(i) THEN SLEEP
  45.  
  46.  
  47. SUB Sort (m AS _MEM)
  48.     $IF 64BIT THEN
  49.         DIM ES AS _INTEGER64, EC AS _INTEGER64
  50.     $ELSE
  51.         DIM ES AS LONG, EC AS LONG
  52.     $END IF
  53.  
  54.     IF NOT m.TYPE AND 65536 THEN EXIT SUB 'We won't work without an array
  55.     IF m.TYPE AND 1024 THEN DataType = 10
  56.     IF m.TYPE AND 1 THEN DataType = DataType + 1
  57.     IF m.TYPE AND 2 THEN DataType = DataType + 2
  58.     IF m.TYPE AND 4 THEN IF m.TYPE AND 128 THEN DataType = DataType + 4 ELSE DataType = 3
  59.     IF m.TYPE AND 8 THEN IF m.TYPE AND 128 THEN DataType = DataType + 8 ELSE DataType = 5
  60.     IF m.TYPE AND 32 THEN DataType = 6
  61.     IF m.TYPE AND 512 THEN DataType = 7
  62.  
  63.     'Convert our offset data over to something we can work with
  64.     DIM m1 AS _MEM: m1 = _MEMNEW(LEN(ES))
  65.     _MEMPUT m1, m1.OFFSET, m.ELEMENTSIZE: _MEMGET m1, m1.OFFSET, ES 'Element Size
  66.     _MEMPUT m1, m1.OFFSET, m.SIZE: _MEMGET m1, m1.OFFSET, EC 'Element Count will temporily hold the WHOLE array size
  67.     _MEMFREE m1
  68.  
  69.     EC = EC / ES - 1 'Now we take the whole element size / the size of the elements and get our actual element count.  We subtract 1 so our arrays start at 0 and not 1.
  70.     'And work with it!
  71.     DIM o AS _OFFSET, o1 AS _OFFSET, counter AS _UNSIGNED LONG
  72.  
  73.     SELECT CASE DataType
  74.         CASE 1 'BYTE
  75.             DIM temp1(-128 TO 127) AS _UNSIGNED LONG
  76.             DIM t1 AS _BYTE
  77.             i = 0
  78.             DO
  79.                 _MEMGET m, m.OFFSET + i, t1
  80.                 temp1(t1) = temp1(t1) + 1
  81.                 i = i + 1
  82.             LOOP UNTIL i > EC
  83.             i1 = -128
  84.             DO
  85.                 DO UNTIL temp1(i1) = 0
  86.                     _MEMPUT m, m.OFFSET + counter, i1 AS _BYTE
  87.                     counter = counter + 1
  88.                     temp1(i1) = temp1(i1) - 1
  89.                     IF counter > EC THEN EXIT SUB
  90.                 LOOP
  91.                 i1 = i1 + 1
  92.             LOOP UNTIL i1 > 127
  93.         CASE 2: 'INTEGER
  94.             DIM temp2(-32768 TO 32767) AS _UNSIGNED LONG
  95.             DIM t2 AS INTEGER
  96.             i = 0
  97.             DO
  98.                 _MEMGET m, m.OFFSET + i * 2, t2
  99.                 temp2(t2) = temp2(t2) + 1
  100.                 i = i + 1
  101.             LOOP UNTIL i > EC
  102.             i1 = -32768
  103.             DO
  104.                 DO UNTIL temp2(i1) = 0
  105.                     _MEMPUT m, m.OFFSET + counter * 2, i1 AS INTEGER
  106.                     counter = counter + 1
  107.                     temp2(i1) = temp2(i1) - 1
  108.                     IF counter > EC THEN EXIT SUB
  109.                 LOOP
  110.                 i1 = i1 + 1
  111.             LOOP UNTIL i1 > 32767
  112.         CASE 3 'SINGLE
  113.             DIM T3a AS SINGLE, T3b AS SINGLE
  114.             gap = EC
  115.             DO
  116.                 gap = 10 * gap \ 13
  117.                 IF gap < 1 THEN gap = 1
  118.                 i = 0
  119.                 swapped = 0
  120.                 DO
  121.                     o = m.OFFSET + i * 4
  122.                     o1 = m.OFFSET + (i + gap) * 4
  123.                     IF _MEMGET(m, o, SINGLE) > _MEMGET(m, o1, SINGLE) THEN
  124.                         _MEMGET m, o1, T3a
  125.                         _MEMGET m, o, T3b
  126.                         _MEMPUT m, o1, T3b
  127.                         _MEMPUT m, o, T3a
  128.                         swapped = -1
  129.                     END IF
  130.                     i = i + 1
  131.                 LOOP UNTIL i + gap > EC
  132.             LOOP UNTIL gap = 1 AND swapped = 0
  133.         CASE 4 'LONG
  134.             DIM T4a AS LONG, T4b AS LONG
  135.             gap = EC
  136.             DO
  137.                 gap = 10 * gap \ 13
  138.                 IF gap < 1 THEN gap = 1
  139.                 i = 0
  140.                 swapped = 0
  141.                 DO
  142.                     o = m.OFFSET + i * 4
  143.                     o1 = m.OFFSET + (i + gap) * 4
  144.                     IF _MEMGET(m, o, LONG) > _MEMGET(m, o1, LONG) THEN
  145.                         _MEMGET m, o1, T4a
  146.                         _MEMGET m, o, T4b
  147.                         _MEMPUT m, o1, T4b
  148.                         _MEMPUT m, o, T4a
  149.                         swapped = -1
  150.                     END IF
  151.                     i = i + 1
  152.                 LOOP UNTIL i + gap > EC
  153.             LOOP UNTIL gap = 1 AND swapped = 0
  154.         CASE 5 'DOUBLE
  155.             DIM T5a AS DOUBLE, T5b AS DOUBLE
  156.             gap = EC
  157.             DO
  158.                 gap = 10 * gap \ 13
  159.                 IF gap < 1 THEN gap = 1
  160.                 i = 0
  161.                 swapped = 0
  162.                 DO
  163.                     o = m.OFFSET + i * 8
  164.                     o1 = m.OFFSET + (i + gap) * 8
  165.                     IF _MEMGET(m, o, DOUBLE) > _MEMGET(m, o1, DOUBLE) THEN
  166.                         _MEMGET m, o1, T5a
  167.                         _MEMGET m, o, T5b
  168.                         _MEMPUT m, o1, T5b
  169.                         _MEMPUT m, o, T5a
  170.                         swapped = -1
  171.                     END IF
  172.                     i = i + 1
  173.                 LOOP UNTIL i + gap > EC
  174.             LOOP UNTIL gap = 1 AND swapped = 0
  175.         CASE 6 ' _FLOAT
  176.             DIM T6a AS _FLOAT, T6b AS _FLOAT
  177.             gap = EC
  178.             DO
  179.                 gap = 10 * gap \ 13
  180.                 IF gap < 1 THEN gap = 1
  181.                 i = 0
  182.                 swapped = 0
  183.                 DO
  184.                     o = m.OFFSET + i * 32
  185.                     o1 = m.OFFSET + (i + gap) * 32
  186.                     IF _MEMGET(m, o, _FLOAT) > _MEMGET(m, o1, _FLOAT) THEN
  187.                         _MEMGET m, o1, T6a
  188.                         _MEMGET m, o, T6b
  189.                         _MEMPUT m, o1, T6b
  190.                         _MEMPUT m, o, T6a
  191.                         swapped = -1
  192.                     END IF
  193.                     i = i + 1
  194.                 LOOP UNTIL i + gap > EC
  195.             LOOP UNTIL gap = 1 AND swapped = 0
  196.         CASE 7 'String
  197.             DIM T7a AS STRING, T7b AS STRING, T7c AS STRING
  198.             T7a = SPACE$(ES): T7b = SPACE$(ES): T7c = SPACE$(ES)
  199.             gap = EC
  200.             DO
  201.                 gap = INT(gap / 1.247330950103979)
  202.                 IF gap < 1 THEN gap = 1
  203.                 i = 0
  204.                 swapped = 0
  205.                 DO
  206.                     o = m.OFFSET + i * ES
  207.                     o1 = m.OFFSET + (i + gap) * ES
  208.                     _MEMGET m, o, T7a
  209.                     _MEMGET m, o1, T7b
  210.                     IF T7a > T7b THEN
  211.                         T7c = T7b
  212.                         _MEMPUT m, o1, T7a
  213.                         _MEMPUT m, o, T7c
  214.                         swapped = -1
  215.                     END IF
  216.                     i = i + 1
  217.                 LOOP UNTIL i + gap > EC
  218.             LOOP UNTIL gap = 1 AND swapped = false
  219.         CASE 8 '_INTEGER64
  220.             DIM T8a AS _INTEGER64, T8b AS _INTEGER64
  221.             gap = EC
  222.             DO
  223.                 gap = 10 * gap \ 13
  224.                 IF gap < 1 THEN gap = 1
  225.                 i = 0
  226.                 swapped = 0
  227.                 DO
  228.                     o = m.OFFSET + i * 8
  229.                     o1 = m.OFFSET + (i + gap) * 8
  230.                     IF _MEMGET(m, o, _INTEGER64) > _MEMGET(m, o1, _INTEGER64) THEN
  231.                         _MEMGET m, o1, T8a
  232.                         _MEMGET m, o, T8b
  233.                         _MEMPUT m, o1, T8b
  234.                         _MEMPUT m, o, T8a
  235.                         swapped = -1
  236.                     END IF
  237.                     i = i + 1
  238.                 LOOP UNTIL i + gap > EC
  239.             LOOP UNTIL gap = 1 AND swapped = 0
  240.         CASE 11: '_UNSIGNED _BYTE
  241.             DIM temp11(0 TO 255) AS _UNSIGNED LONG
  242.             DIM t11 AS _UNSIGNED _BYTE
  243.             i = 0
  244.             DO
  245.                 _MEMGET m, m.OFFSET + i, t11
  246.                 temp11(t11) = temp11(t11) + 1
  247.                 i = i + 1
  248.             LOOP UNTIL i > EC
  249.             i1 = 0
  250.             DO
  251.                 DO UNTIL temp11(i1) = 0
  252.                     _MEMPUT m, m.OFFSET + counter, i1 AS _UNSIGNED _BYTE
  253.                     counter = counter + 1
  254.                     temp11(i1) = temp11(i1) - 1
  255.                     IF counter > EC THEN EXIT SUB
  256.                 LOOP
  257.                 i1 = i1 + 1
  258.             LOOP UNTIL i1 > 255
  259.         CASE 12 '_UNSIGNED INTEGER
  260.             DIM temp12(0 TO 65535) AS _UNSIGNED LONG
  261.             DIM t12 AS _UNSIGNED INTEGER
  262.             i = 0
  263.             DO
  264.                 _MEMGET m, m.OFFSET + i * 2, t12
  265.                 temp12(t12) = temp12(t12) + 1
  266.                 i = i + 1
  267.             LOOP UNTIL i > EC
  268.             i1 = 0
  269.             DO
  270.                 DO UNTIL temp12(i1) = 0
  271.                     _MEMPUT m, m.OFFSET + counter * 2, i1 AS _UNSIGNED INTEGER
  272.                     counter = counter + 1
  273.                     temp12(i1) = temp12(i1) - 1
  274.                     IF counter > EC THEN EXIT SUB
  275.                 LOOP
  276.                 i1 = i1 + 1
  277.             LOOP UNTIL i1 > 65535
  278.         CASE 14 '_UNSIGNED LONG
  279.             DIM T14a AS _UNSIGNED LONG, T14b AS _UNSIGNED LONG
  280.             gap = EC
  281.             DO
  282.                 gap = 10 * gap \ 13
  283.                 IF gap < 1 THEN gap = 1
  284.                 i = 0
  285.                 swapped = 0
  286.                 DO
  287.                     o = m.OFFSET + i * 4
  288.                     o1 = m.OFFSET + (i + gap) * 4
  289.                     IF _MEMGET(m, o, _UNSIGNED LONG) > _MEMGET(m, o1, _UNSIGNED LONG) THEN
  290.                         _MEMGET m, o1, T14a
  291.                         _MEMGET m, o, T14b
  292.                         _MEMPUT m, o1, T14b
  293.                         _MEMPUT m, o, T14a
  294.                         swapped = -1
  295.                     END IF
  296.                     i = i + 1
  297.                 LOOP UNTIL i + gap > EC
  298.             LOOP UNTIL gap = 1 AND swapped = 0
  299.         CASE 18: '_UNSIGNED _INTEGER64
  300.             DIM T18a AS _UNSIGNED _INTEGER64, T18b AS _UNSIGNED _INTEGER64
  301.             gap = EC
  302.             DO
  303.                 gap = 10 * gap \ 13
  304.                 IF gap < 1 THEN gap = 1
  305.                 i = 0
  306.                 swapped = 0
  307.                 DO
  308.                     o = m.OFFSET + i * 8
  309.                     o1 = m.OFFSET + (i + gap) * 8
  310.                     IF _MEMGET(m, o, _UNSIGNED _INTEGER64) > _MEMGET(m, o1, _UNSIGNED _INTEGER64) THEN
  311.                         _MEMGET m, o1, T18a
  312.                         _MEMGET m, o, T18b
  313.                         _MEMPUT m, o1, T18b
  314.                         _MEMPUT m, o, T18a
  315.                         swapped = -1
  316.                     END IF
  317.                     i = i + 1
  318.                 LOOP UNTIL i + gap > EC
  319.             LOOP UNTIL gap = 1 AND swapped = 0
  320.     END SELECT
  321.  

In the time it takes us to load and sort 20000 numbers, we can instead load 500000 numbers and then sort them, as illustrated below:

Code: QB64: [Select]
  1. CONST limit = 500000 'number of items to load and sort
  2.  
  3. DIM Array(limit) AS INTEGER
  4. DIM n(limit) AS INTEGER
  5. m = _MEM(Array())
  6. OPEN "temp.txt" FOR OUTPUT AS #1
  7. FOR i = 0 TO limit 'print a ton of entries
  8.     PRINT #1, RND * 10000
  9.  
  10. OPEN "temp.txt" FOR BINARY AS #1
  11.  
  12. t## = TIMER
  13.  
  14. FOR i = 0 TO 20000
  15.     LINE INPUT #1, temp$
  16.     num = VAL(temp$)
  17.     FOR j = 0 TO i - 1
  18.         IF num < n(j) THEN
  19.             FOR k = i TO j + 1 STEP -1
  20.                 n(k) = n(k - 1)
  21.             NEXT
  22.             EXIT FOR
  23.         END IF
  24.     NEXT
  25.     n(j) = num
  26. t1## = TIMER
  27.  
  28. PRINT USING "###.### seconds to load and sort 20,000 items together"; t1## - t##
  29.  
  30.  
  31.  
  32. t2## = TIMER
  33. OPEN "temp.txt" FOR BINARY AS #1
  34. FOR i = 0 TO limit
  35.     LINE INPUT #1, temp$
  36.     Array(i) = VAL(temp$)
  37. Sort m
  38. t3## = TIMER
  39. PRINT USING "###.### seconds to load and then sort 500,000 items"; t3## - t2##
  40.  
  41. SUB Sort (m AS _MEM)
  42.     $IF 64BIT THEN
  43.         DIM ES AS _INTEGER64, EC AS _INTEGER64
  44.     $ELSE
  45.         DIM ES AS LONG, EC AS LONG
  46.     $END IF
  47.  
  48.     IF NOT m.TYPE AND 65536 THEN EXIT SUB 'We won't work without an array
  49.     IF m.TYPE AND 1024 THEN DataType = 10
  50.     IF m.TYPE AND 1 THEN DataType = DataType + 1
  51.     IF m.TYPE AND 2 THEN DataType = DataType + 2
  52.     IF m.TYPE AND 4 THEN IF m.TYPE AND 128 THEN DataType = DataType + 4 ELSE DataType = 3
  53.     IF m.TYPE AND 8 THEN IF m.TYPE AND 128 THEN DataType = DataType + 8 ELSE DataType = 5
  54.     IF m.TYPE AND 32 THEN DataType = 6
  55.     IF m.TYPE AND 512 THEN DataType = 7
  56.  
  57.     'Convert our offset data over to something we can work with
  58.     DIM m1 AS _MEM: m1 = _MEMNEW(LEN(ES))
  59.     _MEMPUT m1, m1.OFFSET, m.ELEMENTSIZE: _MEMGET m1, m1.OFFSET, ES 'Element Size
  60.     _MEMPUT m1, m1.OFFSET, m.SIZE: _MEMGET m1, m1.OFFSET, EC 'Element Count will temporily hold the WHOLE array size
  61.     _MEMFREE m1
  62.  
  63.     EC = EC / ES - 1 'Now we take the whole element size / the size of the elements and get our actual element count.  We subtract 1 so our arrays start at 0 and not 1.
  64.     'And work with it!
  65.     DIM o AS _OFFSET, o1 AS _OFFSET, counter AS _UNSIGNED LONG
  66.  
  67.     SELECT CASE DataType
  68.         CASE 1 'BYTE
  69.             DIM temp1(-128 TO 127) AS _UNSIGNED LONG
  70.             DIM t1 AS _BYTE
  71.             i = 0
  72.             DO
  73.                 _MEMGET m, m.OFFSET + i, t1
  74.                 temp1(t1) = temp1(t1) + 1
  75.                 i = i + 1
  76.             LOOP UNTIL i > EC
  77.             i1 = -128
  78.             DO
  79.                 DO UNTIL temp1(i1) = 0
  80.                     _MEMPUT m, m.OFFSET + counter, i1 AS _BYTE
  81.                     counter = counter + 1
  82.                     temp1(i1) = temp1(i1) - 1
  83.                     IF counter > EC THEN EXIT SUB
  84.                 LOOP
  85.                 i1 = i1 + 1
  86.             LOOP UNTIL i1 > 127
  87.         CASE 2: 'INTEGER
  88.             DIM temp2(-32768 TO 32767) AS _UNSIGNED LONG
  89.             DIM t2 AS INTEGER
  90.             i = 0
  91.             DO
  92.                 _MEMGET m, m.OFFSET + i * 2, t2
  93.                 temp2(t2) = temp2(t2) + 1
  94.                 i = i + 1
  95.             LOOP UNTIL i > EC
  96.             i1 = -32768
  97.             DO
  98.                 DO UNTIL temp2(i1) = 0
  99.                     _MEMPUT m, m.OFFSET + counter * 2, i1 AS INTEGER
  100.                     counter = counter + 1
  101.                     temp2(i1) = temp2(i1) - 1
  102.                     IF counter > EC THEN EXIT SUB
  103.                 LOOP
  104.                 i1 = i1 + 1
  105.             LOOP UNTIL i1 > 32767
  106.         CASE 3 'SINGLE
  107.             DIM T3a AS SINGLE, T3b AS SINGLE
  108.             gap = EC
  109.             DO
  110.                 gap = 10 * gap \ 13
  111.                 IF gap < 1 THEN gap = 1
  112.                 i = 0
  113.                 swapped = 0
  114.                 DO
  115.                     o = m.OFFSET + i * 4
  116.                     o1 = m.OFFSET + (i + gap) * 4
  117.                     IF _MEMGET(m, o, SINGLE) > _MEMGET(m, o1, SINGLE) THEN
  118.                         _MEMGET m, o1, T3a
  119.                         _MEMGET m, o, T3b
  120.                         _MEMPUT m, o1, T3b
  121.                         _MEMPUT m, o, T3a
  122.                         swapped = -1
  123.                     END IF
  124.                     i = i + 1
  125.                 LOOP UNTIL i + gap > EC
  126.             LOOP UNTIL gap = 1 AND swapped = 0
  127.         CASE 4 'LONG
  128.             DIM T4a AS LONG, T4b AS LONG
  129.             gap = EC
  130.             DO
  131.                 gap = 10 * gap \ 13
  132.                 IF gap < 1 THEN gap = 1
  133.                 i = 0
  134.                 swapped = 0
  135.                 DO
  136.                     o = m.OFFSET + i * 4
  137.                     o1 = m.OFFSET + (i + gap) * 4
  138.                     IF _MEMGET(m, o, LONG) > _MEMGET(m, o1, LONG) THEN
  139.                         _MEMGET m, o1, T4a
  140.                         _MEMGET m, o, T4b
  141.                         _MEMPUT m, o1, T4b
  142.                         _MEMPUT m, o, T4a
  143.                         swapped = -1
  144.                     END IF
  145.                     i = i + 1
  146.                 LOOP UNTIL i + gap > EC
  147.             LOOP UNTIL gap = 1 AND swapped = 0
  148.         CASE 5 'DOUBLE
  149.             DIM T5a AS DOUBLE, T5b AS DOUBLE
  150.             gap = EC
  151.             DO
  152.                 gap = 10 * gap \ 13
  153.                 IF gap < 1 THEN gap = 1
  154.                 i = 0
  155.                 swapped = 0
  156.                 DO
  157.                     o = m.OFFSET + i * 8
  158.                     o1 = m.OFFSET + (i + gap) * 8
  159.                     IF _MEMGET(m, o, DOUBLE) > _MEMGET(m, o1, DOUBLE) THEN
  160.                         _MEMGET m, o1, T5a
  161.                         _MEMGET m, o, T5b
  162.                         _MEMPUT m, o1, T5b
  163.                         _MEMPUT m, o, T5a
  164.                         swapped = -1
  165.                     END IF
  166.                     i = i + 1
  167.                 LOOP UNTIL i + gap > EC
  168.             LOOP UNTIL gap = 1 AND swapped = 0
  169.         CASE 6 ' _FLOAT
  170.             DIM T6a AS _FLOAT, T6b AS _FLOAT
  171.             gap = EC
  172.             DO
  173.                 gap = 10 * gap \ 13
  174.                 IF gap < 1 THEN gap = 1
  175.                 i = 0
  176.                 swapped = 0
  177.                 DO
  178.                     o = m.OFFSET + i * 32
  179.                     o1 = m.OFFSET + (i + gap) * 32
  180.                     IF _MEMGET(m, o, _FLOAT) > _MEMGET(m, o1, _FLOAT) THEN
  181.                         _MEMGET m, o1, T6a
  182.                         _MEMGET m, o, T6b
  183.                         _MEMPUT m, o1, T6b
  184.                         _MEMPUT m, o, T6a
  185.                         swapped = -1
  186.                     END IF
  187.                     i = i + 1
  188.                 LOOP UNTIL i + gap > EC
  189.             LOOP UNTIL gap = 1 AND swapped = 0
  190.         CASE 7 'String
  191.             DIM T7a AS STRING, T7b AS STRING, T7c AS STRING
  192.             T7a = SPACE$(ES): T7b = SPACE$(ES): T7c = SPACE$(ES)
  193.             gap = EC
  194.             DO
  195.                 gap = INT(gap / 1.247330950103979)
  196.                 IF gap < 1 THEN gap = 1
  197.                 i = 0
  198.                 swapped = 0
  199.                 DO
  200.                     o = m.OFFSET + i * ES
  201.                     o1 = m.OFFSET + (i + gap) * ES
  202.                     _MEMGET m, o, T7a
  203.                     _MEMGET m, o1, T7b
  204.                     IF T7a > T7b THEN
  205.                         T7c = T7b
  206.                         _MEMPUT m, o1, T7a
  207.                         _MEMPUT m, o, T7c
  208.                         swapped = -1
  209.                     END IF
  210.                     i = i + 1
  211.                 LOOP UNTIL i + gap > EC
  212.             LOOP UNTIL gap = 1 AND swapped = false
  213.         CASE 8 '_INTEGER64
  214.             DIM T8a AS _INTEGER64, T8b AS _INTEGER64
  215.             gap = EC
  216.             DO
  217.                 gap = 10 * gap \ 13
  218.                 IF gap < 1 THEN gap = 1
  219.                 i = 0
  220.                 swapped = 0
  221.                 DO
  222.                     o = m.OFFSET + i * 8
  223.                     o1 = m.OFFSET + (i + gap) * 8
  224.                     IF _MEMGET(m, o, _INTEGER64) > _MEMGET(m, o1, _INTEGER64) THEN
  225.                         _MEMGET m, o1, T8a
  226.                         _MEMGET m, o, T8b
  227.                         _MEMPUT m, o1, T8b
  228.                         _MEMPUT m, o, T8a
  229.                         swapped = -1
  230.                     END IF
  231.                     i = i + 1
  232.                 LOOP UNTIL i + gap > EC
  233.             LOOP UNTIL gap = 1 AND swapped = 0
  234.         CASE 11: '_UNSIGNED _BYTE
  235.             DIM temp11(0 TO 255) AS _UNSIGNED LONG
  236.             DIM t11 AS _UNSIGNED _BYTE
  237.             i = 0
  238.             DO
  239.                 _MEMGET m, m.OFFSET + i, t11
  240.                 temp11(t11) = temp11(t11) + 1
  241.                 i = i + 1
  242.             LOOP UNTIL i > EC
  243.             i1 = 0
  244.             DO
  245.                 DO UNTIL temp11(i1) = 0
  246.                     _MEMPUT m, m.OFFSET + counter, i1 AS _UNSIGNED _BYTE
  247.                     counter = counter + 1
  248.                     temp11(i1) = temp11(i1) - 1
  249.                     IF counter > EC THEN EXIT SUB
  250.                 LOOP
  251.                 i1 = i1 + 1
  252.             LOOP UNTIL i1 > 255
  253.         CASE 12 '_UNSIGNED INTEGER
  254.             DIM temp12(0 TO 65535) AS _UNSIGNED LONG
  255.             DIM t12 AS _UNSIGNED INTEGER
  256.             i = 0
  257.             DO
  258.                 _MEMGET m, m.OFFSET + i * 2, t12
  259.                 temp12(t12) = temp12(t12) + 1
  260.                 i = i + 1
  261.             LOOP UNTIL i > EC
  262.             i1 = 0
  263.             DO
  264.                 DO UNTIL temp12(i1) = 0
  265.                     _MEMPUT m, m.OFFSET + counter * 2, i1 AS _UNSIGNED INTEGER
  266.                     counter = counter + 1
  267.                     temp12(i1) = temp12(i1) - 1
  268.                     IF counter > EC THEN EXIT SUB
  269.                 LOOP
  270.                 i1 = i1 + 1
  271.             LOOP UNTIL i1 > 65535
  272.         CASE 14 '_UNSIGNED LONG
  273.             DIM T14a AS _UNSIGNED LONG, T14b AS _UNSIGNED LONG
  274.             gap = EC
  275.             DO
  276.                 gap = 10 * gap \ 13
  277.                 IF gap < 1 THEN gap = 1
  278.                 i = 0
  279.                 swapped = 0
  280.                 DO
  281.                     o = m.OFFSET + i * 4
  282.                     o1 = m.OFFSET + (i + gap) * 4
  283.                     IF _MEMGET(m, o, _UNSIGNED LONG) > _MEMGET(m, o1, _UNSIGNED LONG) THEN
  284.                         _MEMGET m, o1, T14a
  285.                         _MEMGET m, o, T14b
  286.                         _MEMPUT m, o1, T14b
  287.                         _MEMPUT m, o, T14a
  288.                         swapped = -1
  289.                     END IF
  290.                     i = i + 1
  291.                 LOOP UNTIL i + gap > EC
  292.             LOOP UNTIL gap = 1 AND swapped = 0
  293.         CASE 18: '_UNSIGNED _INTEGER64
  294.             DIM T18a AS _UNSIGNED _INTEGER64, T18b AS _UNSIGNED _INTEGER64
  295.             gap = EC
  296.             DO
  297.                 gap = 10 * gap \ 13
  298.                 IF gap < 1 THEN gap = 1
  299.                 i = 0
  300.                 swapped = 0
  301.                 DO
  302.                     o = m.OFFSET + i * 8
  303.                     o1 = m.OFFSET + (i + gap) * 8
  304.                     IF _MEMGET(m, o, _UNSIGNED _INTEGER64) > _MEMGET(m, o1, _UNSIGNED _INTEGER64) THEN
  305.                         _MEMGET m, o1, T18a
  306.                         _MEMGET m, o, T18b
  307.                         _MEMPUT m, o1, T18b
  308.                         _MEMPUT m, o, T18a
  309.                         swapped = -1
  310.                     END IF
  311.                     i = i + 1
  312.                 LOOP UNTIL i + gap > EC
  313.             LOOP UNTIL gap = 1 AND swapped = 0
  314.     END SELECT
  315.  


Loading and sorting as you go works good for small data sets, but what you're really implementing is an Insertion Sort method, and there's a lot of other sorting routines which are much more efficient out there.  The more data you need to add into an array, the less useful an insertion sort method becomes.  If you have 100,000 sorted items and need to add a new sorted item into the set, then it's definitely the way to go.  If you have 100,000 items that all need to be sorted completely to begin with, then you should generally choose a more efficient sorting method.

Since the memsort routine is a standard part of my toolbox, I almost never bother with the "load and sort" method.  I generally just load an array and then sort it and be done with it, like the examples above.  ;)



And just for fun, and to really highlight the difference in various sorting methods performance, I took the file loading times completely out and wrote this little demo:

Code: QB64: [Select]
  1. CONST limit = 2000000 'number of items to load and sort
  2.  
  3. DIM Array(limit) AS INTEGER
  4. DIM n(limit) AS INTEGER
  5. m = _MEM(Array())
  6.  
  7. FOR i = 0 TO limit 'print a ton of entries
  8.     num = RND * 100000
  9.     n(i) = num
  10.     Array(i) = num
  11.  
  12. t## = TIMER
  13.  
  14. FOR i = 0 TO 20000
  15.     num = n(i)
  16.     FOR j = 0 TO i - 1
  17.         IF num < n(j) THEN
  18.             FOR k = i TO j + 1 STEP -1
  19.                 n(k) = n(k - 1)
  20.             NEXT
  21.             EXIT FOR
  22.         END IF
  23.     NEXT
  24.     n(j) = num
  25. t1## = TIMER
  26.  
  27. PRINT USING "###.### seconds to insertion sort 20,000 items together"; t1## - t##
  28.  
  29.  
  30.  
  31. t2## = TIMER(0.00001)
  32. Sort m
  33. t3## = TIMER(0.00001)
  34. PRINT USING "###.### seconds to mem sort 2,000,000 items"; t3## - t2##
  35.  
  36. SUB Sort (m AS _MEM)
  37.     $IF 64BIT THEN
  38.         DIM ES AS _INTEGER64, EC AS _INTEGER64
  39.     $ELSE
  40.         DIM ES AS LONG, EC AS LONG
  41.     $END IF
  42.  
  43.     IF NOT m.TYPE AND 65536 THEN EXIT SUB 'We won't work without an array
  44.     IF m.TYPE AND 1024 THEN DataType = 10
  45.     IF m.TYPE AND 1 THEN DataType = DataType + 1
  46.     IF m.TYPE AND 2 THEN DataType = DataType + 2
  47.     IF m.TYPE AND 4 THEN IF m.TYPE AND 128 THEN DataType = DataType + 4 ELSE DataType = 3
  48.     IF m.TYPE AND 8 THEN IF m.TYPE AND 128 THEN DataType = DataType + 8 ELSE DataType = 5
  49.     IF m.TYPE AND 32 THEN DataType = 6
  50.     IF m.TYPE AND 512 THEN DataType = 7
  51.  
  52.     'Convert our offset data over to something we can work with
  53.     DIM m1 AS _MEM: m1 = _MEMNEW(LEN(ES))
  54.     _MEMPUT m1, m1.OFFSET, m.ELEMENTSIZE: _MEMGET m1, m1.OFFSET, ES 'Element Size
  55.     _MEMPUT m1, m1.OFFSET, m.SIZE: _MEMGET m1, m1.OFFSET, EC 'Element Count will temporily hold the WHOLE array size
  56.     _MEMFREE m1
  57.  
  58.     EC = EC / ES - 1 'Now we take the whole element size / the size of the elements and get our actual element count.  We subtract 1 so our arrays start at 0 and not 1.
  59.     'And work with it!
  60.     DIM o AS _OFFSET, o1 AS _OFFSET, counter AS _UNSIGNED LONG
  61.  
  62.     SELECT CASE DataType
  63.         CASE 1 'BYTE
  64.             DIM temp1(-128 TO 127) AS _UNSIGNED LONG
  65.             DIM t1 AS _BYTE
  66.             i = 0
  67.             DO
  68.                 _MEMGET m, m.OFFSET + i, t1
  69.                 temp1(t1) = temp1(t1) + 1
  70.                 i = i + 1
  71.             LOOP UNTIL i > EC
  72.             i1 = -128
  73.             DO
  74.                 DO UNTIL temp1(i1) = 0
  75.                     _MEMPUT m, m.OFFSET + counter, i1 AS _BYTE
  76.                     counter = counter + 1
  77.                     temp1(i1) = temp1(i1) - 1
  78.                     IF counter > EC THEN EXIT SUB
  79.                 LOOP
  80.                 i1 = i1 + 1
  81.             LOOP UNTIL i1 > 127
  82.         CASE 2: 'INTEGER
  83.             DIM temp2(-32768 TO 32767) AS _UNSIGNED LONG
  84.             DIM t2 AS INTEGER
  85.             i = 0
  86.             DO
  87.                 _MEMGET m, m.OFFSET + i * 2, t2
  88.                 temp2(t2) = temp2(t2) + 1
  89.                 i = i + 1
  90.             LOOP UNTIL i > EC
  91.             i1 = -32768
  92.             DO
  93.                 DO UNTIL temp2(i1) = 0
  94.                     _MEMPUT m, m.OFFSET + counter * 2, i1 AS INTEGER
  95.                     counter = counter + 1
  96.                     temp2(i1) = temp2(i1) - 1
  97.                     IF counter > EC THEN EXIT SUB
  98.                 LOOP
  99.                 i1 = i1 + 1
  100.             LOOP UNTIL i1 > 32767
  101.         CASE 3 'SINGLE
  102.             DIM T3a AS SINGLE, T3b AS SINGLE
  103.             gap = EC
  104.             DO
  105.                 gap = 10 * gap \ 13
  106.                 IF gap < 1 THEN gap = 1
  107.                 i = 0
  108.                 swapped = 0
  109.                 DO
  110.                     o = m.OFFSET + i * 4
  111.                     o1 = m.OFFSET + (i + gap) * 4
  112.                     IF _MEMGET(m, o, SINGLE) > _MEMGET(m, o1, SINGLE) THEN
  113.                         _MEMGET m, o1, T3a
  114.                         _MEMGET m, o, T3b
  115.                         _MEMPUT m, o1, T3b
  116.                         _MEMPUT m, o, T3a
  117.                         swapped = -1
  118.                     END IF
  119.                     i = i + 1
  120.                 LOOP UNTIL i + gap > EC
  121.             LOOP UNTIL gap = 1 AND swapped = 0
  122.         CASE 4 'LONG
  123.             DIM T4a AS LONG, T4b AS LONG
  124.             gap = EC
  125.             DO
  126.                 gap = 10 * gap \ 13
  127.                 IF gap < 1 THEN gap = 1
  128.                 i = 0
  129.                 swapped = 0
  130.                 DO
  131.                     o = m.OFFSET + i * 4
  132.                     o1 = m.OFFSET + (i + gap) * 4
  133.                     IF _MEMGET(m, o, LONG) > _MEMGET(m, o1, LONG) THEN
  134.                         _MEMGET m, o1, T4a
  135.                         _MEMGET m, o, T4b
  136.                         _MEMPUT m, o1, T4b
  137.                         _MEMPUT m, o, T4a
  138.                         swapped = -1
  139.                     END IF
  140.                     i = i + 1
  141.                 LOOP UNTIL i + gap > EC
  142.             LOOP UNTIL gap = 1 AND swapped = 0
  143.         CASE 5 'DOUBLE
  144.             DIM T5a AS DOUBLE, T5b AS DOUBLE
  145.             gap = EC
  146.             DO
  147.                 gap = 10 * gap \ 13
  148.                 IF gap < 1 THEN gap = 1
  149.                 i = 0
  150.                 swapped = 0
  151.                 DO
  152.                     o = m.OFFSET + i * 8
  153.                     o1 = m.OFFSET + (i + gap) * 8
  154.                     IF _MEMGET(m, o, DOUBLE) > _MEMGET(m, o1, DOUBLE) THEN
  155.                         _MEMGET m, o1, T5a
  156.                         _MEMGET m, o, T5b
  157.                         _MEMPUT m, o1, T5b
  158.                         _MEMPUT m, o, T5a
  159.                         swapped = -1
  160.                     END IF
  161.                     i = i + 1
  162.                 LOOP UNTIL i + gap > EC
  163.             LOOP UNTIL gap = 1 AND swapped = 0
  164.         CASE 6 ' _FLOAT
  165.             DIM T6a AS _FLOAT, T6b AS _FLOAT
  166.             gap = EC
  167.             DO
  168.                 gap = 10 * gap \ 13
  169.                 IF gap < 1 THEN gap = 1
  170.                 i = 0
  171.                 swapped = 0
  172.                 DO
  173.                     o = m.OFFSET + i * 32
  174.                     o1 = m.OFFSET + (i + gap) * 32
  175.                     IF _MEMGET(m, o, _FLOAT) > _MEMGET(m, o1, _FLOAT) THEN
  176.                         _MEMGET m, o1, T6a
  177.                         _MEMGET m, o, T6b
  178.                         _MEMPUT m, o1, T6b
  179.                         _MEMPUT m, o, T6a
  180.                         swapped = -1
  181.                     END IF
  182.                     i = i + 1
  183.                 LOOP UNTIL i + gap > EC
  184.             LOOP UNTIL gap = 1 AND swapped = 0
  185.         CASE 7 'String
  186.             DIM T7a AS STRING, T7b AS STRING, T7c AS STRING
  187.             T7a = SPACE$(ES): T7b = SPACE$(ES): T7c = SPACE$(ES)
  188.             gap = EC
  189.             DO
  190.                 gap = INT(gap / 1.247330950103979)
  191.                 IF gap < 1 THEN gap = 1
  192.                 i = 0
  193.                 swapped = 0
  194.                 DO
  195.                     o = m.OFFSET + i * ES
  196.                     o1 = m.OFFSET + (i + gap) * ES
  197.                     _MEMGET m, o, T7a
  198.                     _MEMGET m, o1, T7b
  199.                     IF T7a > T7b THEN
  200.                         T7c = T7b
  201.                         _MEMPUT m, o1, T7a
  202.                         _MEMPUT m, o, T7c
  203.                         swapped = -1
  204.                     END IF
  205.                     i = i + 1
  206.                 LOOP UNTIL i + gap > EC
  207.             LOOP UNTIL gap = 1 AND swapped = false
  208.         CASE 8 '_INTEGER64
  209.             DIM T8a AS _INTEGER64, T8b AS _INTEGER64
  210.             gap = EC
  211.             DO
  212.                 gap = 10 * gap \ 13
  213.                 IF gap < 1 THEN gap = 1
  214.                 i = 0
  215.                 swapped = 0
  216.                 DO
  217.                     o = m.OFFSET + i * 8
  218.                     o1 = m.OFFSET + (i + gap) * 8
  219.                     IF _MEMGET(m, o, _INTEGER64) > _MEMGET(m, o1, _INTEGER64) THEN
  220.                         _MEMGET m, o1, T8a
  221.                         _MEMGET m, o, T8b
  222.                         _MEMPUT m, o1, T8b
  223.                         _MEMPUT m, o, T8a
  224.                         swapped = -1
  225.                     END IF
  226.                     i = i + 1
  227.                 LOOP UNTIL i + gap > EC
  228.             LOOP UNTIL gap = 1 AND swapped = 0
  229.         CASE 11: '_UNSIGNED _BYTE
  230.             DIM temp11(0 TO 255) AS _UNSIGNED LONG
  231.             DIM t11 AS _UNSIGNED _BYTE
  232.             i = 0
  233.             DO
  234.                 _MEMGET m, m.OFFSET + i, t11
  235.                 temp11(t11) = temp11(t11) + 1
  236.                 i = i + 1
  237.             LOOP UNTIL i > EC
  238.             i1 = 0
  239.             DO
  240.                 DO UNTIL temp11(i1) = 0
  241.                     _MEMPUT m, m.OFFSET + counter, i1 AS _UNSIGNED _BYTE
  242.                     counter = counter + 1
  243.                     temp11(i1) = temp11(i1) - 1
  244.                     IF counter > EC THEN EXIT SUB
  245.                 LOOP
  246.                 i1 = i1 + 1
  247.             LOOP UNTIL i1 > 255
  248.         CASE 12 '_UNSIGNED INTEGER
  249.             DIM temp12(0 TO 65535) AS _UNSIGNED LONG
  250.             DIM t12 AS _UNSIGNED INTEGER
  251.             i = 0
  252.             DO
  253.                 _MEMGET m, m.OFFSET + i * 2, t12
  254.                 temp12(t12) = temp12(t12) + 1
  255.                 i = i + 1
  256.             LOOP UNTIL i > EC
  257.             i1 = 0
  258.             DO
  259.                 DO UNTIL temp12(i1) = 0
  260.                     _MEMPUT m, m.OFFSET + counter * 2, i1 AS _UNSIGNED INTEGER
  261.                     counter = counter + 1
  262.                     temp12(i1) = temp12(i1) - 1
  263.                     IF counter > EC THEN EXIT SUB
  264.                 LOOP
  265.                 i1 = i1 + 1
  266.             LOOP UNTIL i1 > 65535
  267.         CASE 14 '_UNSIGNED LONG
  268.             DIM T14a AS _UNSIGNED LONG, T14b AS _UNSIGNED LONG
  269.             gap = EC
  270.             DO
  271.                 gap = 10 * gap \ 13
  272.                 IF gap < 1 THEN gap = 1
  273.                 i = 0
  274.                 swapped = 0
  275.                 DO
  276.                     o = m.OFFSET + i * 4
  277.                     o1 = m.OFFSET + (i + gap) * 4
  278.                     IF _MEMGET(m, o, _UNSIGNED LONG) > _MEMGET(m, o1, _UNSIGNED LONG) THEN
  279.                         _MEMGET m, o1, T14a
  280.                         _MEMGET m, o, T14b
  281.                         _MEMPUT m, o1, T14b
  282.                         _MEMPUT m, o, T14a
  283.                         swapped = -1
  284.                     END IF
  285.                     i = i + 1
  286.                 LOOP UNTIL i + gap > EC
  287.             LOOP UNTIL gap = 1 AND swapped = 0
  288.         CASE 18: '_UNSIGNED _INTEGER64
  289.             DIM T18a AS _UNSIGNED _INTEGER64, T18b AS _UNSIGNED _INTEGER64
  290.             gap = EC
  291.             DO
  292.                 gap = 10 * gap \ 13
  293.                 IF gap < 1 THEN gap = 1
  294.                 i = 0
  295.                 swapped = 0
  296.                 DO
  297.                     o = m.OFFSET + i * 8
  298.                     o1 = m.OFFSET + (i + gap) * 8
  299.                     IF _MEMGET(m, o, _UNSIGNED _INTEGER64) > _MEMGET(m, o1, _UNSIGNED _INTEGER64) THEN
  300.                         _MEMGET m, o1, T18a
  301.                         _MEMGET m, o, T18b
  302.                         _MEMPUT m, o1, T18b
  303.                         _MEMPUT m, o, T18a
  304.                         swapped = -1
  305.                     END IF
  306.                     i = i + 1
  307.                 LOOP UNTIL i + gap > EC
  308.             LOOP UNTIL gap = 1 AND swapped = 0
  309.     END SELECT
  310.  

4.34 seconds to insertion sort 20,000 items together.
0.14 seconds to mem sort 2,000,000 items together.

30 times faster, and we sorted 100 times more items...  I think that goes to show why generally speaking, I prefer to just load the array and then sort the array.  ;)
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Dimster

  • Forum Resident
  • Posts: 500
    • View Profile
Re: Top 10 Algorythm
« Reply #7 on: November 04, 2019, 08:49:38 am »
Thanks very much - a lot of very helpful approaches - looking forward to trying them all.

My spelling of Algorythm is deliberate. It helps to remind me there needs to be a rythm to my coding - smooth and simple and flowing. Coding on the other hand implies to me blocks, staunch and static. I like to feel I'm an artist bringing a useful screen to life as opposed to a worker bee plugging in tried a true methods and rules. One of those nuts who likes the imaginative part to of programming. You guys and girls on this forum do Algorythms - amazing creative minds  - as TempodiBasic would say, this is IMHO.

Offline Qwerkey

  • Forum Resident
  • Posts: 755
    • View Profile
Re: Top 10 Algorythm
« Reply #8 on: November 04, 2019, 10:33:24 am »
My spelling of Algorythm is deliberate.

Apologies Dimster.  I acknowledge your clever creation of the portmanteau word.  But when I look at it, all I see is it shouting "change my y to an i"!!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Top 10 Algorythm
« Reply #9 on: November 04, 2019, 11:39:21 am »
;-)) Steve, you have a wonderful well worked-out hammer and you are looking for a nail!

Dimster, you probably have high hopes for your game but let me know when you get to 20,000 players to justify adding 275+ lines for a great Sort routine :D

Also, I didn't even notice the fanciful wordplay until Qwerkey mentioned it, I don't know can I blame it on poor eyesight?

portmanteau - so that is what that is! ;)

Offline Dimster

  • Forum Resident
  • Posts: 500
    • View Profile
Re: Top 10 Algorythm
« Reply #10 on: November 04, 2019, 11:55:26 am »
I could change the Y to an I but I like Quirky.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Top 10 Algorythm
« Reply #11 on: November 04, 2019, 02:35:49 pm »
;-)) Steve, you have a wonderful well worked-out hammer and you are looking for a nail!

Dimster, you probably have high hopes for your game but let me know when you get to 20,000 players to justify adding 275+ lines for a great Sort routine :D

You don't have to add 275 lines for a great sort. I just tend to plug in the memsort routine as it's one which works with all the various data types out there (with the exception of variable length strings).  I don't constantly retype those lines; I just copy/paste them from my toolbox.  :P

If we break the memsort down to its basic form, what we have is a combsort such as the following, which comes in at only 15 lines:

Code: QB64: [Select]
  1. gap = UBOUND(Array)
  2.     gap = 10 * gap \ 13
  3.     IF gap < 1 THEN gap = 1
  4.     i = 0
  5.     swapped = 0
  6.     DO
  7.         IF Array(i) < WordCount(i + gap) THEN
  8.             SWAP Array(i), Array(i + gap)
  9.             SWAP Array(i), Array(i + gap)
  10.             swapped = -1
  11.         END IF
  12.         i = i + 1
  13.     LOOP UNTIL i + gap > UBOUND(Array)
  14. LOOP UNTIL gap = 1 AND swapped = 0
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline Calloway

  • Newbie
  • Posts: 18
  • I still have Laser Disc...
    • View Profile
    • Calloway Sutton
Re: Top 10 Algorythm
« Reply #12 on: November 04, 2019, 10:51:35 pm »
If you're only finding top 10 then why are you keeping all the other data?

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Top 10 Algorythm
« Reply #13 on: November 04, 2019, 11:11:29 pm »
If you're only finding top 10 then why are you keeping all the other data?

Ranking boards would be the obvious answer.   Take a game where you count wins as +2 points and losses as -1 point for your score...

Joe plays 20 games and wins 15, loses 5.  He’s the number 10 player with 25 points....

Unless you track the other player’s data, there’s no way for anyone to ever beat Joe’s top 10 score.   You start, you win, you get 2 points — not enough for top 10, so your score is discarded...

You might want the top 10 so you can give them a free month’s game subscription, invite them to play test the next beta version, or just recognize them with a badge on the leader boards, but you’d still want to keep everyone’s data to calculate their rankings.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline MLambert

  • Forum Regular
  • Posts: 115
    • View Profile
Re: Top 10 Algorythm
« Reply #14 on: November 05, 2019, 03:27:41 am »
cmsort.exe allows me to collate data, in the millions of records, within seconds.

Try it