Hackerboard WikiHaboBlog

[HaBo]

 
Programmieraufgaben Hier wird regelmäßig eine neue Programmieraufgabe gestellt, die dann gelöst werden soll und in Zusammenarbeit mit den Moderatoren auch besprochen werden kann.

Glückspielvorteil

Diskussion: Glückspielvorteil im Forum Programmieraufgaben, in der Kategorie Code Kitchen; 10 gegen 3 Das Spiel wird mit 2 Spielern gespielt: Der erste Spieler setzt 10 Euro - diese sind dem ...

Antwort
Alt 13.11.08, 17:18   #1 (permalink)
CDW
Moderator
 
Benutzerbild von CDW
 
Registriert seit: 20.07.05
CDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: Opteron
Likes: 156
Standard Glückspielvorteil


10 gegen 3
Das Spiel wird mit 2 Spielern gespielt:
Der erste Spieler setzt 10 Euro - diese sind dem zweiten Spieler auf jeden Fall sicher.
Der zweite Spieler würfelt (mit 3 Würfeln) - die Augensumme wird zusammengezählt. Diesen Betrag zahlt der zweite Spieler an den ersten aus.
D.h er bekommt vom ersten Spieler 10 Euro und zahlt die gewürfelte Augensumme an diesen aus.

1.was wäre Deine intuitive Antwort (ohne Programmieren/Rechnen):
wer ist hier im Vorteil ?

Programmieraufgabe:
Dein Programm soll ausgeben, welcher Spieler im Vorteil ist (und/oder ein paar Zahlen ausgeben, so dass es aus diesen ersichtlich wird).

Es bieten sich folgende Varianten: eine Simulation, die das Spiel mehrere 1000 Male durchführt - was kommt hier raus?

oder: ein Programm, welches alle möglichen Würfelkombinationen samt zugehöriger Summe errechnet und aus diesen Daten irgendwelche "Erkenntnisse" gewinnt.

zu den beiden Varianten   

bei der Simulation könnten die Spieler mit einem Startkapital anfangen - nach 1000 Runden könnte man diese Werte vergleichen.
Kombinationen:
einfach alle möglichen Kombinationen der 3 Würfel bilden. Nun soll das Programm berechnen, wieviele Kombinationen eine Augensumme <10,>=10 usw. haben.


PS: ich möchte nochmal auf darauf verweisen:
Erklärung zu diesem Forum
Zitat:
m übrigen geht es darum den Quelltext eurer Lösung zu veröffentlichen. Gerne werden auch Binärdateien angenommen, aber Quelltext ist Pflicht, schließlich soll das ganze auch für andere User einen Sinn ergeben.
Beim Posten des Quelltextes verwendet bitte den Spoiler- mit Code-Tag:
__________________
Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf!
Selig, wer nichts zu sagen hat und trotzdem schweigt.
CDW ist offline   Mit Zitat antworten
Alt 13.11.08, 17:22   #2 (permalink)
Moderator
 
Benutzerbild von xeno
 
Registriert seit: 09.09.04
xeno Leistung: 8086xeno Leistung: 8086
xeno eine Nachricht über ICQ schicken
Likes: 65
Standard

intuitive antwort: da die zahl zwischen 3 und 12 liegt würde ich sagen, der vorteil liegt beim zweiten spieler, da durchschnittlich um die 7,5 augen liegen. code reiche ich nach. ist wahrscheinlich total falsch

edit: zwischen 3 und 18 natürlich

die lösung ist aber interessant:   

Code:
//
// * Spieler A bezahlt 10? an Spieler B
// * Spieler B würfelt mit drei Würfeln
// * Spieler B bezahlt die Anzahl der Augen an Spieler A in ?
//
// Frage: Wer ist im Vorteil?
// Getestet wird in 1.000.000 Durchläufen
//

using System;

class Gluecksspiel {
    public static void Main() {
        Random wuerfel = new Random();
        int vorteilA = 0;
        int vorteilB = 0;
        int gewinnA = 0;
        int gewinnB = 0;
        int vorteilNiemand = 0;

        for( int i=0; i<1000000; i++) {
            int wurf1 = wuerfel.Next(1, 7); 
            int wurf2 = wuerfel.Next(1, 7); 
            int wurf3 = wuerfel.Next(1, 7); 
    
            if( (wurf1 + wurf2 + wurf3) > 10) {
                vorteilA++;
                gewinnA += (wurf1 + wurf2 + wurf3)-10;
            } else if( (wurf1 + wurf2 + wurf3) < 10) {
                vorteilB++;
                gewinnB += 10-(wurf1 + wurf2 + wurf3);
            } else {
                vorteilNiemand++;
            }   
    
        }   
        gewinnA -= 1000000;
        gewinnB -= 1000000;
        Console.WriteLine("Vorteile für Spieler A:      {0}", vorteilA);
        Console.WriteLine("Gewinn von Spieler A:        {0}\n", gewinnA);
        Console.WriteLine("Vorteile für Spieler B:      {0}", vorteilB);
        Console.WriteLine("Gewinn von Spieler B:        {0}\n", gewinnB);
        Console.WriteLine("Ausgleichende Gerechtigkeit: {0}", vorteilNiemand);
    }   
}
Ausgabe:

Vorteile für Spieler A: 500009
Gewinn von Spieler A: 458121

Vorteile für Spieler B: 374508
Gewinn von Spieler B: -42793

Ausgleichende Gerechtigkeit: 125483

SpielerA bekommt also in 50% aller fälle mehr geld zurück bei einem Gewinn von etwa 46cent pro Spiel.
xeno ist offline   Mit Zitat antworten
   
HaBOT
 

Werbung ist gerade online    
Alt 13.11.08, 17:35   #3 (permalink)
 
Registriert seit: 26.06.05
SilentBoB Leistung: Facit NTK
Likes: 0
Standard

Zitat:
da die zahl zwischen 3 und 12 liegt
die Zahl liegt doch zwischen 3 und 18 (3x6) oder hab ich jz nen Denkfehler?

Oh ok hast schon editiert
SilentBoB ist offline   Mit Zitat antworten
Alt 13.11.08, 17:37   #4 (permalink)
 
Registriert seit: 16.05.08
Binäru$ Leistung: Facit NTK
Likes: 0
Standard

Zitat:
Original von xeno
intuitive antwort: da die zahl zwischen 3 und 12 liegt würde ich sagen, der vorteil liegt beim zweiten spieler, da durchschnittlich um die 7,5 augen liegen. code reiche ich nach. ist wahrscheinlich total falsch
Denke bei 3 Würfeln liegt die Zahl zwischen 3 und 18.
Intuitiv werden die Zahlen 9,10,11,12 am öftersten gewürfelt also glaube ich, dass Spieler 1 die besseren Karten besitzt.
Binäru$ ist offline   Mit Zitat antworten
Alt 13.11.08, 18:06   #5 (permalink)
 
Benutzerbild von Eydeet
 
Registriert seit: 14.04.06
Eydeet Leistung: Facit NTK
Likes: 4
Standard

@xeno: Ich denke, du hast da einen kleinen Schönheitsfehler in deinem Programm:
...   
Du zählst Vorteile, aber nicht, wie groß diese Vorteile tatsächlich sind. So könnte es theoretisch sein, dass Spieler 2 in der Hälfte der Fälle 1 Euro gewinnt, in der anderen Hälfte aber 5 Euro verliert. ;)

Meine Lösung (Python)   
Code:
import random
geldA = 0

for i in range(100000):
    summe  = random.randrange(1, 7)
    summe += random.randrange(1, 7)
    summe += random.randrange(1, 7)
    geldA = geldA - 10 + summe

print "Geldgewinn von Spieler 1:", geldA, "Euro"
print "Geldgewinn von Spieler 2:", -geldA, "Euro"
Einige Testläufe über 100 000 Spiele:
Geldgewinn von Spieler 1: 50860 Euro
Geldgewinn von Spieler 2: -50860 Euro
-------
Geldgewinn von Spieler 1: 48116 Euro
Geldgewinn von Spieler 2: -48116 Euro
-------
Geldgewinn von Spieler 1: 48626 Euro
Geldgewinn von Spieler 2: -48626 Euro

Spieler 1 gewinnt also grob gerundet pro Spiel durchschnittlich 50ct.

Das würde sich auch in etwa mit meinem mathematischen Ansatz decken:
Ein Würfel zeigt im Durchschnitt (1+2+3+4+5+6)/6 (=3,5) an. Bei drei Würfeln wäre das 3,5 * 3 = 10,5.
Eydeet ist offline   Mit Zitat antworten
Alt 13.11.08, 18:20   #6 (permalink)
Moderator
 
Benutzerbild von xeno
 
Registriert seit: 09.09.04
xeno Leistung: 8086xeno Leistung: 8086
xeno eine Nachricht über ICQ schicken
Likes: 65
Standard

@Eydeet:

stimmt, hab ich nicht dran gedacht. hab das mal eingebaut und festgestellt, daß Spieler A tatsächlich etwa 46cent pro runde gewinnt. kannst du diesen genaueren wert bestätigen?
xeno ist offline   Mit Zitat antworten
Alt 13.11.08, 18:23   #7 (permalink)
 
Registriert seit: 16.05.08
Binäru$ Leistung: Facit NTK
Likes: 0
Standard

C#   
Code:
Random augenzahl = new Random();
int rundenanzahl = 10000;
int wurfsumme;
int geld2 = 0;

for (int i = 0; i < rundenanzahl; i++)
    {
       wurfsumme = 0;
       for (int j = 0; j < 3; j++)
           {
                 wurfsumme += augenzahl.Next(1,7);
           }
       geld2 += 10 - wurfsumme;
    }
Ergebnis:
Spieler1 verdient: 5109
Spieler2 verdient: -5109
Binäru$ ist offline   Mit Zitat antworten
Alt 13.11.08, 18:52   #8 (permalink)
 
Registriert seit: 09.02.06
goflo Leistung: Facit NTK
Likes: 0
Standard

Meine cpp Lösung:

main.cpp   

Code:
#include <iostream>
#include <time.h>

using namespace std;

int main() {
	int rSum = 0;
	int sumPlayer1 = 0;
	int sumPlayer2 = 0;
	
	srand(time(NULL));
	
	for (int i = 0; i < 100000; i++) {
		rSum = 0;
		
		for (int j = 0; j < 3; j++) {
			rSum += (rand() % 6) + 1;
		}
		
		sumPlayer2 += 10 - rSum;
		sumPlayer1 += rSum;
	}
	
	cout << "Konto Spieler 1: " << sumPlayer1 << endl;
	cout << "Konto Spieler 2: " << sumPlayer2 << endl;
	
	return 0;
}
Ergebnis zum Beispiel nach 100.000 Runden:
Konto Spieler 1: 1050175
Konto Spieler 2: -50175
goflo ist offline   Mit Zitat antworten
Alt 13.11.08, 19:16   #9 (permalink)
 
Registriert seit: 16.05.08
Binäru$ Leistung: Facit NTK
Likes: 0
Standard

@goflo, ich glaube du hast noch nen kleinen Denkfehler in deinem Programm
...   

Code:
r = (rand() % 16) + 3;
Du würfelst mit nur 1nen Würfel welcher die Augenzahlen 3-18 besitzt anstatt mit 3 Würfel(Augenzahl je Würfel = 1-6)
=> bei dir ist die Chance eine 18 zu würfeln genausogroß wie jene Chance eine 11 zu würfeln. Ne 18 kannst du aber nur mit 3 6er erreichen, im Gegensatz dazu eine 11 mit 3+3+5, 4+4+3, 6+4+1, usw..
Binäru$ ist offline   Mit Zitat antworten
Alt 13.11.08, 19:32   #10 (permalink)
 
Registriert seit: 09.02.06
goflo Leistung: Facit NTK
Likes: 0
Standard

@ Binäru$:
Muss ich dir recht geben. Da habe ich es mir wohl zu einfach gemacht...
goflo ist offline   Mit Zitat antworten
Alt 13.11.08, 19:48   #11 (permalink)
 
Benutzerbild von Eydeet
 
Registriert seit: 14.04.06
Eydeet Leistung: Facit NTK
Likes: 4
Standard

Zitat:
Original von xeno
hab das mal eingebaut und festgestellt, daß Spieler A tatsächlich etwa 46cent pro runde gewinnt. kannst du diesen genaueren wert bestätigen?
Das kommt ungefähr hin. Ich habe etwa 50 Cent pro Runde ausgerechnet.
Eydeet ist offline   Mit Zitat antworten
Alt 13.11.08, 21:47   #12 (permalink)
Moderator
 
Benutzerbild von Elderan
 
Registriert seit: 30.03.04
Elderan Leistung: 8086
Likes: 14
Standard

Hallo,
hier mein PHP Programm, welches sich stochastischen Mitteln zunutze macht, um die Frage zu beantworten:
PHP   

PHP-Code:
<?php
$kombinationen 
= array();

//Anzahl an Kombinationen pro Augensumme
for($a 1$a <= 6$a++) {
    for(
$b 1$b <= 6$b++) {
        for(
$c 1$c <= 6$c++) {
            
$kombinationen[$a+$b+$c]++;
        }
    }
}

$einsatz_spieler_1 10;

//Was fuer eine Augensumme hat Spieler2 im Schnitt
$sum 0;
for(
$i=3;$i<=18$i++) {
    
$sum += $kombinationen[$i]*$i;
}
$durchschnittsgewinn $sum/(6*6*6);

echo 
"Durchschnittsaugenzahl für Spieler 2: $durchschnittsgewinn (Augensumme) <br>";
echo 
"Macht fuer Spieler 1: ".($durchschnittsgewinn $einsatz_spieler_1)." Euro pro Spiel";

?>


Oder mathematisch:
Mathematik   

Die Anzahl an Kombinationen für eine bestimmte Augensumme ist zwischen 10 und 11 symmetrisch, d.h. P(10) = P(11), P(9) = P(12) usw. (achja, hier zu sagen, dass ein Würfel die Zahlen 1 bis 6 hat und der Schnitt 3,5 ist, also 3*3,5=10,5 reicht so noch nicht aus, wenn man für Kombinationen argumentiert.)

Da Spieler1 10 Euro einsetzt, wird er häufiger etwas gewinnen als verlieren, da er nur bei 3 bis 9 verliert, bei 11 bis 18 gewinnt. Also bei 7 Augensummen verliert, bei 8 Augensummen gewinnt, und 1 mal nix passiert.

Da er bei 9 einen Euro verliert aber bei 11 einen Euro gewinnt und P(11) > P(9) gilt, stehen seine Chancen ganz gut ;)


Um das zu berechnen was Spieler1 gewinnt:
Naja Spieler2 muss ja für jeden Würfel die Augenzahl an Spieler1 zurückzahlen. Da ein Würfel die Augenzahlen 1, ..., 6 hat, und jede gleich wahrscheinlich ist, muss Spieler2 pro Würfel im Schnitt 3,50 Euro Zahlen, Insgesamt also im Schnitt 10,50 Euro.
Elderan ist offline   Mit Zitat antworten
Alt 14.11.08, 13:40   #13 (permalink)
 
Registriert seit: 28.09.04
reach44 Leistung: Facit NTK
reach44 eine Nachricht über ICQ schicken
Likes: 0
Standard

Meine Java-Lösung:
Java   

Code:
public class Vorteil
{
	public static void main (String[] args)
	{
		int p1Guthaben=0, spielAnzahl=10000, p2Guthaben=0;
		for (int x=0; x<spielAnzahl;x++)
		{
			int wuerfel=0;
			for (int y=0; y<3; y++) wuerfel += ((int)(Math.random()*6))+1;
			p2Guthaben += 10 - wuerfel;
			p1Guthaben += wuerfel - 10;
		}
	System.out.println(p1Guthaben + " " + p2Guthaben);
	}
}
reach44 ist offline   Mit Zitat antworten
Alt 15.11.08, 20:25   #14 (permalink)
CDW
Moderator
Themenstarter
 
Benutzerbild von CDW
 
Registriert seit: 20.07.05
CDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: OpteronCDW Leistung: Opteron
Likes: 156
Standard

Seltsam, dass nur Elderan die Kombinationen betrachtet hat - dabei finde ich diese um einiges Aussagekräfitger als Simulationen
Prolog   

Code:
wuerfeln(W):-member(W,[1,2,3,4,5,6]).
wuerfele(Comparator,Limit,Count):-findall(_,
	       (wuerfeln(W1),wuerfeln(W2),wuerfeln(W3),
	        call(Comparator,W1+W2+W3,Limit)),Sums),
	length(Sums,Count).
Anfragen:
Syntax: (Operator,Limit, "Kombinationen, die die Bedingung erfüllen" )

Zitat:
wuerfele(=:=,10,Kombos),length(Kombos,Anzahl).
Anzahl = 27,
Kombos = [(1,3,6),(1,4,5),...

?- wuerfele(<,10,Kombos),length(Kombos,Anzahl).
Anzahl = 81,
Kombos = [(1,1,1),(1,1,2),(1,1,3)...

?- wuerfele(>,10,Kombos),length(Kombos,Anzahl).
Anzahl = 108,
Kombos = [(1,4,6),(1,5,5),(1,5,6)...
Sind also 27 Möglichkeiten, eine 10 zu würfeln, 81 unter 10 zu bleiben und 108 > als 10

vollständigkeitshalber die Simulation:
Code:
wuerfele(Sum):-Sum is random(6)+random(6)+random(6)+3.
sim(0,0,0).
sim(Count,P1,P2):-NCount is Count-1,
	sim(NCount,P1_,P2_),wuerfele(Num),P1 is P1_-10+Num,P2 is P2_+10-Num.
Zitat:
Anfrage:
?- sim(1000000,Player1,Player2).
Player1 = 501701,
Player2 = -501701 ?
yes
__________________
Noch mal, für alle Pseudo-Geeks: 1+1=0. -> 10 wäre Überlauf!
Selig, wer nichts zu sagen hat und trotzdem schweigt.
CDW ist offline   Mit Zitat antworten
Alt 16.11.08, 20:23   #15 (permalink)
 
Registriert seit: 28.09.07
Kenniej91 Leistung: Facit NTK
Likes: 0
Standard

Zitat:
Original von Eydeet
Zitat:
Original von xeno
hab das mal eingebaut und festgestellt, daß Spieler A tatsächlich etwa 46cent pro runde gewinnt. kannst du diesen genaueren wert bestätigen?
Das kommt ungefähr hin. Ich habe etwa 50 Cent pro Runde ausgerechnet.
Wieso etwa?
3.50? pro Würfel als Erwartungswert, mal 3 ist 10.50?^^

Beziehungsweise mein Programm:
Code:
int main(void)
{
double a = 1 + 2 +3 + 4 + 5 + 6;
a /= 6; 
if((10 / 3) < a)
{
cout << "Spieler 2 ist im Vorteil" << endl;
}
else
{
cout << "Spieler 1 ist im Vorteil" << endl;
}
cin >> a;
}
Gehört also zu Fragestellung 2,
auch wenn's n bisschen geschummelt ist^^
Kenniej91 ist offline   Mit Zitat antworten
Antwort
   

Werbung ist gerade online    

[HaBo] » Software Home » Code Kitchen » Programmieraufgaben » Glückspielvorteil
Themen-Optionen
Ansicht

Forumregeln
Es ist Ihnen nicht erlaubt, neue Themen zu verfassen.
Es ist Ihnen nicht erlaubt, auf Beiträge zu antworten.
Es ist Ihnen nicht erlaubt, Anhänge hochzuladen.
Es ist Ihnen nicht erlaubt, Ihre Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks sind aus
Pingbacks sind aus
Refbacks sind aus



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61