2024(e)ko martxoaren 21(a), osteguna

10. astea | itsas-bataila (II)






Itsas-bataila

Itsas-batailaren jokoa programatuko dugu. Bi dimentsioatako 6x6 taula batean gertatuko dira ekintza guztiak, taularen errenkadak izendatzeko zenbaki osoak erabiliko dira (1-etik 6-ra), eta taularen zutabeak izendatzeko karaktereak erabiliko dira (A-tik F-ra)

Ordenadoreak etsaien armada kokatuko du 6x6 itsasoan, eta etsaien armada hori hondoratu beharko dugu gehienez 19 jaurtiketa erabiliz. Etsaien armada sei itsasontziz osaturik dago:

  • 2 korazatu, armadako itsasontzi handienak dira (bakoitzak 3 zati)
  • 3 destruktore, armadako itsasontzi ertainak dira (bakoitzak 2 zati) 
  • 1 itsaspeko, armadako itsasontzi txikiena da (1 zati)

Hondoratu behar dugun etsaien armada 6x6 itsasoan kokatzeko, bi dimentsiotako array bat erabiliko dugu, hots, karaktereen array bat. Korazatua adierazteko K idatziko dugu, destruktorea adierazteko D idatziko dugu, itsaspekoa adierazteko P idatziko dugu, ura adierazteko, u idatziko dugu, eta, gainerako toki guztietan X idatzirik egongo da. Adibidez:


Lehendik programaturik dagoen unitate bat erabiliko dugu, itsas_w izeneko unitatea hain zuzen ere. Unitate horren iturburu-programa ez daukagu, baina bere interfazea ezagutzen dugu. Hori dela eta, guk idatziko dugun programan itsas_w unitatearen ondoko datu-mota erabil dezakegu eta ondoko azpiprogramen deiak egin ditzakegu: 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
unit itsas_w ;
 
interface        (* ----------------------------- interfazearen hasiera ----- *)
 
   type tacItsasoa = array[1..6, 'A'..'F'] of char ;
   procedure EtsaienArmadaHasieratu ;
   procedure EtsaienArmadaKokatu ;
   procedure EtsaienArmadaErakutsi ;
   function fncSuEgin(iErrenkada: integer;
                        cZutabea: char): char ;   { K, D, P edo X }
   procedure EtsaienArmadaGuztiakKokatu ;
    
                 (* ----------------------------- interfazearen amaiera ----- *)
 
implementation   (* ------------------------- inplementazioaren hasiera ----- *)
 
   ...
 
end.             (* --------- inplementazioaren eta unitatearen amaiera ----- *) 

Interfazean adierazten dira unitateak bezero-programarekin partekatuko dituen elementuak: konstanteak, datu-motak, funtzioak, prozedurak eta abar. Adibide honetan, datu-mota bat partekatzeaz gain funtzio bat eta lau prozedura partekatzen dira.

Interfazearen datu-motaren azalpena:

  • tacItsasoa datu-motak itsasoa ereduztatzen du, 6x6 itsaso zati horretan burutuko da bataila. Errenkadak izendatzeko zenbakizko indizeak erabiliko dira (1-etik 6-ra) eta zutabeak izendatzeko letrak erabiliko dira (A-tik F-ra)

Interfazearen bost azpiprogramen azalpenak:

  • fncSuEgin funtzioak 6x6 arrayaren koordenatuak hartuko ditu eta posizio horren karakterea itzuliko du (K, D, P edo X)
  • EtsaienArmadaHasieratu prozedurak 6x6 itsasoan X markak idatziko ditu
  • EtsaienArmadaKokatu prozedurak 6x6 itsasoan K, D eta P markak idatziko ditu
  • EtsaienArmadaErakutsi prozedurak 6x6 itsasoaren edukia pantailaratuko du. Honi esker gure programa-bezerotik posible zaigu jakitea etsaien ontziteria non dagoen, baina prozedura honi dei egiten badiogu itsas-bataila galdu dugulako izango da
  • EtsaienArmadaGuztiakErakutsi prozedurak 6x6 itsasoaren edukia pantailaratuko du, guztira 16 kokapen desberdin definitu dira itsas_w unitatean

Bost azpiprograma horiek gure programatik aktiba ditzakegu. Horretarako, uses klausulari esker itsas_w unitatea behar-beharrekoa zaigula adieraziko dugu gure iturburu-programaren hasieran:

1
2
3
4
5
6
7
8
9
program ItsasBatailak_w ;
 
uses
   crt, itsas_w ;
const                     (* 2 korazatu, 3 destruktore eta 1 itsaspeko *)
   ARMADA_OSOA = 13 ;     (* 2x3 + 3x2 + 1 = 13 *)
   JAURTIK_MAX = 19
type 
   tsJaurtiketa = string[2] ;

Hori dela eta, gure bezero-programak EtsaienArmadaKokatu prozedurari deia egitean etsaien armadaren kokapen zehatz bat gertatuko da (16 kokapen posibleetatik bat) eta jokoa hasi ahalko da. Jakin badakigu etsaien armadak 6 ontzi izango dituela eta bi ontziren artean beti ura dagoela; esate baterako, ondoko irudian erakusten den kokapena ez da itsas_w unitateak emandakoa kokapena desegokia delako:

Erroreak daudelako, goiko irudia ez du eman EtsaienArmadaKokatu prozedurak


ItsasBatailak_w.pas bezero-programak itsas_w eta crt unitateak beharko dituela dakigu. Baina, zer gertatuko litzateke  bezero-programak deklaratu eta garatuko balu unitatearen interfazeko funtzioa edo prozeduraren bat? Honako hau galdetzen da: EtsaienArmadaKokatu prozedura unitatean garaturik dago (bezero-programaren erabiltzaileak jakin ez dezan etsaien ontziteria non dagoen), bezero-programak EtsaienArmadaKokatu prozedura berri bat idatz dezake? Bai idatz dezake, errorerik ez dago ez sintaxian ez exekuzioan.

Aurreko erantzunak beste galdera bat sorarazten du: baldin eta EtsaienArmadaKokatu bi prozedura badaude (bat unitatekoa eta bestea bezero-programakoa), zein aktibatuko da bezero-programa exekutatzean? Bezero-programakoa, hots, bezero-programako EtsaienArmadaKokatu prozedura piztuko da eta unitateko EtsaienArmadaKokatu prozedura ez balego bezala da. Ondorioz, unitatean garaturik dagoen zerbait bezero-programan garatzen bada, azken honek "estaltzen" du unitatekoa.

ItsasBatailak_w.pas bezero-programak itsas_w eta crt unitateak beharko ditu eta bere programa nagusia ondoko hau izan daiteke, non aboJaurtiketaErrepikaturik array karratuan egindako jaurtiketak gordetzen ditugun (boolearren 6x6 array bat da) :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
{ -----------------------Programa Nagusia-------------------------- }
var
   iErrenkada, iJaurtiKont, iOntziZatiak, iUrKont: integer ;
   cZutabea: char ;
   acItsasoarenEgoera: tacItsasoa ;
   aboJaurtiketaErrepikaturik: tboJaurtiketenHistoria ;
   sJaurtiketa: tsJaurtiketa ;
   boJaurtiketaEgokia, boErrepikatuGabea: boolean ;
   cEmaitza: char ;
      
begin
   clrscr ;
   writeln ;
    
   writeln('///////////////////////////////////////////////////////////////////') ;
   writeln ;
   writeln('Garaile ateratzeko, gehienez ', JAURTIK_MAX, ' jaurtiketa dituzu') ;
   writeln
   
   EtsaienArmadaHasieratu ;    (* unitatean garaturik *) 
   EtsaienArmadaKokatu ;       (* unitatean garaturik *)
 
   JaurtiketenHistoriaHasi(aboJaurtiketaErrepikaturik) ;    (* hasieran denak "FALSE" *)
   ItsasoarenEgoeraHasieratu(acItsasoarenEgoera) ;          (* hasieran denak "X" *)
   ItsasoaErakutsi(acItsasoarenEgoera) ;
    
   writeln ;     
   writeln('ARMISTIZIOA:') ;
   writeln('Amore eman eta bataila galdutzat jotzen baduzu, etsaien armada ikus dezakezu.') ;
   writeln('Garaitu zaituen etsaien armadaren kokapena ikusi nahi duzu, "AR" erantzun. ') ;
   writeln ;
    
   iUrKont := 0 ;
   iOntziZatiak := 0 ;
   iJaurtiKont := 0 ;
   repeat
      if iUrKont >= 6 then
      begin
         TextColor(LightCyan) ;
         writeln('Jaurtiketa okerrak askotan egin dituzu, armistizioa eskatzerik daukazu!!!') ;
         TextColor(White) ;
      end ;  
       
      iJaurtiKont := iJaurtiKont + 1 ;
      boJaurtiketaEgokia := FALSE ;  
      repeat
         repeat
            write(iJaurtiKont:3, '. jaurtiketa egin (adibidez 3C koordenatuak, armistizioa eskatzeko "AR"): ') ;
            readln(sJaurtiketa) ;
            sJaurtiketa := upcase(sJaurtiketa) ;
            boJaurtiketaEgokia := fnboJaurtiketaAztertu(sJaurtiketa) ;    
         until boJaurtiketaEgokia ;
          
         boErrepikatuGabea := fnboErrepikatuGabea(sJaurtiketa, aboJaurtiketaErrepikaturik) ;
      until boErrepikatuGabea ;
       
      if sJaurtiketa <> 'AR' then
      begin
         val(sJaurtiketa[1], iErrenkada) ;
         //writeln('iErrenkada = ', iErrenkada) ;
         cZutabea := sJaurtiketa[2] ;
     
         cEmaitza := fncSuEgin(iErrenkada, cZutabea) ;    (* unitatean garaturik *)
       
         case cEmaitza of    { K, D, P edo X }        
            'K': begin
                    writeln(iErrenkada:3, cZutabea, ' ---> K, korazatua') ;
                    iOntziZatiak := iOntziZatiak + 1 ;
                    acItsasoarenEgoera[iErrenkada,cZutabea] := 'K' ;
                    aboJaurtiketaErrepikaturik[iErrenkada,cZutabea] := TRUE ;
                 end ;
            'D': begin
                    writeln(iErrenkada:3, cZutabea, ' ---> D, destruktorea') ;
                    iOntziZatiak := iOntziZatiak + 1 ;
                    acItsasoarenEgoera[iErrenkada,cZutabea] := 'D' ;
                    aboJaurtiketaErrepikaturik[iErrenkada,cZutabea] := TRUE ;
                 end ;     
            'P': begin
                    writeln(iErrenkada:3, cZutabea, ' ---> P, itsaspekoa') ;
                    iOntziZatiak := iOntziZatiak + 1 ;
                    acItsasoarenEgoera[iErrenkada,cZutabea] := 'P' ;
                    aboJaurtiketaErrepikaturik[iErrenkada,cZutabea] := TRUE ;
                 end ;     
            'X': begin
                    writeln(iErrenkada:3, cZutabea, ' ---> URA') ;
                    acItsasoarenEgoera[iErrenkada,cZutabea] := 'u' ;
                    aboJaurtiketaErrepikaturik[iErrenkada,cZutabea] := TRUE ;
                    iUrKont := iUrKont + 1 ;
                 end ;     
         end ;
          
         writeln((JAURTIK_MAX-iJaurtiKont):4, ' jaurtiketa geratzen d(ir)a');
         writeln ;
         ItsasoaErakutsi(acItsasoarenEgoera) ;
         writeln ;
      end ;      
   until (iOntziZatiak = ARMADA_OSOA) or
         (iJaurtiKont = JAURTIK_MAX) or
         (sJaurtiketa = 'AR') ;
    
   writeln ;
    
   if sJaurtiketa = 'AR' then
   begin
      writeln('ARMISTIZIOA, garaile atera diren etsaien ontziteria:') ;
      writeln ;
      EtsaienArmadaErakutsi ;    (* unitatean garaturik *)
   end
   else
   begin
      if (iOntziZatiak = ARMADA_OSOA) and (iJaurtiKont <= JAURTIK_MAX) then
      begin
         TextColor(LightGreen) ;
         writeln(iJaurtiKont, ' jaurtiketekin etsaien armada osoa hondoratu duzunez, gerra irabazi duzu!!!') ;
         TextColor(White) ;
      end
      else
      begin
         TextColor(LightRed) ;
         writeln(iJaurtiKont, ' jaurtiketa ondoren itsas-bataila galdu duzu!!!') ;
         TextColor(White) ;
         writeln('Garaitu zaituen etsaien ontziteria:') ;
         writeln ;
         EtsaienArmadaErakutsi ;    (* unitatean garaturik *)
      end ;
   end ;
        
   writeln ;
   writeln('///////////////////////////////////////////////////////////////////') ;
    
   writeln ;
   repeat until keypressed ;
end.

acItsasoarenEgoera karaktereen array horretan itsas-batailaren egoera gordeko dugu uneoro. Bataila hasi aurretik ItsasoarenEgoeraHasieratu prozedurak X karakterez betetzen du 6x6 arraya. Etsaien armada hondoratu nahian, 6x6 itsasoko koordenatu pare bat hautatzeko aukera izango dugu (5D bezalako karaktere-katea) eta koordenatu horiek fncSuEgin funtzioari pasatuz, honek jaurtiketaren emaitza itzuliko digu, eta, ondorioz ItsasoarenEgoeraHasieratu prozedurak bete dituen X guztietatik bat ordeztuko dugu. Arrayaren posizio horretako balio berria, honako hauetatik bat izango da:

  • u ura, gure jaurtiketak huts egin du
  • K korazatua, gure jaurtiketak korazatu baten zatia suntsitu du 
  • D destruktorea, gure jaurtiketak destruktore baten zatia suntsitu du 
  • P itsaspekoa, gure jaurtiketak itsaspekoa suntsitu eta hondoratu du 


Etsaien armadak 3+3+2+2+2+1=13 zatiz osaturik dago, eta guztiak suntsitu arte itsas-bataila ez da bukatuko eta garaile aterako gara 19 jaurtiketa behar izan badugu (19 jaurtiketa edo gutxiago beharko dira itsas-bataila irabazteko). Dagozkigun 19 jaurtiketak agortzean, batailaren galtzaileak gu izango gara eta programa bukatuko da. Baina 19. jaurtiketa egin baino lehenago, bataila galdutzat jotzen badugu, armistizioa eskatu ahalko dugu (AR koordenatuak sartuz) eta etsaien ontziteria pantailaratu ondoren programa bukatuko da.

Ikusi balizko exekuzio bat, non 16 jaurtiketan ura egin ondoren, amore eman eta armistizioa eskatzea erakabi dugun. Ondorioz, programa amaitu aurretik etsaien armadaren kokapena erakusten da:






    Windows:
  • ItsasBatailak_w.pas   bezero-programaren iturburu-kodea
  • itsas_w.pas   unitatearen iturburu-kodea, hau konpilatzean:
    • itsas_w.ow   unitatearen objektu-kodea lortzen da (itsas_w.pas konpilatu ondoren)
    • itsas_w.ppw   unitate konpilatua lortzen da (itsas_w.pas konpilatu ondoren)
  • ItsasBatailak_w.exe   programa exekutagarria fitxategi hauekin lor daiteke:
    • ItsasBatailak_w.pas
    • itsas_w.ow
    • itsas_w.ppw
    Windows:
  • ItsasBatailak_w.zip   unitate konpilatua eta bezero-programaren iturburu-kodea (itsas_w.ow eta itsas_w.ppw gehi ItsasBatailak_w.pas)
 

    Mac:
  • ItsasBatailak.pas   bezero-programaren iturburu-kodea
  • itsas.pas   unitatearen iturburu-kodea
  • itsas.o   unitatearen objektu-kodea
  • itsas.ppu   unitate konpilatua
  • ItsasBatailak   programa exekutagarria (goiko fitxategiekin lor daiteke)


 

10. astea | itsas-bataila (I)






Itsas-bataila

Itsas-batailaren jokoa programatuko dugu. Bi dimentsioatako 6x6 taula batean gertatuko dira ekintza guztiak, taularen errenkadak izendatzeko zenbaki osoak erabiliko dira (1-etik 6-ra), eta taularen zutabeak izendatzeko karaktereak erabiliko dira (A-tik F-ra)

Ordenadoreak etsaien armada kokatuko du 6x6 itsasoan, eta etsaien armada hori hondoratu beharko dugu gehienez 19 jaurtiketa erabiliz. Etsaien armada sei itsasontziz osaturik dago:

  • 2 korazatu, armadako itsasontzi handienak dira (bakoitzak 3 zati)
  • 3 destruktore, armadako itsasontzi ertainak dira (bakoitzak 2 zati) 
  • 1 itsaspeko, armadako itsasontzi txikiena da (1 zati)

Hondoratu behar dugun etsaien armada 6x6 itsasoan kokatzeko, bi dimentsiotako array bat erabiliko dugu, hots, karaktereen array bat. Korazatua adierazteko K idatziko dugu, destruktorea adierazteko D idatziko dugu, itsaspekoa adierazteko P idatziko dugu, ura adierazteko, u idatziko dugu, eta, gainerako toki guztietan X idatzirik egongo da. Adibidez:


Baina bataila hasi aurretik, ikus dezagun etsaien ontziteriak har ditzaken kokapen posibleak zeintzuk diren. Horretarako, programa bat idatziko dugu eta bere helburu bakarra EtsaienArmadaGuztiakKokatu delako prozedurari dei egitea da. Dakigunez, EtsaienArmadaGuztiakKokatu prozedura itsas_w unitatean garaturik dago.

Guztira 16 kokapen desberdin direlako EtsaienArmadaGuztiakErakutsi prozedurak for-to-do agindu baten bitartez, iterazio bakoitzean bi dei egingo ditu: EtsaienArmadaHasieratu prozedurari eta EtsaienArmadaKokatu prozedurari. Hirurak itsas_w unitatean garaturik daude.

Lehendik programaturik dagoen unitate bat erabiliko dugu, itsas_w izeneko unitatea hain zuzen ere. Unitate horren iturburu-programa ez daukagu, baina bere interfazea ezagutzen dugu. Hori dela eta, guk idatziko dugun programan itsas_w unitatearen ondoko datu-mota erabil dezakegu eta ondoko azpiprogramen deiak egin ditzakegu:  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
unit itsas_w ;
 
interface        (* ----------------------------- interfazearen hasiera ----- *)
 
   type tacItsasoa = array[1..6, 'A'..'F'] of char ;
   function fncSuEgin(iErrenkada: integer;
                        cZutabea: char): char ;   { K, D, P edo X }
   procedure EtsaienArmadaHasieratu ;  
   procedure EtsaienArmadaErakutsi ;  
   procedure EtsaienArmadaKokatu ;
   procedure EtsaienArmadaGuztiakKokatu ;
    
                 (* ----------------------------- interfazearen amaiera ----- *)
 
implementation   (* ------------------------- inplementazioaren hasiera ----- *)
 
   ...
 
end.             (* --------- inplementazioaren eta unitatearen amaiera ----- *)  

Interfazean adierazten dira unitateak bezero-programarekin partekatuko dituen elementuak: konstanteak, datu-motak, funtzioak, prozedurak eta abar. Adibide honetan, datu-mota bat partekatzeaz gain funtzio bat eta lau prozedura partekatzen dira.

Interfazearen datu-motaren azalpena:

  • tacItsasoa datu-motak itsasoa ereduztatzen du, 6x6 itsaso zati horretan burutuko da bataila. Errenkadak izendatzeko zenbakizko indizeak erabiliko dira (1-etik 6-ra) eta zutabeak izendatzeko letrak erabiliko dira (A-tik F-ra)

Interfazearen bost azpiprogramen azalpenak:

  • fncSuEgin funtzioak 6x6 arrayaren koordenatuak hartuko ditu eta posizio horren karakterea itzuliko du (K, D, P edo X)
  • EtsaienArmadaHasieratu prozedurak 6x6 itsasoan X markak idatziko ditu
  • EtsaienArmadaKokatu prozedurak 6x6 itsasoan K, D eta P markak idatziko ditu
  • EtsaienArmadaErakutsi prozedurak 6x6 itsasoaren edukia pantailaratuko du. Honi esker gure programa-bezerotik posible zaigu jakitea etsaien ontziteria non dagoen, baina prozedura honi dei egiten badiogu itsas-bataila galdu dugulako izango da
  • EtsaienArmadaGuztiakErakutsi prozedurak 6x6 itsasoaren edukia pantailaratuko du, guztira 16 kokapen desberdin definitu dira itsas_w unitatean

Bost azpiprograma horiek gure programatik aktiba ditzakegu. Horretarako, uses klausulari esker itsas_w unitatea behar-beharrekoa zaigula adieraziko dugu gure iturburu-programaren hasieran. Dena den EtsaiakNon_w programan azpiprograma bakarra erabiliko dugu, EtsaienArmadaGuztiakErakutsi prozedura:

1
2
3
4
program EtsaiakNon_w ;
 
uses
   crt, itsas_w ;

Hori dela eta, gure bezero-programak EtsaienArmadaGuztiakErakutsi prozedurari dei egitean etsaien armadaren kokapen guztiak zeintzuk izan daitezkeen erakutsiko ditu pantailan. Orotara 16 kokapen desberdinetatik hona hemen lehen laurak:

EtsaienArmadaGuztiakErakutsi prozedurak pantailaratzen duenenaren zati bat


EtsaiakNon_w.pas bezero-programak itsas_w eta crt unitateak beharko dituela dakigu. Baina, zer gertatuko litzateke  bezero-programak deklaratu eta garatuko balu unitatearen interfazeko funtzioa edo prozeduraren bat? Honako hau galdetzen da: EtsaienArmadaGuztiakKokatu prozedura unitatean garaturik dago (bezero-programaren erabiltzaileak jakin ez dezan etsaien ontziteria non egon daitekeen), bezero-programak EtsaienArmadaGuztiakKokatu prozedura berri bat idatz dezake? Bai idatz dezake, errorerik ez dago ez sintaxian ez exekuzioan.

Aurreko erantzunak beste galdera bat sorarazten du: baldin eta EtsaienArmadaGuztiakKokatu bi prozedura badaude (bat unitatekoa eta bestea bezero-programakoa), zein aktibatuko da bezero-programa exekutatzean? Bezero-programakoa, hots, bezero-programako EtsaienArmadaGuztiakKokatu prozedura piztuko da eta unitateko EtsaienArmadaGuztiakKokatu prozedura ez balego bezala da. Ondorioz, unitatean garaturik dagoen zerbait bezero-programan garatzen bada, azken honek "estaltzen" du unitatekoa.

EtsaiakNon_w.pas bezero-programak itsas_w eta crt unitateak beharko ditu jarraian ikusten den bezala:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
program EtsaiakNon_w ;
 
uses
   crt, itsas_w ;
 
{ -----------------------Programa Nagusia-------------------------- }
 
begin
   clrscr ;
   writeln ;
    
   writeln('///////////////////////////////////////////////////////////////////') ;
   writeln ;
   writeln ;
      
   EtsaienArmadaGuztiakKokatu ;
     
   writeln ;
   writeln ;
   writeln('///////////////////////////////////////////////////////////////////') ;
    
   writeln ;
   repeat until keypressed ;
end.
 



    Windows:
  • EtsaiakNon_w.pas   bezero-programaren iturburu-kodea
  • itsas_w.pas   unitatearen iturburu-kodea, hau konpilatzean:
    • itsas_w.ow   unitatearen objektu-kodea lortzen da (itsas_w.pas konpilatu ondoren)
    • itsas_w.ppw   unitate konpilatua lortzen da (itsas_w.pas konpilatu ondoren)
  • EtsaiakNon_w.exe   programa exekutagarria fitxategi hauekin lor daiteke:
    • EtsaiakNon_w.pas
    • itsas_w.ow
    • itsas_w.ppw
    Windows:
  • EtsaiakNon_w.zip   unitate konpilatua eta bezero-programaren iturburu-kodea (itsas_w.ow eta itsas_w.ppw gehi EtsaiakNon_w.pas)
 

    Mac:
  • EtsaiakNon.pas   bezero-programaren iturburu-kodea
  • itsas.pas   unitatearen iturburu-kodea
  • itsas.o   unitatearen objektu-kodea
  • itsas.ppu   unitate konpilatua
  • EtsaiakNon   programa exekutagarria (goiko fitxategiekin lor daiteke)


 

Unitateak






Aurrekariak

Dakigunez programa exekutagarria eskuratzeko iturburu-programaren itzulketa bat burutu behar da, eta horretarako konpiladorearen eta estekatzailearen beharra daukagu. Biak jarraian lan egiten dutelako (lehenik konpiladorea eta ondoren estakatailea) guretzat prozesu bakarra bezala agertzen zaigu. Eskematikoki:

Adibide honetan Aritm unitate bat sortuko dugu eta bezero-programak unitate horren erabilpena egingo du. Adibide honek kopuru osoak landuko ditu oinarrizko eragiketa aritmetikoak eginez.



Aritm.pas unitatea

Unitate bat programatuko dugu bere barnean bi funtzio eta prozedura bat izango dituena, unitateari Aritm deituko diogu. Unitatearen iturburu-programari Aritm.pas deituko diogu eta bere kodea ondoko hau da:  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{================================================unitatearen hasiera=======}
unit Aritm;
 
{------------------------------------------------zati publikoa-------------}
interface
   procedure ZatiduraEtaHondarra(    iZbk1, iZbk2: integer;
                                 var iZati, iHond: integer);
   function fniBatu(iZbk1, iZbk2: integer): integer;
   function fniKendu(iZbk1, iZbk2: integer): integer;
{------------------------------------------------zati publikoa-------------}
 
{------------------------------------------------zati pribatua-------------}
implementation
   procedure ZatiduraEtaHondarra(    iZbk1, iZbk2: integer;
                                 var iZati, iHond: integer);
   begin
      iZati := iZbk1 div iZbk2;
      iHond := iZbk1 mod iZbk2;
   end;
    
   function fniBatu(iZbk1, iZbk2: integer): integer;
   begin
      fniBatu := iZbk1 + iZbk2;
   end;
       
   function fniKendu(iZbk1, iZbk2: integer): integer;
   begin
      fniKendu := iZbk1 - iZbk2;
   end;
{------------------------------------------------zati pribatua-------------}
 
end.
{================================================unitatearen amaiera=======}

Unitateren egiturak bi zati ditu, bat publikoa eta bestea pribatua. Zati publikoa interface blokean zehazten da, deklarazio bat besterik ez da, eta programa-bezeroak ezagutu behar du derrigorrez. Zati pribatua implementation blokean garatzen da eta bere kodea bezeroak ez du zertan ezagutu behar.

Aritm.pas iturburu-programa konpilatu ondoren Aritm.ow objektu-programa eta Aritm.ppw unitate konpilatua lortzen dira. Berez, unitate bat ezin da exekutatu, bere barneko bi funtzioak eta prozedura beste programa batek (unitatearen bezeroak) erabiliko ditu. 



Bezero.pas bezero-programa

Orain programa bat idatziko dugu Aritm unitatea erabiliko duena, programa honi Bezero.pas deituko diogu, eta bere kodea programatuko duen programatzaileak unitatearen interfazea ezagutu behar du (interface blokea ezagutu behar du):

1
2
3
4
5
interface
   procedure ZatiduraEtaHondarra(    iZbk1, iZbk2: integer;
                                 var iZati, iHond: integer);
   function fniBatu(iZbk1, iZbk2: integer): integer;
   function fniKendu(iZbk1, iZbk2: integer): integer;

Bezero.pas programan fniBatu funtzioaren deia egin nahi bada, lehendik Aritm unitatea erabiliko dela adierazi behar du programatzaileak uses klausularen bidez. Ikusi Bezero.pas iturburu-programaren kodea non ZatiduraEtaHondarra, fnBatu eta fnKendu azpiprogramak erabiltzen diren:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
{ Bezeroak ezagutzen duena:                                                    }
{ ------------------------                                                     }
{ procedure ZatiduraEtaHondarra(    iZbk1, iZbk2: integer;                     }
{                               var iZati, iHond: integer);                    }
{ function fniBatu(iZbk1, iZbk2: integer): integer;                            }
{ function fniKendu(iZbk1, iZbk2: integer): integer;                           }
      
program BezeroProgramaBat;
uses
   Aritm;
 
var
   iEragigai1, iEragigai2, iBatura, iKendura, iZatidura, iHondarra: integer;
    
begin
   writeln;
   writeln;
   write('Lehen eragigaia eman: ':30);
   readln(iEragigai1);
   repeat
      write('Bigarren eragigaia eman: ':30);
      readln(iEragigai2);
      if iEragigai2 = 0 then
         writeln('Datua ezin daiteke 0 izan':30);
   until iEragigai2 <> 0;
    
   iBatura := fniBatu(iEragigai1, iEragigai2);     { Aritm unitatean garaturik }
   iKendura := fniKendu(iEragigai1, iEragigai2);   { Aritm unitatean garaturik }
   ZatiduraEtaHondarra(iEragigai1, iEragigai2,
                       iZatidura, iHondarra);      { Aritm unitatean garaturik }
    
   writeln;
   writeln(iEragigai1:15, '  +  ', iEragigai2, ' = ', iBatura);
   writeln(iEragigai1:15, '  -  ', iEragigai2, ' = ', iKendura);
   writeln(iEragigai1:15, ' div ', iEragigai2, ' = ', iZatidura);
   writeln(iEragigai1:15, ' mod ', iEragigai2, ' = ', iHondarra);
    
   readln;
end.

Bezero.exe programa exekutagarria eskuratzeko, Bezero.pas programaren iturburu-kodea konpilatu beharra dago. Horretarako, Bezero.pas programaren iturburu-kodea eta Aritm.pas unitatearen iturburu-programa karpeta berean kokatu behar ditugu.


Bezero.pas programaren iturburu-kodea eta Aritm.pas unitatearen iturburu-programa konpilatu ondoren, haien objektu-programak estekatu egiten dira Bezero.exe programa exekutagarria eskuratzeko.

Konpilatu/Estekatu ekintzen eskema:

Unitatearen Aritm.pas iturburu-programa ez bagenu? Nola lortuko genuke Bezero.exe programa exekutagarria Bezero.pas iturburu-programatik abiatuta? Bezero.exe programa exekutagarria eskuratzeko, hiru fitxategi hauek beharko genituzke:

  1. Bezero.pas programaren iturburu-kodea,
  2. unitatearen Aritm.ow objektu-programa eta
  3. unitatearen Aritm.ppw unitate konpilatua

Azken bi fitxategiak Aritm.pas unitatearen konpilaziotik eratorriak dira. Aipatutako hiru fitxategi horiek karpeta berean kokatu behar dira Bezero.exe programa exekutagarria lortzearren.



Orain gure beste programa bat idatziko dugu BesteBezero.pas deituko duguna. Azken programa hau aurreko Bezero.pas programa bezalakoa da (Aritm unitatea erabiliko du), baina BesteBezero.pas programa berriak fniBatu funtzioa garaturik izango du (bi datuen batuketa bat egin ondoren, batura bider 100 egingo du emaitza itzuli aurretik).

BesteBezero.pas programan, 4 eta 3 datuekin fniBatu funtzioaren deia egitean, emaitza zein izango da? Aritm unitatean garaturik dagoen fniBatu funtzioa piztuko balitz emaitza 7 litzateke, baina BesteBezero.pas programan kodetu den fniBatu funtzioa piztuko balitz emaitza 700 litzateke. Erantzuna 700 da, BesteBezero.pas programaren fniBatu funtzioak unitatearen fniBatu funtzioa estaltzen duelako.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
{ Bezeroak ezagutzen duena:                                                    }
{ ------------------------                                                     }
{ procedure ZatiduraEtaHondarra(    iZbk1, iZbk2: integer;                     }
{                               var iZati, iHond: integer);                    }
{ function fniBatu(iZbk1, iZbk2: integer): integer;     (* EZ BALEGO BEZALA *) }
{ function fniKendu(iZbk1, iZbk2: integer): integer;                           }
      
program BesteBezeroProgramaBat;
uses
   Aritm;
 
function fniBatu(iZbk1, iZbk2: integer): integer;
begin
   fniBatu := (iZbk1 + iZbk2)*100;       (* BATURA BIDER 100 *)
end;
    
(* -------------------------programa nagusia------------------------- *)  
var
   iEragigai1, iEragigai2, iBatura, iKendura, iZatidura, iHondarra: integer;
    
begin
   writeln;
   writeln;
   write('Lehen eragigaia eman: ':30);
   readln(iEragigai1);
   repeat
      write('Bigarren eragigaia eman: ':30);
      readln(iEragigai2);
      if iEragigai2 = 0 then
         writeln('Datua ezin daiteke 0 izan':30);
   until iEragigai2 <> 0;
    
   iBatura := fniBatu(iEragigai1, iEragigai2);     { BEZERO-PROGRAMAKOA }
   iKendura := fniKendu(iEragigai1, iEragigai2);   { Aritm unitatetik hartutakoa }
   ZatiduraEtaHondarra(iEragigai1, iEragigai2,
                       iZatidura, iHondarra);      { Aritm unitatetik hartutakoa }
    
   writeln;
   writeln(iEragigai1:15, '  +  ', iEragigai2, ' = ', iBatura);
   writeln(iEragigai1:15, '  -  ', iEragigai2, ' = ', iKendura);
   writeln(iEragigai1:15, ' div ', iEragigai2, ' = ', iZatidura);
   writeln(iEragigai1:15, ' mod ', iEragigai2, ' = ', iHondarra);
    
   readln;
end.
BesteBezero.exe programa exekutagarriaren irteera bat:
Bezero-programaren fniBatu funtzioak Aritm unitatearen fniBatu funtzioa estaltzen du




        Win  |  Unitate konpilatua eta bezero-programaren iturburu-kodea:


       Mac  |  Unitate konpilatua eta bezero-programaren iturburu-kodea:

 

Konpiladorea eta estekatzailea






Aurrekariak

Dakigunez ordenadore baten funtzionamendua programa batek gidatzen du. Baina, defini dezagun programa bat zer den informatikaren arloan:

Programa: Ordenagailu bati programazio-lengoaia batean idatzita ematen zaion agindu-segida, lan jakin bat egiteko behar diren oinarrizko eragiketak ordenagailuak exkutatzeko moduan zehatz-mehatz azaltzen dituena. 

Baina ez dugu ahaztu behar ordenagailua makina digitala dela eta exekuta dezakeen programa berari dagokion makina-kodean idatzirik eman behar zaiola.

Makina-kode: makina-kodea edo makina-programa ordenadoreak ulertzen duen agindu-multzoa da. Ordenagailuaren PUZak (prozesatzeko unitate zentralak) zuzenean, itzulpenik gabe, exekuta dezakeen agindu-multzoa. Agindu horiek sistema bitarrean adierazten dira eta bakoitzak eragiketa aritmetiko edo logiko bat adierazten du. Ordenagailu batetik bestera alda daiteke. 

Modu beretsuan, ez dugu ahaztu behar guk goi-mailako lengoaiaren bat erabiliko dugula programa idazteko eta horregatik gure programa "itzuli" beharko dela ordenadoreak exekuta dezan. Hori dela eta, guk idatzitako programari iturburu-programa esaten zaio, hauxe da bere definizioa.

Iturburu-programa: iturburu-programa edo iturburu-kodea goi-mailako lengoaian idatzitako sententzia eta aginduen multzoa da. Ordenagailuak exekutatu ahal izateko konpiladore, mihiztatzaile edo interpretatzaileen bidez makina-lengoaiara bihurtu behar dena, hots, iturburu-programa itzuli beharra dago ordenadoreak exekuta dezan. 

Eskematikoki:

Iturburu-programa itzuli beharra dagoela eta, goi-mailako lengoaian bi motatakoak izan daitezke: Interpretatuak eta Konpilatuak. Goi-mailako lengoaia interpretatuetan interpretatzaile bat aplikatzen zaio programari makina-kodea lortzeko. Goi-mailako lengoaia konpilatuetan programaren itzultzaile lana konpiladoreak egingo du.

Interpretatzaile: Goi-mailako lengoaia itzultzeko programa orokorra da, aginduak irakurri ahala aztertu eta exekutatzen dituena. Goi-mailako lengoaia interpretatuen adibideak: Python, PHP, Perl, MATLAB, Ruby, JavaScript, ... 

Konpiladore: Goi-mailako lengoaian idatzitako programa oso bat hartu eta itzuli edo konpilatzen duen programa da. Goi-mailako lengoaia konpilatuen adibideak: Pascal, C, C++, ... 

Informatikaren arloan konpilatzea iturburu-programa bat itzultzea da, ordenadore baten makina-kodera itzultzea alegia. Konpilatze prozesuak fase desberdinak ditu eta horiekin ez da programa exekutagarria lortzen, konpilatzeari beste estekatzea gehitu behar baitzaio.

Konpilatzearen faseak ondoko irudian erakusten dira:

Non bost fase hauek desberdintzen diren:

  1. Analisi lexikala: Lexikoaren analisia, hitzen analisia, lehenengo fasea da; hemen iturburu-programa ezkerretik eskuinera irakurtzen da eta osagai lexikoetan (tokenak) biltzen da, esanahi bat duten karaktere-sekuentziak direnak. Gainera, zuriune guztiak, lerro zuriak, iruzkinak eta beharrezkoa ez den gainerako informazioa iturburu-programatik ezabatzen da. Lengoaiaren sinboloak (hitz gakoak, eragileak, etab.) behar bezala idatzi direla ere egiaztatzen da. Adibidez, fase honetan aurkitzen dira ";" baten falta, edo ">=" ordez "=>" idatzi dela, edo aldagai baten etiketa okerra, edo etiketa bera bikoiztuta dagoela
  2. Analisi sintaktikoa: Fase honetan, tokenak edo osagai lexikoak hierarkikoki biltzen dira gramatika-esaldietan, eta horiek konpiladoreak erabiltzen ditu bere irteera sintetizatzeko. Aurreko fasetik lortutakoa sintaktikoki zuzena den egiaztatzen da (lengoaiaren gramatikaren araberakoa da). Oro har, iturburu-programaren esaldi gramatikalak analisi sintaktikoko zuhaitz baten bidez adierazten dira. Adibidez, fase honetan parekatzen dira adierazpen desberdinen parentesi bikoteak edo begin-end bikoteak
  3. Analisi semantikoa: Analisi semantikoaren faseak iturburu-programa berrikusten du akats semantikoak aurkitzen saiatzeko, eta datu-motei buruzko informazioa biltzen du kodea sortzeko ondorengo faserako. Analisi semantikoaren zeregin garrantzitsu bat datu-motak egiaztatzea da. Hemen, konpiladoreak operadore bakoitzak iturburu-lengoaiaren espezifikazioagatik baimendutako operandoak dituen egiaztatuko du. Adibidez, integer datu-motako aldagai bati zenbaki erreal ezingo zaio esleitu, edo div operadore aritmetikoa ezin zaio zenbaki erreal bati aplikatu
  4. Kodearen sortzea: Sintesi-fasea honetan iturburu-programaren baliokidea den objektu-kodea sortzean datza. Iturburu-programak analisi-akatsik ez duenean bakarrik sortzen da objektu-kodea; horrek ez du esan nahi programa behar bezala exekutatuko denik, programa batek kontzeptu-akatsak edo gaizki kalkulatutako esamoldeak izan baititzake
  5. Kodearen optimizatzea: Kodea optimizatzeko fasea bitarteko kodea hobetzean datza, exekutatzeko makina-kode azkarragoa izan dadin. Alde handia dago konpiladoreek exekutatzen duten kode-optimizazioaren kopuruan. Optimizazio handia egiten dutenetan, "Konpiladore optimizatzaileak" deituak, konpiladorearen denboraren zati esanguratsu bat fase honetan luzatzen da. Hala ere, optimizazio sinple batzuk nabarmen hobetzen dute objektu-programa gauzatzeko denbora, konpilazioa gehiegi atzeratu gabe

Objektu-kodea eta objektu-programa aipatu dira goian, izan ere konpilatzearen emaitza .obj luzapena, edo .o luzapena, edo .ow luzapena, edo .ppw luzapena duen fitxategi bat izango da eta fitxategi horri objektu-programa esaten zaio. Objektu-programaren fitxategi hau, makina-kodean idatzita egon arren ezin da exekutatu programa-liburutegien kodea falta zaiolako. Linker edo estekatzaile delako programak objektu-kodetik abiatuta .exe luzapeneko programa-exekutagarria lortuko du.



Estekatu aditzaren esanahia lotu edo elkartu da. Esan bezala, linker edo estekatzaile delako programak .obj objektu-kodetik abiatuta .exe luzapeneko programa-exekutagarria lortuko du, objektu-kodeari falta zaizkion programa-liburutegiak gehituz. Baina, programa-liburutegiaren eta estekatzailearen definizioak eman ditzagun.

Programa-liburutegi: Programatzaileen eskueran dauden prozedura edo programa prekonpilatuen multzoa. 

Iturburu-programa konpilatu ondoen lortzen den objektu-kodeari aurredefinituriko prozedura eta funtzioak falta zaizkio. Prozedura eta funtzio horiek programa-liburutegietan bildurik daude makina-kodean itzulirik. Estekatzaile delako programak objektu-kodea eta programa-liburutegiak lotu/elkartu egiten egiten ditu. 

Estekatzaile: Independenteki idatzi eta independenteki konpilatu programa edo moduluak elkarrekin lotu eta programa exekutagarri koherente bat eratzen duen programa. 

Eskematikoki:

Baina non aurkitzen dira .ow eta .ppw luzapeneko prekonpilatutako moduluak? Dev-Pas konpiladorearen kasuan, irudi honek adierazten digu modulu horiek estekatzaileak non bilatuko dituen; konpiladorea C:\Dev-Pas karpetan instalatu bada, unitate prekonpilatuak C:\Dev-Pas\units\rtl karpetan kokatuko dira:

Unitateen eta liburutegien direktorio horiek Dev-Pas konpilazio-ingurunea instalatzean ezartzen dira, behar izanez gero Options > Compiler options > Directories bidea jarraituz alda ditzakegu:


 

10. astea | Eratostenes-en bahea (I)

Galbahe (edo bahe) baten irudia. Galbaheri esker aleak sailka daitezkeen bezala, zenbaki zerrenda bati galbahe logikoren bat aplikatuz zenbakien segida desberdinak lor daitezke, adibidez: zenbaki lehenak identifikatzeko Eratostenes matematikari greziarrak asmatutakoa

Ariketa honi bi modutan ekingo diogu:


Eratostenes-en bahea zenbaki lehenak aurkitzeko algoritmo bat da, emandako n zenbaki arrunt bat baino txikiagoak direnen artean.

Lehendabizi, taula bat egiten da 2 eta n arteko zenbaki arruntekin, jarraian multiploak markatzen dira hurrengo ordena jarraituz:

  • 2tik hasita, haren multiplo guztiak markatzen dira, ostean, hurrengo zenbakiarekin jarraituko da baina bi egoera daude:
    • Hurrengo zenbakia markaturik gabe dago, adibidez 3 zenbakia, eta lehen bezala bere multiplo guztiak markatzen dira
    • Hurrengo zenbakia markaturik dago, adibidez 4 zenbakia, kasu honetan ez da ezer markatzen eta bere hurrengo zenbakia hartzen da
  • 5ekin markatu beharko litzateke (goiko lehen kasua), 6kin ez litzateke ezer markatuko (goiko bigarren kasua), 7ekin markatu beharko litzateke (goiko lehen kasua), 8, 9 eta 10ekin ez litzateke ezer markatuko (goiko bigarren kasuak), e.a.
    Prozedura errepikatzen da hau betetzen den bitartean: (MarkatuGabekoZenbakia)2 < n. Beste modu batez esanik, markatu gabeko zenbakiaren karratua n baino handiagoa denean eten prozesu errepikakorra

Eratostenes-en bahearen animazioa 120 baino gutxiagoko zenbaki lehenentzat:

Sieve of Eratosthenes animation
SKopp at German Wikipedia, CC BY-SA 3.0, via Wikimedia Commons

Hona hemen datu-taularen irudia MAX konstanteak 21 balio duenean, non 0 markak zenbaki lehen adierazten duen eta 1 markak zenbaki zatigarri adierazten duen:

  1    2   3    4   5    6   7    8    9   10 11  12 13  14  15  16 17  18 19  20  21   zenbakia  
  2    0  0  1  0  1  0  1  1  1  0  1  0  1  1  1  0  1  0  1  1 marka

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21



Ariketaren balizko kodea ikusi:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
(*
   Muga den kopuru arrunta emanez, muga hori baino txikiagoak diren
   "Zenbaki Lehenak" lortzeko metodo bat aurkitu zuen Eratostenesek.
    
   Algoritmoa:
   ----------
   2tik iMuga-rako zenbakiak zerrenda batean jartzen dira. Lehenengo, 2ren
   multiplo guztiak markatzen dira, eta 2 zenbakia emaitza den lehenen
   zerrendari gehituko zaio. Ondoren, 3ren multiplo guztiak markatuko dira,
   eta 3 zenbakia gehituko zaio lehenen zerrendari. Gero, 4ari begiratzen
   zaio, markatuta dagoela ikusten da, eta horrek esan nahi du 2rekin
   zatigarria dela, eta, beraz, ez da lehena. Ondoren, 5era iristen da;
   markatuta ez dagoenez, lehena da, bere multiplo guztiak markatzen dira
   eta lehenen zerrendara gehituko da.
   Prozesu errepikakorra bukatzeko baldintza: Une jakin batean aztertuko den
   zenbakiaren karratua iMuga-tik beherakoa bada, jarraitu beharra dago.
   Bestela, algoritmoa amaitu egiten da, eta markatu gabe geratu diren
   guztiak zenbaki lehenak dira (emaitza-zerrendari gehitu beharrekoak).
    
   Animazio hau ikusi:
 
   Bi programa hauek aztertu:
      * EratostenesenBahea_1 zenbaki osoen bi dimentsiotako array bat
      * EratostenesenBahea_2 erregistroen dimentsio bakarreko array bat
*)
 
Program EratostenesenBahea_1;
const
   MAX = 120;
type
   taiDatuak = array[1..2, 2..MAX] of integer;   // 2 errenkada eta MAX-1 zutabe
   taiLehenak = array[1..MAX-1] of integer;
 
 
procedure DatuakLortu(var aiDatuak: taiDatuak; var iLuzeraDatuak: integer);
var
   k: integer;
begin
   iLuzeraDatuak := MAX;
   for k:=2 to iLuzeraDatuak do
   begin
      aiDatuak[1,k] := k;
      aiDatuak[2,k] := 0;   // 0 (FALSE) lehena eta 1 (TRUE) zatigarria
   end;
end;
 
 
procedure DatuakIkusi(const aiDatuak: taiDatuak; iLuzeraDatuak: integer);
var
   k: integer;
   iKont_0: integer;    // lehenen kopurua
   iKont_1: integer;    // zatigarrien kopurua
begin
   iKont_0 := 1;    // 1 zenbakia lehena da eta ez dugu begizta barruan prozesatuko
   iKont_1 := 0;    // zatigarrien kopurua
   writeln('--------------------------------------------------------------------------------');
   write('   1-LEHEN');
   for k:=2 to iLuzeraDatuak do
   begin
      write(aiDatuak[1,k]:4);
      if aiDatuak[2,k]=0 then
      begin
         write('-LEHEN');
         iKont_0 := iKont_0 +1;
      end
      else
      begin
         write('__ZAT.');
         iKont_1 := iKont_1 +1;
      end;
   end;
   writeln;
   writeln('--------------------------------------------------------------------------------');
   writeln(' Zenbakien kopurua = ', iLuzeraDatuak, '     Lehenen kopurua = ', iKont_0, '     Zatigarrien kopurua = ', iKont_1);
end;
 
 
procedure LehenakLortu(const aiDatuak: taiDatuak; iLuzeraDatuak: integer;
                       var aiLehenak: taiLehenak; var iLuzeraLehenak: integer);
var
   k: integer;
begin
   iLuzeraLehenak := 1;
   aiLehenak[iLuzeraLehenak] := 1;
   for k:=2 to iLuzeraDatuak do
   begin
      if aiDatuak[2,k]=0 then
      begin
         iLuzeraLehenak := iLuzeraLehenak +1;
         aiLehenak[iLuzeraLehenak] := aiDatuak[1,k];
      end;
   end;
end;
 
 
procedure LehenakIkusi(const aiLehenak: taiLehenak; iLuzeraLehenak: integer);
var
   k: integer;
begin
   writeln('********************************************************************************');
   for k:=1 to iLuzeraLehenak do
   begin
      write(aiLehenak[k]:3, ', ');
   end;
   writeln;
   writeln('********************************************************************************');
   writeln('  iLuzeraLehenak = ', iLuzeraLehenak);
end;
 
 
{-----------------------programa nagusia eta bere aldagaiak-----------------------}
var
   aiDatuak: taiDatuak;
   iLuzeraDatuak: integer;
   aiLehenak: taiLehenak;
   iLuzeraLehenak: integer;
   iIterazioa: integer;
   k: integer;
begin
   DatuakLortu(aiDatuak, iLuzeraDatuak);
   writeln;
   writeln('Hasierako datuak:');
   DatuakIkusi(aiDatuak, iLuzeraDatuak);
   writeln;
   writeln;
   writeln('1 zenbakia alde batera utzirik, prozesu errepikakorra 2 zenbakiarekin hasiko da');
   writeln;
   writeln;
 
   iIterazioa := 2;         // lehenengo iterazioan, 2ren multiploak markatzen dira
   repeat
      writeln('================================================================================');
      if aiDatuak[2,iIterazioa] = 0 then
      begin
         write(iIterazioa, ' zenbakia lehena da, ');
         writeln(iIterazioa, ' zenbakiaren multiploak markatzen...');
         for k:=iIterazioa+1 to MAX do
         begin
            if aiDatuak[1,k] mod iIterazioa = 0 then
            begin
               aiDatuak[2,k] := 1;    // zatigarria delako 1 marka dagokio
               writeln(aiDatuak[1,k]:4, ' zenbakia markaturik zatigarria delako');
            end;
         end;
      end
      else
         writeln(iIterazioa, ' zenbakia zatigarria da');
 
      writeln(iIterazioa, ' arteko datuak:');
      DatuakIkusi(aiDatuak, iLuzeraDatuak);
      writeln('================================================================================');
      iIterazioa := iIterazioa +1;
      if iIterazioa*iIterazioa <= MAX then
         writeln(' ', iIterazioa, 'x', iIterazioa, ' = ', iIterazioa*iIterazioa, ' <= ', MAX, '   prozesu errepikakorrarekin jarraitu')
      else
         writeln(' ', iIterazioa, 'x', iIterazioa, ' = ', iIterazioa*iIterazioa, ' > ', MAX, '   prozesu errepikakorra amaitu');
      writeln;
      writeln;
   until iIterazioa*iIterazioa > MAX;
 
   LehenakLortu(aiDatuak, iLuzeraDatuak, aiLehenak, iLuzeraLehenak);
   writeln('Lehenen zerrenda:');
   LehenakIkusi(aiLehenak, iLuzeraLehenak);
    
   writeln;
   writeln;
   write('ENTER sakatu exekuzioa amaitzeko... ');
   readln;
end.
 



Eratostenes (antzinako grezieraz: Ἐρατοσθένης; K.a. 276 inguru - K.a. 195 inguru) matematikari, geografo, kirolari, poeta eta astronomo greziarra izan zen. Alexandriako Liburutegia famatuaren zuzendari izendatu zuten eta aurkikuntza ugari egin zituen, hala nola, latitude eta longitude sistema. Eratostenes ezaguna da Lurraren zirkunferentzia kalkulatzen lehen greziarra izan zelako, baita Lurraren ardatzak duen makurdura. Bestalde, garaiko ezagutza geografikoaren araberako mundu mapa eratu zuen ere. 

                   
 

10. astea | Zortearen Zenbakien Segida

Galbahe (edo bahe) baten irudia. Galbaheri esker aleak sailka daitezkeen bezala, zenbaki zerrenda bati galbahe logikoren bat aplikatuz zenbakien segida desberdinak lor daitezke, adibidez: "Zortearen Zenbakien Segida" delakoa

Galbahe (edo bahe) baten aplikatzearen aditza bahetu da. Artikulu honetan Zortearen Zenbakien Segida lortuko dugu baina ikusi ere 10. astea | Eratostenesen bahea (I) eta 11. astea | Eratostenesen bahea (II) artikuluak non zenbaki lehenak lantzen diren.

Zortearen Zenbakien Segida eskuratzeko zenbaki arruntei galbahe jakin bat aplikatuko zaie. Zenbaki arrunten zerrenda batean Zortearen Zenbakiak identifikatzeko, zenbakien posizioak aintzat hartuko dira bahetze prozesuan. Cuaderno de Cultura Científica web guneneko artikulu hau ikusi: Los números de la suerte.

Demagun 1etik hasita eta 99 arteko Zortearen Zenbakiak lortu nahi ditugula. Programaren irteerak aztertuz algoritmoa asma dezagun.

Hasierako datuek jarraian erakusten den zerrenda osatzen dute, hots, 1 eta 99 arteko zenbaki arruntek (biak barne) osatzen duten zerrenda:

1 eta 99 arteko zenbaki arruntak behin baino gehiagotan bahetuz Zortearen Zenbakiak lortuko ditugu. Zerrenda hau gordetzeko aiDatuak arraya erabil daiteke

Zerrenda horretako Zortearen Zenbakiak lor ditzagun urratsez-urrats...

Prozesu arrepikakor guztiek bezala, hasieraketa bat egin beharko da. Kasu honetan, repeat-until (edo while-do) agindura sartu aurretik zenbaki bikoitiak kenduko dira hasierako zerrendatik. Lehen bahetze jardun horren arabera emaitza-zerrenda hau osatuko da:

aiDatuak hasierako arraytik abiatuta aiEmaitza array hau lortzen da repeat-until (edo while-do) agindutik kanpo

Algoritmoaren oinarria

Bi array izango ditugu aiDatuak arraya eta aiEmaitza arraya, une jakin bateko aiDatuak arrayari bahetze prozesua aplikatuz lortuko da une horri dagokion aiEmaitza arraya. Baina baheketa desberdinak behar direnez, baheketak errepikatu beharko dira (repeat-until edo while-do aginduaren bat beharko da).

Prozesu errepikorraren aginduaren hasieran aiDatuak arraya aldatuko dugu eta bere balio berriak aurreko aiEmaitza arrayarenak izango dira, begiztaren barnean aiEmaitza arraya berkalkulatuko dugu. Iterazio batetik bestera, joku hau egingo dugu: n iterazio jakin batean lortu dugun aiEmaitza emaitza, n+1 iterazioan aiDatuak datua izango da eta honi esker aiEmaitza emaitza berria kalkulatuko dugu.


Hona hemen algoritmoaren kode zatirik garrantzitsuena:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Program ZenbakiArruntakBahetzen;
const
   MAX = 99;
type
   taiZenbakiak = array[1..MAX] of integer;
 
{-----------------------programa nagusia eta bere aldagaiak-----------------------}
var
   aiDatuak: taiZenbakiak;   // une jakin bateko datuak
   iLuzeraDatuak: integer;
   aiEmaitza: taiZenbakiak;  // une jakin bateko emaitza
   iLuzeraEmaitza: integer;
   iIterazioa: integer;
begin
   { prozesu errepikakorretik kanpo, lehen baheketan, bikoitiak kenduko dira }
 
   iIterazioa := 2;   // bigarren iterazioan 2. posiziokoa eta hurrengoak kentzeko
   repeat
      aiDatuak := aiEmaitza;
      iLuzeraDatuak := iLuzeraEmaitza;
       
      { aiDatuak abiapuntuz harturik aiEmaitza berria kalkulatu }
       
      iIterazioa := iIterazioa +1;
   until { irteteko baldintza };
 
   writeln;
   write('ENTER sakatu exekuzioa amaitzeko... ');
   readln;
end.


Prozesu errepikakorraren barnean, iIterazioa aldagaiak 2 balio du eta horren arabera, uneko aiDatuak arrayaren bigarren posizioko elementuaren balioa hartu behar da (ikusten denez, balio hori 3 da) eta 3., 6., 9. e.a. posizioko elementuak bahetuz aiEmaitza array berria lortuko da:

2. iterazioaren balioa 3 da, horregatik 3 posizioko jauziak egingo dira. Horrela: 3. posizioko 5 balioa kendu,
6. posizioko 11 balioa kendu, 9. posizioko 17 balioa kendu, 12. posizioko 23 balioa kendu, eta abar

2. iterazioa amaitzean uneko zerrendak 34 elementu izango ditu:

 1  3  7  9 13 15 19 21 25 27 31 33 37 39 43 45 49 51 55 57 61 63 67 69 ... 99
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ... 34


iIterazioa aldagaiak 3 balio du eta horren arabera, uneko aiDatuak arrayaren hirugarren posizioko elementuaren balioa hartu behar da (ikusten denez, balio hori 7 da) eta zazpiko jauziak egingo dira 7., 14., 21. eta 28. posizioko elementuak bahetuz aiEmaitza array berria lortzeko:

3. iterazioaren balioa 7 da, horregatik 7 posizioko jauziak egingo dira. Horrela: 7. posizioko 19 balioa kendu,
14. posizioko 39 balioa kendu, 21. posizioko 61 balioa kendu eta 28. posizioko 81 balioa kendu

3. iterazioa amaitzean uneko zerrendak 30 elementu izango ditu:

 1  3  7  9 13 15 21 25 27 31 33 37 43 45 49 51 55 57 63 67 69 73 75 79 ... 99
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ... 30


iIterazioa aldagaiak 4 balio du eta horren arabera, uneko aiDatuak arrayaren laugarren posizioko elementuaren balioa hartu behar da (ikusten denez, balio hori 9 da) eta bederatziko jauziak egingo dira 9., 18. eta 27. posizioko elementuak bahetuz aiEmaitza array berria lortzeko:

4. iterazioaren balioa 9 da, horregatik 9 posizioko jauziak egingo dira. Horrela: 9. posizioko 27 balioa kendu,
18. posizioko 57 balioa kendu eta 27. posizioko 91 balioa kendu

4. iterazioa amaitzean uneko zerrendak 27 elementu izango ditu:

 1  3  7  9 13 15 21 25 31 33 37 43 45 49 51 55 63 67 69 73 75 79 85 87 ... 99
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ... 27


iIterazioa aldagaiak 5 balio du eta horren arabera, uneko aiDatuak arrayaren bosgarren posizioko elementuaren balioa hartu behar da (ikusten denez, balio hori 13 da) eta hamahiruko jauziak egingo dira 13. eta 26. posizioko elementuak bahetuz aiEmaitza array berria lortzeko:

5. iterazioaren balioa 13 da, horregatik 13 posizioko bi jauzi egingo dira.
Horrela: 13. posizioko 45 balioa kendu eta 26. posizioko 97 balioa kendu

5. iterazioa amaitzean uneko zerrendak 25 elementu izango ditu:

 1  3  7  9 13 15 21 25 31 33 37 43 49 51 55 63 67 69 73 75 79 85 87 93 99
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25


iIterazioa aldagaiak 6 balio du eta horren arabera, uneko aiDatuak arrayaren seigarren posizioko elementuaren balioa hartu behar da (ikusten denez, balio hori 15 da) eta hamabosteko jauziak egingo dira 15. posizioko elementu bakarra bahetuz aiEmaitza array berria lortzeko:

6. iterazioaren balioa 15 da, horregatik 15 posizioko jauziak egingo dira.
Baina, 15. posizioko 55 balioa kendu ostean gehiagorik ezingo da kendu

6. iterazioa amaitzean uneko zerrendak 24 elementu izango ditu:

 1  3  7  9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79 85 87 93 99
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24


iIterazioa aldagaiak 7 balio du eta horren arabera, uneko aiDatuak arrayaren zazpigarren posizioko elementuaren balioa hartu behar da (ikusten denez, balio hori 21 da) eta hogeita bateko jauziak egingo dira 21. posizioko elementu bakarra bahetuz aiEmaitza array berria lortzeko:

7. iterazioaren balioa 21 da, horregatik 21 posizioko jauziak egingo dira.
Baina, 21. posizioko 85 balioa kendu ostean gehiagorik ezingo da kendu

7. iterazioa amaitzean uneko zerrendak 23 elementu izango ditu:

 1  3  7  9 13 15 21 25 31 33 37 43 49 51 63 67 69 73 75 79 87 93 99
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

Ikusten den bezala, azken zerrendako 1. elementua 1 da, 2. elementua 3 da eta 23. elementua 99 da. Hurrengo iterazioan jauzien neurria 25ekoa da baina zerrendak 23 elementu dituenez ez da 8. iteraziorik izango:

8. iteraziorik ez da izango bere balioa 25 delako eta zerrendaren elementu kopurua 23 delako


Ariketaren balizko kode osoa ikusi:

ORAINDIK EZKUTATURIK!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
{
   "Zortearen Zenbakiak" ala "Josephus Flaviusen Baheketa"
    
   Zortearen Zenbakien Segida lortzeko zenbaki arruntei galbahe jakin
   bat aplikatuko zaie. Zortearen Zenbakiak zerrendan identifikatzeko
   bahetze prozesuan zenbaki arrunten posizioak aintzat hartuko dira.
   Web gune hau ikusi:
    
}
 
Program ZenbakiArruntakBahetzen;
const
   MAX = 99;
type
   taiZenbakiak = array[1..MAX] of integer;
 
 
procedure DatuakLortu(var aiDatuak: taiZenbakiak; var iLuzeraDatuak: integer);
var
   k: integer;
begin
   iLuzeraDatuak := MAX;
   for k:=1 to iLuzeraDatuak do
   begin
      aiDatuak[k] := k;
   end;
end;
 
procedure ZenbakiakIkusi(aiZenbakiak: taiZenbakiak; iLuzera: integer);
var
   k: integer;
begin
   writeln('--------------------------------------------------------------------------------');
   for k:=1 to iLuzera do
   begin
      write(aiZenbakiak[k]:4);
   end;
   writeln;
   writeln('--------------------------------------------------------------------------------');
end;
 
 
{-----------------------programa nagusia eta bere aldagaiak-----------------------}
var
   aiDatuak: taiZenbakiak;
   aiEmaitza: taiZenbakiak;
   iLuzeraDatuak: integer;
   iLuzeraEmaitza: integer;
   iIterazioa: integer;
   k: integer;
begin
   DatuakLortu(aiDatuak, iLuzeraDatuak);
   writeln;
   writeln('Hasierako datuak:');
   ZenbakiakIkusi(aiDatuak, iLuzeraDatuak);
   writeln('iLuzeraDatuak=', iLuzeraDatuak);
   writeln;
   writeln;
    
   iIterazioa := 2;         // lehen baheketan bikoitiak kenduko dira
   writeln('1. iterazioa kanpoan, jauzien neurria: ', aiDatuak[iIterazioa], '=aiDatuak[', iIterazioa, ']');
   iLuzeraEmaitza := 0;
   for k:=1 to iLuzeraDatuak do
   begin
      if k mod aiDatuak[iIterazioa] <> 0 then
      begin
         iLuzeraEmaitza := iLuzeraEmaitza +1;
         aiEmaitza[iLuzeraEmaitza] := aiDatuak[k];
      end;
   end;
   ZenbakiakIkusi(aiEmaitza, iLuzeraEmaitza);
   writeln('iLuzeraEmaitza=', iLuzeraEmaitza);
   writeln;
   writeln;
 
   iIterazioa := 2;         // bigarren iterazioan 2. posiziokoa eta hurrengoak kentzeko
   repeat
      aiDatuak := aiEmaitza;
      iLuzeraDatuak := iLuzeraEmaitza;
       
      writeln(iIterazioa, '. iterazioan jauzien neurria: ', aiDatuak[iIterazioa], '=aiDatuak[', iIterazioa, ']');
      iLuzeraEmaitza := 0;
      for k:=1 to iLuzeraDatuak do
      begin
         if k mod aiDatuak[iIterazioa] <> 0 then
         begin
            iLuzeraEmaitza := iLuzeraEmaitza +1;
            aiEmaitza[iLuzeraEmaitza] := aiDatuak[k];
         end
         else
            writeln(aiDatuak[k]:4, ' kenduta');
      end;
      ZenbakiakIkusi(aiEmaitza, iLuzeraEmaitza);
      write('iLuzeraEmaitza=', iLuzeraEmaitza);
      writeln('        Hurrengo iterazioaren jauzien neurria: ', aiEmaitza[iIterazioa+1]);
       
      writeln;
      writeln;
      iIterazioa := iIterazioa +1;
   until iLuzeraDatuak < aiEmaitza[iIterazioa];
 
   writeln;
   write('ENTER sakatu exekuzioa amaitzeko... ');
   readln;
end.