Socken (Simulationen)
Herr Gressly besitzt fünf verschiedene Arten von Socken. Sie haben verschiedene Farben und Muster. Die Anzahlen der zusammengehörigen Socken sind 20, 6, 8, 16 bzw. 5(!). Bei einer Sockenart hat er demnach nicht mehr alle Paare vollständig. Jeden Morgen nimmt er im Dunkeln zufällig 4, 5 oder 6 Socken aus seiner Sockenschachtel und hofft, dass zwei derselben Sorte dabei sind. Ist ein zusammengehöriges Paar dabei, so werden die restlichen Socken zurückgelegt. Ist kein Paar dabei, wird dieser Tag als "Pechtag" verbucht, und Herr Gressly holt sich die Sockenschachtel ans Licht und entnimmt ihr irgendein passendes Paar. Nach 11 Tagen werden alle benutzten Socken gewaschen und die Schachtel wird wieder gefüllt.
Simulieren Sie ein Jahr (365 Tage) und geben Sie aus, an wie vielen Tagen Herr Gressly auf Anhieb ein zusammengehörendes Paar herausgefischt hat und wie oft er Pech hatte.
0 Kommentare
2 Lösung(en)
package eu.gressly.hw.simulation.socken;
/**
* Soll ein Index aus einer vorgegebenen Verteilung gewählt werden,
* so ist i. d. R. nach dem Algorithmus von Walker (S. Knuth: "The Art of Computer Programming")
* vorzugehen. Wenn die Verteilung jedoch ständig ändert, ist der folgende Algorithmus
* auch nicht schlecht.
* @author Philipp Gressly (phi@gressly.ch)
*/
/*
* History: first Implementation: May 2, 2010
* Bugs :
*/
public class ZufallsVerteilung {
/**
* Zufallsindex nach vorgegebener Verteilung.
* @param verteilung Array mit Anzahlen z. B. {7, 2, 9}
* @return Ein Index (im Bsp. 0, 1 oder 2) mit entsprechender Wahrscheinlichketi [0]:[1]:[2] == 7:2:9
*/
int indexNachVerteilung(int [] verteilung) {
int total = anzahlInVerteilung(verteilung);
int zufallsNr = (int) (1 + total * Math.random());
int index = 0;
int enPassant = 0;
while(index < verteilung.length) {
enPassant = enPassant + verteilung[index];
if(enPassant >= zufallsNr) {
return index;
}
index = index + 1;
}
return verteilung.length - 1; // last index
}
int anzahlInVerteilung(int[] verteilung) {
int total = 0;
int index = 0;
while(index < verteilung.length) {
total = total + verteilung[index];
index = index + 1; }
return total;
}
} // end of class ZufallsVerteilung
/**********************************************/
package eu.gressly.hw.simulation.socken;
/**
* @author Philipp Gressly (phi@gressly.ch)
*/
/*
* History: first Implementation: May 2, 2010
* Bugs :
*/
public class Socken {
int[] SOCKENLAGER = {20, 6, 8, 5, 16 }; // Sockenarten nummeriert von 0 .. 4.
int[] kiste = new int[SOCKENLAGER.length ];
public static void main(String[] args) {
new Socken().top(); }
public void top() {
int totalPechtage = 0;
int jahr = 0;
while(jahr < 10000) {
totalPechtage = totalPechtage + anzPechtage();
jahr = jahr + 1;
}
System.out.println("Total Pechtage nach 10000 Jahren : " + totalPechtage);
System.out.println("Pechtage im Schnitt : " + (totalPechtage / 10000.0));
}
public int anzPechtage() {
int pechtage = 0;
int jahrestage = 1;
waschen();
int elfTageZaehler = 1;
while(jahrestage <= 365) {
boolean pechtag = simuliereTag();
if(pechtag) {
pechtage = pechtage + 1;
}
elfTageZaehler = elfTageZaehler + 1;
if(elfTageZaehler > 11) {
waschen();
}
jahrestage = jahrestage + 1;
}
return pechtage;
}
/**
* global: kiste
*/
boolean simuliereTag() {
int wieVieleHeute = (int) (4 + Math.random() * 3);
int[] handvoll;
handvoll = entnimmSocken(wieVieleHeute);
boolean istGlueckstag = istEinPaarDabei(handvoll);
if(istGlueckstag) {
entnimmPaarAusHandvollUndLegeRestlicheZurueck(handvoll); }
else {
entnimmPaarAusKiste();
}
return ! istGlueckstag;
}
void entnimmPaarAusKiste() {
entnimmPaarAusBehaelter(kiste);
}
int entnimmPaarAusBehaelter(int[] behaelter) {
int[] paarArray = new int[behaelter.length];
int index = 0;
while(index < behaelter.length) {
paarArray[index] = behaelter[index] / 2; //ganzzahlige Division!
index = index + 1;
}
int sockenArt = zv.indexNachVerteilung(paarArray);
behaelter[sockenArt] = behaelter[sockenArt] - 2; // Paar
return sockenArt;
}
void entnimmPaarAusHandvollUndLegeRestlicheZurueck(int[] handvoll) {
int sockenArt = entnimmPaarAusBehaelter(handvoll);
legeZuruck(handvoll, sockenArt);
}
/**
* Lege alle Socken aus der "Hanvoll" wieder zurück
*/
void legeZuruck(int[] handvoll, int sockenArt) {
int index = 0;
while(index < handvoll.length) {
kiste[index] = kiste[index] + handvoll[index];
index = index + 1; }
}
boolean istEinPaarDabei(int[] handvoll) {
int i = 0;
while(i < handvoll.length) {
if(handvoll[i] > 1) {
return true;
}
i = i + 1;
}
return false;
}
/**
* Entnimm Socken und erzeuge eine "Handvoll".
* Die entnommenen Socken werden effektiv aus der "kiste" entfernt.
*/
int[] entnimmSocken(int wieVieleHeute) {
int handvoll[] = new int[SOCKENLAGER.length]; // handvoll = z. B. [1, 2, 0, 0, 1]
int nr = 0;
while(nr < wieVieleHeute) {
int art = entnimmZufaelligeSocke();
handvoll[art] = handvoll[art] + 1;
nr = nr + 1;
}
return handvoll;
}
/**
* Entnimm eine zufällige socke und gib die Sockenart (= index in SOCKENLAGER) zurück.
*/
int entnimmZufaelligeSocke() {
int index = waehleZufaelligeSocke();
kiste[index] = kiste[index] - 1;
if(kiste[index] < 0) {
System.out.println("ERROR: Socke muss existieren");
}
return index;
}
/**
* Hier könnte mit den Kategorien von A. J. Walker (1977) effektiver gearbeitet werden.
* Da sich die Menge in den Kategorien jedoch ständig verändrert, ist mir auch kein
* schlauer Algorithmus bekannt. (phi)
*/
ZufallsVerteilung zv = new ZufallsVerteilung();
int waehleZufaelligeSocke() {
return zv.indexNachVerteilung(kiste);
}
/**
* Alle Socken waschen und die "kiste" wieder mit dem TOTAL-inhalt füllen.
*/
void waschen() {
int pos = 0;
while(pos < SOCKENLAGER.length) {
kiste[pos] = SOCKENLAGER[pos];
pos = pos + 1;
}
}
}
// end of class Socken
let soxBox = [],
luckyDays = 0, yuckyDays = 0,
msg = '';
Array.prototype.getPairs = function() {
let arr = this.slice();
out = [];
while (arr.length > 0) {
let tmp = arr.shift();
if (arr.includes(tmp) && !out.includes(tmp)) out.push(tmp);
}
return out;
}
function refill() {
soxBox = [20, 6, 8, 16, 5];
msg += ' *'
}
function hazzy(min = 0, max = 4) { // 0,4 ist für einen griff in $soxBox
return Math.floor(Math.random() * (max - min+1) + min);
}
function grabSeeAndRefillAfter11days() {
// grab
let handful = [];
let i = hazzy(4, 6);
while (handful.length < i) {
let h = hazzy();
if (soxBox[h] > 0) {
handful.push(h);
soxBox[h]--;
}
}
// see
let pairs = handful.getPairs();
if (pairs.length > 0) { // paar(e) in der handvoll
luckyDays++; msg += '^^ '
// zufälliges paar entnehmen
i = (pairs.length == 1) ? pairs[0] : pairs[hazzy(0, pairs.length)];
handful.splice(handful.indexOf(i), 1);
handful.splice(handful.indexOf(i), 1);
// rest zurücklegen
for (i = 0; i < handful.length; i++) soxBox[handful[i]]++;
} else { // kein paar in der handvoll
yuckyDays++; msg += ':( '
// handvoll zurücklegen
for (i = 0; i < handful.length; i++) soxBox[handful[i]]++;
// zufälliges paar händisch entnehmen
let found = false;
while (!found) {
h = hazzy();
if (soxBox[h] >= 2) {
soxBox[h] -= 2;
found = true;
}
}
}
// refillAfter11days
if ((luckyDays + yuckyDays) % 11 == 0) refill();
}
// 4 probewochen
refill();
for (let x = 1; x <= 28; x++) {
msg = `#${x}: `;
grabSeeAndRefillAfter11days();
document.write(msg += `[${soxBox.join('|')}]<br>`);
}
// bilanz für 365 tage
for (x = 1; x <= 365-28; x++) grabSeeAndRefillAfter11days();
document.write(`
<p>Post 356 tagoj, s° Gresli blindtrovis <b>${luckyDays}</b> samparojn,
sed malbon?ancis <b>${yuckyDays}</b> fojojn. Tio estas sukcesa kvoto de
<b>${100-(yuckyDays/luckyDays * 100).toPrecision(2)} %</b>.</p>
`);
Lösung von: Lisa Salander (Heidi-Klum-Gymnasium Bottrop)
Verifikation/Checksumme:
Pro Jahr entstehen ca. 19 Pechtage.
Aktionen
Neue Lösung hinzufügen
Bewertung
Durchschnittliche Bewertung:
Meta
Zeit: | 2-4 |
Schwierigkeit: | k.A. |
Webcode: | rs4y-t2k2 |
Autor: | Philipp G. Freimann (BBW (Berufsbildungsschule Winterthur) https://www.bbw.ch) |