Gyakorlati alapok

Chilipaprika zabáltatása algoritmikusan

 

Adott egy játék: egy tálban szaloncukrok és 1 db chilipaprika található. (Az édesség fajtája természetesen nem lényeges, csupán egy, de fontos tulajdonsága számít, hogy legyen pontosan megszámolható.)

 

www.informatika-programozas.hu

 

A szaloncukorból 1, 2 vagy 3 darabot húzhatunk. A cél, hogy utolsónak a chilipaprika maradjon és az veszít, akié az utolsó darab. (A játék klasszikus változata szerint ezt a vesztesnek meg kell ennie.) Ha nincs chilipaprika, az veszít, akié az utolsó darab szaloncukor.

 

A játék mögött természetesen algoritmus húzódik meg, így a beavatott játékos (itt a gép) mindig nyerni fog. A tréfa kedvéért először játsszunk a géppel egy kicsit, de úgy, hogy ne pillantsunk rá a működtető Java-kódra:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.Scanner;

public class Main {
public static void main(String[] args) {
    int szalonCukorSzam = 17;
    int szamlalo = 1;
    int aktualisSzam = 0;
    int aktualisSzamGep = 0;
    String szam = "";
    System.out.println("Ön 1, 2 vagy 3 szaloncukrot húzhat.

                                Az veszít, akié a chilipaprika (vagy az utolsó szaloncukor). Ön kezd!");
    Scanner scanner = new Scanner(System.in);
    do{
        do{
            System.out.println("Írja be, hogy " + szamlalo + ". körben hány szaloncukrot húz! (1-2-3)");
            szam = scanner.nextLine();
            }while(!szam.equals("1") && !szam.equals("2") && !szam.equals("3"));
        aktualisSzam = Integer.parseInt(szam);
    szalonCukorSzam -= aktualisSzam;
    aktualisSzamGep = 4 - aktualisSzam;
    System.out.println("A gép jön és " + aktualisSzamGep + " db-ot húzott.");
    szalonCukorSzam -= aktualisSzamGep;
    szamlalo++;
    }while(szalonCukorSzam > 1);
    System.out.println("Ön vesztett,

                                mert Ön jön és a tálban " + szalonCukorSzam + " db szaloncukor van.");
    }
}

 

Végeredmény:

Ön 1, 2 vagy 3 szaloncukrot húzhat. Az veszít, akié a chilipaprika (vagy az utolsó szaloncukor). Ön kezd!
Írja be, hogy hány szaloncukrot húz! (1-2-3)
1
A gép jön és 3 db-ot húzott.
Írja be, hogy hány szaloncukrot húz! (1-2-3)
2
A gép jön és 2 db-ot húzott.
Írja be, hogy hány szaloncukrot húz! (1-2-3)
3
A gép jön és 1 db-ot húzott.
Írja be, hogy hány szaloncukrot húz! (1-2-3)
3
A gép jön és 1 db-ot húzott.
Ön vesztett, mert Ön jön és a tálban 1 db szaloncukor van.

 

A gép nyilvánvalóan nem csal és algoritmikus eszközökkel fog nyerni, ezért most nézzük meg eme rejtély megoldását!

 

Az első fontos részletet a játék többszöri átjátszása után már észrevehetjük: mindig 4 húzási kör + 1 végkör lesz. Ezt a felismerést megkönnyíti ama tény, hogy az alábbi kódban a körök már jelezve vannak, e nélkül kissé nehezebb, de nem lehetetlen ezen felfedezés. Nézzük meg ezt a bővített verziót is:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.Scanner;

public class Main {
public static void main(String[] args) {
    int szalonCukorSzam = 17;
    int szamlalo = 1;
    int aktualisSzam = 0;
    int aktualisSzamGep = 0;
    String szam = "";
    System.out.println("Ön 1, 2 vagy 3 szaloncukrot húzhat.

                                Az veszít, akié a chilipaprika (vagy az utolsó szaloncukor). Ön kezd!");
    Scanner scanner = new Scanner(System.in);
    do{
        do{
            System.out.println("Írja be, hogy " + szamlalo + ". körben hány szaloncukrot húz! (1-2-3)");
            szam = scanner.nextLine();
            }while(!szam.equals("1") && !szam.equals("2") && !szam.equals("3"));
        aktualisSzam = Integer.parseInt(szam);
    szalonCukorSzam -= aktualisSzam;
    aktualisSzamGep = 4 - aktualisSzam;
    System.out.println("A gép jön és " + aktualisSzamGep + " db-ot húzott.");
    szalonCukorSzam -= aktualisSzamGep;
    szamlalo++;
    }while(szalonCukorSzam > 1);
    System.out.println("Ön vesztett,

                                mert Ön jön és a tálban " + szalonCukorSzam + " db szaloncukor van.");
    }
}

 

Végeredmény:

Ön 1, 2 vagy 3 szaloncukrot húzhat. Az veszít, akié a chilipaprika (vagy az utolsó szaloncukor). Ön kezd!
Írja be, hogy 1. körben hány szaloncukrot húz! (1-2-3)
e
Írja be, hogy 1. körben hány szaloncukrot húz! (1-2-3)
4
Írja be, hogy 1. körben hány szaloncukrot húz! (1-2-3)
1
A gép jön és 3 db-ot húzott.
Írja be, hogy 2. körben hány szaloncukrot húz! (1-2-3)
2
A gép jön és 2 db-ot húzott.
Írja be, hogy 3. körben hány szaloncukrot húz! (1-2-3)
3
A gép jön és 1 db-ot húzott.
Írja be, hogy 4. körben hány szaloncukrot húz! (1-2-3)
4
Írja be, hogy 4. körben hány szaloncukrot húz! (1-2-3)
3
A gép jön és 1 db-ot húzott.
Ön vesztett, mert Ön jön és a tálban 1 db szaloncukor van.

 

Amit az örökkön vesztes nem tud, hogy 16 db szaloncukorral + 1 chilipaprikával játszunk, ez összesen 17 db elem, amely páratlan szám. 17 felbontható 4 x 4  + 1 egységre, amelyet alább 1 számmal reprezentálok:

 

1 1 1 1

1 1 1 1

1 1 1 1

1 1 1 1

1

 

Ebből következően: mindig 4 húzási kör + 1 végkör lesz, azaz mindig lesz 1 utolsó elem (chilipaprika), ha úgy játszom: mindig annyit húzok, hogy 1 kör összeredménye 4 legyen, azaz:

 

aktualisSzam + aktualisSzamGep = 4

 

3 eset lehetséges...

...tehát...

 

1 + 3 = 4

2 + 2 = 4

3 + 1 = 4

 

A nyertes nem tesz mást, mint az aktualisSzam + aktualisSzamGep = 4 tartásával úgy manipulálja a szaloncukor mennyiségét, vele a körszámot, hogy az utolsó 5. kör mindig a vesztesre essen.

 

A kód ugyanakkor járulékos szolgáltatásként egy do-while ciklus segítségével azt is megakadályozza, hogy 1-2-3 számoktól különböző karakterek kerüljenek a rendszerbe:

 

do{
    System.out.println("Írja be, hogy " + szamlalo + ". körben hány szaloncukrot húz! (1-2-3)");
    szam = scanner.nextLine();
}while(!szam.equals("1") && !szam.equals("2") && !szam.equals("3"));
 

Aki pedig esetleg kételkedik a kód hitelességében, az lefuttathatja az alábbi kódverziót, amelyben minden egyes húzáskor ki lesz írva a pillanatnyi szaloncukor-mennyiség is:

 

www.informatika-programozas.hu - Futtatható Java-kód!

 

 

 

 

 

 

 

 

import java.util.Scanner;

public class Main {
public static void main(String[] args) {
    int szalonCukorSzam = 17;
    int szamlalo = 1;
    int aktualisSzam = 0;
    int aktualisSzamGep = 0;
    String szam = "";
    System.out.println("Ön 1, 2 vagy 3 szaloncukrot húzhat.

                                Az veszít, akié a chilipaprika (vagy az utolsó szaloncukor). Ön kezd!");
    Scanner scanner = new Scanner(System.in);
    do{
        do{
            System.out.println("Írja be, hogy " + szamlalo + ". körben hány szaloncukrot húz! (1-2-3)");
            szam = scanner.nextLine();
            }while(!szam.equals("1") && !szam.equals("2") && !szam.equals("3"));
        aktualisSzam = Integer.parseInt(szam);
    szalonCukorSzam -= aktualisSzam;
    aktualisSzamGep = 4 - aktualisSzam;
    System.out.println("A tálban " + szalonCukorSzam + " db szaloncukor van.");
    System.out.println("A gép jön és " + aktualisSzamGep + " db-ot húzott.");
    szalonCukorSzam -= aktualisSzamGep;
    System.out.println("A tálban " + szalonCukorSzam + " db szaloncukor van.");
    szamlalo++;
    }while(szalonCukorSzam > 1);
    System.out.println("Ön vesztett,

                                mert Ön jön és a tálban " + szalonCukorSzam + " db szaloncukor van.");
    }
}

 

Végeredmény:

Ön 1, 2 vagy 3 szaloncukrot húzhat. Az veszít, akié a chilipaprika (vagy az utolsó szaloncukor). Ön kezd!
Írja be, hogy 1. körben hány szaloncukrot húz! (1-2-3)
e
Írja be, hogy 1. körben hány szaloncukrot húz! (1-2-3)
4
Írja be, hogy 1. körben hány szaloncukrot húz! (1-2-3)
1
A gép jön és 3 db-ot húzott.
Írja be, hogy 2. körben hány szaloncukrot húz! (1-2-3)
2
A gép jön és 2 db-ot húzott.
Írja be, hogy 3. körben hány szaloncukrot húz! (1-2-3)
3
A gép jön és 1 db-ot húzott.
Írja be, hogy 4. körben hány szaloncukrot húz! (1-2-3)
4
Írja be, hogy 4. körben hány szaloncukrot húz! (1-2-3)
3
A gép jön és 1 db-ot húzott.
Ön vesztett, mert Ön jön és a tálban 1 db szaloncukor van.