2025(e)ko otsailaren 18(a), asteartea

4. jarduera (II) | Dadoen jokoa

ZER DAKIDAN:
Hainbat funtzio estandar ikasi dut eta for agindua ikasi dut ere.



ZER IKASIKO DUDAN:
Agindu errepikakor habiaratuen gaia sakonduko dut jarduera handiago batean. Bide batez, rand() eta srand() funtzioak praktikatuko ditut.

Artikulu honekin loturik dago 4. jarduera (I) | Dadoen jokoa izenburuko artikulua.



Planteamendua

Jokalarien kopurua ezezaguna da programaren hasieran, eta bere balioa teklatuaren bitartez eman beharko zaio programari.

Bi jokalarien artean berdinketa gertatzean, irabazlea txanpon baten bitartez erabakiko da

Jokalariek dado batekin jokatuko dute. Jokalari bakoitzak dadoaren hiru jaurtiketa egin ondoren, bere emaitza lortzeko dadoaren hiru jaurtiketen puntuak batu behar dira (baliorik txikiena 3 izango da eta baliorik handiena 18 izan daiteke). Programaren azken emaitza bikoitza izango da:

  • Jokalari guztien artean zenbatgarrenak irabazi duen
  • Zenbat puntuekin irabazi du jokalari horrek

Dadoa hiru aldiz jaurti ondoren puntuen baturak, uneko maximoarekin bat egiten badu, berdinketa hausteko txanpon bat erabiliko dugu.

Dadoaren jaurtiketa simulatzeko gogoratu blog honetako Ariketa 19 | Zenbakien funtzio estandarrak artikuluan ematen den (a) programa, non srand() eta rand() funtzio estandarrak erabili diren. Dadoaren aukerak 6 direlako rand()%6+1 aplikatu beharko da:
...
srand(time(NULL));   // srand() zenbaki aleatorioak berriro hasiarazteko, 
                     // hazia behar du. Hazia, adibidez, time(NULL) funtzioa
                     // izan daiteke, zeinek igarotako segundoak long batean
                     // itzultzen dituen 1970-01-01 datatik hasita
iJaurtiketarenBalioa = rand() % 6 + 1;   // 1 eta 6 arteko balioa
...


Irabazlea

Hiru jaurtiketak egin ondoren haien batura handiena lortuko duen jokalariak irabaziko du. Bi jokalarik (edo gehiagok) puntu-kopuru maximoa lortuz gero, irabazlea erabakitzeko txanpon bat erabiliko da. Programa honek bi bertsio izango ditu:

  1. Programa honen lehen bertsioan, berdinketa hausteko txanpona behin bakarrik jaurtitzen da, eta
  2. programa honen bigarren bertsioan, berdinketa hausteko txanpona birritan jaurtitzen da jokalari banarentzat.

Barruko begizta bukatzean, baina oraindik kanpoko begiztan gaudelarik, une horretan irabazlea zein den erabakitzen da. Ondorioz, emaitzak izango diren iMaximoa eta iIrabazlea aldagaien eguneraketak burutuko dira horrela badagokie. Berdinketa gertatzen bada, programaren puntu horretan prozesatu behar da:

/* 4a4-Jarduera_DadoenJokoa: laugarren urratsa, barruko iterazioak */

    ...

    // kanpoko begizta
    for (iKont1 = 1; iKont1 <= iJokalariKopurua; iKont1++)
    {
        printf("\n");
        iPuntuenBatura = 0;
        // barruko begizta
        for (iKont2 = 1; iKont2 <= 3; iKont2++)
        {
            iPuntuak = rand() % 6 + 1; // 1 eta 6 bitarteko zenbakiak
            printf("%d. jokalariak %d puntu lortu ditu %d. jaurtiketan.\n", iKont1, iPuntuak, iKont2);
            iPuntuenBatura += iPuntuak;
        }
        printf("%d. jokalariak guztira %d puntu lortu ditu.\n", iKont1, iPuntuenBatura);
        if (iPuntuenBatura > iMaximoa)  // irabazlea eguneratu
        {
            iMaximoa = iPuntuenBatura;
            iIrabazlea = iKont1;
        }
        else
        {
            if (iPuntuenBatura == iMaximoa) // berdinketan zein da irabazlea?
            {
                      // berdinketa hausteko kodea
            } // if
        } // else
    } // for

    ...
}


Iterazioa jakin batean, berdinketa lortu duten jokalarientzat txanpon bat jaurtitzen da, eta txanponaren jaurtiketaren emaitzak erabakitzen du uneko irabazlea:

/* 4b1-Jarduera_DadoenJokoa: berdinketa hautsi txanpon jaurtiketa bakar batez */

// Zenbat jokalari izango diren zehaztu beharra dago.
// Kanpoko begiztan: jokalarien txandak erakusten dira.
// Barruko begiztan: jokalarien puntuak lortuz irabazlea erabakitzen da;
//                   berdinketarik gertatzean, txanpon bat jaurti egiten
//                   da behin bakarrik horrela irabazlea erabakiz.
// Azken emaitzak erakusten dira: irabazlea eta maximoa.

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtziorako

int main()
{
    int iJokalariKopurua, iMaximoa, iIrabazlea, iPuntuak, iPuntuenBatura;
    int iJokalaria, iJaurtiketa;

    do
    {
        printf("Zenbat jokalari dira? ");
        scanf("%d", &iJokalariKopurua);
    } while (iJokalariKopurua <= 1); // gutxienez 2 jokalari

    srand(time(NULL)); // Random zenbakiak sortzeko hasieratu
    iIrabazlea = 0;
    iMaximoa = 0;

    // jokalarien jarduerak iteratu
    for (iJokalaria = 1; iJokalaria <= iJokalariKopurua; iJokalaria++)
    {
        printf("\n");
        iPuntuenBatura = 0;

        for (iJaurtiketa = 1; iJaurtiketa <= 3; iJaurtiketa++)
        {
            iPuntuak = rand() % 6 + 1; // 1 eta 6 bitarteko zenbakiak
            printf("%d. jokalariak %d puntu lortu ditu %d. jaurtiketan.\n", iJokalaria, iPuntuak, iJaurtiketa);
            iPuntuenBatura += iPuntuak;
        }
        if (iPuntuenBatura > iMaximoa)  // irabazlea eguneratu
        {
            iMaximoa = iPuntuenBatura;
            iIrabazlea = iJokalaria;
        }
        else
        {
            if (iPuntuenBatura == iMaximoa) // berdinketa kudeatzeko txanpon jaurtiketa bat simulatu
            {
                printf("Berdinketa!!! Txanpon bat jaurtitzen...\n");
                if (rand() % 2 == 0)
                    printf("%d. jokalaria aukeratua izan da.\n", iIrabazlea);
                else
                {
                    iIrabazlea = iJokalaria;
                    printf("%d. jokalaria aukeratua izan da.\n", iIrabazlea);
                }
            }  // if
        }  // else
    }  // for

    printf("\nIrabazlea %d. jokalaria da, %d punturekin!\n", iIrabazlea, iMaximoa);

    printf("\nENTER sakatu exekuzioa amaitzeko... ");
    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // ENTER sakatu programatik irteteko
    return 0;
}


Berdinketa lortu duten jokalari biek txanpon bat jaurtiko dute bi aldiz, batek irabazi arte. Orain arteko irabazleak txanpona birritan jaurtitzean iAurrekoarenPuntuak aldagaian metatuko da bere emaitza. Eta berdinketa lortu duen une honetako jokalariak txanpona birritan jaurtitzean iUnekoarenPuntuak aldagaian metatuko da bere emaitza:

/* 4b2-Jarduera_DadoenJokoa: berdinketa hautsi txanponbat birritan jaurtiz */

// Zenbat jokalari izango diren zehaztu beharra dago.
// Kanpoko begiztan: jokalarien txandak erakusten dira.
// Barruko begiztan: jokalarien puntuak lortuz irabazlea erabakitzen da;
//                   berdinketarik gertatzean, bigarren txanda bat jokatu
//                   non txanpon bat birritan jaurtitzen den.
// Azken emaitzak erakusten dira: irabazlea eta maximoa.

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtziorako

int main()
{
    int iJokalariKopurua, iMaximoa, iIrabazlea, iPuntuak, iPuntuenBatura;
    int iJokalaria, iJaurtiketa;
    int iAurrekoarenPuntuak, iUnekoarenPuntuak;

    do
    {
        printf("Zenbat jokalari dira? ");
        scanf("%d", &iJokalariKopurua);
    } while (iJokalariKopurua <= 1); // gutxienez 2 jokalari

    srand(time(NULL)); // Random zenbakiak sortzeko hasieratu
    iIrabazlea = 0;
    iMaximoa = 0;

    // jokalarien jarduerak iteratu
    for (iJokalaria = 1; iJokalaria <= iJokalariKopurua; iJokalaria++)
    {
        printf("\n");
        iPuntuenBatura = 0;

        for (iJaurtiketa = 1; iJaurtiketa <= 3; iJaurtiketa++)
        {
            iPuntuak = rand() % 6 + 1; // 1 eta 6 bitarteko zenbakiak
            printf("%d. jokalariak %d puntu lortu ditu %d. jaurtiketan.\n", iJokalaria, iPuntuak, iJaurtiketa);
            iPuntuenBatura += iPuntuak;
        }

        if (iPuntuenBatura > iMaximoa)  // irabazlea eguneratu
        {
            iMaximoa = iPuntuenBatura;
            iIrabazlea = iJokalaria;
        }
        else
        {
            if (iPuntuenBatura == iMaximoa) // berdinketa kudeatzeko txanpon jaurtiketak simulatu
            {
                do // errepikatu bietariko batek irabazi arte
                {
                    iAurrekoarenPuntuak = 0;
                    for (iJaurtiketa = 1; iJaurtiketa <= 2; iJaurtiketa++)
                    {
                        iAurrekoarenPuntuak += rand() % 2 + 1;
                    }
                    iUnekoarenPuntuak = 0;
                    for (iJaurtiketa = 1; iJaurtiketa <= 2; iJaurtiketa++)
                    {
                        iUnekoarenPuntuak += rand() % 2 + 1;
                    }
                    printf("Berdinketa haustean, aurreko jokalariak %d puntu eta uneko jokalariak %d puntu.\n",
                            iAurrekoarenPuntuak, iUnekoarenPuntuak);
                } while (iAurrekoarenPuntuak == iUnekoarenPuntuak);

                if (iAurrekoarenPuntuak > iUnekoarenPuntuak)
                    printf("Dagoeneko irabazlea, aurreko %d. jokalaria %d puntuekin berdinketa hautsita.\n", iIrabazlea, iMaximoa);
                else
                {
                    iIrabazlea = iJokalaria;
                    printf("Dagoeneko irabazlea, uneko %d. jokalaria %d puntuekin berdinketa hautsita.\n", iIrabazlea, iMaximoa);
                }
            }  // if
        }  // else
    }  // for

    printf("\nIrabazlea %d. jokalaria da, %d punturekin!\n", iIrabazlea, iMaximoa);

    printf("\nENTER sakatu exekuzioa amaitzeko... ");
    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // ENTER sakatu programatik irteteko
    return 0;
}






  • 4b1-Jarduera_DadoenJokoa.cbp | main.c  
  • 4b2-Jarduera_DadoenJokoa.cbp | main.c  


 

4. jarduera (I) | Dadoen jokoa

ZER DAKIDAN:
Hainbat funtzio estandar ikasi dut eta for agindua ikasi dut ere.



ZER IKASIKO DUDAN:
Agindu errepikakor habiaratuen gaia sakonduko dut jarduera handiago batean. Bide batez, rand() eta srand() funtzioak praktikatuko ditut.

Artikulu honekin loturik dago 4. jarduera (II) | Dadoen jokoa izenburuko artikulua.



Planteamendua

Jokalarien kopurua ezezaguna da programaren hasieran, eta bere balioa teklatuaren bitartez eman beharko zaio programari.

Irudiak erakusten duen programaren exekuzio horretan jokalariak 5 dira

Jokalariek dado batekin jokatuko dute. Jokalari bakoitzak dadoaren hiru jaurtiketa egin ondoren, bere emaitza lortzeko dadoaren hiru jaurtiketen puntuak batu behar dira (baliorik txikiena 3 izango da eta baliorik handiena 18 izan daiteke). Programaren azken emaitza bikoitza izango da:

  • Jokalari guztien artean zenbatgarrenak irabazi duen
  • Zenbat puntuekin irabazi du jokalari horrek
Dadoaren jaurtiketa simulatzeko gogoratu blog honetako Ariketa 19 | Zenbakien funtzio estandarrak artikuluan ematen diren (a1) eta (a2) programak. Dadoaren balioa eskuratzeko rand() funtzio estandarra erabiliko da (gogoratu srand() funtzioaren beharra dagoela). Jakina denez, dadoaren aukerak 6 dira eta horregatik iJaurtiketarenBalioa%6+1 aplikatu beharko da:
...
srand(time(NULL));   // srand() zenbaki aleatorioak berriro hasiarazteko, 
                     // hazia behar du. Hazia, adibidez, time(NULL) funtzioa
                     // izan daiteke, zeinek igarotako segundoak long batean
                     // itzultzen dituen 1970-01-01 datatik hasita
iJaurtiketarenBalioa = rand();   // 0 eta RAND_MAX=32767 arteko balioa
iJaurtiketarenBalioa = iJaurtiketarenBalioa % 6 + 1;   // 1 eta 6 artekoa
...


Irabazlea

Hiru jaurtiketak egin ondoren haien batura handiena lortuko duen jokalariak irabaziko du. Bi jokalarik (edo gehiagok) puntu-kopuru maximoa lortuz gero, irabazlea lehen jokalaria izango da.

Zenbat jokalari izango diren galdetuko du programak, eta zenbaki oso bat den erabiltzailearen erantzuna iJokalariKopurua aldagaian gordeko da. Hona hemen 4a1-Jarduera_DadoenJokoa programaren kodea:

/* 4a1-Jarduera_DadoenJokoa: lehen urratsa, jokalarien kopurua zehaztu */

#include <stdio.h>

int main()
{
    int iJokalariKopurua;

    do
    {
        printf("Zenbat jokalari dira? ");
        scanf("%d", &iJokalariKopurua);
    } while (iJokalariKopurua <= 1); // gutxienez 2 jokalari

    printf("%d jokalari izango dira.\n", iJokalariKopurua);

    printf("\nENTER sakatu exekuzioa amaitzeko... ");
    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}


Kanpoko begizta planteatzen da, prozesu errepikakor bat delako eta zenbat itzuli eman behar diren ezaguna delako for agindu bat erabiliko da. Emaitzak izango diren iMaximoa eta iIrabazlea aldagaien hasieraketak begiztatik kanpo egingo dira. Jarraian 4a2-Jarduera_DadoenJokoa programaren kodea hemen erakusten da:

/* 4a2-Jarduera_DadoenJokoa: bigarren urratsa, iterazioak burutu */

// Zenbat jokalari izango diren teklatuz zehaztu ondoren,
// kanpoko begiztan jokalarien txandak erakusten dira.
// iIrabazlea eta iMaximoa aldagaiak ez dira erabiltzen.

#include <stdio.h>

int main()
{
    int iJokalariKopurua, iMaximoa, iIrabazlea;
    int iKont1;

    do
    {
        printf("Zenbat jokalari dira? ");
        scanf("%d", &iJokalariKopurua);
    } while (iJokalariKopurua <= 1); // gutxienez 2 jokalari

    iIrabazlea = 0;
    iMaximoa = 0;

    // jokalarien jarduerak iteratu
    for (iKont1 = 1; iKont1 <= iJokalariKopurua; iKont1++)
    {
        printf("%d. jokalariaren jarduera, 3 jaurtiketen batura kalkulatu beharko da.\n", iKont1);
    }

    printf("\nENTER sakatu exekuzioa amaitzeko... ");
    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}


Barruko begizta planteatzen da, prozesu errepikakor bat delako eta zenbat itzuli eman behar diren ezaguna delako, berriro ere, for agindu bat erabiliko da. Jokalari bakoitzaren puntuaketa diren iPuntuenBatura aldagaiaren hasieraketa begiztatik kanpo egingo da. Bestalde, random(6) funtzioak eman ditzaken balioak 0 eta 5 artean daudelako unitate bat gehitu behar zaie. Hona hemen 4a3-Jarduera_DadoenJokoa programaren kodea:

/* 4a3-Jarduera_DadoenJokoa: hirugarren urratsa, barruko iterazioak */

// Kanpoko begiztan jokalarien txandak erakusten dira.
// Barruko begiztan jokalarien puntuak lortzen dira.
// iIrabazlea eta iMaximoa aldagaiak ez dira erabiltzen.

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtziorako

int main()
{
    int iJokalariKopurua, iMaximoa, iIrabazlea, iPuntuak, iPuntuenBatura;
    int iKont1, iKont2;

    do
    {
        printf("Zenbat jokalari dira? ");
        scanf("%d", &iJokalariKopurua);
    } while (iJokalariKopurua <= 1); // gutxienez 2 jokalari

    srand(time(NULL)); // zenbaki sasi-aleatorioak sortzeko hazia
    iIrabazlea = 0;
    iMaximoa = 0;

    // jokalarien jarduerak iteratu
    for (iKont1 = 1; iKont1 <= iJokalariKopurua; iKont1++)
    {
        printf("\n");
        iPuntuenBatura = 0;

        for (iKont2 = 1; iKont2 <= 3; iKont2++)
        {
            iPuntuak = rand() % 6 + 1; // 1 eta 6 bitarteko zenbakiak
            printf("%d. jokalariak %d puntu lortu ditu %d. jaurtiketan.\n", iKont1, iPuntuak, iKont2);
            iPuntuenBatura += iPuntuak;
        }
        printf("%d. jokalariak guztira %d puntu lortu ditu.\n", iKont1, iPuntuenBatura);
        // irabazlea zein da dagoeneko?
    }

    printf("\nENTER sakatu exekuzioa amaitzeko... ");
    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}


Barruko begizta bukatzean, baina oraindik kanpoko begiztan gaudelarik, une horretan irabazlea zein den erabakitzen da. Ondorioz, emaitzak izango diren iMaximoa eta iIrabazlea aldagaien eguneraketak burutuko dira horrela badagokie. Hauxe da 4a4-Jarduera_DadoenJokoa programaren kodea:

/* 4a4-Jarduera_DadoenJokoa: laugarren urratsa, barruko iterazioak */

// Kanpoko begiztan jokalarien txandak erakusten dira.
// Barruko begiztan jokalarien puntuak lortzen dira eta
// irabazlea dagoeneko zein den erabakitzen da.

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtziorako

int main()
{
    int iJokalariKopurua, iMaximoa, iIrabazlea, iPuntuak, iPuntuenBatura;
    int iKont1, iKont2;

    do
    {
        printf("Zenbat jokalari dira? ");
        scanf("%d", &iJokalariKopurua);
    } while (iJokalariKopurua <= 1); // gutxienez 2 jokalari

    srand(time(NULL)); // zenbaki sasi-aleatorioak sortzeko hazia
    iIrabazlea = 0;
    iMaximoa = 0;

    // jokalarien jarduerak iteratu
    for (iKont1 = 1; iKont1 <= iJokalariKopurua; iKont1++)
    {
        printf("\n");
        iPuntuenBatura = 0;

        for (iKont2 = 1; iKont2 <= 3; iKont2++)
        {
            iPuntuak = rand() % 6 + 1; // 1 eta 6 bitarteko zenbakiak
            printf("%d. jokalariak %d puntu lortu ditu %d. jaurtiketan.\n", iKont1, iPuntuak, iKont2);
            iPuntuenBatura += iPuntuak;
        }
        printf("%d. jokalariak guztira %d puntu lortu ditu.\n", iKont1, iPuntuenBatura);
        if (iPuntuenBatura > iMaximoa)  // (>) irabazlea eguneratu
        {
            iMaximoa = iPuntuenBatura;
            iIrabazlea = iKont1;
        }
    }

    // azken emaitzak erakutsi

    printf("\nENTER sakatu exekuzioa amaitzeko... ");
    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}

Goiko kodean maximoa lortzen da; ikusten denez, bigarren jokalariren batek puntuazio maximoarekin berdinketa suertatzen denean irabazlea ez da aldatzen; beraz, maximoaren lehen jokalaria irabazletzat jotzen den. Baina, nahi izanez gero berdinketaren bigarren jokalaria irabazlea izatea, alderaketa honela izan beharko litzateke:

...
    if (iPuntuenBatura >= iMaximoa)  // (>=) berdinketan irabazlea eguneratu
    {
        iMaximoa = iPuntuenBatura;
        iIrabazlea = iKont1;
    }
...


Programatik irten aurretik, azken emaitzak iMaximoa eta iIrabazlea aldagaien edukiak erakusten dira. Hona hemen 4a5-Jarduera_DadoenJokoa programaren kodea:

/* 4a5-Jarduera_DadoenJokoa: bosgarren urratsa, emaitzak erakutsi */

// Kanpoko begiztan jokalarien txandak erakusten dira.
// Barruko begiztan jokalarien puntuak lortzen dira eta
// dagoeneko irabazlea zein den ezaguna da. Bukatzeko,
// azken emaitzak erakusten dira (irabazlea eta puntuak).

#include <stdio.h>
#include <stdlib.h>   // rand() eta srand() funtzioetarako
#include <time.h>     // time() funtziorako

int main()
{
    int iJokalariKopurua, iMaximoa, iIrabazlea, iPuntuak, iPuntuenBatura;
    int iKont1, iKont2;

    do
    {
        printf("Zenbat jokalari dira? ");
        scanf("%d", &iJokalariKopurua);
    } while (iJokalariKopurua <= 1); // gutxienez 2 jokalari

    srand(time(NULL)); // zenbaki sasi-aleatorioak sortzeko hazia
    iIrabazlea = 0;
    iMaximoa = 0;

    // jokalarien jarduerak iteratu
    for (iKont1 = 1; iKont1 <= iJokalariKopurua; iKont1++)
    {
        printf("\n");
        iPuntuenBatura = 0;

        for (iKont2 = 1; iKont2 <= 3; iKont2++)
        {
            iPuntuak = rand() % 6 + 1; // 1 eta 6 bitarteko zenbakiak
            printf("%d. jokalariak %d puntu lortu ditu %d. jaurtiketan.\n", iKont1, iPuntuak, iKont2);
            iPuntuenBatura += iPuntuak;
        }
        printf("%d. jokalariak guztira %d puntu lortu ditu.\n", iKont1, iPuntuenBatura);
        if (iPuntuenBatura > iMaximoa)  // irabazlea eguneratu
        {
            iMaximoa = iPuntuenBatura;
            iIrabazlea = iKont1;
        }
    }

    printf("\nIrabazlea %d. jokalaria da, %d punturekin!\n", iIrabazlea, iMaximoa);

    printf("\nENTER sakatu exekuzioa amaitzeko... ");
    getchar(); // ENTER teklari itxaron (bufferra garbitzeko)
    getchar(); // edozein tekla sakatu programatik irteteko
    return 0;
}


Esan bezala, bi jokalarik (edo gehiagok) puntu-kopuru maximoa lortuz gero, irabazlea lehen jokalaria izango da. Baina berdinketak beste modu batez hautsi beharko litzateke, adibidez: Dadoa hiru aldiz jaurti ondoren iPuntuenBatura puntuen baturak iMaximoa edukiarekin bat egiten badu, berdinketa hausteko txanpon bat erabil daiteke 4. jarduera (II) | Dadoen jokoa artikuluan erakusten den bezala:

/* 4a4-Jarduera_DadoenJokoa: laugarren urratsa, barruko iterazioak */

    ...

    // kanpoko begizta
    for (iKont1 = 1; iKont1 <= iJokalariKopurua; iKont1++)
    {
        printf("\n");
        iPuntuenBatura = 0;
        // barruko begizta
        for (iKont2 = 1; iKont2 <= 3; iKont2++)
        {
            iPuntuak = rand() % 6 + 1; // 1 eta 6 bitarteko zenbakiak
            printf("%d. jokalariak %d puntu lortu ditu %d. jaurtiketan.\n", iKont1, iPuntuak, iKont2);
            iPuntuenBatura += iPuntuak;
        }
        printf("%d. jokalariak guztira %d puntu lortu ditu.\n", iKont1, iPuntuenBatura);
        if (iPuntuenBatura > iMaximoa)  // irabazlea eguneratu
        {
            iMaximoa = iPuntuenBatura;
            iIrabazlea = iKont1;
        }
        else
        {
            if (iPuntuenBatura == iMaximoa) // berdinketan zein da irabazlea?
            {
                      // berdinketa hausteko kodea
            } // if
        } // else
    } // for

    ...
}






  • 4a1-Jarduera_DadoenJokoa.cbp | main.c  
  • 4a2-Jarduera_DadoenJokoa.cbp | main.c  
  • 4a3-Jarduera_DadoenJokoa.cbp | main.c  
  • 4a4-Jarduera_DadoenJokoa.cbp | main.c  
  • 4a5-Jarduera_DadoenJokoa.cbp | main.c  


 

2025(e)ko otsailaren 12(a), asteazkena

3. jarduera (III) | Errusiar Biderketaren Metodoa programatzen

ZER DAKIDAN:
Hainbat funtzio estandar ikasi dut eta for agindua ikasi dut ere.



ZER IKASIKO DUDAN:
Agindu errepikakor habiaraturkin sakondu aurretik, for agindu isolatua erabiliko dut jarduera handiago batean.

Dakigunez, artikulu honekin lotuta daude bi artikulu hauek:


3. jarduera (I) | Errusiar Biderketaren Metodoa zertan den izenburuko artikulua gogoratuz, ariketa honetan bi zenbiren arteko biderkadura kalkulatzen duen programari bukaera emango diogu.

Datuak iBiderkagai1 eta iBiderkagai2 kopuru osoak eta positiboak izango dira (biak 0 eta 1000000 artekoak, zero eta miloi bat artekoak). Adibidez emandako datuak 30 eta 40 badira, eskatzen den pantailaraketaren zatirik mamitsuena hau da:
                   Erdiak   Dobleak
                   ------   -------
         0. maila      30        40  <<< errenkada hau ez da konputatuko
         1. maila      15        80
         2. maila       7       160
         3. maila       3       320
         4. maila       1       640
Goiko taulan adierazten den bezala iBiderkagai1 aldagaiaren balioa bikoitia bada edo bere erdiak bikoitiak badira, mezu bat agertzeaz gain iBiderkagai2 aldagaiaren balioa eta bere dobleak ez dira batuketan kontuan izango.

Hona hemen programaren balizko irteera bat emandako datuak 30 eta 40 izatean:



Hemen programa beraren irteera emandako datuak 31 eta 40 izatean. Ikus daitekeenez, errekada guztiak konputatzen dira, for kanpoko errenkada eta for barruko lau errenkadak:



Eta hemen programa beraren irteera emandako datuak 32 eta 40 izatean. Non, konputatzen den errenkada bakarra azkena den:
                   Erdiak   Dobleak
                   ------   -------
         0. maila      32        40  <<< errenkada hau ez da konputatuko
         1. maila      16        80  <<< errenkada hau ez da konputatuko
         2. maila       8       160  <<< errenkada hau ez da konputatuko
         3. maila       4       320  <<< errenkada hau ez da konputatuko
         4. maila       2       640  <<< errenkada hau ez da konputatuko
         5. maila       1      1280





/* 3c-Jarduera_ErrusiarBiderketa_1: for aginduaren adibidea. */

// Errusiar Biderketaren Metodoa' aplikatzen duen programa bat idatzi nahi da,
// horretarako kalkulu errepikarrak egin behar dira.

// DATUAK:
//       Sarrerako datuak, positiboak diren bi zenbaki osoko.
// EMAITZA:
//       Irteera bi datuen arteko biderkadura izango da. Zenbaki osoen ariketa
//       izanik, emaitzaren eta doblearen datu-mota 'long int' aukeratuko dugu.
//       Kasu horretan, gainezkatzea gertatu ez dadin balio maximoa 45000 da.
//       3c-Jarduera_ErrusiarBiderketa_2.cbp beste bertsioan 'double' datu-motak
//       hartzen dira eta maximoa 1000000000 (1000 miloi) izan daiteke.

// Prozesu errepikakorraren iterazio kopurua zehazteko, iIterazioak kalkulatu:
//                         2^fMailak = iBiderkagai1;
//                         fMailak·log2(2) = log2(iBiderkagai1);
//                         fMailak = log2(iBiderkagai1);
//                         iIterazioak = (int)fMailak;
//                         iIterazioak = (int)log2(iBiderkagai1);

#include <stdio.h>   // printf() eta scanf() funtzioetarako
#include <math.h>    // log2() funtzioarako

#define GUREMINIMOA 0
#define GUREMAXIMOA 45000   // long datu-mota erabiliz

int main()
{
    int iBiderkagai1, iBiderkagai2;
    int iErrenkada;
    int iIterazioak;
    int iErdia;
    long lDoblea;
    long lBiderkadura, lKonprobazioa;

    printf("\n");
    printf("\n ---------------------------------");
    printf("\n | Errusiar Biderketaren Metodoa |");
    printf("\n ---------------------------------\n");

    printf("\n Bi biderkagaiak eman... \n\n");

    do
    {
        printf(" Lehen biderkagaia (%d eta %d artekoa), 4059 adibidez: ", GUREMINIMOA, GUREMAXIMOA);
        scanf("%d", &iBiderkagai1);
        if (iBiderkagai1 < GUREMINIMOA)
            printf("\a Lehen datua %d edo handiago izango da! \n", GUREMINIMOA);
        if (iBiderkagai1 > GUREMAXIMOA)
            printf("\a Lehen datua %d edo txikiago izango da! \n", GUREMAXIMOA);
    } while (iBiderkagai1 < GUREMINIMOA || iBiderkagai1 > GUREMAXIMOA);

    do
    {
        printf(" Bigarren biderkagaia (%d eta %d artekoa), %d adibidez: ", iBiderkagai1, GUREMAXIMOA, iBiderkagai1);
        scanf("%d", &iBiderkagai2);
        if (iBiderkagai2 < iBiderkagai1)
            printf("\a Bigarren datua %d edo handiago izango da! \n", iBiderkagai1);
        if (iBiderkagai2 > GUREMAXIMOA)
            printf("\a Bigarren datua %d edo txikiago izango da! \n", GUREMAXIMOA);
    } while (iBiderkagai2 < iBiderkagai1 || iBiderkagai2 > GUREMAXIMOA);

    printf("\n                    Erdiak     Dobleak");
    printf("\n                    ------     -------");

    iErdia = iBiderkagai1;
    lDoblea = iBiderkagai2;
    iIterazioak = (int)log2(iBiderkagai1);
    lBiderkadura = 0;   // hasieraketa 0 da, biderkadura lortzeko batuketak egingo direlako
    if (iBiderkagai1 % 2 == 0)  // bikoiti
    {
        printf("\n  %2d. (kanpokoa)   %7d     %d  <<< errenkada hau ez da konputatuko", 0, iBiderkagai1, iBiderkagai2);
    }
    else
    {
        printf("\n  %2d. (kanpokoa)   %7d     %d", 0, iBiderkagai1, iBiderkagai2);
        lBiderkadura = lBiderkadura + lDoblea;
    }
    for (iErrenkada=1; iErrenkada<=iIterazioak; iErrenkada++)
    {
        iErdia = iErdia / 2;
        lDoblea = lDoblea*2;

        if (iErdia % 2 == 0)  // bikoiti
        {
            printf("\n  %2d. iterazioa    %7d     %ld  <<< errenkada hau ez da konputatuko", iErrenkada, iErdia, lDoblea);
        }
        else  // bakoiti
        {
            printf("\n  %2d. iterazioa    %7d     %ld", iErrenkada, iErdia, lDoblea);
            lBiderkadura = lBiderkadura + lDoblea;
        }
    }

    printf("\n");
    printf("\n\t %9d x %d = %ld  Errusiar Metodoaren arabera", iBiderkagai1, iBiderkagai2, lBiderkadura);
    lKonprobazioa = iBiderkagai1*iBiderkagai2;
    printf("\n\t %9d x %d = %ld  ohiko * eragilea erabiliz", iBiderkagai1, iBiderkagai2, lKonprobazioa);

    printf("\n\n");
    return 0;
}


  • 3a-Jarduera_ErrusiarBiderketa_1.cbp | main.c       [metodoa zertan den]
  • 3a-Jarduera_ErrusiarBiderketa_2.cbp | main.c       [metodoa zertan den]
  • 3a-Jarduera_ErrusiarBiderketa_3.cbp | main.c       [metodoa zertan den]
  • 3b-Jarduera_ErrusiarBiderketa.cbp | main.c           [metodoa prestatzen]
  • 3c-Jarduera_ErrusiarBiderketa_1.cbp | main.c       [metodoa programatzen]
  • 3c-Jarduera_ErrusiarBiderketa_2.cbp | main.c       [metodoa programatzen]


 

3. jarduera (II) | Errusiar Biderketaren Metodoa prestatzen

ZER DAKIDAN:
Hainbat funtzio estandar ikasi dut eta for agindua ikasi dut ere.



ZER IKASIKO DUDAN:
Agindu errepikakor habiaraturkin sakondu aurretik, for agindu isolatua erabiliko dut jarduera handiago batean.

Dakigunez, artikulu honekin lotuta daude bi artikulu hauek:


3. jarduera (I) | Errusiar Biderketaren Metodoa zertan den izenburuko artikulua gogoratuz, ariketa honetan bi zenbiren arteko biderkadura kalkulatzen duen programari hasiera emango diogu.

Errusiar Biderketaren Metodoa prestatzen artikulu honen helbura da zehaztea zenbat maila izango diren osoa den zenbaki jakin baterako. Datua: iZenbakia zenbaki osoa. Inkognita: iIterazioak zenbaki osoa.

Datua den iZenbakia zenbaki oso bat irakurriko dugu (0 eta 15000 artekoa). Adibidez emandako datua 36 bada, eskatzen den pantailaraketaren zatirik mamitsuena hau da:
                                  Erdiak   Dobleak
                                  ------   -------
                        1. maila      18        72
                        2. maila       9       144
                        3. maila       4       288
                        4. maila       2       576
                        5. maila       1      1152
iZenbakia aldagaian 36 hartu bada, goiko taularen mailak 5 izango dira, zenbakiaren balioa eta mailen kopurua estuki lotuta daude 2 konstantearen bitartez (horri esker erdiak eta dobleak lortzen baitira). Maila kopurua iterazioen kopurua izango da eta iIterazioak aldagaian gordetzen da, baina iIterazioak ezagutzeko hauxe da kalkulua non fMailak zenbaki erreal bat den:

2fMailak = iZenbakia
log2(2fMailak) = log2(iZenbakia)
fMailak·log2(2) = log2(iZenbakia)
fMailak·1 = log2(iZenbakia)

fMailak = log2(iZenbakia)
      non log2 logaritmo bitarraren funtzioa den (ikusi blogeko Ariketa 19 | Zenbakien funtzio estandarrak artikuluan ematen diren (c) eta (d) programak).

Bilatzen dugu iIterazioak aldagaiaren balioa fMailak aldagaiaren zati osoa izango da. Beraz:

fMailak = log2(iZenbakia)
iIterazioak = (int)fMailak
iIterazioak = (int)log2(iZenbakia)

Hona hemen eskatzen den programaren balizko irteera bat, non iIterazioak kalkulatu ondoren, zatirik interesgarriena  for (iKont=1; iKont<=iIterazioak; iKont++)  aginduarena den:


Ikusi ere long datu-motarekin lan eginez dobleak kalkulatzean MAX_LONG konstantea berehala gainditzen dela. Horregatik, programaren azken bertsioan dobleak gordetzen duen aldagaia float bezala deklaratuko dugu.




/* 3b-Jarduera_ErrusiarBiderketa: for aginduaren adibidea. */

// Zenbaki osoekin lan eginez, iZenbakia teklatuz irakurri
// ziurtatuz datua 64 edo handiagoa dela (adibidez 65), eta
// irakurritako datuaren lehen 4 erdiak eta lehen 4 dobleak
// pantailan idatzi. Datuaren balio maximoa 15000 izango da.

#include <stdio.h>   // printf() eta scanf() funtzioetarako
#include <math.h>    // log2() funtzioarako
#define GUREMINIMOA 64
#define GUREMAXIMOA 15000
#define ITERAZIOKOPURUA 4

int main()
{
    int iZenbakia, iKont;
    int iErdia, iIterazioak;
    long lDoblea;

    printf("\n");
    printf("\n Kopuru osoko eta positiboekin lan egingo da");
    printf("\n -------------------------------------------\n");

    printf("\n [%d, %d] arteko zenbaki osoa eman eta iterazio kopuru", GUREMINIMOA, GUREMAXIMOA);
    printf("\n desberdineko bere erdiak eta dobleak pantailaratuko dira.\n\n");
    do
    {
        printf(" Biderkagai bat adierazten duen zenbaki osokoa eman (789 adibidez): ");
        scanf("%d", &iZenbakia);
        if (iZenbakia < GUREMINIMOA)
            printf(" Datua %d edo handiago izango da! \n", GUREMINIMOA);
        if (iZenbakia > GUREMAXIMOA)
            printf(" Datua %d edo txikiago izango da! \n", GUREMAXIMOA);
    } while (iZenbakia < GUREMINIMOA || iZenbakia > GUREMAXIMOA);

    printf("\n \t \t \tErdiak\tDobleak");
    printf("\n \t \t \t------\t-------");

    iErdia = iZenbakia;
    lDoblea = iZenbakia;
    for (iKont=1; iKont<=ITERAZIOKOPURUA; iKont++)
    {
        iErdia = iErdia / 2;
        lDoblea = lDoblea*2;
        printf("\n \t %2d. iterazioa \t %5d \t%ld", iKont, iErdia, lDoblea);
    }

    printf("\n\n Ikusi %d datuarekin, erdiaren azken balioa %d dela, baina...", iZenbakia, iErdia);
    printf("\n Zenbat iterazio behar dira %d-rekin azken erdia 1 izan dadin?", iZenbakia);
    printf("\n Erantzuna: log2(iZenbakia) iterazio, %d-rako %d iterazio.", iZenbakia, (int)log2(iZenbakia));

    printf("\n");
    printf("\n \t \t \tErdiak\tDobleak");
    printf("\n \t \t \t------\t-------");

    iErdia = iZenbakia;
    lDoblea = iZenbakia;
    iIterazioak = (int)log2(iZenbakia);
    for (iKont=1; iKont<=iIterazioak; iKont++)
    {
        iErdia = iErdia / 2;
        lDoblea = lDoblea*2;
        printf("\n \t %2d. iterazioa \t %5d \t%ld", iKont, iErdia, lDoblea);
    }

    printf("\n\n Zer gertatzen da %d datuarekin %d iterazio egin ordez %d iterazio egitean?", iZenbakia, iIterazioak, iIterazioak+3);

    printf("\n");
    printf("\n \t \t \tErdiak\tDobleak");
    printf("\n \t \t \t------\t-------");

    iErdia = iZenbakia;
    lDoblea = iZenbakia;
    iIterazioak = (int)log2(iZenbakia)+3;
    for (iKont=1; iKont<=iIterazioak; iKont++)
    {
        iErdia = iErdia / 2;
        lDoblea = lDoblea*2;
        printf("\n \t %2d. iterazioa \t %5d \t%ld", iKont, iErdia, lDoblea);
    }

    iIterazioak = (int)log2(GUREMAXIMOA);
    printf("\n\n Eta GUREMAXIMOA=%d datuarekin %d iterazio egin ordez %d iterazio egitean?", GUREMAXIMOA, iIterazioak, iIterazioak+7);

    printf("\n");
    printf("\n \t \t \tErdiak\tDobleak");
    printf("\n \t \t \t------\t-------");

    iErdia = GUREMAXIMOA;
    lDoblea = GUREMAXIMOA;
    iIterazioak = (int)log2(GUREMAXIMOA)+7;
    for (iKont=1; iKont<=iIterazioak; iKont++)
    {
        iErdia = iErdia / 2;
        lDoblea = lDoblea*2;
        printf("\n \t %2d. iterazioa \t %5d \t%ld", iKont, iErdia, lDoblea);
    }

    printf("\n\n");
    return 0;
} 


  • 3a-Jarduera_ErrusiarBiderketa_1.cbp | main.c       [metodoa zertan den]
  • 3a-Jarduera_ErrusiarBiderketa_2.cbp | main.c       [metodoa zertan den]
  • 3a-Jarduera_ErrusiarBiderketa_3.cbp | main.c       [metodoa zertan den]
  • 3b-Jarduera_ErrusiarBiderketa.cbp | main.c           [metodoa prestatzen]
  • 3c-Jarduera_ErrusiarBiderketa_1.cbp | main.c       [metodoa programatzen]
  • 3c-Jarduera_ErrusiarBiderketa_2.cbp | main.c       [metodoa programatzen]


 

3. jarduera (I) | Errusiar Biderketaren Metodoa zertan den

ZER DAKIDAN:
Hainbat funtzio estandar ikasi dut eta for agindua ikasi dut ere.



ZER IKASIKO DUDAN:
Agindu errepikakor habiaraturkin sakondu aurretik, for agindu isolatua erabiliko dut jarduera handiago batean.

Artikulu honekin loturik, bi artikulu hauek jorratuko ditugu:


Mundu guztiak ez du biderkatzen guk hemen egiten dugun bezala. Bi zenbakiren biderkadura lortzeko darabilgun metodoan hamar zifren (0tik 9ra) biderkatzeko taulak ezagutu behar ditugu, txiki txikitatik ikasi genituen hamar taula horiek; adibidez, hauxe da 7ren biderkatzeko taula:

                        7 x 0 =  0
                        7 x 1 =  7
                        7 x 2 = 14
                        7 x 3 = 21
                        7 x 4 = 28
                        7 x 5 = 25
                        7 x 6 = 42
                        7 x 7 = 49
                        7 x 8 = 56 
                        7 x 9 = 63
Baina, errusiar biderketa bezala ezagutzen den metodoan ez da biderkatzeko taularik ezagutu behar; zenbaki baten doblea eta erdia lortzeko gai izan behar gara. Bi datuen dobleak eta erdiak eskuratu ondoren, batuketa bat burutu behar da hasierako bi zenbakiren arteko biderkadura kalkulatzeko. Bideo honek metodoa bera ederki azaltzen du eta metodoak barneratzen duen printzipio matematikoa ere: 


Jatorrizko bideoa ingelesez ekoizturik dago eta hemen ikus dezakezu


Demagun lau biderketa hauek egin nahi ditugula errusiar biderketaren metodoa aplikatuz:

    33 x 7 =          34 x 7 =          35 x 7 =          36 x 7 =   

33 x 7

Lehenengo biderkagaiaren erdiak eta bigarren biderkagaiaren dobleak kalkulatuz ondoko taula osatu. Zenbaki baten erdia eskuratzean dezimalak ez dira kontutan hartuko; esate baterako 33ren erdia 16,5 da baina taulan 16 idatziko da: 
33 7
   16       14   
    8       28   
    4       56   
    2      112   
1 224

?

Ezkerreko zutabeko bikoitiak diren errenkada osoak ezabatu:
33 7
   16       14   
    8       28   
    4       56   
    2      112   
1 224

231

Eskumako zutabean geratu diren zenbakien batuketa eginez, lortu den 7+224=231 batura hori bilatzen dugun emaitza da, hots, lortutako batura helburuko 33x7=231 biderkadura bezalakoa da.

34 x 7

Lehenengo biderkagaiaren erdiak eta bigarren biderkagaiaren dobleak kalkulatuz, eta ezkerreko zutabetik abiatuta bikoitiak diren errenkadak ezabatuz ondoko taula osatzen da, non lehenago esan den bezala 17ren erdia 8,5 izan arren taulan 8 idatziko dugun:
    34        7   
   17  
   14   
    8       28   
    4       56   
    2      112   
1 224

238

Eskumako zutabean geratu diren zenbakien batuketa eginez, lortu den 14+224=238 batura bilatzen dugun emaitza da, hots, lortutako batura helburuko 34x7=238 biderkadura bezalakoa da.

35 x 7

Lehenengo biderkagaiaren erdiak eta bigarren biderkagaiaren dobleak kalkulatuz, eta ezkerreko zutabetik abiatuta bikoitiak diren errenkadak ezabatuz ondoko taula osatzen da, non lehenago esan den bezala 17ren erdia 8,5 izan arren taulan 8 idatziko dugun:
    35  
    7   
   17  
   14   
    8       28   
    4       56   
    2      112   
1 224

238

Eskumako zutabean geratu diren zenbakien batuketa eginez, lortu den 7+14+224=245 batura bilatzen dugun emaitza da, hots, lortutako batura helburuko 35x7=245 biderkadura bezalakoa da.

36 x 7

Lehenengo biderkagaiaren erdiak eta bigarren biderkagaiaren dobleak kalkulatuz, eta ezkerreko zutabetik abiatuta bikoitiak diren errenkadak ezabatuz ondoko taula osatzen da, non lehenago esan den bezala 9ren erdia 4,5 izan arren taulan 4 idatziko dugun:
    36  
    7   
    18       14  
   9  
   28  
    4       56   
    2      112   
1 224

252

Eskumako zutabean geratu diren zenbakien batuketa eginez, lortu den 28+224=252 batura bilatzen dugun emaitza da, hots, lortutako batura helburuko 36x7=252 biderkadura bezalakoa da.







Errusiar Biderketaren Metodoa aplikatzeko programaren lehen hurbilpena jarraian doa. Hauek dira kodea eta programa horren balizko irteera bat:

/* 3a-Jarduera_ErrusiarBiderketa: for aginduaren adibidea. */

// Zenbaki osoekin lan eginez, iZenbakia teklatuz irakurri
// ziurtatuz datua 64 edo handiagoa dela (adibidez 65), eta
// irakurritako datuaren lehen 4 erdiak eta lehen 4 dobleak
// pantailan idatzi.

#include <stdio.h>   // printf() eta scanf() funtzioetarako
#include <math.h>    // log2() funtzioarako 
#define GUREMINIMOA 64
#define ITERAZIOKOPURUA 4

int main()
{
    int iZenbakia, iKont;
    int iErdia;
    long lDoblea;

    printf("\n");
    printf("\n Kopuru osoko eta positiboekin lan egingo da");
    printf("\n -------------------------------------------\n");

    printf("\n %d edo handiagoa den zenbaki osokoa eman eta konstantea den", GUREMINIMOA);
    printf("\n %d iterazioetan bere erdiak eta dobleak pantailaratuko dira.\n\n", ITERAZIOKOPURUA);
    do
    {
        printf(" Biderkagai bat adierazten duen zenbaki osokoa eman (345 adibidez): ");
        scanf("%d", &iZenbakia);
        if (iZenbakia < GUREMINIMOA)
            printf(" Datua %d edo handiago izango da! \n", GUREMINIMOA);
    } while (iZenbakia < GUREMINIMOA);

    printf("\n \t \t \tErdiak\tDobleak");
    printf("\n \t \t \t------\t-------");

    iErdia = iZenbakia;
    lDoblea = iZenbakia;
    for (iKont=1; iKont<=ITERAZIOKOPURUA; iKont++)
    {
        iErdia = iErdia / 2;
        lDoblea = lDoblea*2;
        printf("\n \t %2d. iterazioa \t %5d \t%ld", iKont, iErdia, lDoblea);
    }

    printf("\n\n Ikusi %d datuarekin, erdiaren azken balioa %d dela, baina...", iZenbakia, iErdia);
    printf("\n Zenbat iterazio behar dira %d-rekin azken erdia 1 izan dadin?", iZenbakia);
    printf("\n Erantzuna: log2(iZenbakia) iterazio, %d-rako %d iterazio.", iZenbakia, (int)log2(iZenbakia));

    printf("\n");
    printf("\n Programa honen jarraipena '3b-Jarduera_ErrusiarBiderketa.cbp' proiektuan...");

    printf("\n\n");
    return 0;
}



  • 3a-Jarduera_ErrusiarBiderketa_1.cbp | main.c       [metodoa zertan den]
  • 3a-Jarduera_ErrusiarBiderketa_2.cbp | main.c       [metodoa zertan den]
  • 3a-Jarduera_ErrusiarBiderketa_3.cbp | main.c       [metodoa zertan den]
  • 3b-Jarduera_ErrusiarBiderketa.cbp | main.c           [metodoa prestatzen]
  • 3c-Jarduera_ErrusiarBiderketa_1.cbp | main.c       [metodoa programatzen]
  • 3c-Jarduera_ErrusiarBiderketa_2.cbp | main.c       [metodoa programatzen]


 

2025(e)ko otsailaren 11(a), asteartea

Ariketa 25 | for habiaratuen hiru bertsio


ZER DAKIDAN:
Menpekoa den for agindu errepikakor bat beste for nagusi baten barnean nola erabili ikasi dut, hots, badakit for habiaratuak erabiltzen.



ZER IKASIKO DUDAN:
Menpekoa den for agindu errepikakor bat beste for nagusi baten barneko programaren bertsio hobetua programatuko dut (beharrezkoak ez diren iterazioak sahiestuz programa azkarrago ibiliko da).

Hurrengo lau ariketak berdintsuak dira:


Batugaien iZenbat kopurua zehaztuko duen balioa teklatuz irakurriz, kalkulatu ondoko batukaria eta emaitza liBatukaria aldagaian gorde. Ziurtatu iZenbat kopuru osoa, positiboa eta bikoitia dela.

Batukariaren batugaiak zenbait zenbakien faktorialak dira, hauek:

liBatukaria = 0! + 2! + 4! + 6! + ... + (iZenbat-2)! + iZenbat!

Batukaria lortzen duen programaren bi bertsio egingo ditugu.



1. BERTSIOA                 iZenbat=8                        
Kanpoko  i
hasieraketa
0!=1
1
2
3 4
5 6
7 8
Barruko  j
1
1..2
1..3
1..4
1..5
 1..6
1..7 1..8
liFaktoriala
1
2
6 24
120  720
5040 40320
liBatukaria
1
1
3
3 27
27 747
747 41067


  1. BERTSIOA 

 Kanpoko FOR
Kanpoko prozesu errepikakorra iZenbat aldiz errepikatuko da. Gogoratu prozesu errepikakorrera sartu aurretik beharrezkoak diren hasieraketak egin behar direla. Suposatuz prozesu errepikakorraren 0! lehen batugaia kanpoan egiten dela, lehen iterazioa i=1 hau izango litzateke:
           liBatukaria  =  liBatukaria + liFaktoriala ;
           liBatukaria   [hasieraketa] + [lehenengoa]
           liBatukaria      (0!=1)     +      1!         
           
           if (i % 2 != 0)   /* ez da betetzen */
             liBatukaria = liBatukaria + liFaktoriala ; 
    
Suposatuz prozesu errepikakorraren 0! kanpoan egiten dela, bigarren iterazioa i=2 hau izango litzateke:
           liBatukaria  =  liBatukaria + liFaktoriala ;
           liBatukaria     [metatua]   + [bigarrena]
           liBatukaria          1      +      2!            
           
           if (i % 2 != 0)   /* bai betetzen da */
             liBatukaria = liBatukaria + liFaktoriala ; 
                   3            1      +      2! 
    
Suposatuz prozesu errepikakorraren 0! kanpoan egiten dela, hirugarren iterazioa i=3 hau izango litzateke:
           liBatukaria  =  liBatukaria + liFaktoriala ;
           liBatukaria     [metatua]   + [hirugarrena]
           liBatukaria          3      +      3!            
           
           if (i % 2 != 0)   /* ez da betetzen */
             liBatukaria = liBatukaria + liFaktoriala ; 
    
Suposatuz prozesu errepikakorraren 0! kanpoan egiten dela, laugarren iterazioa i=4 hau izango litzateke:
           liBatukaria  =  liBatukaria + liFaktoriala ;
           liBatukaria     [metatua]   + [laugarrena]
           liBatukaria          3      +      4!            
           
           if (i % 2 != 0)   /* bai betetzen da */
              liBatukaria = liBatukaria + liFaktoriala ; 
                  27             3      +      4! 
     

 Barruko FOR
Barruko prozesu errepikakorrak faktoriala kalkulatuko du. Konkretuki, kanpoko i kontagailuaren faktoriala kalkulatuko du:
  liFaktoriala = 1 ;   /* i iterazioaren faktoriala kalkulatu */
  for (j=1; j<= i; j++)
  {
     liFaktoriala = liFaktoriala * j ;
     printf("i=%2d    j=%2d    liFaktoriala=%ld\n", i, j, liFaktoriala) ;
  }
    
/* Ariketa-25a_forHabiaratua-1: faktorialen batukari bat */

// iZenbat kopuru osoa, positiboa eta bikoitia teklatuaren bitartez irakurri
// eta batukari hau kalkulatu:
//      liBatukaria = 0! + 2! + 4! + ... + (iZenbat-2)! + iZenbat!

// 1. bertsioa: kanpoko begiztan iZenbat iterazio.

#include <stdio.h>

int main()
{
    int iZenbat, i, j;
    long liBatukaria, liFaktoriala;

    printf("\n\n");

    // erabiltzaileari datuak eskatu beharrezko baldintzak betetzen dituen bitartean
    do
    {
        printf("iZenbat zenbaki osoa, positiboa eta bikoitia eman: ");
        scanf("%d", &iZenbat);
        if (iZenbat < 0)
            printf("Kopuru positiboa behar da\n");
        if (iZenbat % 2 != 0)
            printf("Kopurua zenbaki bikoitia izan behar da\n");
    } while (iZenbat < 0 || iZenbat % 2 != 0);

    printf("\n");

    liBatukaria = 1; // 0! = 1, eta hasieran liBatukaria hori da

    printf("Hasieran, liBatukaria=%ld\n\n", liBatukaria);

    for (i = 1; i <= iZenbat; i++)
    {
        liFaktoriala = 1; // faktorialaren kalkulua hasieratu behar da i-rako
        for (j = 1; j <= i; j++)
        {
            liFaktoriala = liFaktoriala * j;
            printf("i=%2d    j=%2d    liFaktoriala=%ld\n", i, j, liFaktoriala);
        }

        if (i % 2 == 0)
            liBatukaria = liBatukaria + liFaktoriala;
        else
            printf("i=%2d bakoitia delako ez inkrementatu, ", i);

        printf("liBatukaria=%ld\n\n", liBatukaria);
    }

    printf("Batukaria = %ld\n", liBatukaria);

    printf("\n\n");
    printf("=======================\n");
    printf("RETURN sakatu amaitzeko\n");
    printf("=======================\n");
    getchar(); // Amaieran erabiltzailearen enter itxaron
    getchar();

    return 0;
}



      2. BERTSIOA                 iZenbat=8             
Kanpoko  i
hasieraketa
0!=1
1
2
3 4
Barruko  j
1..1x2
1..2x2
1..3x2
1..4x2
liFaktoriala
2
24
720 40320
liBatukaria
1
3
27
747 41067


  2. BERTSIOA 

 Kanpoko FOR
Kanpoko prozesu errepikakorra iZenbat/2 aldiz errepikatuko da. Gogoratu prozesu errepikakorrera sartu aurretik beharrezkoak diren hasieraketak egin behar direla. Suposatuz prozesu errepikakorraren 0! lehen batugaia kanpoan egiten dela, lehen iterazioa i=1 hau izango litzateke:
           liBatukaria  =  liBatukaria  + liFaktoriala ;
           liBatukaria    [hasieraketa] + [lehenengoa]
           liBatukaria       (0!=1)     +    (2*1)!
           
           liBatukaria  = liBatukaria + liFaktoriala ; 
                3              1      +      2!           
Suposatuz prozesu errepikakorraren 0! kanpoan egiten dela, bigarren iterazioa i=2 hau izango litzateke:
           liBatukaria  =  liBatukaria  + liFaktoriala ;
           liBatukaria     [metatua]    + [bigarrena]
           liBatukaria         3        +    (2*2)!            
           
           liBatukaria  = liBatukaria + liFaktoriala ; 
               27              3      +      4! 
    

 Barruko FOR
Barruko prozesu errepikakorrak faktoriala kalkulatuko du. Konkretuki, kanpoko i kontagailuaren dobleari dagokion faktoriala kalkulatuko du:
  liFaktoriala = 1 ;   /* i iterazioaren faktoriala kalkulatu */
  for (j=1; j<= i*2; j++)
  {
     liFaktoriala = liFaktoriala * j ;
     printf("i=%2d    j=%2d    liFaktoriala=%ld\n", i, j, liFaktoriala) ;
  }
    
/* Ariketa-25b_forHabiaratua-2: faktorialen batukari bat */

// iZenbat kopuru osoa, positiboa eta bikoitia teklatuaren bitartez irakurri
// eta batukari hau kalkulatu:
//      liBatukaria = 0! + 2! + 4! + ... + (iZenbat-2)! + iZenbat!

// 2. bertsioa: kanpoko begiztan iZenbat/2 iterazio.

#include <stdio.h>

int main()
{
    int iZenbat, i, j;
    long liBatukaria, liFaktoriala;

    printf("\n\n");

    // erabiltzaileari datuak eskatu beharrezko baldintzak betetzen dituen bitartean
    do
    {
        printf("iZenbat zenbaki osoa, positiboa eta bikoitia eman: ");
        scanf("%d", &iZenbat);
        if (iZenbat < 0)
            printf("Kopuru positiboa behar da\n");

        if (iZenbat % 2 != 0)
            printf("Kopurua zenbaki bikoitia izan behar da\n");
    } while (iZenbat < 0 || iZenbat % 2 != 0);

    printf("\n");

    liBatukaria = 1; // 0! = 1, eta hasieran liBatukaria hori da

    printf("Hasieran, liBatukaria=%ld\n\n", liBatukaria);

    for (i = 1; i <= iZenbat / 2; i++)
    {
        liFaktoriala = 1; // faktorialaren kalkulua hasieratu behar da i*2-rako
        for (j = 1; j <= i * 2; j++)
        {
            liFaktoriala = liFaktoriala * j;
            printf("i=%2d    j=%2d    liFaktoriala=%ld\n", i, j, liFaktoriala);
        }

        liBatukaria = liBatukaria + liFaktoriala;

        printf("liBatukaria=%ld\n\n", liBatukaria);
    }

    printf("Batukaria = %ld\n", liBatukaria);

    printf("\n\n");
    printf("=======================\n");
    printf("RETURN sakatu amaitzeko\n");
    printf("=======================\n");
    getchar(); // amaieran erabiltzailearen enter itxaron
    getchar();

    return 0;
}



      3. BERTSIOA                 iZenbat=8             
Kanpoko  i
hasieraketa
0!=1
2
4
6 8
Barruko  j
1..2
1..4
1..6
1..8
liFaktoriala
2
24
720 40320
liBatukaria
1
3
27
747 41067


  3. BERTSIOA 

 Kanpoko FOR
Kanpoko prozesu errepikakorra iZenbat aldiz errepikatuko da eta kanpoko aldagaiaren inkrementua i+2 izango da. Gogoratu prozesu errepikakorrera sartu aurretik beharrezkoak diren hasieraketak egin behar direla. Suposatuz prozesu errepikakorraren 0! lehen batugaia kanpoan egiten dela, lehen iterazioa i=2 hau izango litzateke:
           liBatukaria  =  liBatukaria  + liFaktoriala ;
           liBatukaria    [hasieraketa] + [lehenengoa]
           liBatukaria       (0!=1)     +    (2)!
           
           liBatukaria  = liBatukaria + liFaktoriala ; 
                3              1      +      2!           
Suposatuz prozesu errepikakorraren 0! kanpoan egiten dela, bigarren iterazioa i=4 hau izango litzateke:
           liBatukaria  =  liBatukaria  + liFaktoriala ;
           liBatukaria     [metatua]    + [bigarrena]
           liBatukaria         3        +    (4)!            
           
           liBatukaria  = liBatukaria + liFaktoriala ; 
               27              3      +      4! 
    

 Barruko FOR
Barruko prozesu errepikakorrak faktoriala kalkulatuko du. Konkretuki, kanpoko i kontagailuaren dagokion faktoriala kalkulatuko du:
  liFaktoriala = 1 ;   /* i iterazioaren faktoriala kalkulatu */
  for (j=1; j<=i; j++)
  {
     liFaktoriala = liFaktoriala * j ;
     printf("i=%2d    j=%2d    liFaktoriala=%ld\n", i, j, liFaktoriala) ;
  }
    
/* Ariketa-25c_forHabiaratua-3: faktorialen batukari bat */

// iZenbat kopuru osoa, positiboa eta bikoitia teklatuaren bitartez irakurri
// eta batukari hau kalkulatu:
//      liBatukaria = 0! + 2! + 4! + ... + (iZenbat-2)! + iZenbat!

// 3. bertsioa: kanpoko begiztan iZenbat iterazio eta kontrol-aldagaia i=i+2.

#include <stdio.h>

int main()
{
    int iZenbat, i, j;
    long liBatukaria, liFaktoriala;

    printf("\n\n");

    // erabiltzaileari datuak eskatu beharrezko baldintzak betetzen dituen bitartean
    do
    {
        printf("iZenbat zenbaki osoa, positiboa eta bikoitia eman: ");
        scanf("%d", &iZenbat);
        if (iZenbat < 0)
            printf("Kopuru positiboa behar da\n");

        if (iZenbat % 2 != 0)
            printf("Kopurua zenbaki bikoitia izan behar da\n");
    } while (iZenbat < 0 || iZenbat % 2 != 0);

    printf("\n");

    liBatukaria = 1; // 0! = 1, eta hasieran liBatukaria hori da

    printf("Hasieran, liBatukaria=%ld\n\n", liBatukaria);

    for (i = 2; i <= iZenbat; i = i + 2)
    {
        liFaktoriala = 1; // faktorialaren kalkulua hasieratu behar da i-rako
        for (j = 1; j <= i; j++)
        {
            liFaktoriala = liFaktoriala * j;
            printf("i=%2d    j=%2d    liFaktoriala=%ld\n", i, j, liFaktoriala);
        }

        liBatukaria = liBatukaria + liFaktoriala;

        printf("liBatukaria=%ld\n\n", liBatukaria);
    }

    printf("Batukaria = %ld\n", liBatukaria);

    printf("\n\n");
    printf("=======================\n");
    printf("RETURN sakatu amaitzeko\n");
    printf("=======================\n");
    getchar(); // amaieran erabiltzailearen enter itxaron
    getchar();

    return 0;
}







  • Ariketa-25a_forHabiaratuak.cbp | main.c  
  • Ariketa-25b_forHabiaratuak.cbp | main.c  
  • Ariketa-25c_forHabiaratuak.cbp | main.c