Κυριακή 6 Ιανουαρίου 2019

New Primes Algorithm

This program first publish here
Use Revision 20 (bug on ELSE <number labels> fixed)

Now we can make a bigger computation using Fast! mode which eliminate Gui/console refresh to gain speed. We can make a refresh each 50primes, so we have a tiny delay on refreshing if we move a window above M2000 console.
Also I change IsPrime to not add to Inventory Known1, because we want this inventory to have all primes without any missing until the last one.
I provide another IsPrime2 which use PrimeNth to add to Known1.
Inventories are reference type. Lambda functions are value type, but closures which are reference type copied the reference by value, so we get then by reference. Inventories start now with 3 known primes, and PrimeNth works for odd numbers only (see x+=2 before the loop statement)
Loop statement check a flag in a block of code ({ }), so when the block ends restart again (resetting the loop flag)


Module CheckPrimes {
      \\ Inventories are lists, Known and Known1 are pointers to Inventories
      Inventory Known=1:=2@,2:=3@,3:=5@
      Inventory Known1=2@, 3@, 5@
      \\ In a lambda all closures are copies
      \\ but Known and Know1 are copies of pointers
      \\ so are closures like by reference
      PrimeNth=lambda Known, Known1 (n as long) -> {
            if n<1 then Error "Only >=1"
            if exist(known, n) then =eval(known) : exit
            if n>5 then {
                 i=len(known1)
                 x=eval(known1, i-1)+2
            } else x=5 : i=2
            {
                  if i=n then =known(n) : exit
                  ok=false
                  if frac(x) then 1000
                  if frac(x/2) else 1000
                  if frac(x/3) else 1000
                  x1=sqrt(x) : d=5@
                  Repeat
                        if frac(x/d ) else exit
                        d += 2: if d>x1 then ok=true : exit
                        if frac(x/d) else exit
                        d += 4: if d<= x1 else ok=true: exit
                   Always
      1000 If ok then i++:Append Known, i:=x : if not exist(Known1, x) then Append Known1, x
                   x+=2 : Loop }
      }
      \\ IsPrime has same closure, Known1
      IsPrime=lambda Known1 (x as decimal) -> {
            if exist(Known1, x) then =true : exit
            if Eval(Known1, len(Known1)-1)>x then exit
            if frac(x/2) else exit
            if frac(x/3) else exit
            x1=sqrt(x):d = 5@
            {if frac(x/d ) else exit
                  d += 2: if d>x1 then =true : exit
                  if frac(x/d) else exit
                  d += 4: if d<= x1 else =true: exit
                  loop
             }
      }
      \\ fill Known1, PrimeNth is a closure here
      IsPrime2=lambda Known1, PrimeNth (x as decimal) -> {
            if exist(Known1, x) then =true : exit
            i=len(Known1)
            if Eval(Known1, i-1)>x then exit
            {
                  z=PrimeNth(i)
                  if z<x then loop else.if z=x then =true :exit
                  i++
            }
      }
      Print "First twenty primes"
      n=PrimeNth(20)
      For i=1 to 20 : Print Known(i),: Next i
      Print
      Print "Primes between 100 and 150:"
      c=0
      For i=100 to 150
            If IsPrime2(i) Then print i, : c++
      Next i
      Print
      Print "Count:", c
      Print "Primes between 7700 and 8000:"
      c=0
      For i=7700 to 8000
            If IsPrime(i) Then print i, : c++
      Next i
      Print
      Print "Count:", c
      Print "200th Prime:"
      Print PrimeNth(200)
      Print "List from 190th to 199th Prime:"
      For i=190 to 199 : Print Known(i), : Next i
      Print
      Print "Wait"
      Refresh ' because refresh happen on next Print, which take time
      ' using set fast we get no respond from GUI/M2000 Console
      ' also Esc, Break and Ctrl+C not work
      ' we have to use Refresh each 500 primes to have one Refresh
      Set fast !
      for i=500 to 10000 step 50: m=PrimeNth(i): Print "."; :Refresh:Next i
      Print
      Print "10000th Prime:", PrimeNth(10000)
      ' reset speed to fast (there are three levels: slow/fast/fast!)
      set fast
      Print
      Rem 1 : Print Known
      Rem 2: Print Known1
}
CheckPrimes









First twenty primes
 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
Primes between 100 and 150:
 101 103 107 109 113 127 131 137 139 149
Count: 10
Primes between 7700 and 8000:
 7703 7717 7723 7727 7741 7753 7757 7759 7789 7793 7817 7823 7829 7841 7853 7867 7873 7877 7879 7883 7901 7907 7919 7927 7933 7937 7949 7951 7963 7993
Count: 30
200th Prime: 
 1223
List from 190th to 199th Prime:
 1151 1153 1163 1171 1181 1187 1193 1201 1213 1217
Wait
.... (truncate for output)
10000th Prime: 104729
 



And this is the code for optimization for PrimeNth()


PrimeNth=lambda Known, Known1 (n as long) -> {
      if n<1 then Error "Only >=1"
      if exist(known, n) then =eval(known) : exit
      if n>5 then {
           i=len(known1)
           x=eval(known1, i-1)+2
      } else x=5 : i=2
      {
            if i=n then =known(n) : exit
            if frac(x) then 999
            if frac(x/2) else 999
            if frac(x/3) else 999
            x1=sqrt(x) : d=5@
            {if frac(x/d ) else 999
                  d += 2: if d>x1 then 1000
                  if frac(x/d) else 999
                  d += 4: if d<= x1 else 1000
                  loop
             }
999 x++ : Restart
1000 i++:Append Known, i:=x : if not exist(Known1, x) then Append Known1, x
         x++ : Loop }
}


Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.