Logo

Főoldal

Blog

Elmélet

3D Studio

Adatvédelmi nyilatkozat

GY.I.K.

Házirend

Szerző: Marosi Csaba / marosi.csaba@3d-studio.hu

DiscordGitHubLinkedIn
Developedia
Developedia
/Feladatgyűjtemény
Feladatgyűjtemény
/Metódusok, függvények
Metódusok, függvények
Metódusok, függvények

Metódusok, függvények

‣
Saját minimum- és maximumkereső függvény

Írjátok meg a saját verziótokat a következő függvényekből:

  • float Math.Min( float a, float b) (Unity-ben Mathf.Min)
  • float Math.Max( float a, float b) (Unity-ben Mathf.Max)

Ha szükséges, nézzetek utána a megadott függvények működésének a C# dokumentációban! (A Google a barátotok.)

‣
Megoldás
float Min(float f1, float f2)
{
	if (f1 < f2)
		return f1;
	else
		return f2;
}

float Max(float f1, float f2)
{
	return f1 > f2 ? f1 : f2;    // Feletételes értékadás operátort használva
}
‣
Saját abszolút értek és előjel függvény

Írjátok meg a saját verziótokat a következő függvényekből:

  • float Math.Abs(float number) (Unity-ben Mathf.Abs)
  • float Math.Sign(float number) (Unity-ben Mathf.Sign)

Ha szükséges, nézzetek utána a megadott függvények működésének a C# dokumentációban! (A Google a barátotok.)

‣
Megoldás
float Abs(float f)
{
	if (number >= 0)
		return number;
	else 
		return -number;
}  

float Sign(float f)
{
	if (number >= 0)
		return 1;
	else 
		return -1;
}
‣
Saját Clamp függvények

Írjátok meg a saját verziótokat a következő függvényből:

  • float Math.Clamp(float value, float min, float max) (Unity-ben Mathf.Clamp)

Ha szükséges, nézzetek utána a megadott függvény működésének a C# vagy Unity dokumentációban! (A Google a barátotok.)

B feladat: Készítsétek el a metódus speciális verzióját Clamp01 néven, ami pontosan 0 és 1 közé szorítja a számot!

‣
Megoldás
‣
Saját kerekítő függvények

Írjátok meg a saját float verziótokat a következő egészre kerektő függvényekből:

  • float Math.Floor( float number ) (Unity-ben Mathf.Floor)
  • float Math.Ceiling( float number ) (Unity-ben Mathf.Ceil)
  • float Math.Round( float number ) (Unity-ben Mathf.Round)

Ha szükséges, nézzetek utána a megadott függvények működésének a C# dokumentációban! (A Google a barátotok.)

Javaslat: A fent megadott sorrendben készítsd el a függvényeket!

A negatív tartományban nem kötelező, hogy működjenek a függvény.

‣
Megoldás
float Floor(float f)
{
    return f - (f % 1);
}

float Ceil(float f)
{
    float reminder = f % 1;
    if (reminder == 0)
        return f;

    return f + (1 - reminder);
}

float Round(float f)
{
    float reminder = f % 1;

    if (reminder < 0.5f)
        return Floor(f);
    else
        return Ceil(f);
}
‣
Megoldás (Úgy hogy negatív tartományban is működik)
‣
Pitagoraszi számhármas teszt függvény

Írjunk függvényt, ami megállapítja 3 int paraméteréről, hogy pitagoraszi számhármasok-e bármilyen sorrendben is adjuk be a számokat!

‣
Definíció
‣
Megoldás
bool IsPythagorean(int a, int b, int c)
{
	float hypotenuse = Math.Max(Math.Max(a, b), c); // Átfogó
	float leg1 = Math.Min(Math.Min(a, b), c);       // Kisebbik befogó
	float leg2 = a + b + c - hypotenuse - leg1;     // Nagyobbik befogó

	// (Unity-ben Math helyett használhatjuk a Mathf könyvtárat)

	// Pihagorasz tétel alkalmazása:
	return leg1 * leg1 + leg2 * leg2 == hypotenuse * hypotenuse;
}
‣
Számjegyösszeg függvény

Írj függvényt, ami visszaadja egy szám számjegyeinek összegét!

A megoldáshoz nincs szükség semmi másra, mint beépített típusokon végezhető elemi műveletekre és vezérlési szerkezetekre (szekvencia, elágazás, ciklus).

‣
Megoldás
int SumOfDigits(int n)
{
	int sum = 0;             // Az összeg nulláról indul
	while (n != 0)           // Addig megyek el, amig a számom nem nulla
	{
		int digit = n % 10;  // Veszem az utoló számjegyet
		sum += digit;        // Növelem az összeget a számjegy értékével
		n /= 10;             // Levágom az utolsó számjegyet
	}
	return sum;
}
‣
Bármihez kerekítő függvény

Írj függvényt, ami kerekít egy lebegőpontos számot egy másikhoz!

‣
Példák
‣
Megoldás
‣
Hány osztója van?

Írj függvényt, ami megadja, hány osztója van egy számnak!

‣
Prímteszt függvény

Írj függvényt, ami egy bemeneti egész számról eldönti, hogy prím-e és visszatér az eredménnyel!

A megoldáshoz nincs szükség semmi másra, mint beépített típusokon végezhető elemi műveletekre és vezérlési szerkezetekre (szekvencia, elágazás, ciklus).

‣
Megoldás
bool IsPrime(int number)
{	
	// Letesztelem az összes számot, 2 és n/2 közt, hogy osztó-e.
	// n/2 felett fölösleges osztót keresni
	for (int i = 2; i <= number / 2; i++) 
	{
	    if (number % i == 0)    // Ha találok osztót,
	        return false;       // akkor nem prím
	}
	
	return true;                // Ha NEM találok osztót, akkor prím
}
‣
N × N metódus

Írj metódust, ami kiírja az első “n” olyan számot, amiben a számjegyek összege “n”!

“n”-t paraméterben kapja meg a függvény.

‣
Segítség

Ha egy probléma túl összetett, bontsd fel részfeleadatokra: Használj nyugodtan egy segéd metódust!

‣
Megoldás
‣
Első N prímszám metódus

Írj metódust, ami kiírja az első n darab prímszámot!

n egész számot paraméterben kapja meg a függvény.

‣
Megoldás
‣
Legkisebb közös többszörös függvény

Írj függvényt, ami két bemeneti egész számnak kiszámolja majd kiírja a legkisebb közös többszörösét.

Két természetes (pozitív egész) szám legkisebb közös többszöröse az a legkisebb természetes szám, amely mindkét számmal maradék nélkül osztható.

‣
Példák

Paraméterek: 15, 30 Visszatérés: 30 Paraméterek: 2, 3 Visszatérés: 6 Paraméterek: 12, 16 Visszatérés: 48 Paraméterek: 12, 4 Visszatérés: 12 Paraméterek: 17, 15 Visszatérés: 85 Paraméterek: 80, 20 Visszatérés: 80 Paraméterek: 9, 15 Visszatérés: 45 Paraméterek: 100, 10 Visszatérés: 100

‣
Megoldás
int LeastCommonMultiple(int a, int b)
{
	// Számítások elvégzése: 
	int min = Math.Min(a, b);      // (Unity-ben Mathf)
	int max = Math.Max(a, b);      // (Unity-ben Mathf)
	int testedNum = max;
	
	while (testedNum % min != 0)
	{
	    testedNum += max;
	}
	
	return testedNum;
}
‣
Legnagyobb közös osztó függvény

Írj függvényt, ami két paraméterben kapott egész számnak kiszámolja a legnagyobb közös osztóját és visszatér vele!

Két természetes (pozitív egész) szám legnagyobb közös osztója az a legnagyobb természetes szám, amellyel mindkét szám maradék nélkül osztható.

‣
Példák

Paraméterek: 15, 35 Visszatérés: 5 Paraméterek: 2, 3 Visszatérés: 1 Paraméterek: 12, 16 Visszatérés: 4 Paraméterek: 12, 4 Visszatérés: 4 Paraméterek: 17, 15 Visszatérés: 1 Paraméterek: 80, 20 Visszatérés: 20 Paraméterek: 9, 15 Visszatérés: 3 Paraméterek: 100, 10 Visszatérés: 10

‣
Megoldás
‣
Eukleidész megoldása (Az egyik legrégebbi ismert algoritmus: ~Kr.e. 300)
// Két szám legnagyobb közös ösztója nem változik,
// ha a nagyobbikat lecseréljük a két szám különbségére.

int GreatestCommonDivisor(int a, int b)
{
	while (a != b)
	{
		if (a > b)
		  a = a − b;
	  else
			b = b − a;
	}
	return a
}
‣
Érmék és bankók - függvény

Írj függvényt, ami visszaadja, egy paraméterként megadott egész számról, hogy legkevesebb hány magyar érmével vagy bankóval kifejezni!      

(Vegyük úgy, hogy még van 1 és 2 forintos.)

‣
Példa

Bemenet: 32 431

Kimenet: 8 (mivel 20000 + 10000 + 2000 + 200 + 200 + 20 + 10 + 1 = 32 431)

‣
Megoldás

Tömbök nélkül:

Elegánsabb (rövidebb és általánosíthatóbb) megoldás tömbbel:

readonly int[] notes =
	{20000,10000,5000,2000,1000,500,200,100,50,20,10,5,2,1};
// (a readonly nem kötelező)

int HowManyNotes(int num)
{
	int result = 0;
	for (int i = 0; i < notes.Length; i++)
	{
		int noteValue = notes[i];
		result += num / noteValue;
		num = num % noteValue;
	}

	// (foreach ciklus is használható for helyett)
	return result;
}
‣
Tökéletes szám tesztelő - függvény

Írj függvényt, ami egy paraméterben kapott egy egész számról eldönti, hogy “tökéletes szám”-e!

icon
Tökéletes számok

A számelméletben tökéletes számnak nevezzük azokat a természetes számokat, amelyek megegyeznek az önmaguknál kisebb osztóik összegével.

Pl.: 6 egy tökéletes szám, mert az osztói : 1, 2, 3 és ezek összege 6

28 egy tökéletes szám, mert az osztói : 1, 2, 4, 7, 14 és ezek összege 28

‣
Megoldás
‣
Bináris → Decimális - átalakító függvény

Írj függvényt, ami egy paraméterben kapott 2-es számrendszer béli (bináris) számot átalakít 10-es számrendszer béli (decimális) alakjára.

Ha a bemenet nem bináris szám (más számjegyet is tartalmaz mint 0 és 1), a kimenet legyen 0.

‣
Megoldás
‣
Decimális → Bináris - átalakító függvény

Írj függvényt, ami egy paraméterben kapott egész (decimális) számot átalakít a 2-es számrendszer (bináris) béli alakjára.

‣
Megoldási stratégia
  1. Csak pozitív számokkal számolok ezért kezdetben szétválasztom a bemenetet előjel és abszolút értekre. A későbbi számításokat az abszolút értéken végzem.
    • Abszolút érték: decimalNum
    • Előjelérték: signValue
  2. Kiszámolom a bináris szám legnagyobb helyiértékén lévő számértéket. Ezt az értéket eltárolom egy int változóba: digitValue
  3. Létrehozok egy változót a bináris számnak 0 kezdeti értékkel: binNumber
  4. Összeállítom a bináris számot egy ciklussal, aminek minden lefutásával egy helyiértéket írok hozzá a bináris számhoz. Elölről haladok hátra a legnagyobb helyiértéktől a legkisebb felé.
    1. Minden egyez ciklus lefutásban az éppen utolsó helyiértéket számolom.
    2. A ciklus addig fut, amig van még számjegy a hátra. Ezt úgy tesztelem, hogy a lefutásonként csökkentem a digitValue értéket. Mivel 2-es számrendszerbeli számról van szó, ezért minden lefutás végén felezem ezt a számot.
    3. Ha a digitValue értéke 0, akkor nincs több számjegy: kilépek a cliklusból.
    4. Az eredeti decimális számot minden cikluslefutásban csökkentem annyival, amennyit már felhasználtunk a bináris számban.
    5. Minden ciklus lefutásban tehát:
      • A bináris szám minden helyiértékét “elcsúsztatom” ballra egy 10-szeres szorzással.
      • Ha a decimalNum nagyobb vagy egyenlő, mint az bináris számjegy aktuális értéke, akkor 1-est írok a binNumber utolsó számjegyébe (+1) és csökkentem a decimalNum értékét.
      • Osztom 2-vel a digitValue értékét: Következő számjegy értéke.
‣
Megoldás
‣
Hol lehet mindennek haszna a játékfejlesztésben?

Hát őszintén szólva nem sok helyen. 🙂 Csak nagyon speciális játékban kellhet ilyesmi.

Az programozás egy jelentős része algoritmizálás (Algoritmusok kitalálása, megtervezése). A feladatok nagy részére nincs kész válasz. Neked kell azt előállítani. Ehhez az általános algoritmizáló képesség elengedhetetlen.

Ezt fejlesztjük az efféle feladatok megoldásakor.

‣
Legalább az egyikkel osztható

Írj függvényt, aminek két pozitív egész szám paramétere van és szintén egy egész számmal tér vissza! A függvény feladata, hogy megmondja, hány olyan szám létezik, ami osztható legalább az egyik paraméterrel.

‣
Megoldás
‣
Hányat tudunk venni?

Egy árussal találkozunk egy játékban, akinél az a szabály, hogy maximum 100 aranyig ad minden kliensének hitelt.

Írd meg az árus kódjában azt a függvényt, ami megadja, hogy maximum hányat tudunk venni egy tárgyból

A paraméterek:

  • Mennyi a tárgy teljes ára
  • Mennyi pénze van a vevőnek?
  • Hány százalékos kedvezmény jár a tárgyra?
  • Mennyi hitelt vett fel eddig a vásárló?
‣
Megoldás
‣
Hatványozás függvény

Írj függvényt, ami egy tetszőleges számot emel egy tetszőleges egész hatványra!

‣
Megoldás
float Clamp(float f, float min, float max)
{
	if (f <= min)   // Ha f kisebb vagy egyenlő mint a minimum
		return min;   // Visszatérek a minimummal

	if (f >= max)   // Ha f kisebb vagy egyenlő mint a maximum
		return max;   // Visszatérek a maximummal
    
	return f;       // Egyébként visszadom f-et magát.
}

float Clamp01(float f)      // Felhasználom az előbb megírt függvényt
{
	return Clamp(f, 0, 1);    // speciális bementekkel
}
float Floor(float f)
{
    float reminder = f % 1;
    if (reminder < 0)
        reminder = 1 + reminder;

    return f - reminder;
}

float Ceil(float f)
{
    float reminder = f % 1;
    if (reminder < 0)
        reminder = 1 + reminder;

    if (reminder == 0)
        return f;

    return f + (1 - reminder);
}


float Round(float f)
{
    float reminder = f % 1;
    if (reminder < 0)
        reminder = 1 + reminder;

    if (reminder < 0.5f)
        return Floor(f);
    else
        return Ceil(f);
}
Round(3, 10)        // 3 kerekítve 10-esekre = 0
Round(17, 10)       // 17 kerekítve 10-esekre = 20
Round(1274.5f, 10)  // 1274.5 kerekítve 10-esekre = 1270
Round(13.2f, 5)     // 13.2 kerekítve 5-ösökre = 15
Round(-2, 5)        // -2 kerekítve 5-ösökre = 0
Round(-2.6f, 5)     // -2.6 kerekítve 5-ösökre = -5
Round(3, 1)         // 3 kerekítve 1-esekre = 3
Round(3.6f, 1)      // 3.6 kerekítve 1-esekre  = 4
Round(3.4, 0.5f)    // 3 kerekítve 1-esekre = 3.5
Round(77.77f, 0.5f) // 77.77 kerekítve felekre = 78
float RoundTo(float n, float roundTo)
{
	if (roundTo == 0)              // Ezt az esetet nem tudjuk kezelni
		return n;                    // Nullával való osztá lenne

	roundTo = Math.Abs(roundTo);   // Ez mindig pozítív kell, hogy legyen
                                 // (Unity-ben Mathf)

	int wholeParts = (int)(n / roundTo);    // Egész rész
	float reminder = n % roundTo;           // Maradék

	if (n >= 0)                    // Ha pozítív számmal dolgozunk
	{
		if (reminder > roundTo / 2)  // Ha a maradék nagyobb, mint a kerekítendő rész fele
			wholeParts++;              // Felfelé kerekítünk
	}
	else                           // Ha negatív számmal dolgozunk
	{
		if (-reminder > roundTo / 2) // Ha a maradék nagyobb, mint a kerekítendő rész fele
			wholeParts--;              // Lefelé kerekítünk
	}

	return wholeParts * roundTo;   // Az egész rész szorozva a kerekítedndővel
}
void WriteNumbersWithSumOfDigits(int n)
{
	int numbersFound = 0;      // Hány elemet találtunk eddig
	for (int i = 1; numbersFound < n; i++) // Végignézzük az összes számot
	{                                      // addig, amíg nem találok eleget.
		if (SumOfDigits(i) == n) // Ha a számjegyek összege megegyezik a számmal,
		{
			// Kiírjuk a számot a feladat szerint.     (Csak az egyik kell)
			Console.WriteLine(i);  // Parancsori kiíratás
			Debug.Log(i);          // Unity kiíratás

			numbersFound++;        // Jegyzem, hogy eggyel több megvan
                             // (Ha ezt kihagyjuk, végtelen ciklust kapunk)
		}
	}
}

// Segédfüggvény
int SumOfDigits(int n)    // A számjegyek összege
{
	int sum = 0;            // Az összeg nulláról indul
	while (n != 0)          // Addig megyek el, amig a számom nem nulla
	{
		int digit = n % 10;   // Veszem az utoló számjegyet
		sum += digit;         // Növelem az összeget a számjegy értékével
		n /= 10;              // Levágom az utolsó számjegyet
	}
	return sum;
}
void WriteFirstPrimes(int n)
{
	int numbersFound = 0; // Hány elemet találtunk eddig
	for (int i = 1; numbersFound < n; i++)  // Végignézzük az összes számot
	{
		if (IsPrime(i))          // He igaz a feltétel
		{
			// Kiírjuk a számot a feladat szerint.     (Csak az egyik kell)
			Console.WriteLine(i);  // Parancsori kiíratás
			Debug.Log(i);          // Unity kiíratás

			numbersFound++;        // Ha ezt kihagyjuk, végtelen ciklust kapunk
		}
	}
}

// Segédfüggvény
bool IsPrime(int n)        // Prímszám-e
{
	if (n < 2)               // 2 alatt nincs prím
		return false;

	// Letesztelem az összes számot, 2 és gyök n közt, hogy osztó-e.
	float sqrt = (float) Math.Sqrt(n);    // n négyzetgyöke  (Unity-ben Mathf)
                                           
	// A négyzetgyök felett fölösleges osztót keresni
	for (int i = 2; i <= sqrt; i++)   
	{
		if (n % i == 0)     // Ha találtunk osztót
		return false;   // Akkor nem prím
	}

	return true;  // Ha nem találtunk osztót, akkor prím
}
int GreatestCommonDivisor(int a, int b)
{
	int min = Math.Min(a, b);        // (Unity-ben Mathf)

	for (int i =  min ; i > 1; i--)  // Megnézem az összes számot lefelé
	{                                      
		if (a % i == 0 && b % i == 0) // Ha osztó mindkettővel, akkor
		{
								                  // megtaláltam a legnyagyobbat:
			return i;										// Korai visszatérés
		}															
	}

	return 1; // Visszatérek 1-el ha nagyobbat nem találtam
}
int HowManyNotes(int num)
{
    int result = 0;

    result += num / 20000;   // Teszteljük 20 000-es bankóra
    num = num % 20000;

    result += num / 10000;   // Teszteljük 20 000-es bankóra
    num = num % 10000;

    // 1000-es 100-as és 10-es és 1-es nagyságrendet egy ciklusban:
    for (int m = 1000; m > 0; m /= 10)
    {
        int noteValue = 5 * m;      // 5000, 500, 50, 5
        result += num / noteValue; 
        num = num % noteValue;

        noteValue = 2 * m;          // 2000, 200, 20, 2
        result += num / noteValue;
        num = num % noteValue;

        noteValue = 1 * m;          // 1000, 100, 10, 1
        result += num / noteValue;
        num = num % noteValue;
    }

    return result;
}
bool IsPerfectNumber(int num)
{
	int sum = 0;                        // Ebbe gyűjtöm az osztók összegét
	for (int i = 1; i <= num / 2; i++)  // Végignézem a számokat 1-től num/2-ig
	{                                   // Tovább nem érdemes menni
		if (num % i == 0)									// Ha találok egy osztót,
		sum += i;													// Az értékét hozzáadom az összeghez
	}

	return sum == num;	// Ha az összeg egyenlő a számmal, akkor tökéletes
}
int BinaryToDecimal(int binaryNum)
{
    int decimalNum = 0;    // Kinullázom a végeredményt 
    int digitValue = 1;    // Ebben számolom, hogy az egyes helyiértéken mennyivel szorzunk

    while (binaryNum > 0)  // Egyenként végigmegyek a bináris szám minden számjegyén
    {
        int digit = binaryNum % 10;    // Levágjuk az utolsó számjegyet

        if (digit > 1)         // Ha bármelyik számjegy nem 0 vagy 1
        {
            decimalNum = 0;    // akkor az eredmény 0
            break;             // ás kilépünk a ciklusból
        }

        decimalNum += digit * digitValue;

        binaryNum = binaryNum / 10;   // Törlöm az utolsó számjegyet (Azt már kezeltem)
        digitValue *= 2;              // Következő helyiérték már dupla akkora szorzójú
    }

    return decimalNum;
}
int ToBinary(int decNumber)  // Bemenet: A decimális szám
{
	int signValue = decNumber >= 0 ? 1 : -1; // Előjelet elmentem
	decNumber = Math.Abs(decNumber);    // Csak a pozitív résszel számolok

	// Megkeresem 2 legynagyobb hatványát, ami még kisebb, mint a szám.
	// Ez lesz a legelső bináris számjegy értéke.
	int digitValue = 1;
				
	while (digitValue <= decNumber)
		digitValue *= 2;

	digitValue /= 2;
	
	// Összeállítom a számot:
	// Elölről haladok hátra a legnagyobb helyiértéktől a legkisebb felé

	int binNumber = 0;				// Ebbe gyűjtöm a bináris számot
 	while (digitValue > 0)		// A bináris szám minden számjegyére.
	{
		binNumber *= 10;				// Egy számjeggyel előrébb csúsztatom a számot
		if (decNumber >= digitValue )
		{
			binNumber += 1;				    // Hátsó számjegy = 1
			decNumber -= digitValue;  // CSökkentem a decimális szám értékét
		}

		digitValue /= 2;  // Következő bináris számjegy értéke
	}

	return binNumber * signValue;	// Előjelet visszaállítom
}
	int CountDivisible(int a, int b)  // Bemenet: A 2 egész szám
	{
		int min = a < b ? a : b;  // A kisebbik szám
		int max = a > b ? a : b;  // A nagyobbik szám

		int count = 0;  // A számláló

		for (int i = 1; i <= max; i++)  // Végig megyünk az 1-től a nagyobbik számig
			if (min % i == 0 || max % i == 0)  // Ha az i osztója legalább az egyiknek
				count++;  // Akkor növeljük a számlálót
				
		return count;  // Visszaadjuk az eredményt
	}
	int GetMaxAmount(int itemPrice, int buyerMoney, int discountPercent, int buyerCredit)
	{
		// Számítsuk ki a tárgy kedvezményes árát
		float discountRate = 1 - discountPercent / 100f;
		float realPrice = itemPrice * discountRate;

		// Számítsuk ki a vevő rendelkezésre álló összes pénzét (beleértve a hitelt is)
		int totalMoney = buyerMoney + (100 - buyerCredit);

		// Visszaadjuk a maximális mennyiséget
		return (int)(totalMoney / realPrice);
	}
float Pow(float baseNumber, int power)  // Két paraméteres függvény: alap és kitevő
{
	// Annyiszor vesszük az alap számot szorzótényezőnek, ahányadik hatványra emeljük

	float result = 1; // Eredmény változó: 1-gyel kezdünk és a hatványozás során ezt módosítjuk
	for (int i = 0; i < power; i++) // Annyiszor szorozzuk az alap számmal, ahányadik hatványra emeljük
	{
		result *= baseNumber; // Minden ciklusban megszorozzuk az eredményt az alap számmal
	}
	return result; // Eredmény visszaadása
}