Πέμπτη 9 Ιουλίου 2026

Έκδοση 15 Αναθεώρηση 2 - Χειρισμός Bits έως 64bit

 Νέες συναρτήσεις για χειρισμό bits σε 64bit εύρους τιμές. Μπορούμε να αλλάζουμε μπιτ, να ελέγχουμε καθώς και όλες τις άλλες δυνατότητες που έχουν και οι επεξεργαστές (CPU), όπως ολίσθηση και περιστροφή.

b=ΔΥΑΔ64.ΑΠΟ(0xFFFF_FFFF_FFFF_FFFF,0xAAAA_AAAA_AAAA_AAAA)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΚΑΙ(b, 0xFFFF_0000_0000_FFFF)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.Η(b, 0x1234_5678_0000)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΠΡΟΣΘΕΣΗ(b, 0X8000_0000_0000_0001)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΠΡΟΣΘΕΣΗ(b, 0X8000_0000_0000_0001)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΟΛΙΣΘΗΣΗ(b, 8)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΟΛΙΣΘΗΣΗ(b, -32)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΠΕΡΙΣΤΡΟΦΗ(b, -16)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΟΧΙ(b)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΚΑΙ(b,0Xffff_ffff_ffff)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΑΝΤΙΣΤΡΟΦΟ(b)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΑΝΤΙΣΤΡΟΦΟ(0x7FF_FFFF_FFFF_FFFF)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΑΝΤΙΣΤΡΟΦΟ(b)
ΔΕΚΑΕΞ b
b=ΔΥΟΜΙΣΑ64(0XAAAA_1234, 0xBBBB_5555)
ΔΕΚΑΕΞ b
b=ΔΥΟΜΙΣΑ(0XAAAA, 0x5555)
ΔΕΚΑΕΞ b
' ΔΥΑΔΙΚΟ.ΠΡΟΣΘΕΣΗ(a,b,c, ....)
b1=ΔΥΑΔΙΚΟ.ΠΡΟΣΘΕΣΗ(0X8000_0001, 0xFFFF_1234, 1)
ΔΕΚΑΕΞ b1, ΠΑΝΩΜΙΣΟ(b1), ΚΑΤΩΜΙΣΟ(b1)
b=ΔΥΑΔ64.ΠΡΟΣΘΕΣΗ(b, 0xFFFF_1234_0000_0000)
ΔΕΚΑΕΞ b, ΠΑΝΩΜΙΣΟ64(b), ΚΑΤΩΜΙΣΟ64(b)
ΔΕΚΑΕΞ ΔΥΟΜΙΣΑ64(ΚΑΤΩΜΙΣΟ64(b), ΠΑΝΩΜΙΣΟ64(b))
' ΔΥΑΔΙΚΟ.ΑΦΑΙΡΕΣΗ(a,b,c, ....)
b=ΔΥΑΔΙΚΟ.ΑΦΑΙΡΕΣΗ(0XFFFF_0001, 0XFFFF_0005, 1)
ΔΕΚΑΕΞ b, ΠΑΝΩΜΙΣΟ(b), ΚΑΤΩΜΙΣΟ(b)
b=ΔΥΑΔ64.ΑΦΑΙΡΕΣΗ(0X0000_FFFF_FFFF_0001, 0XFFFF_FFFF_FFFF_0005, 1)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΒΑΛΕ(b,62)
ΔΕΚΑΕΞ b
b=ΔΥΑΔ64.ΒΓΑΛΕ(b,47)
ΔΕΚΑΕΞ b
ΤΥΠΩΣΕ ΔΥΑΔ64.ΕΧΕΙ(b, 29, 27)=true
b=ΔΥΑΔ64.ΒΓΑΛΕ(b,29, 15)
ΔΕΚΑΕΞ b
B=ΔΥΑΔ64.ΒΑΛΕ(0,60,58,4,1) ' make a 64bit setting 4 bits
ΔΕΚΑΕΞ b
ΤΥΠΩΣΕ ΔΥΑΔ64.ΕΧΕΙ(b, 57)=false
B=ΔΥΑΔ64.ΒΑΛΕ(b,57)
ΔΕΚΑΕΞ b
ΤΥΠΩΣΕ ΔΥΑΔ64.ΕΧΕΙ(b, 57)=true
b2=ΔΥΑΔΙΚΟ.ΒΑΛΕ(0,9,8,0)
ΔΕΚΑΕΞ b2
ΤΥΠΩΣΕ b2=0x301 ' bit 9,8,0
ΔΕΚΑΕΞ ΤΙΜΗ(2^9+2^8+2^0->ΛΟΓΙΣΤΙΚΟΣ), b2
b2=ΔΥΑΔΙΚΟ.ΒΓΑΛΕ(b2,12, 8)
ΔΕΚΑΕΞ b2,
ΤΥΠΩΣΕ b2=0x201
ΤΥΠΩΣΕ ΔΥΑΔ(-1%)=0ΧFFFF
ΤΥΠΩΣΕ ΔΥΑΔ(-1)=0ΧFFFF_FFFF
ΤΥΠΩΣΕ ΔΥΑΔ64(-1)=0ΧFFFF_FFFF_FFFF_FFFF
ΤΥΠΩΣΕ ΔΥΑΔΙΚΟ.ΑΚΕΡΑΙΟ64(-1)=0ΧFFFF_FFFF_FFFF_FFFF
ΤΥΠΩΣΕ ΤΥΠΟΣ(ΔΥΑΔΙΚΟ.ΑΚΕΡΑΙΟ64(-1))="Decimal"
ΤΥΠΩΣΕ ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFFF_FFFF_FFFF, 2)=0XFFFF%
ΤΥΠΩΣΕ ΤΥΠΟΣ(ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFFF, 4))="Currency"
ΤΥΠΩΣΕ ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFFF_FFFF_FFFF, 4)=0XFFFF_FFFF&
ΤΥΠΩΣΕ ΤΥΠΟΣ(ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFFF_FFFF_FFFF))="Long Long"
ΤΥΠΩΣΕ ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFFF_FFFF_FFFF)=0XFFFF_FFFF_FFFF_FFFF&&
ΤΥΠΩΣΕ ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFAA, 8)=0ΧFFFF_FFAA&&
ΤΥΠΩΣΕ ΤΥΠΟΣ(ΑΚΕΡΑΙΟ.ΔΥΑΔΙΚΟ(0ΧFFFF_FFAA, 8))="Long Long"

Και στα αγγλικά:

b=BIT64.XOR(0xFFFF_FFFF_FFFF_FFFF,0xAAAA_AAAA_AAAA_AAAA)
hex b
b=BIT64.AND(b, 0xFFFF_0000_0000_FFFF)
hex b
b=BIT64.OR(b, 0x1234_5678_0000)
hex b
b=BIT64.ADD(b, 0X8000_0000_0000_0001)
hex b
b=BIT64.ADD(b, 0X8000_0000_0000_0001)
hex b
b=BIT64.SHIFT(b, 8)
hex b
b=BIT64.SHIFT(b, -32)
hex b
b=BIT64.ROTATE(b, -16)
hex b
b=BIT64.NOT(b)
hex b
b=BIT64.AND(b,0Xffff_ffff_ffff)
hex b
b=BIT64.NEG(b)
hex b
b=BIT64.NEG(0x7FF_FFFF_FFFF_FFFF)
hex b
b=BIT64.NEG(b)
hex b
b=HILOWLONG(0XAAAA_1234, 0xBBBB_5555)
hex b
b=HILOWWORD(0XAAAA, 0x5555)
hex b
' BINARY.ADD(a,b,c, ....)
b1=BINARY.ADD(0X8000_0001, 0xFFFF_1234, 1)
hex b1, HIWORD(b1), LOWORD(b1)


b=BIT64.ADD(b, 0xFFFF_1234_0000_0000)
hex b, HILONG(b), LOLONG(b)
hex HILOWLONG(LOLONG(b), HILONG(b))
' BINARY.SUB(a,b,c, ....)
b=BINARY.SUB(0XFFFF_0001, 0XFFFF_0005, 1)
hex b, HIWORD(b), LOWORD(b)
b=BIT64.SUB(0X0000_FFFF_FFFF_0001, 0XFFFF_FFFF_FFFF_0005, 1)
hex b
b=BIT64.SET(b,62)
hex b
b=BIT64.RESET(b,47)
hex b
print BIT64.TEST(b, 29, 27)=true
b=BIT64.RESET(b,29, 15)
hex b
B=BIT64.SET(0,60,58,4,1) ' make a 64bit setting 4 bits
hex b
print BIT64.TEST(b, 57)=false
B=BIT64.SET(b,57)
hex b
print BIT64.TEST(b, 57)=true
b2=BINARY.SET(0,9,8,0)
hex b2
print b2=0x301 ' bit 9,8,0
hex val(2^9+2^8+2^0->currency), b2
b2=BINARY.RESET(b2,12, 8)
hex b2,
print b2=0x201
print uint(-1%)=0ΧFFFF
print uint(-1)=0ΧFFFF_FFFF
print uint64(-1)=0ΧFFFF_FFFF_FFFF_FFFF
print type(uint64(-1))="Decimal"
print sint(0ΧFFFF_FFFF_FFFF_FFFF, 2)=0XFFFF%
print type(sint(0ΧFFFF_FFFF, 4))="Currency"
print sint(0ΧFFFF_FFFF_FFFF_FFFF, 4)=0XFFFF_FFFF&
print type(sint(0ΧFFFF_FFFF_FFFF_FFFF))="Long Long"
print sint(0ΧFFFF_FFFF_FFFF_FFFF)=0XFFFF_FFFF_FFFF_FFFF&&
print sint(0ΧFFFF_FFAA, 8)=0ΧFFFF_FFAA&&
print type(sint(0ΧFFFF_FFAA, 8))="Long Long"



Τετάρτη 8 Ιουλίου 2026

Shift 64bit (using 32bit shift)

This is a module to demostrate the bit shift for 64bit using 32bit shifts (and rotate). The HiLow structure define a union of a long long (64bit) unsigned integer with two long (32bit) unsigned integers. For 32 bit unsinged integers we use currency variables (because they can hold all the possible values), and this is the return type from binary.xxx() functions. For 64 bit unsigned integers we use decimal type. So a 0xFFFF_FFFF_FFFF_FFFF is a decimal type with the value of an unsigned integer 64bit equal to 18446744073709551615 decimal. We can use 18446744073709551615@ to define decimal literal. The 0xFFFF_FFFF_FFFF_FFFF&& literal is a signed long long and has value -1. M2000 use & for signed long, so 0xFFFF_FFFF& is -1 long, and use % for signed integer 16bit, so 0xFFFF% is -1. Also there is the Byte which is always unsigned from 0 to 255. So we make a HiLow variable (a buffer type) z and that became a closure to final lambda function (buffers are reference type so we put the pointer to lambda). Using buffer we can pass the address using z(0) which 0 is the offset of first item (the z has one item now but we can make it with many more) to an external function (passing the address is same like passing by reference but not the reference of the reference, so the reference stay as is, the value can be change). M2000 functions can use "reference of reference" if we use &z from each side (from caller and callee should defined as byreference using &), so if we pass a reference type by reference you can change the reference not only the value. This isn't something to do here. We only use the union to get the value of low long or high long  of the 64 bit long long.


Module Shift64bit {
  bit.shift=lambda ->{
    structure HiLow {
      {ab as long long} 'union with 2 long
      a as long, b as long
    }
    HiLow z ' make a z and put as closure to lambda
    =lambda z (z|ab, b, only32bit as boolean=false)-> {
      if abs(b)>63 then
        z|ab=0
      else.if b<-31 then
        b+=32
        z|a=binary.shift(z|b, b)
        z|b=0
      else.if b<0 then
        mask=binary.shift(0xFFFFFFFF, 32+b)
        z|a=binary.and(binary.rotate(z|b, b), mask)+binary.shift(z|a, b)
        z|b=binary.shift(z|b, b)
      else.if b=0 then
      else.if b<31 then
        mask=binary.shift(0xFFFFFFFF, b-32)
        z|b=binary.shift(z|b, b)+binary.and(binary.rotate(z|a, b), mask)
        z|a=binary.shift(z|a, b)
      else
        b-=32
        z|b=binary.shift(z|a, b)
        z|a=0
      end if
      if only32bit then =z|a else =z|ab  
    }
  }()
  a=0x1234AAAA
  aa=a+0xFFFF_AAAA_0000_0000
  for n=-64 to 64 step 4
    if abs(n)>63 then
      b=0#
      c=0@
    else
      refresh 100
      if abs(n)>31 then
        b=0
      else
        b=binary.shift(a, n)
      end if
      c=bit.shift(aa, n)
    end if
    print "bit shift:";n
    
    hex a
    hex b
    hex aa
    hex c
    push key$: drop
  next
  refresh 25
}
Shift64bit

 

Long multiplication using variable base (from 2 to 36)

A long multiplication using a lambda function with closures two lists, so we do the multiplication and additions using "memory". Also carry addition performed using "memory" also (through precalculated lists). We have to produce the final lambda by passing the base for the numbers. All computations use only strings in final lambda.

function placecoma(a as string) {
  if len(a)<4 then =a :exit  
  k=StrRev$(a)
  a=""
  for i=4 to len(k) step 3
    a+=mid$(k,i-3, 3)+","
  next
  a+=mid$(k, i-3)
  a=strrev$(a)
  if left$(a,1)="," then =mid$(a,2) else =a
}
long_mul=lambda (s=10) ->{
  m=list
  ad=list
  s1=s-1
  symb="0123456789ABCDEFGHIJKLMNOPQRSTUVWXZ"
  for i=0 to s1:for j=0 to s1:
    c=i*j
    if c<s then
      m(mid(symb,i+1,1)+mid(symb,j+1,1))=mid(symb,c+1,1)
    else
      m(mid(symb,i+1,1)+mid(symb,j+1,1))=mid(symb,(c div s)+1,1)+mid(symb,(c mod s)+1,1)
    end if  
  next:next
  for i=0 to s1:for j=0 to s1:
    c=i+j
    if c<s then
      ad(mid(symb,i+1,1)+mid(symb,j+1,1))=mid(symb,c+1,1)
    else
      ad(mid(symb,i+1,1)+mid(symb,j+1,1))=mid(symb,(c div s)+1,1)+mid(symb,(c mod s)+1,1)
    end if
  next:next    
  =lambda m, ad (a as string, b as string) -> {    
    a=filter(a,",")
    b=filter(b,",")
    sign=1
    if left(a,1)="-" then sign=-1:insert 1,1 a=""
    if left(b,1)="-" then sign*=-1:insert 1,1 b=""
    ii=len(b)+1
    jj=len(a)+1
    zero=0
    acc="0"
    f=list:=0
    if a="0" then =a :exit
    for i=1 to len(b)
      bb=mid(b,ii-i,1)
      c="0"
      if not exist(f, bb) then
        dd=string$("0", len(a))
        for j=1 to len(a)
          d=m(mid(a,jj-j,1)+bb)
          if c<>"0" then
            if len(d)>1 then              
              d1=ad(right(d,1)+c)
              if len(d1)>1 then
                d2=ad(left(d,1)+left(d1,1))
                d=d2+d1
              else
                insert 2,1 d=d1
              end if
            else
              d=ad(d+c)
            end if
          end if
          c="0" :  if len(d)>1 then c=left(d,1):d=right(d,1)
          insert jj-j,1 dd=d
        next
        if c<>"0" then f(bb)=c+dd else f(bb)=dd
      end if
      if bb<>"0" then
        p1=len(f(bb))
        p=len(acc)-zero
        if p<1 then
          acc=string$("0",2-p)+acc
          p=len(acc)-zero
        end if
        c="0"
        for kk=p1 to 1
          d=""+ad(mid(acc, p,1)+mid(f(bb),kk,1))
          if c<>"0" then
            if len(d)>1 then              
              d1=ad(right(d,1)+c)
              if len(d1)>1 then
                d2=ad(left(d,1)+left(d1,1))
                d=d2+d1
              else
                insert 2,1 d=d1
              end if
            else
              d=""+ad(d+c)
            end if
          end if          
          c="0" : if len(d)>1 then c=left(d,1):d=right(d,1)
          insert p, 1 acc=d
          p-- : if p<1 and kk>1 then p=1:acc=c+acc:c="0"
        next
        if c<>"0" then
        if p<1 then acc=c+acc else insert p, 1 acc=c
        end if
      end if
      zero+=1
    next
    if sign<0 then
      ="-"+acc
    else
      =acc
    end if
  }
}
long_mul10=long_mul(10)
a="18,446,744,073,709,551,616"
print placecoma(long_mul10(a, a))="340,282,366,920,938,463,463,374,607,431,768,211,456"
print long_mul10("-832764873673674323484", "234242938742937483278432798279428")=""+(-832764873673674323484u*234242938742937483278432798279428u)
long_mul2=long_mul(2)
print long_mul2("1010101","11")="11111111"
long_mul16=long_mul(16)
print long_mul16("55","3")="FF", 0x55*0x3=0xFF


print long_mul16("55","2")="AA"
long_mul8=long_mul(8)
print long_mul8("7","2")="16"  ' 14 = 14


Δευτέρα 6 Ιουλίου 2026

ΤΑΞΙΝΟΜΗΣΗ ΦΥΣΑΛΙΔΑΣ

Συνήθως στη ταξινόμηση φυσαλίδας δείχνουν μια ταξινόμηση ενός σταθερού πίνακα τιμών που ξεκινάει από το πρώτο στοιχείο προς το τελευταίο, και με διαδοχικά περάσματα ο αλγόριθμος σταματάει ότι σε ένα πέρασμα δεν γίνεται καμία αλλαγή

Στο πρόγραμμα που ακολουθεί (το γράφουμε σε ένα τμήμα, με αντιγραφή από εδώ), βλέπουμε δυο αλγόριθμους, ένας δουλεύει από κάτω προς τα πάνω και ένας ανάποδα. Στη πράξη αν ο πίνακας αυξάνεται από το τέλος, δηλαδή είχε 10 στοιχεία και τα κάνουμε 11, τότε θα θέλαμε η ταξινόμηση να γίνεται από πάνω προς τα κάτω, ειδικά όταν τα πρώτα 10 είναι ήδη ταξινομημένα! Αυτό το πρόγραμμα δείχνει με οπτικό τρόπο γιατί μας συμφέρει αυτό! Ο στάνταρ τρόπος θα ήταν καλός αν βάζαμε τα νέα στοιχεία πριν από τα παλιά, δηλαδή τα παλιά να μετακινηθούν ένα στοιχείο για να έχουμε θέση για το πρώτο νέο στοιχείο. Αυτό είναι εύκολο στη Μ2000 γιατί με το Α#Αρχή((200,)) βάζουμε τον αυτόματο πίνακα ενός στοιχείου, το (200,) πριν από τα στοιχεία του Α() και ο νέος πίνακας γίνεται ο νέος Α(), που στην ρουτίνα ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ_1 είναι τοπική ως Α() άρα δεν είναι το Α() πριν την κλήση.

Σε κάθε περίπτωση μετράμε τις αλλαγές και τις συγκρίσεις και καλούμε μια απλή ρουτίνα (μόνο με μια ΔΙΑΜΕΣΟΥ (GOSUB) και επιστροφή με το ΕΠΙΣΤΡΟΦΗ (RETURN) (όπως στη BASIC).

Γενικά οι Ρουτίνες  (ΡΟΥΤΙΝΑ/ΤΕΛΟΣ ΡΟΥΤΙΝΑΣ) όπως και οι απλές ρουτίνες (ΕΤΙΚΕΤΑ/ΕΠΙΣΤΡΟΦΗ), έχουν θέαση στα στοιχεία του τμήματος. Η απλή ρουτίνα δεν έχει τοπικές μεταβλητές  (αν φτιάξουμε με το ΤΟΠΙΚΗ ή ΤΟΠΙΚΕΣ δεν θα μας πει οχι το σύστημα αλλά στην επιστροφή δεν θα τις σβήσει, άρα σε κάθε κλήση θα σκιάζουμε τις προηγούμενες με το ίδιο όνομα!

Τα τμήματα διαφέρουν από τις ρουτίνες γιατί εντός  ενός τμήματος βλέπουμε ότι φτιάχνουμε και μόνο ότι έχει δηλωθεί και φτιαχτεί πιο πριν ως γενικό, αλλά πάντα κάτι τοπικό με το ίδιο όνομα σκιάζει το γενικό. Σς αντικελίμενα το τμήμα είναι μεθοδος και βλέπει επίσης και τις ιδιότητες, μεταβλητές και τμήματα/συναρτήσεις του αντικειμένου.  Επίσης δεν μπορούμε να κάνουμε άλματα ή να καλέσουμ διαμέσου ετικέτας σε ετικέτα εκτός του τμήματος, όπως μπορούμε να κάνουμε σε ρουτίνα. Ένα τμήμα δεν βλέπει ούτε το "αδελφάκι" τμήμα που φτιάχτηκε στο ίδιο "γονικό" τμήμα (με εξαίρεση τα τμήματα ενός αντικειμένου που αποτελούν μεθόδους του. Επίσης δεν μπορεί να καλέσει τον εαυτό του με το όνομά του μόνο (θέλει μια ΚΑΛΕΣΕ όνομα_τμήματος). Μια ρουτίνα μπορεί να καλέσει τον εαυτό της!

Τα τμήματα όπως και οι ρουτίνες μεταβιβάζουν τον τρέχον σωρό στη κλήση οπότε αν θέλουμε (με προσοχή) μπορούμε να αφήνουμε στοιχεία στο σωρό τιμών. Για παράδειγμα μπορούμε να βάλουμε στο σωρό τιμών το όρισμα της παραμέτρου (του Α()) και μετά να καλέσουμε τη ρούτινα:

ΒΑΛΕ Α()#ΑΡΧΗ((200,)): ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ_1

Η ρουτίνα ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ_1 παίρνει τον πίνακα και τον βάζει στο Α() χωρίς να ορίσουμε με την ΠΙΝΑΚΑΣ τον πίνακα. Επειδή δουλεύουμε εδώ με μιας διάστασης πίνακα, μαθαίνουμε πόσα στοιχεία έχει με την ΜΗΚΟΣ(Α()) και εξ ορισμού η βάση των πινάκων είναι το 0 άρα έχουμε από το 0 έως το ΜΗΚΟΣ(Α())-1 δείκτες για στοιχεία στο Α(). Και στις δυο ρουτίνες δουλεύουμε με δυο μεταβλητές που αυξάνουμε μαζί ή μειώνουμε ανάλογα από που ξεκινάμε.


100 87 55 45 3 2 1
1 100 87 55 45 3 2
1 2 100 87 55 45 3
1 2 3 100 87 55 45
1 2 3 45 100 87 55
1 2 3 45 55 100 87
1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:21
ΣΥΓΚΡΙΣΕΙΣ:42

1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:0
ΣΥΓΚΡΙΣΕΙΣ:6

2 3 45 55 87 100 1
1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:6
ΣΥΓΚΡΙΣΕΙΣ:12

100 1 2 3 45 55 87
1 100 2 3 45 55 87
1 2 100 3 45 55 87
1 2 3 100 45 55 87
1 2 3 45 100 55 87
1 2 3 45 55 100 87
1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:6
ΣΥΓΚΡΙΣΕΙΣ:42

100 1 2 3 45 55 87
1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:6
ΣΥΓΚΡΙΣΕΙΣ:12

1 2 55 3 45 87 100
1 2 3 55 45 87 100
1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:2
ΣΥΓΚΡΙΣΕΙΣ:18

1 2 55 3 45 87 100
1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:2
ΣΥΓΚΡΙΣΕΙΣ:12

1 2 3 45 55 87 100 -10
-10 1 2 3 45 55 87 100
-10 1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:7
ΣΥΓΚΡΙΣΕΙΣ:14

200 -10 1 2 3 45 55 87 100
-10 1 2 3 45 55 87 100 200
-10 1 2 3 45 55 87 100 200
ΑΛΛΑΓΕΣ:8
ΣΥΓΚΡΙΣΕΙΣ:16



ΣΤΑΤΙΚΗ ΡΟΥΤΙΝΑ ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ_1
' για να καλούμε τη ρουτίνα χωρίς παρενθέσεις.


ΜΕΤΑΒΛΗΤΕΣ ΑΛΛΑΓΕΣ, ΣΥΓΚΡΙΣΕΙΣ, ΠΡΟΗΓΟΥΜΕΝΕΣ
ΜΕΤΑΒΛΗΤΕΣ Κ, Ι, Τ1, Τ2
ΤΥΠΩΣΕ "ΤΑΞΙΜΟΜΗΣΗ ΦΥΣΑΛΙΔΑΣ"
ΠΙΝΑΚΑΣ Α()
Α()=(100,87,55,45,3, 2,1) ' 21 ΑΛΛΑΓΕΣ 42 ΣΥΓΚΡΙΣΕΙΣ
ΔΙΑΜΕΣΟΥ ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ
Α()=(1,2,3,45,55,87,100) ' 0 ΑΛΛΑΓΕΣ 6 ΣΥΓΚΡΙΣΕΙΣ
ΔΙΑΜΕΣΟΥ ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ
Α()=(2,3,45,55,87,100,1) ' 6 ΑΛΛΑΓΕΣ 12 ΣΥΓΚΡΙΣΕΙΣ
ΔΙΑΜΕΣΟΥ ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ
Α()=(100,1,2,3,45,55,87)
ΔΙΑΜΕΣΟΥ ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ ' 6 ΑΛΛΑΓΕΣ 42 ΣΥΓΚΡΙΣΕΙΣ
ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ_1 (100,1,2,3,45,55,87) ' 6 ΑΛΛΑΓΕΣ 12 ΣΥΓΚΡΙΣΕΙΣ
Α()=(1,2,55,3,45,87,100) ' 2 ΑΛΛΑΓΕΣ 18 ΣΥΓΚΡΙΣΕΙΣ
ΔΙΑΜΕΣΟΥ ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ


' 2 ΑΛΛΑΓΕΣ 18 ΣΥΓΚΡΙΣΕΙΣ
ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ_1 (1,2,55,3,45,87,100)


' ΕΔΩ ΕΙΝΑΙ ΤΟ ΚΕΡΔΟΣ ΑΝ ΕΧΟΥΜ ΗΔΗ ΤΑΞΙΝΟΜΗΜΕΜΟ ΠΙΝΑΚΑ
' ΑΝΑΛΟΓΑ ΑΝ ΒΑΛΟΥΜΕ ΕΝΑ ΝΕΟ ΣΤΟΙΧΕΙΟ ΣΤΗΝ ΑΡΧΗ Η ΣΤΟ ΤΕΛΟΣ
' ΔΙΑΛΕΓΟΥΜΕ ΡΟΥΤΙΝΑ


' ΒΆΖΟΥΜΕ ΕΝΑΝ ΠΙΝΑΚΑ ΣΤΟ ΤΕΛΟΣ ΤΟΥ ΠΙΝΑΚΑ
Α()=Α()#ΤΕΛΟΣ((-10,)) ' ΣΥΜΦΕΡΕΙ Η ΑΝΑΣΤΡΟΦΗ
ΔΙΑΜΕΣΟΥ ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ ' 7 ΑΛΛΑΓΡΣ 14 ΣΥΓΚΡΙΣΕΙΣ
' ΒΑΖΟΥΜΕ ΕΝΑΝ ΠΙΝΑΚΑ ΣΤΗΝ ΑΡΧΗ ΤΟΥ ΠΙΝΑΚΑ
ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ_1 Α()#ΑΡΧΗ((200,)) ' 8 ΑΛΛΑΓΕΣ 16 ΣΥΓΚΡΙΣΕΙΣ


ΤΕΛΟΣ
' ΧΡΗΣΗ ΡΟΥΤΙΝΑΣ ΜΕ ΤΟΠΙΚΕΣ ΜΕΤΑΒΛΗΤΕΣ
' ΚΛΗΣΗ ΑΠΛΩΝ ΡΟΥΤΙΝΩΝ ΜΕΣΑ ΑΠΟ ΤΗΝ ΡΟΥΤΙΝΑ
' ΞΕΚΙΝΑΕΙ ΑΠΟ ΤΟ ΠΡΩΤΟ ΣΤΟΙΧΕΙΟ ΠΡΟΣ ΤΟ ΤΕΛΕΥΤΑΙΟ
ΡΟΥΤΙΝΑ ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ_1(Α())
  ΤΟΠΙΚΕΣ ΑΛΛΑΓΕΣ=0, ΣΥΓΚΡΙΣΕΙΣ=0, ΠΡΟΗΓΟΥΜΕΝΕΣ=0
  ΤΟΠΙΚΕΣ Τ1=ΜΗΚΟΣ(Α()), Τ2=Τ1-1, Κ, Ι
  ΑΝ Τ2<1 ΤΟΤΕ ΛΑΘΟΣ "ΘΕΛΩ ΤΟΥΛΑΧΙΣΤΟΝ ΔΥΟ ΣΤΟΙΧΕΙΑ"
  ΔΙΑΜΕΣΟΥ ΕΜΦΑΝΙΣΗ_ΠΙΝΑΚΑ


  ΕΠΑΝΕΛΑΒΕ
    Κ=0:Ι=Κ+1: ΠΡΟΗΓΟΥΜΕΝΕΣ=ΑΛΛΑΓΕΣ
    ΕΠΑΝΕΛΑΒΕ ΣΥΓΚΡΙΣΕΙΣ++
      ΑΝ Α(Ι)<Α(Κ) ΤΟΤΕ ΑΛΛΑΞΕ Α(Ι), Α(Κ): ΑΛΛΑΓΕΣ++
      Ι++:Κ++
    ΟΣΟ Ι<Τ1
    ΔΙΑΜΕΣΟΥ ΕΜΦΑΝΙΣΗ_ΠΙΝΑΚΑ
  ΟΣΟ ΠΡΟΗΓΟΥΜΕΝΕΣ<>ΑΛΛΑΓΕΣ
  
  ΔΙΑΜΕΣΟΥ ΑΠΟΤΕΛΕΣΜΑΤΑ
ΤΕΛΟΣ ΡΟΥΤΙΝΑΣ
' ΧΡΗΣΗ ΑΠΛΗΣ ΡΟΥΤΙΝΑΣ ΧΩΡΙΣ ΤΟΠΙΚΕΣ ΜΕΤΑΒΛΗΤΕΣ
' ΕΠΙΣΗΣ ΧΡΗΣΗ ΕΤΙΚΕΤΩΝ ΚΑΙ ΤΗΣ ΠΡΟΣ (GOTO)
' ΞΕΚΙΝΑΕΙ ΑΠΟ ΤΕΛΕΥΤΑΙΟ ΣΤΟΙΧΕΙΟ ΠΡΟΣ ΤΟ ΠΡΩΤΟ
ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ:
  ΑΛΛΑΓΕΣ=0:ΣΥΓΚΡΙΣΕΙΣ=0:ΠΡΟΗΓΟΥΜΕΝΕΣ=0
  Τ1=ΜΗΚΟΣ(Α()):Τ2=Τ1-1
  ΑΝ Τ2<1 ΤΟΤΕ ΛΑΘΟΣ "ΘΕΛΩ ΤΟΥΛΑΧΙΣΤΟΝ ΔΥΟ ΣΤΟΙΧΕΙΑ"
  ΔΙΑΜΕΣΟΥ ΕΜΦΑΝΙΣΗ_ΠΙΝΑΚΑ


ΕΚΚΙΝΗΣΗ: ' στις ετικέτες μπορούμε να βάλουμε δίπλα μόνο σημειώσεις.
  Κ=Τ2:Ι=Κ-1: ΠΡΟΗΓΟΥΜΕΝΕΣ=ΑΛΛΑΓΕΣ


10ΣΥΓΚΡΙΣΕΙΣ++
  ΑΝ Α(Ι)>Α(Κ) ΤΟΤΕ ΑΛΛΑΞΕ Α(Ι), Α(Κ): ΑΛΛΑΓΕΣ++
  Ι--:Κ--:ΑΝ Ι>=0 ΤΟΤΕ 10
  
  ΔΙΑΜΕΣΟΥ ΕΜΦΑΝΙΣΗ_ΠΙΝΑΚΑ
  ΑΝ ΠΡΟΗΓΟΥΜΕΝΕΣ<>ΑΛΛΑΓΕΣ ΤΟΤΕ ΠΡΟΣ ΕΚΚΙΝΗΣΗ
  
  ΔΙΑΜΕΣΟΥ ΑΠΟΤΕΛΕΣΜΑΤΑ
ΕΠΙΣΤΡΟΦΗ


ΑΠΟΤΕΛΕΣΜΑΤΑ:  
  ΤΥΠΩΣΕ "ΑΛΛΑΓΕΣ:";ΑΛΛΑΓΕΣ
  ΤΥΠΩΣΕ "ΣΥΓΚΡΙΣΕΙΣ:";ΣΥΓΚΡΙΣΕΙΣ
  ΤΥΠΩΣΕ "ΠΑΤΑ ΕΝΑ ΠΛΗΚΤΡΟ": ΒΑΛΕ ΚΟΜ$: ΠΕΤΑ
ΕΠΙΣΤΡΟΦΗ


ΕΜΦΑΝΙΣΗ_ΠΙΝΑΚΑ:
  ΤΥΠΩΣΕ Α()#ΓΡΑΦΗ$(" ")
ΕΠΙΣΤΡΟΦΗ



Υπάρχει και ένας τρόπος  βελτιστοποίησης, όπου όμως αν παρατηρήσετε απλά λιγοστεύει τις συγκρίσεις όταν δεν έχουμε ταξινομημένο πίνακα. Δείτε στα τελευταία δυο παραδείγματα γλιτώνουμε μόνο μια σύγκριση!


100 87 55 45 3 2 1
1 100 87 55 45 3 2
1 2 100 87 55 45 3
1 2 3 100 87 55 45
1 2 3 45 100 87 55
1 2 3 45 55 100 87
1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:21
ΣΥΓΚΡΙΣΕΙΣ:22

1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:0
ΣΥΓΚΡΙΣΕΙΣ:6

2 3 45 55 87 100 1
1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:6
ΣΥΓΚΡΙΣΕΙΣ:11

100 1 2 3 45 55 87
1 100 2 3 45 55 87
1 2 100 3 45 55 87
1 2 3 100 45 55 87
1 2 3 45 100 55 87
1 2 3 45 55 100 87
1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:6
ΣΥΓΚΡΙΣΕΙΣ:22

100 1 2 3 45 55 87
1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:6
ΣΥΓΚΡΙΣΕΙΣ:11

1 2 55 3 45 87 100
1 2 3 55 45 87 100
1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:2
ΣΥΓΚΡΙΣΕΙΣ:15

1 2 55 3 45 87 100
1 2 3 45 55 87 100
1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:2
ΣΥΓΚΡΙΣΕΙΣ:11

1 2 3 45 55 87 100 -10
-10 1 2 3 45 55 87 100
-10 1 2 3 45 55 87 100
ΑΛΛΑΓΕΣ:7
ΣΥΓΚΡΙΣΕΙΣ:13

200 -10 1 2 3 45 55 87 100
-10 1 2 3 45 55 87 100 200
-10 1 2 3 45 55 87 100 200
ΑΛΛΑΓΕΣ:8
ΣΥΓΚΡΙΣΕΙΣ:15

200 -10 1 2 3 45 55 87 100
-10 1 2 3 45 55 87 100 200
-10 1 2 3 45 55 87 100 200
ΑΛΛΑΓΕΣ:8
ΣΥΓΚΡΙΣΕΙΣ:15

Στην απλή ρουτίνα βάζουμε μια Ν στις μεταβλητές στην αρχή έξω από τη ρουτίνα, και στην ρουτίνα βάζουμε την αρχική τιμή Ν=0, μετά το Ι>=0 γίνεται Ι>=1 και μετά πριν το ΠΡΟΣ ΕΚΚΙΝΗΣΗ βάζουμε το Ν++ (να αυξάνει κατά 1).

ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ:
  ΑΛΛΑΓΕΣ=0:ΣΥΓΚΡΙΣΕΙΣ=0:ΠΡΟΗΓΟΥΜΕΝΕΣ=0
  Τ1=ΜΗΚΟΣ(Α()):Τ2=Τ1-1
  ΑΝ Τ2<1 ΤΟΤΕ ΛΑΘΟΣ "ΘΕΛΩ ΤΟΥΛΑΧΙΣΤΟΝ ΔΥΟ ΣΤΟΙΧΕΙΑ"
  ΔΙΑΜΕΣΟΥ ΕΜΦΑΝΙΣΗ_ΠΙΝΑΚΑ
  Ν=0
ΕΚΚΙΝΗΣΗ: ' στις ετικέτες μπορούμε να βάλουμε δίπλα μόνο σημειώσεις.
  Κ=Τ2:Ι=Κ-1: ΠΡΟΗΓΟΥΜΕΝΕΣ=ΑΛΛΑΓΕΣ
10ΣΥΓΚΡΙΣΕΙΣ++
  ΑΝ Α(Ι)>Α(Κ) ΤΟΤΕ ΑΛΛΑΞΕ Α(Ι), Α(Κ): ΑΛΛΑΓΕΣ++
  Ι--:Κ--:ΑΝ Ι>=Ν ΤΟΤΕ 10
  
  ΔΙΑΜΕΣΟΥ ΕΜΦΑΝΙΣΗ_ΠΙΝΑΚΑ
  ΑΝ ΠΡΟΗΓΟΥΜΕΝΕΣ<>ΑΛΛΑΓΕΣ ΤΟΤΕ Ν++: ΠΡΟΣ ΕΚΚΙΝΗΣΗ
  
  ΔΙΑΜΕΣΟΥ ΑΠΟΤΕΛΕΣΜΑΤΑ
ΕΠΙΣΤΡΟΦΗ



Στη Ρουτίνα βάζουμε μια Ν, που γίνεται Τ1+1 γιατί με το που θα μπούμε στην εξωτερική ΕΠΑΝΕΛΑΒΕ θα κάνουμε το Ν-- και στην εσωτερική ΕΠΑΝΕΛΑΒΕ στην ΟΣΟ βάζουμε το Ι<Ν από το Ι<Τ1

ΡΟΥΤΙΝΑ ΤΑΞΙΝΟΜΗΣΗ_ΦΥΣΑΛΙΔΑΣ_1(Α())
  ΤΟΠΙΚΕΣ ΑΛΛΑΓΕΣ=0, ΣΥΓΚΡΙΣΕΙΣ=0, ΠΡΟΗΓΟΥΜΕΝΕΣ=0
  ΤΟΠΙΚΕΣ Τ1=ΜΗΚΟΣ(Α()), Τ2=Τ1-1, Κ, Ι, Ν
  ΑΝ Τ2<1 ΤΟΤΕ ΛΑΘΟΣ "ΘΕΛΩ ΤΟΥΛΑΧΙΣΤΟΝ ΔΥΟ ΣΤΟΙΧΕΙΑ"
  ΔΙΑΜΕΣΟΥ ΕΜΦΑΝΙΣΗ_ΠΙΝΑΚΑ
  Ν=Τ1+1
  ΕΠΑΝΕΛΑΒΕ
    Ν--
    Κ=0:Ι=Κ+1: ΠΡΟΗΓΟΥΜΕΝΕΣ=ΑΛΛΑΓΕΣ
    ΕΠΑΝΕΛΑΒΕ ΣΥΓΚΡΙΣΕΙΣ++
      ΑΝ Α(Ι)<Α(Κ) ΤΟΤΕ ΑΛΛΑΞΕ Α(Ι), Α(Κ): ΑΛΛΑΓΕΣ++
      Ι++:Κ++
    ΟΣΟ Ι<Ν
    ΔΙΑΜΕΣΟΥ ΕΜΦΑΝΙΣΗ_ΠΙΝΑΚΑ
  ΟΣΟ ΠΡΟΗΓΟΥΜΕΝΕΣ<>ΑΛΛΑΓΕΣ
  
  ΔΙΑΜΕΣΟΥ ΑΠΟΤΕΛΕΣΜΑΤΑ
ΤΕΛΟΣ ΡΟΥΤΙΝΑΣ


Για να εξάγουμε τα στοιχεία και να τα βάλουμε σε κάποιο blog ή έγγραφο:
Βάζουμε μια γραμμή στην αρχή του προγράμματος:
εγγραφο εγ$

Μετά αλλάζουμε δυο ρουτίνες για να γεμίζουμε το έγγραφο

ΑΠΟΤΕΛΕΣΜΑΤΑ:  
  ΤΥΠΩΣΕ "ΑΛΛΑΓΕΣ:";ΑΛΛΑΓΕΣ
  ΤΥΠΩΣΕ "ΣΥΓΚΡΙΣΕΙΣ:";ΣΥΓΚΡΙΣΕΙΣ
  εγ$="ΑΛΛΑΓΕΣ:"+ΑΛΛΑΓΕΣ+{
  }+"ΣΥΓΚΡΙΣΕΙΣ:"+ΣΥΓΚΡΙΣΕΙΣ+{
  
  }
  ΤΥΠΩΣΕ "ΠΑΤΑ ΕΝΑ ΠΛΗΚΤΡΟ": ΒΑΛΕ ΚΟΜ$: ΠΕΤΑ
ΕΠΙΣΤΡΟΦΗ


ΕΜΦΑΝΙΣΗ_ΠΙΝΑΚΑ:
  εγ$=Α()#ΓΡΑΦΗ$(" ")+{
  }
  ΤΥΠΩΣΕ Α()#ΓΡΑΦΗ$(" ")
ΕΠΙΣΤΡΟΦΗ


Και πριν τον τερματισμό του προγράμματος στέλνουμε τα στοιχεία στο πρόχειρο:

Πρόχειρο εγ$


Ή αν θέλουμε να εξάγουμε αρχείο  (utf-8 με BOM) και να το ανοίξουμε στο πρόχειρο:
Σώσε.Εγγραφο εγ$, "bubble.txt"
Συστημα "notepad", κατ$+"bubble.txt"