ugrás a tartalomhoz

JavaScript, osztással kapcsolatos feladat

marcee93 · 2011. Okt. 13. (Cs), 11.47
Gimnáziumban tanulok programozni, de a tanárom nem magyaráz érthetően, és nem tudom megoldani a feladatot, ami igy hangzik: 2 véletlenszerű számot generálunk 10 és 80 között. a, nézzük meg melyiknek van több osztója b,melyik számnak nagyobb az osztói összege.

Valaki tudna segiteni?
 
1

var darab = 2 var szam =

kuka · 2011. Okt. 13. (Cs), 12.19

var darab = 2
var szam = []
var oszto = []
var maxoszto = 0

for (var i = 0; i < darab; i++ ) {
  szam[i] = Math.round(Math.random() * 70 + 10)

  oszto[i] = 0
  for (var j = 2; j < szam[i] / 2; j++ )
    if (! (szam[i] % j))
      oszto[i]++

  maxoszto = Math.max(maxoszto, oszto[i])

  document.writeln(i + '. szam : ' + szam[i] + ', ' + oszto[i] + ' osztoja van.')
}

document.writeln('A legtobb, azaz ' + maxoszto + ' osztoja a kovetkezo szamoknak van :')

for (var i = 0; i < darab; i++ )
  if (oszto[i] == maxoszto)
    document.writeln(' - ' + i + '. szam : ' + szam[i])
Sajnos gőzöm sincs mi az az „osztói összeg”.
2

osztóinak az összege

Poetro · 2011. Okt. 13. (Cs), 12.35
osztóinak az összege
3

Upsz. Valami bonyolultabb

kuka · 2011. Okt. 13. (Cs), 12.47
Upsz. Valami bonyolultabb értelmet sejtettem mögötte. Úgy viszont sima ügy:

var darab = 2
var szam = []
var oszto = []
var osztosszeg = []
var maxoszto = maxosztosszeg = 0

for (var i = 0; i < darab; i++ ) {
  szam[i] = Math.round(Math.random() * 70 + 10)

  oszto[i] = osztosszeg[i] = 0
  for (var j = 2; j < szam[i] / 2; j++ )
    if (! (szam[i] % j)) {
      oszto[i]++
      osztosszeg[i] += j
    }

  maxoszto = Math.max(maxoszto, oszto[i])
  maxosztosszeg = Math.max(maxosztosszeg, osztosszeg[i])

  document.writeln(i + '. szam : ' + szam[i] + ', ' + oszto[i] + ' osztoja van, osztoi osszege pedig ' + osztosszeg[i])
}

document.writeln('A legtobb, azaz ' + maxoszto + ' osztoja a kovetkezo szamoknak van :')

for (var i = 0; i < darab; i++ )
  if (oszto[i] == maxoszto)
    document.writeln(' - ' + i + '. szam : ' + szam[i])

document.writeln('A legtobb, azaz ' + maxosztosszeg + ' osztoi osszege a kovetkezo szamoknak van :')

for (var i = 0; i < darab; i++ )
  if (osztosszeg[i] == maxosztosszeg)
    document.writeln(' - ' + i + '. szam : ' + szam[i])
4

off

zzrek · 2011. Okt. 13. (Cs), 13.11
Én hetedikes koromban kaptam egy C-16-ost, nem tanított senki programozni a szakközépben, de szégyelltem volna ilyesmiben segítséget kérni, az jelentett élvezetet, hogy magam rájöttem hogy hogyan is oldjam meg a problémákat. Ez a jó a programozásban, ez ad sikerélményt. Ne add alább sose, amit a tanár felad, te magad próbáld meg kiagyalni, különben nokedli vagy. Persze az is lehetséges, hogy téged egyáltalán nem érdekel a programozás, a benne rejlő kihívás... Akkor viszont az sem gond, ha épp egy kettessel átmész, egyszerűen mondd meg a tanárnak, hogy nem tudtad megcsinálni a házit, mondd el neki hogy hol akadtál el.
Akár így, akár úgy, gerinctelenség másokkal megcsináltatni aztán beadni, hogy milyen fej voltál.
6

az jelentett élvezetet, hogy

kuka · 2011. Okt. 13. (Cs), 13.29
az jelentett élvezetet, hogy magam rájöttem hogy hogyan is oldjam meg a problémákat.
Egyetértek, ez így valóban megfizethetetlen érzés. Persze csak akkor, ha hagynak a magad ritmusában fejlődni. Ha mondjuk holnapra kell a megoldás, az sokat ront az érzésen.
Akár így, akár úgy, gerinctelenség másokkal megcsináltatni aztán beadni, hogy milyen fej voltál.
Tartsuk szem előtt, hogy az eredeti kérés „Valaki tudna segiteni?” volt, tehát a kérdező nem megoldást kért. Sajnos a magyarázataim általában förtelmesre sikerülnek, ezért inkább kész kóddal szoktam válaszolni. Persze azért jól esne ha viszontlátnánk itt pár kérdést, azt bizonyítandó, hogy a kérdező Ctrl-C + Ctrl-V-nél többet foglalkozott vele.
9

Akár így, akár úgy,

Hidvégi Gábor · 2011. Okt. 13. (Cs), 13.51
Akár így, akár úgy, gerinctelenség másokkal megcsináltatni aztán beadni, hogy milyen fej voltál.
Úgyis ő bánja meg, mert ha egyszer "éles" helyzetben lesz szükség arra a tudásra, amit nem szerzett meg, akkor le fog szerepelni.

Továbbá arról se felejtkezzünk el, hogy iskolában, egyetemen olyan feladatokat szoktak adni, ami a már megszerzett ismeretanyagra épül. Meg arra hivatkozni, hogy a tanár nem érthetően magyaráz, eléggé gyenge kifogás, mert bizony a diák felelőssége, hogy ha nincs meg valami, akkor visszakérdezzen.

Már párszor leírtam, hogy az ilyen kész kódokkal többet lehet ártani, mint segíteni, mert az illető nem fog megtanulni gondolkodni, hanem mindig vissza fog járni ide, és persze lesznek is, akik megoldják helyette a feladatait, és ennyi erővel hívhatnánk a Weblabort Amatőrfórumnak is. Szerintem célszerűbb lenne vagy elhajtani őket, vagy pedig ötletet adni, hogy merre induljanak el.
5

Másik megoldás

Poetro · 2011. Okt. 13. (Cs), 13.22
var darab = 2,
    min = 10,
    max = 80,
    osztok, osztokOsszege, szam, i, j,
    maxOsztokOsszege = {szam : 0, ertek: 0},
    maxOsztokSzama = {szam : 0, ertek: 0};
  
// Generálunk megfelelő mennyiségű számot, és kiszámítjuk adatait.
for (i = 0; i < darab; i++ ) {
  // Generálunk egy véletlen számot min és max között.
  szam = Math.round(Math.random() * (max - min)) + min;
  osztok = 2; // Egy szám osztója 1 és önmaga
  osztokOsszege = szam + 1;
  // A szám felétől megyünk kettőig lefelé.
  for (j = szam >> 1; j >= 2; j -= 1) {
    if (!(szam % j)) {
      osztok++;
      osztokOsszege += j;
    }
  }

  // Megnézzük, ennek a számnak van-e több osztója
  if (osztok > maxOsztokSzama.ertek) {
    maxOsztokSzama.ertek = osztok;
    maxOsztokSzama.szam = szam;
  }
  // Megnézzük, ennek a számnak nagyobb-e az osztóinak összege
  if (osztokOsszege > maxOsztokOsszege.ertek) {
    maxOsztokOsszege.ertek = osztokOsszege;
    maxOsztokOsszege.szam = szam;
  }
  
  // Kiírjuk a szám adatait.
  console.log((i + 1) + '. szam : ' + szam + ', '
    + osztok + ' osztoja van, '
    + 'ezek összege ' + osztokOsszege);  
}

// Kiírjuk az összegzést.
console.log('A legtöbb osztóval rendelkező szám a ' + maxOsztokSzama.szam
  + ', melynek ' + maxOsztokSzama.ertek + ' osztója van.');
console.log('A szám melynek osztóinak összege a legnagyobb a ' + maxOsztokOsszege.szam
  + ', osztóinak összege ' + maxOsztokOsszege.ertek + '.');
Kimenet:
1. szam : 33, 4 osztoja van, ezek összege 48
2. szam : 35, 4 osztoja van, ezek összege 48
A legtöbb osztóval rendelkező szám a 33, melynek 4 osztója van.
A szám melynek osztóinak összege a legnagyobb a 33, osztóinak összege 48.
7

Én azért nem ezt a

kuka · 2011. Okt. 13. (Cs), 13.38
Én azért nem ezt a megközelítést használtam, mert mindkét számnak 4 osztója van, politikailag úgy korrekt, hogy mindkettőt felsoroljuk.
8

Hibás

Poetro · 2011. Okt. 13. (Cs), 13.46
Viszont a te kódod hibás, mivel nem jól számolja ki az osztók számát, és az osztóinak összegét. Például a te kódod egyet adna vissza osztok számára 6 esetén, és az összegük is hibás lenne ezért.
10

Upsz. A for feltétel. Valóban

kuka · 2011. Okt. 13. (Cs), 13.53
Upsz. A for feltétel. Valóban elnéztem. Köszönöm az észrevételt.
11

Ez egy szimpla szövegértéses

inf · 2011. Okt. 13. (Cs), 16.16
Ez egy szimpla szövegértéses dolog. Próbáld meg előbb papíron megcsinálni programozás nélkül. Ha az megy, akkor gondolj bele, hogy mindezt hogyan valósítanád meg programozva. Ennyi. A másodikban tudunk segíteni, az elsőben nem, mert nem vagyunk irodalom vagy matek tanárok.

Na most az egyszer:

2 véletlenszerű számot generálunk 10 és 80 között
a, nézzük meg melyiknek van több osztója
b, melyik számnak nagyobb az osztói összege

Legyen az első szám 13, a második 49. (2 véletlen szám generálása)

Ott van a 13-as, annak 1 és 13 az osztója. (osztók listájának lekérése)
Ezt úgy lehet megnézni, hogy egyesével megnézzük az összes számra 1 és 13 között, hogy ha leosztjuk vele a 13-at, akkor egész számot kapunk e.
Na most nem muszáj végigmenni, elég 13/2=6,5-ig menni, utána már úgysem lesz több osztó, mert mindegyik 1 és 2 közötti törtet fog adni.

Nézzük a 49-eset: 1, 7, 49 ugyanilyen alapon. (osztók listájának lekérése)
Persze biztosan vannak okosabb módszerek is ennek kiderítésére, de nem vagyok progmatos.

Osztók száma: (osztók listájából az osztók száma 2x)
13: 2
49: 3
tehát 49-nél van több. (összehasonlítás)

Osztók összege: (osztók listájából az osztók összege 2x)
1+13=14
1+7+49=57
a másodiknak nagyobb. (összehasonlítás)


Na most hogyan lehet ezt a feladatot modellezni?

Nézzük meg, hogy mi lesz az eredményben?
- a random számok
- melyiknél nagyobb az osztók száma
- melyiknél nagyobb az osztók összege

Mit csináltunk, amikor ezekre rájöttünk, nézzük végig.
- véletlen szám generálása
- osztók listájának lekérése
- osztók listájából az osztók száma
- összehasonlítás
- osztók listájából az osztók összege
- összehasonlítás

Na most ebből nagyjából látszik a struktúra. (Ha nem látszana, akkor elindulhatunk az eredményből is, aztán tdd-vel úgy is eljutunk a programhoz, de azt itt elmagyarázni túl hosszadalmas lenne.)

Mit látunk ránézésre abból, hogy mit csináltunk kézzel?
- Kell egy generator osztály, ami véletlen számokat ad.
- Kell egy osztó lista osztály, ami a megadott szám alapján számolódik, amiből le lehet kérni az osztók számát és azok összegét.
- Kell egy egész szám összehasonlító osztály.
- Kell egy osztály, ami leírja a feladatot.
- Kell egy osztály, ami tárolja az eredményt.
- Kell egy osztály, ami megjeleníti az eredményt.

Na most azért írjunk interface-t mindegyikhez.

interface RandomPositiveIntegerGeneratorInterface
{
	PositiveInteger generateRandomPositiveInteger(PositiveInteger lowerLimit, PositiveInteger upperLimit);
}

interface DivisorListInterface
{
	void countDivisors(PositiveInteger value);
	Array<PositiveInteger> divisors;
	PositiveInteger getCount();
	PositiveInteger getSummary();
}

interface PositiveIntegerSorterInterface
{
	Integer getOrder(PositiveInteger leftValue, PositiveInteger rightValue);
}

interface ExerciseInterface
{
	void doExercise();
}

interface ExerciseResultInterface
{
	PositiveInteger firstNumber;
	PositiveInteger secondNumber;
	Integer divisorCountOrder;
	Integer divisorSummaryOrder;
}

interface ExerciseViewInterface
{
	void showResult(ExerciseResultInterface exerciseResult);
}
Na most ebből a következő tesztek jönnek (nem írom meg őket js-ben, nincs kedvem)

test RandomPositiveIntegerGeneratorInterface
{
	PositiveInteger generateRandomPositiveInteger(PositiveInteger lowerLimit, PositiveInteger upperLimit);
		//az alsó és felső határnál ha rosszat adunk, akkor kivételt dob e
		//pozitív szám e az eredmény
		//az eredmény az alsó és felső határ között van e
}

test DivisorListTest
{
	void countDivisors(PositiveInteger value);
		//ha rosszat adunk meg értéknek, akkor kivételt dob e
		//kiszámolja e az osztókat
	Array<PositiveInteger> divisors;
	PositiveInteger getCount();
		//a helyes értéket adja e
	PositiveInteger getSummary();
		//a helyes értéket adja e
}

test PositiveIntegerSorterTest
{
	Integer getOrder(PositiveInteger leftValue, PositiveInteger rightValue);
		//a helyes értéket adja e: ha az első nagyobb, akkor -1, ha egyenlőek, akkor 0, ha a második nagyobb, akkor +1
}


test ExerciseTest
{
	void doExercise();
	//mockolni kell, hogy helyesen használja e a többi osztályt, érdemes tehát úgy átalakítani, hogy ez megoldható legyen, szerintem lényegtelen tesztelni
}

test ExerciseResultTest
{
	//csak setter és getter, nem kell tesztelni
	PositiveInteger firstNumber;
	PositiveInteger secondNumber;
	Integer divisorCountOrder;
	Integer divisorSummaryOrder;
}

test ExerciseViewTest
{
	//nincsenek meg az eszközök view tesztelésére, max nézni lehet, hogy jót ad e, vagy stringeket összehasonlítani, lényegtelen tesztelni
	void showResult(ExerciseResultInterface exerciseResult);
}
Megvalósítás:

function isInteger(value)
{
	return !isNaN(value) && !(value%1);
}

function isPositiveInteger(value)
{
	return isInteger(value) && value>0;
}


RandomPositiveIntegerGenerator=function (){};
RandomPositiveIntegerGenerator.prototype=
{
	generateRandomPositiveInteger: function (lowerLimit, upperLimit)
	{
		if (!isPositiveInteger(lowerLimit) || !isPositiveInteger(upperLimit) || lowerLimit>=upperLimit)
		{
			throw new Error("Problems with lower and upper limit.");
		}
		var randomFloatBeetweenZeroAndOne=Math.random();
		var range=upperLimit-lowerLimit+1;
		return lowerLimit+Math.floor(range*randomFloatBeetweenZeroAndOne);
	}
};

DivisorList=function (value)
{
	this.countDivisors(value);
};
DivisorList.prototype=
{
	countDivisors: function (value)
	{
		if (!isPositiveInteger(value))
		{
			throw new TypeError("not positive integer given");
		}
		this.divisors=[];
		for (var possibleDivisor=1; possibleDivisor<=value; ++possibleDivisor)
		{
			if (isInteger(value/possibleDivisor))
			{
				this.divisors.push(possibleDivisor);
			}
		}
	},
	getCount: function ()
	{
		return this.divisors.length;
	},
	getSummary: function ()
	{
		var summary=0;
		for (var index=0, count=this.getCount(); index<count; ++index)
		{
			var divisor=this.divisors[index];
			summary+=divisor;
		}
		return summary;
	}
};

PositiveIntegerSorter=function (){};
PositiveIntegerSorter.prototype=
{
	getOrder: function (leftValue, rightValue)
	{
		if (!isPositiveInteger(leftValue) || !isPositiveInteger(rightValue))
		{
			throw new TypeError("postitive integer required for left and right values");
		}
		var difference=rightValue-leftValue;
		return (
			difference>1
			?1
			:(
				difference<1
				?-1
				:0
			)
		);
	}
};


Exercise=function (){};
Exercise.prototype=
{
	doExercise: function ()
	{
		var lowerLimit=10;
		var upperLimit=80;
			
		var generator=new RandomPositiveIntegerGenerator();
		var leftValue=generator.generateRandomPositiveInteger(lowerLimit,upperLimit);
		var rightValue=generator.generateRandomPositiveInteger(lowerLimit,upperLimit);
		
		var leftValueDivisors=new DivisorList(leftValue);
		var rightValueDivisors=new DivisorList(rightValue);
		
		var sorter=new PositiveIntegerSorter();
		var divisorCountOrder=sorter.getOrder(leftValueDivisors.getCount(), rightValueDivisors.getCount());
		var divisorSummaryOrder=sorter.getOrder(leftValueDivisors.getSummary(), rightValueDivisors.getSummary());
		
		var result=new ExerciseResult();
			result.leftValue=leftValue;
			result.rightValue=rightValue;
			result.divisorCountOrder=divisorCountOrder;
			result.divisorSummaryOrder=divisorSummaryOrder;
			
		var view=new ExerciseView();
		view.showResult(result);
	}
}

ExerciseResult=function (){};

ExerciseView=function (){};
ExerciseView.prototype=
{
	showResult: function (exerciseResult)
	{
		var newLine="\n";
		var output="results: "+newLine;
			output+="left value: "+exerciseResult.leftValue+newLine;
			output+="right value: "+exerciseResult.rightValue+newLine;
			output+="which has greater divisor count? "+(exerciseResult.divisorCountOrder==-1?exerciseResult.leftValue:exerciseResult.rightValue)+newLine;
			output+="which has greater divisor summary? "+(exerciseResult.divisorSummaryOrder==-1?exerciseResult.leftValue:exerciseResult.rightValue);
		alert(output);
	}
}

var exercise=new Exercise();
	exercise.doExercise();
Amit ebből látni kell, hogy a tényleges modellje a feladatnak az ez a rész:

		var lowerLimit=10;
		var upperLimit=80;
			
		var generator=new RandomPositiveIntegerGenerator();
		var leftValue=generator.generateRandomPositiveInteger(lowerLimit,upperLimit);
		var rightValue=generator.generateRandomPositiveInteger(lowerLimit,upperLimit);
		
		var leftValueDivisors=new DivisorList(leftValue);
		var rightValueDivisors=new DivisorList(rightValue);
		
		var sorter=new PositiveIntegerSorter();
		var divisorCountOrder=sorter.getOrder(leftValueDivisors.getCount(), rightValueDivisors.getCount());
		var divisorSummaryOrder=sorter.getOrder(leftValueDivisors.getSummary(), rightValueDivisors.getSummary());
		
		var result=new ExerciseResult();
			result.leftValue=leftValue;
			result.rightValue=rightValue;
			result.divisorCountOrder=divisorCountOrder;
			result.divisorSummaryOrder=divisorSummaryOrder;
Ha ez összeállt fejben, akkor onnantól már pillanatok alatt meg lehet valósítani. Teszteket azért érdemes előbb megírni, mint az egyes metódusokat, mert úgy tudod menet közben tesztelni, hogy jó e már, vagy még tákolni kell rajta, na meg persze azért, mert a végén úgysem lesz kedved megírni, csak megnézel 1-2 eredményt, aztán ráfogod teszteletlenül, hogy működik.

Elsőre ez a sok gépelés értelmetlennek tűnhet, de ha megnézed a lényegi részt, amit kiemeltem, akkor azt elolvasva tudod, hogy mit csinál a kód, nem kell kibogarászni az algoritmusból... És ugye mi szerzők vagyunk, akiknek olvasói vannak, szóval a programodat az utánad jövő fejlesztőknek: az olvasóknak írod, és nem magadnak. Ha ők nem értik ránézésre, hogy mit csinál a program, akkor sokat fogsz csuklani te és drága jó anyád...


szerk:
A Sorter nem a legjobb megnevezés ide, a Comparer viszont még rosszabb lenne, mert az általában true-t ad, ha egyenlőek az értékek, és false-t ha nem azok. A Sorter-nél jobb elnevezés nem jutott eszembe eddig.
12

Először is köszi a

marcee93 · 2011. Okt. 17. (H), 08.46
Először is köszi a megoldásokat. Azért kértem segítséget mert javascriptben a tanár eddig 1 példát mondott, egy új ablakot megnyit és egy exit gombbal lehet kilépni belőle. Ezek után egyből egy ilyen feladattal szúrta ki a szemünket. Valamilyen szinten jogos, amit páran írtak. Arra reagálva, hogy mondjam azt h nincs kész a házim , mert elakadtam csak annyit tudok mondani, hogy nem ismered a tanárt. Nála nincs kifogás. Mégegyszer köszönöm a segítséget mindenkitől.