[3] Concurs - Numere prime

[3] Concurs - Numere prime

Postby Mihai » 15 Feb 2010, 22:14

Fiind foarte pasionat de numere [probabil, prietenii l-ar considera un ciudat - daca ar avea vreunul], George se intreaba ce procent din numerele naturale din intervalul inchis [1,N] (1<N<=2.000.000) sunt prime. Puteti sa-l ajutati ?

Exemplu:
Pentru N=15, numerele prime din intervalul [1,15] sunt: 2 3 5 7 11 13. In total, sunt 6 numere, deci se va afisa "40.00 %".

Atentie!
Intre numarul obtinut si simbolul "%", se va lasa un spatiu;
Rezultatul va fi afisat totdeauna cu 2 zecimale (sau mai mult);
Pentru a fi considerat corect, diferenta dintre rezultatul generat de program si cel corect trebuie sa fie, in modul, mai mica de 0.01;
Citirea lui N se va face din fisierul "bitcell3.in" iar afisarea rezultatului se va face in fisierul "bitcell3.out", in vederea evaluarii automate.

Durata:
15-20 Februarie - inscrierea in concurs
21 Februarie - declararea castigatorului

L.E.: Am modificat. Oboseala isi face simtit efectul. Daca mai gasiti lucruri in neregula, va rog nu mai postati in topicul concursului ci dati mesaj privat unuia dintre moderatori, pentru ca se face offtopic inutil, si vor fi mai greu de urmarit posturile cu adevarat importante.
0,0p / 0 votes
User avatar
Mihai
Byte
 
Joined: 29 Dec 2009
Status: 25

Re: [3] Concurs - Numere prime

Postby andreiandreiq » 18 Feb 2010, 18:26

Bitcell3.out trebuie sa contina si numerele care sunt prime sau doar procentul ?
0,0p / 0 votes
Image
User avatar
andreiandreiq
Word
 
Joined: 30 Dec 2009
Status: 33.33

Re: [3] Concurs - Numere prime

Postby Mihai » 19 Feb 2010, 13:46

Doar procentul.
0,0p / 0 votes
User avatar
Mihai
Byte
 
Joined: 29 Dec 2009
Status: 25

Re: [3] Concurs - Numere prime

Postby Wardog » 19 Feb 2010, 20:43

Particip eu, desi nu sunt prea multumit de rezolvarea gasita. Am incercat sa implementez ceva operatii pe biti pentru reducerea consumului de memorie, dar nu am reusit. Niciodata nu am inteles operatiile pe biti. :(

Programul e in atasament.

Later edit: Se pare ca nu pot folosi functia Private Message. Cum procedez cu sursa atunci? Pun linkul aici?
0,0p / 0 votes
Attachments
wardog_prime.zip
(10.57 KiB) Downloaded 51 times
Last edited by Wardog on 20 Feb 2010, 02:47, edited 1 time in total.
User avatar
Wardog
Bit
 
Joined: 17 Feb 2010
Status: 1

Re: [3] Concurs - Numere prime

Postby DarkByte » 20 Feb 2010, 01:16

Sursa o vei pune la sfarsitul concursului, cand trage Mihai alarma ;)

P.S. Contributia mea la concurs - in atasament.
1p / 1 votes
Attachments
darkbyte_prime.zip
(25.61 KiB) Downloaded 43 times
User avatar
DarkByte
11011011
 
Joined: 29 Dec 2009
Status: 136

Re: [3] Concurs - Numere prime

Postby v0id » 20 Feb 2010, 17:57

Programul meu: in atasament.

L.E.: A trebuit sa-l corectez pt. ca n-am fost atent la enunt... In loc de "<= 2.000.000", eu am considerat "< 2.000.000". Asta e, unii inca mai sunt obisnuiti ca la matematica, sa lase un patratel inainte si dupa operatori ca sa fie mai citet, iar orice alta forma de scriere este "parsata" gresit :p Noul executabil in atasament.
Multumesc lui DarkByte ca mi-a atras atentia.
1p / 1 votes
Attachments
v0id_prime.zip
(268.77 KiB) Downloaded 41 times
A good coder is never on holiday - he may be working on a different machine, that's about as far as it gets.
User avatar
v0id
Word
 
Joined: 05 Jan 2010
Location: 127.0.0.1
Status: 39.5

Re: [3] Concurs - Numere prime

Postby andreiandreiq » 20 Feb 2010, 21:39

Programul meu: in atasament.
1p / 1 votes
Attachments
andreiq_prime.zip
(6.22 KiB) Downloaded 48 times
Image
User avatar
andreiandreiq
Word
 
Joined: 30 Dec 2009
Status: 33.33

Re: [3] Concurs - Numere prime

Postby Dexter » 20 Feb 2010, 23:16

Hop şi eu pe ultima sută de metri... :p
(in atasament)
3p / 1 votes
Attachments
dexter_prime.zip
(9.57 KiB) Downloaded 51 times
User avatar
Dexter
Word
 
Joined: 04 Jan 2010
Location: Secret Lab
Status: 44.5

Re: [3] Concurs - Numere prime

Postby Mihai » 21 Feb 2010, 12:38

@WarDog: posteaza te rog sursa.
0,0p / 0 votes
User avatar
Mihai
Byte
 
Joined: 29 Dec 2009
Status: 25

Re: [3] Concurs - Numere prime

Postby Wardog » 21 Feb 2010, 16:42

  1. #include <fstream>
  2. #include <iomanip>
  3.  
  4. using namespace std;
  5.  
  6. ifstream f1 ("bitcell3.in");
  7. ofstream f2 ("bitcell3.out");
  8.  
  9. int v[2000000];
  10. long long n;
  11. float p;
  12.  
  13. void citire ()
  14. {
  15.     f1>>n;
  16.     f1.close ();
  17. }
  18.  
  19. void ciur ()
  20. {
  21.     for ( int i = 0; i < n; i++ )
  22.     {
  23.         v[i] = 1;
  24.     }
  25.     for( int i = 2;i*i <= n; i++ )
  26.     {
  27.         if(v[i]==1)
  28.             for ( int j = 2; j*i <= n; j++ )
  29.                 v[i*j]=0;
  30.     }
  31.  
  32. }
  33.  
  34. void rezolvare ()
  35. {
  36.     for ( int i = 2; i <= n; i++ )
  37.     {
  38.         if ( v[i] ) p++;
  39.     }
  40.  
  41.     p = (p/n)*100;
  42.  
  43.     f2<<setprecision(4)<<p<<" "<<"%"<<endl;
  44.     f2.close ();
  45. }
  46.  
  47. int main ()
  48. {
  49.     citire ();
  50.     ciur ();
  51.     rezolvare ();
  52.     return 0;
  53. }
1p / 1 votes
User avatar
Wardog
Bit
 
Joined: 17 Feb 2010
Status: 1

Re: [3] Concurs - Numere prime

Postby Mihai » 21 Feb 2010, 19:52

Castigatorul concursului este Dexter. Implementarea ciurului este foarte rapida multumita operatiilor pe biti.
Au mai fost si alte implementari de ciur (v0id si wardog, daca nu ma insel) insa au fost ceva mai lente. DarkByte a venit cu o solutie destul de rapida bazata pe factorizare.
Cea mai lenta solutie este cea a lui andreiandreiq, care testeaza pentru fiecare numar din intervalul [1,N] daca este prim.
In continuare, puteti vedea sursele:

DarkByte:
  1. program bitcell3;
  2.  
  3. {$APPTYPE CONSOLE}
  4.  
  5. uses SysUtils, Windows;
  6.  
  7. const LookupPrime : array [1..332] of Word = // pre-generated lookup table
  8.       (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89,
  9.        97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191,
  10.        193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293,
  11.        307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
  12.        421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
  13.        547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653,
  14.        659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787,
  15.        797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919,
  16.        929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019, 1021, 1031, 1033,
  17.        1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129,
  18.        1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249,
  19.        1259, 1277, 1279, 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367,
  20.        1373, 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481,
  21.        1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579,
  22.        1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693,
  23.        1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801,
  24.        1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931,
  25.        1933, 1949, 1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039,
  26.        2053, 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143,
  27.        2153, 2161, 2179, 2203, 2207, 2213, 2221, 2237);
  28.  
  29.   _FinishMessage = 'Press Enter to finish the program ...';
  30.  
  31. var nStart, nFinish, prCounter, prim: Longint;
  32.     tDurata: Cardinal;
  33.  
  34. procedure ReadFile; // input
  35. var fPrime: TextFile;
  36.     fName: String;
  37. begin
  38.   nStart := 1;
  39.  
  40.   fName := ExtractFilePath(ParamStr(0)) + 'bitcell3.in';
  41.   if FileExists(fName) then
  42.     begin
  43.       try
  44.         AssignFile(fPrime, fName);
  45.         try
  46.           ReSet(fPrime);
  47.           Read(fPrime, nFinish);
  48.           if (nFinish < 2) or (nFinish > 2000000) then
  49.             begin
  50.               WriteLn('Oopsie daisy ... allowed numbers are between 2 and 2 millions.');
  51.               WriteLn(_FinishMessage);
  52.               ReadLn;
  53.               halt(0);
  54.             end;
  55.         finally
  56.           CloseFile(fPrime);
  57.         end;
  58.       except
  59.         WriteLn('Weird error found : finders keepers !');
  60.         WriteLn(_FinishMessage);
  61.         ReadLn;
  62.       end;
  63.     end
  64.     else
  65.       begin
  66.         WriteLn('Fisierul "bitcell3.in" lipseste !');
  67.         WriteLn(_FinishMessage);
  68.         ReadLn;
  69.         Halt(0);
  70.       end;
  71. end;
  72.  
  73. procedure ComputePrimeNumbers; // calculations
  74. var iCounter, cnt, radNr: Longint;
  75.     ePrim, impar: Boolean;
  76. begin
  77.   prCounter := 0;
  78.  
  79.   prim := 0;
  80.   impar := False;
  81.  
  82.   iCounter := nStart;
  83.   while iCounter <= nFinish do
  84.     begin
  85.       radNr := Round(Sqrt(iCounter));
  86.  
  87.       ePrim := True;
  88.       cnt := 1;
  89.  
  90.       while cnt <= 332 do
  91.         begin
  92.           if LookupPrime[cnt] > radNr
  93.             then Break;
  94.  
  95.           if (iCounter mod LookupPrime[cnt] = 0) then
  96.             begin
  97.               ePrim := False;
  98.               Break;
  99.             end;
  100.           Inc(cnt);
  101.         end;
  102.  
  103.       if ePrim
  104.         then inc(prCounter);
  105.  
  106.       if (not Impar) then
  107.         if Odd(iCounter)
  108.           then Impar := True;
  109.  
  110.       if Impar
  111.         then Inc(iCounter, 2)
  112.         else Inc(iCounter);
  113.     end;
  114. end;
  115.  
  116. procedure WriteFile; // output
  117. var fPrime: TextFile;
  118.     fName: String;
  119. begin
  120.   fName := ExtractFilePath(ParamStr(0)) + 'bitcell3.out';
  121.   try
  122.     AssignFile(fPrime, fName);
  123.     try
  124.       ReWrite(fPrime);
  125.       Write(fPrime, ((prCounter * 100) / nFinish) : 7 : 5); // writing the percentage
  126.       Write(fPrime, ' %');
  127.     finally
  128.       CloseFile(fPrime);
  129.     end;
  130.   except
  131.     WriteLn('Weird error found : finders keepers !');
  132.     WriteLn(_FinishMessage);
  133.     ReadLn;
  134.   end;
  135.  
  136.   fName := ExtractFilePath(ParamStr(0)) + 'bitcell3.exec';
  137.   try
  138.     AssignFile(fPrime, fName);
  139.     try
  140.       ReWrite(fPrime); // logging the program's duration
  141.       Write(fPrime, 'Calculations done in ' + IntToStr(tDurata) + ' milliseconds.');
  142.     finally
  143.       CloseFile(fPrime);
  144.     end;
  145.   except
  146.     WriteLn('Weird error found : finders keepers !');
  147.     WriteLn(_FinishMessage);
  148.     ReadLn;
  149.   end;
  150. end;
  151.  
  152. begin
  153.   ReadFile;
  154.  
  155.   tDurata := GetTickCount;           // computing's start time
  156.   ComputePrimeNumbers;
  157.   tDurata := GetTickCount - tDurata; // computing's duration
  158.  
  159.   WriteFile;
  160. end.


v0id:
  1. unit frmMain;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, StdCtrls;
  8.  
  9. type
  10.   TFormMain = class(TForm)
  11.     btnCalculate: TButton;
  12.     lblN: TLabel;
  13.     lblResultsTop: TLabel;
  14.     memResults: TMemo;
  15.     procedure btnCalculateClick(Sender: TObject);
  16.   private
  17.     { Private declarations }
  18.   public
  19.     { Public declarations }
  20.   end;
  21.  
  22.  
  23.   TPrimes = class(TObject)
  24.   private
  25.     FNotPrimes: TBits;
  26.     FMaxNo: integer;
  27.   public
  28.     constructor Create(aMaxNo: integer);
  29.     destructor Destroy; override;
  30.     function IsItPrime(aNumber: integer) : boolean;
  31.   end;
  32.  
  33. var
  34.   FormMain: TFormMain;
  35.  
  36. const
  37.   FILENAME_INPUT = 'bitcell3.in';
  38.   FILENAME_OUTPUT = 'bitcell3.out';
  39.  
  40. implementation
  41.  
  42. {$R *.dfm}
  43.  
  44. //---------------------------------TPrimeNumbers--------------------------------
  45. constructor TPrimes.Create(aMaxNo: integer);
  46. var
  47.   lFirst, lSecond: integer;
  48. begin
  49.   // False = PRIM
  50.   FNotPrimes := TBits.Create;
  51.   FNotPrimes.Size := aMaxNo + 1;
  52.   FMaxNo := aMaxNo;
  53.  
  54.   for lFirst := 2 to FMaxNo div 2 do
  55.     if (not FNotPrimes[lFirst]) then
  56.       begin
  57.         // Numerele pare altele decat 2 nu sunt prime
  58.         if (lFirst <> 2) and ((lFirst mod 2) = 0) then
  59.           Continue;
  60.  
  61.         // Pornire de la al doilea element
  62.         lSecond := lFirst + lFirst;
  63.         while (lSecond <= FMaxNo) do
  64.           begin
  65.             // Nu este prim
  66.             FNotPrimes[lSecond] := True;
  67.             Inc(lSecond, lFirst);
  68.           end;
  69.       end;
  70.  
  71.    // Setare elemente 1 si 2
  72.    FNotPrimes[1] := True;
  73.    FNotPrimes[2] := False;
  74. end;
  75.  
  76. function TPrimes.IsItPrime(aNumber: integer) : boolean;
  77. begin
  78.   Result := not FNotPrimes[aNumber];
  79. end;
  80.  
  81. destructor TPrimes.Destroy;
  82. begin
  83.   FNotPrimes.Free;
  84.   inherited;
  85. end;
  86.  
  87.  
  88. //---------------------------------TFormMain------------------------------------
  89. procedure TFormMain.btnCalculateClick(Sender: TObject);
  90. var
  91.   lTempList: TStringList;
  92.   lPrimeNumbers: TPrimes;
  93.   lInputN: integer;
  94.   lPrimeStr: string;
  95.   lPrimeCount: integer;
  96.   lPercentStr: string;
  97.   iCounter: integer;
  98. begin
  99.   memResults.Clear;
  100.  
  101.   // Verificare daca exista fisierul de intrare
  102.   if (not FileExists(ExtractFilePath(ParamStr(0)) + FILENAME_INPUT)) then
  103.      begin
  104.        MessageDlg('Fisierul de intrare "' + FILENAME_INPUT + '" nu exista!', mtError, [mbOK], 0);
  105.        Exit;
  106.      end;
  107.  
  108.   // TStringList pt. salvare/incarcare fisiere. Religia imi interzice sa folosesc TextFile.
  109.   lTempList := TStringList.Create;
  110.   try
  111.     lTempList.LoadFromFile(ExtractFilePath(ParamStr(0)) + FILENAME_INPUT);
  112.  
  113.     // Verificare daca avem un N valid
  114.     try
  115.       lInputN := StrToInt(lTempList.Strings[0]);
  116.     except
  117.       on E: Exception do
  118.         begin
  119.           if (E is EConvertError)
  120.             then MessageDlg('Fisierul de intrare nu contine un numar!' + E.Message, mtError, [mbOK], 0)
  121.             else MessageDlg('S-a intalnit o exceptie la citirea numarului din fisierul de intrare: ' + E.Message, mtError, [mbOK], 0);
  122.           Exit;
  123.         end;
  124.     end;
  125.  
  126.     // Verificare daca N se incadreaza in conditia 1 < N <= 2.000.000
  127.     if (lInputN < 2) or (lInputN > 2000000) then
  128.       begin
  129.         MessageDlg('Numarul ' + IntToStr(lInputN) + ' nu se incadreaza in conditia 1 < N <= 2.000.000!', mtError, [mbOK], 0);
  130.         Exit;
  131.       end;
  132.  
  133.  
  134.     // In sfarsit procesare...
  135.     lblN.Caption := 'N: ' + IntToStr(lInputN);
  136.     Application.ProcessMessages;
  137.  
  138.     lPrimeStr := EmptyStr;
  139.     lPrimeCount := 0;
  140.     lPrimeNumbers := TPrimes.Create(lInputN);
  141.     try
  142.       for iCounter := 2 to lInputN do
  143.         begin
  144.           if lPrimeNumbers.IsItPrime(iCounter) then
  145.             begin
  146.               if (lPrimeStr = EmptyStr)
  147.                 then lPrimeStr := IntToStr(iCounter)
  148.                 else lPrimeStr := lPrimeStr + ' ' + IntToStr(iCounter);
  149.               Inc(lPrimeCount);
  150.             end;
  151.         end;
  152.     finally
  153.       FreeAndNil(lPrimeNumbers);
  154.     end;
  155.     lPercentStr := FormatFloat('0.00000000000000000000', lPrimeCount * 100 / (iCounter - 1)) + ' %';
  156.  
  157.     // Adaugare rezultate in TMemo
  158.     memResults.Lines.Add(lPrimeStr + #13#10);
  159.     memresults.Lines.Add('Numere prime gasite: ' + IntToStr(lPrimeCount));
  160.     memResults.Lines.Add('Procent numere prime: ' + lPercentStr);
  161.  
  162.     // Scriere procent in fisier
  163.     lTempList.Clear;
  164.     lTempList.Add(lPercentStr);
  165.     lTempList.SaveToFile(ExtractFilePath(ParamStr(0)) + FILENAME_OUTPUT);
  166.   finally
  167.     FreeAndNil(lTempList);
  168.   end;
  169. end;
  170.  
  171. end.


andreiandreiq
  1. uses crt;
  2. var N:1..2000000;
  3.     i:1..2000000;
  4.     procent:real;
  5.     m:1..2000000;
  6.     f,g:text;
  7.   function Esteprim(x:longint):boolean;
  8.   var prim:boolean;
  9.       rad,d:longint;
  10.   begin
  11.     if x=1 then prim:=false
  12.     else if x mod 2=0 then
  13.            if x=2 then prim:=True
  14.            else prim:=false
  15.         else
  16.            begin
  17.              d:=3;
  18.              prim:=true;
  19.              rad:=trunc(sqrt(x));
  20.              while (d<=rad) and prim do
  21.                 if x mod d=0 then prim:=false
  22.                 else d:=d+2;
  23.            end;
  24.   Esteprim:=prim;
  25.   end;
  26. begin
  27.  
  28.   clrscr;
  29.   assign(f,'bitcell3.in');
  30.   reset(f);
  31.   assign(g,'bitcell3.out');
  32.   rewrite(g);
  33.   readln(f,N);
  34.    if N>2000000 then
  35.    Writeln('Numarul este mai mare de 2 milioane')
  36.    else
  37.    for i:=1 to N do
  38.    begin
  39.       if Esteprim(i)
  40.       then  m:=m+1;
  41.  
  42.     procent:=(100/n)*m;
  43.    end;
  44.     writeln(g,procent:3:2,' %');
  45.  
  46. close(f);
  47. close(g);
  48. end.


Dexter:
  1.  
  2. /*
  3. Rezolvarea este bazata pe 'Ciurul lui Eratostene' ( http://ro.wikipedia.org/wiki/Ciurul_lui_Eratostene )
  4.  
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <math.h> //sqrt
  9.  
  10. #define AFISEAZA_TIMP_EXECUTIE 1
  11. #define FISIER_IN "bitcell3.in"
  12. #define FISIER_OUT "bitcell3.out"
  13.  
  14. #define REGISTER_SIZE (sizeof(int)*8)//marimea unui registru din CPU;
  15. //folosind int-uri cu aceeasi dimensiune ca a registrului,
  16. //vom beneficia de viteza mai mare de acces la nivel de CPU
  17.  
  18. #define getBit(bitfield,i) ((bitfield[(i)/(REGISTER_SIZE)]>>((i)%(REGISTER_SIZE)))&1)
  19. #define setBit(bitfield,i) (bitfield[(i)/(REGISTER_SIZE)]|=(1<<((i)%(REGISTER_SIZE))))
  20.  
  21. int c=0,s=sizeof(int);
  22.  
  23. long int N; //datele de intrare
  24.  
  25. unsigned int*bitField=0;
  26. unsigned int n; //spatiu alocat dinamic
  27.  
  28. //variabile folosite in program
  29. unsigned int i,j,k,bitMask=0,currentBitMask,offset,a,b;
  30. unsigned int*p,*stop;
  31.  
  32. FILE*f;
  33.  
  34. #if AFISEAZA_TIMP_EXECUTIE
  35. #include <time.h>
  36. time_t start_t,stop_t;
  37. #endif/*
  38. void afiseaza_biti(int integer)
  39. {
  40.     int bit,i;
  41.     for(i=0;i<REGISTER_SIZE;i++){
  42.         bit=(integer>>(i%(REGISTER_SIZE)))&1;
  43.         printf("%d ",bit);
  44.     }
  45. }*/
  46.  
  47. int main(){
  48. #if AFISEAZA_TIMP_EXECUTIE
  49.     start_t=clock();
  50. #endif
  51.    
  52. /* 
  53.     freopen("bitcell3.in","r",stdin);
  54.     //freopen("bitcell3.out","w",stdout);
  55.     scanf("%d",N);
  56. */
  57.     f=fopen("bitcell3.in","r");
  58.     if(!f) return 1; //lipseste fisierul de intrare
  59.     fscanf(f,"%ld",&N);
  60.     fclose(f);
  61.    
  62.     //conditii preliminare
  63.     if(N<0||N>2000000)
  64.     {
  65.         puts("-1");//input invalid
  66.         return 1;
  67.     }
  68.     if(N<2)
  69.     {
  70.         puts("0");//zero
  71.         return 0;
  72.     }
  73.    
  74.     //alocam pana la 2 000 000 biti, cate unul pentru fiecare numar de la 1 la 2 000 000
  75.     //bitul i va fi 1 daca numarul i nu este prim, iar 0 daca
  76.    
  77.     n=N/REGISTER_SIZE; //alocam spatiu pentru cei N biti
  78.     if(N%REGISTER_SIZE)n++; //rotunjind prin adaos, la urmatorul int
  79.    
  80.     bitField=new unsigned int[n];//alocam spatiul necesar (conform problemei, maxim 250 000 bytes, adica ~244 KB)
  81.     /*
  82.      bitul cel mai nesemnificativ, din bitField[0] corespunde lui 1
  83.     */
  84.    
  85.     //preliminar, excludem numerele pare, initializand vectorul cu bitii 0 si 1, alternativ
  86.     //1)creem o masca de biti cu 0 si 1, de marimea int-ului (16,32,64, sau cine mai stie...)
  87.  
  88.     bitMask=0xAAAA;// 1010 1010
  89.     for(i=16;i<REGISTER_SIZE;i+=16)//din 16 in 16 biti
  90.     {
  91.         bitMask<<=16;
  92.         bitMask|=0xAAAA;// 1010 1010
  93.     }
  94.    
  95.     //2)aplicam masca in tot vectorul, initializandu-l si eliminand numerele pare
  96.  
  97.     p=bitField; //p = cursor
  98.     stop=bitField+n;//stop = pozitia de oprire, la finalul zonei alocate
  99.  
  100.     while(p<stop) //cat timp cursorul nu a ajuns la final,
  101.         *p++=bitMask; //copie int-ul, apoi treci la pozitia urmatoare
  102.    
  103.     //Am folosit implementarea cu pointeri doar pentru a grabi putin executia, la nivel de asamblare
  104.  
  105.     /*
  106.             In vederea implementarii algoritmului, vom lua fiecare numar impar mai mare decat 2
  107.         si vom exclude multiplii sai din lista numerelor prime.
  108.    
  109.         Astfel, la nivel de bit, bitField[i*k]=1, unde k*i reprezinta multiplii lui i
  110.     */
  111.    
  112.     //in momentul de fata, 2 este marcat ca neprim, iar 1 ca prim
  113.     bitField[0]^=3; //corectam printr-o operatie XOR pe biti
  114.    
  115.     unsigned int end=(unsigned int)sqrt((unsigned int)N);
  116.     for(i=3;i<=end;i+=2) //numerele impare din 2 in 2, incepand cu 3...
  117.     {
  118.         if(0==getBit(bitField,i-1)) //daca bitul este zero, adica numarul este prim...
  119.         {
  120.            
  121.             if(i<REGISTER_SIZE)
  122.             {
  123.                 /* Observatie:
  124.                     Pentru numerele mai mici decat `REGISTER_SIZE`, se poate crea o masca de biti,
  125.                 care aplicata pe bitField cu operatorul |, marcheaza numerele neprime.
  126.                    
  127.                     Exemplu: i=3, REGISTER_SIZE=32
  128.                 MSB                                 LSB
  129.                 0100 1001 0010 0100 1001 0010 0100 1001
  130.                    
  131.                     Notam:
  132.                 reg = REGISTER_SIZE
  133.                 i = numarul curent
  134.                 n = cmmmc(i,reg)   --cel mai mic multiplu comun
  135.                 m = n/reg
  136.                     In masca de biti, la fiecare i biti, se repeta un 1, iar la fiecare n biti se repeta
  137.                 alinierea bitilor in int-uri. Am notat cu m = numarul de int-uri dintr-un ciclu complet.
  138.                     Dupa ce am realizat prima masca (unde bitul cel mai nesemnificativ este 1), celelalte
  139.                 configuratii le obtinem printr-o rotatie pe biti, la stanga (sunt intotdeauna i configuratii
  140.                 diferite).             
  141.                     Astfel: pentru i=3, REGISTER_SIZE=32, avem
  142.                 MSB                                  LSB
  143.                 0100 1001 0010 0100  1001 0010 0100 1001  -- configuratia 1
  144.                 1001 0010 0100 1001  0010 0100 1001 0010  -- configuratia 2
  145.                 0010 0100 1001 0010  0100 1001 0010 0100  -- configuratia 3
  146.  
  147.                     Cu un offset corespunzator, fiecare masca, aplicata pe bitField din m in m pozitii,
  148.                 va marca automat numerele neprime.
  149.                 */
  150.  
  151.                
  152.                 bitMask=1;
  153.                 for(j=0;j<REGISTER_SIZE/i;j++)//folosim variabila j pentru a adauga bitii de 1
  154.                 {
  155.                     bitMask<<=i;
  156.                     bitMask|=1;
  157.                 }
  158.                 //am creat prima masca de biti, de dimensiunea unui int
  159.                
  160.                 /*
  161.                 R=REGISTER_SIZE
  162.                 i=numarul prim
  163.                 R*a=int-ul pe care aplicam masca (raportat la bitField)
  164.                 i*b=primul bit din masca (raportat la bitField)
  165.                 X=offsetul bitului de inceput (raportat la bitMask)
  166.                
  167.                 avem relatia: R*a+X=i*b, unde:
  168.                 -X ia valori de la 1 la i
  169.                 -r = constant
  170.                 -i = constant
  171.                 -a si b sunt variabile, cautam b=f(a)
  172.                
  173.                 pentru a de la 0 la i
  174.                     b = (R*a +X)/i  trebuie sa se imparta exact
  175.                 */
  176.                
  177.                 for(offset=0;offset<i;offset++) //offset = `x` de mai sus
  178.                 {
  179.                     for(a=0;a<i;a++)
  180.                         if(!((REGISTER_SIZE*a+offset)%i))
  181.                             break; //l-am gasit pe `a`
  182.                    
  183.                     currentBitMask=bitMask<<((offset+i-1)%i);
  184.                    
  185.                     for(j=0;j*i+a<n;j++)
  186.                         bitField[j*i+a]|=currentBitMask;
  187.                 }
  188.                 bitField[0]^=1<<(i-1); //repara bitul i (l-am setat la 1 odata cu restul lui bitField)
  189.             }
  190.             else
  191.             {/* Aici vroiam sa mai fac o optimizare...
  192.                 Distanta dintr 2 biti cu valoarea 1 este mai mare decat REGISTER_SIZE, deci avem int-uri neatinse, iar numarul de masti
  193.             diferite este = REGISTER_SIZE. Mai trebuia sa gasesc cate un offset pentru fiecare din mastile acestea si sa le aplic pe bitField,
  194.             ca in liniile de mai sus.
  195.                 Din pacate, am ramas la varianta de mai jos:
  196.             */
  197.                 for(j=2;j*i<=((unsigned int)N);j++)
  198.                     setBit(bitField,i*j-1);
  199.             }
  200.         }
  201.     }
  202.     f=fopen("bitcell3.out","w");
  203.  
  204.     j=0;
  205.     for(i=0;i<((unsigned int)N);i++){
  206.         if(0==getBit(bitField,i))
  207.             j++;
  208.     }
  209.    
  210.     fprintf(f,"%.3f %%",(((float)j*100)/i));
  211.     fclose(f);
  212.    
  213. #if AFISEAZA_TIMP_EXECUTIE
  214.     stop_t=clock();
  215.     printf("\n\nExecution time: %f\n",float(stop_t-start_t)/CLK_TCK);
  216. #endif
  217.     return 0;
  218. }
  219.  


Sursa lui wardog o puteti vedea in postul anterior.
Felicitari tuturor participantilor, si asteptam cu totii un nou concurs :)!
0,0p / 0 votes
User avatar
Mihai
Byte
 
Joined: 29 Dec 2009
Status: 25

Re: [3] Concurs - Numere prime

Postby Dexter » 21 Feb 2010, 20:42

Ca o paranteză...

Mi-au rămas unele linii de cod nefolosite/neşterse în sursa mai sus, şi asta pentru că am amânat rezolvarea problemei până în ultimul moment. După ce voi face ultimele finisaje, varianta finală va putea fi descărcată de aici.
0,0p / 0 votes
User avatar
Dexter
Word
 
Joined: 04 Jan 2010
Location: Secret Lab
Status: 44.5

Re: [3] Concurs - Numere prime

Postby v0id » 21 Feb 2010, 21:11

As avea si eu niste paranteze :) (daca nu e OK ca am postat aici, va rog sa-mi spuneti unde ar fi OK)

1. Nu m-am gandit sa pun si eu niste timere ca sa se vada viteza de executie. Am facut-o acum, iar cine e curios poate descarca aceasta varianta din atasament. Minunati-va de overhead-ul adus de afisarea numerelor prime :))

2. Nu pot rula programele lui andreiandreiq si Wardog pe Windows 7 x64. Al lui andreiandreiq imi da eroarea asta, iar al lui Wardog imi da asta. Imi amintesc si de programul lui Archangel de la concursul precedent, care imi dadea aceeasi eroare ca al lui Wardog... Acel program l-am testat pe vreo 4 masini si abia pe a 5-a masina mi-a mers. Acum daca stau sa-mi aduc aminte, primele 4 masini aveau toate Windows x64 instalat, iar a 5-a era avea Windows x86.
Se pune intrebarea: programele compilate de voi nu merg pe platforme x64? Asta mi s-ar parea mult prea tare :D As fi curios daca mai poate confirma cineva treaba asta...
0,0p / 0 votes
Attachments
v0id_prime2.zip
(270.84 KiB) Downloaded 21 times
A good coder is never on holiday - he may be working on a different machine, that's about as far as it gets.
User avatar
v0id
Word
 
Joined: 05 Jan 2010
Location: 127.0.0.1
Status: 39.5

Re: [3] Concurs - Numere prime

Postby Mihai » 21 Feb 2010, 22:11

@Dexter:
Ma bucur ca ai reusit sa-l termini la timp. Scuze ca nu ti-am raspuns la PM-ul ala, dar eram plecat.
@void:
Intr-adevar, afisarea numerelor prime ingreuneaza foarte mult executia programului tau.
Cat despre programul lui Wardog, nici mie nu mi-a mers - de asta i-am si cerut sursa :).
Oricum, eu am Windows x86, dar banuiesc ca e vorba de vreo dependinta.
@WarDog: In ce ai scris programul :D ?
0,0p / 0 votes
User avatar
Mihai
Byte
 
Joined: 29 Dec 2009
Status: 25

Re: [3] Concurs - Numere prime

Postby Wardog » 21 Feb 2010, 22:44

Mihai wrote:@Dexter:
Ma bucur ca ai reusit sa-l termini la timp. Scuze ca nu ti-am raspuns la PM-ul ala, dar eram plecat.
@void:
Intr-adevar, afisarea numerelor prime ingreuneaza foarte mult executia programului tau.
Cat despre programul lui Wardog, nici mie nu mi-a mers - de asta i-am si cerut sursa :).
Oricum, eu am Windows x86, dar banuiesc ca e vorba de vreo dependinta.
@WarDog: In ce ai scris programul :D ?

Programul l-am compilat in Visual C++ 2008. Incerc sa il compilez si in Borland C++ si il pun aici, doar asa sa vad daca este vina compilatorului.
Later edit: in atasament.
0,0p / 0 votes
Attachments
wardog_prime2.zip
(41.1 KiB) Downloaded 21 times
User avatar
Wardog
Bit
 
Joined: 17 Feb 2010
Status: 1

Re: [3] Concurs - Numere prime

Postby andreiandreiq » 21 Feb 2010, 23:42

@Wardog : acuma merge programul
PS. @Dexter: te asteptam maine cu noul concurs:P
0,0p / 0 votes
Image
User avatar
andreiandreiq
Word
 
Joined: 30 Dec 2009
Status: 33.33

Re: [3] Concurs - Numere prime

Postby DarkByte » 22 Feb 2010, 00:43

v0id wrote:... Imi amintesc si de programul lui Archangel de la concursul precedent, care imi dadea aceeasi eroare ca al lui Wardog... Acel program l-am testat pe vreo 4 masini si abia pe a 5-a masina mi-a mers. Acum daca stau sa-mi aduc aminte, primele 4 masini aveau toate Windows x64 instalat, iar a 5-a era avea Windows x86.
Se pune intrebarea: programele compilate de voi nu merg pe platforme x64? Asta mi s-ar parea mult prea tare :D As fi curios daca mai poate confirma cineva treaba asta ...
Programul lui Archangel a mers pe calculatorul meu "main" de la birou, dude. Vista x65-1 ...

In alta ordine de idei, felicitari participantilor si, evident, lui Dexter :>

Imi place varietatea ideilor si a codului, keep 'em coming :)

P.S. Dexter, daca ne pui sa facem ceva soft de ghidare rachete, I'll pass :D ;))
0,0p / 0 votes
User avatar
DarkByte
11011011
 
Joined: 29 Dec 2009
Status: 136

Re: [3] Concurs - Numere prime

Postby v0id » 22 Feb 2010, 10:59

"Dude", nu stiu eu ce teste ai facut tu la birou pe programul lui Archangel.
Daca poti veni cu ceva constructiv ca oamenii sa se lamureasca de ce nu le merg programele compilate, cu atat mai bine. Deci... Din ce spuneti tu si Mihai, problema nu tine de platforma x64. Foarte bine atunci, era doar o presupunere de-a mea. Oricum, o problema clar exista, deci distractie placuta la gasirea si rezolvarea ei!
0,0p / 0 votes
A good coder is never on holiday - he may be working on a different machine, that's about as far as it gets.
User avatar
v0id
Word
 
Joined: 05 Jan 2010
Location: 127.0.0.1
Status: 39.5


Return to Concursuri de programare desktop

Who is online

Users browsing this forum: No registered users and 0 guests