C# :: Aufgabe #349

3 Lösungen Lösungen öffentlich

Ermittlung der Anzahl fairer Würfel

Fortgeschrittener - C# von hollst - 03.02.2021 um 13:01 Uhr
Zwei Würfel A und B nennt man fair, wenn im statistischen Mittel Würfel A gegenüber B genauso oft gewinnt wie umgekehrt. Das ist bei den normalen Spielwürfeln, deren sechs Spielflächen jeweils mit den Zahlen von 1 bis 6 belegt sind, in der Regel der Fall, wenn kein Würfel gezinkt ist (sei hier vorausgesetzt).

Wir nehmen jetzt den Fall an, dass die insgesamt zwölf Spielflächen der zwei Würfel nicht zweimal mit jeweils von 1 bis 6, sondern jeweils mit sechs unterschiedlichen Zahlen aus dem Intervall von 1 bis 12 belegt sind. D. h. hat man sich bei Würfel A für sechs verschiedenen Zahlen aus 1 ... 12 entschieden, so wird B mit den verbleibenden sechs Zahlen belegt. Damit gibt es sehr viele Fälle, bei denen keine zwei faire Würfel entstehen würden, bspw. wenn Würfel A mit 1 ... 6 und Würfel B mit 7 ... 12 belegt wären. In diesem Beispiel gewänne Würfel B immer gegen Würfel A. Würde man allerdings Würfel A mit 1, 2, 3, 10, 11, 12 und Würfel B mit 4 ... 9 belegen, so hätte man wieder ein faires Würfelpaar. Neben der gerade genannten zwei Flächenbelegungen gibt es allerdings weitere, die ebenfalls fair sind.

Die Programmieraufgabe bestehe darin, mittels Simulation alle Flächenbelegungen für zwei Würfel mit den Zahlen von 1 bis 12 zu ermitteln, bei denen die Würfel fair sind.

Lösungen:

3 Kommentare
1x
vote_ok
von JKooP (18090 Punkte) - 09.02.2021 um 19:28 Uhr
NET 5.x; C# 8.x

Hier eine ineffiziente Simulation durch Zufallswerte.
Der Wert für die Durchläufe (100000) der Schleife hätte auch kleiner gewählt werden können,
da das Ergebnis ab ca. 2000 Durchläufen konstant bleibt.
Quellcode ausblenden C#-Code
using System;
using System.Collections.Generic;
using System.Linq;

namespace CS_NET5_Aufgabe_349_Anzahl_Fairer_Wuerfel
{
    class Program
    {
        static void Main(string[] args)
        {
            var counter = 0;
            var dicUnique = new Dictionary<string, string>();
            var lstStringFirstSix = new List<string>();

            for (int i = 0; i < 100_000; i++)
            {
                var lstAll = Enumerable.Range(1, 12).OrderBy(x => Guid.NewGuid()).ToList();
                var lstFirstSix = lstAll.Take(6).OrderBy(x => x);
                var lstLastSix = lstAll.TakeLast(6).OrderBy(x => x);

                if (lstFirstSix.Sum() == lstLastSix.Sum()) // == 39
                {
                    var stringFirstSix = string.Join("-", lstFirstSix);
                    var stringLastSix = string.Join("-", lstLastSix);

                    if (!dicUnique.ContainsKey(stringFirstSix) && !dicUnique.ContainsValue(stringFirstSix))
                    {
                        dicUnique.Add(stringFirstSix, stringLastSix);
                        counter++;
                        lstStringFirstSix.Add(stringFirstSix);
                    }
                }
            }

            var lstFirstSixSorted = lstStringFirstSix.OrderBy(x => x);

            foreach (var l in lstFirstSixSorted)
                Console.WriteLine($"W1: [{l}]\tW2: [{dicUnique[l]}]");

            Console.WriteLine($"\nAnzahl fairer Würfelpaare: {counter}");
        }
    }
}

1 Kommentar
vote_ok
von Frank (410 Punkte) - 23.02.2021 um 16:59 Uhr
Quellcode ausblenden C#-Code
using System;
using System.Collections.Generic;

namespace FaireWuerfel
{
    class Program
    {
        static void Main(string[] args)
        {
            List<Combination> list = new List<Combination>();
            for (int a = 1; a < 5; a++)
            {
                for (int b = 2; b < 6; b++)
                {
                    for (int c = 3; c < 7; c++)
                    {
                        if (a == b || a == c || b == c || c < b || b < a)
                            continue;
                        list.Add(new Combination(a, b, c));
                    }
                }
            }
            foreach (Combination combination in list)
            {
                Console.WriteLine($"A = {combination.A}, B = {combination.B}, C = {combination.C}");
            }
            Console.WriteLine($"Anzahl der Kombinationen: {list.Count}");
        }

    }

    public class Combination
    {
        public Combination(int a, int b, int c)
        {
            this.A = a;
            this.B = b;
            this.C = c;
        }
        public int A { get; set; }
        public int B { get; set; }
        public int C { get; set; }
    }
}
vote_ok
von hollst (13980 Punkte) - 08.04.2021 um 17:27 Uhr
Quellcode ausblenden C#-Code
using System;
using static System.Console;
using System.Diagnostics;
using System.Text;
using System.Collections.Generic;

K_aus_N_Enumeration lte = new K_aus_N_Enumeration(6, 12);
$"{lte.Sequences.Count}".Wl();

int counter = 0;
Random rand = new();
Stopwatch sw = new();

sw.Start();
for (var i = 0; i < lte.Sequences.Count; i++)  {
    int[] Complementary = lte.Sequences[i].Complementary();
    double stat = Stats(lte.Sequences[i], Complementary, rand, (int)1e+6);
    $"{lte.Sequences[i].ToMyString()}  {lte.Sequences[i].Sum()}  {Complementary.ToMyString()}  {stat.ToString("F2")} ".Wl();
    if (Math.Abs(50.0 - stat) < 1.0)   
        $"{++counter}".Wl();
}
sw.Stop();

$"counter: {counter}   {sw.Elapsed.Dauer()}".Wl();
"ready, press any key".Rk();

static double Stats(int[] a1, int[] a2, Random r, int max_trails)  {
    int counter1 = 0;
    for(var i = 0; i < max_trails; i++)  {
        int w1 = r.Next(a1.Length);
        int w2 = r.Next(a2.Length);
        if (a1[w1] > a2[w2])
            counter1++;
    }
    return 100.0 * counter1 / max_trails;
}
static class Extension  {
    public static void Rk(this string s)  {
        WriteLine(s);
        ReadKey();
    }

    public static void Wl(this string s) => WriteLine(s);

    public static string ToMyString(this int[] a)  {
        StringBuilder sb = new();
        for (var i = 0; i < a.Length; i++)
            sb.Append($"{a[i],3}");
        return sb.ToString();
    }

    public static int Sum(this int[] a)  {
        int result = 0;
        foreach (int x in a)
            result += x;
        return result;
    }

    public static int[] Complementary(this int[] a)    {        
        List<int> temp = new();
        for(var i = 1; i <= 2 * a.Length; i++)
            if(!Array.Exists(a, element => element == i))
                temp.Add(i);
        return temp.ToArray();
    }

    public static string Dauer(this TimeSpan ts) => //20210105
        String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
        ts.Hours, ts.Minutes, ts.Seconds,
        ts.Milliseconds / 10);
}

public class K_aus_N_Enumeration  {
    int k, aus; // k = Number of lottery numbers
    int[] sequence;

    public List<int[]> Sequences = new();

    public K_aus_N_Enumeration(int K, int Aus)  {
        k = K;
        aus = Aus;
        sequence = new int[k];
        init();
        run();
    }

    void init()  {
        for (var i = 0; i < sequence.Length; i++)
            sequence[i] = i + 1;
    }

    void run()  {
        bool bo_nosteps = false;
        while (!bo_nosteps)  {
            int[] temp = new int[sequence.Length];
            sequence.CopyTo(temp, 0);
            Sequences.Add(temp);

            int runner = 0;
            for (var step = sequence.Length - 1; step >= 0; step--)
                if (sequence[step] < aus - runner)  {
                    sequence[step]++;
                    for (var j = 1; j <= runner; j++)
                        sequence[step + j] = sequence[step] + j;
                    break;
                }
                else
                    runner++;
            if (runner == k)
                bo_nosteps = true;
        }
    }
}
1800753

Du scheinst einen AdBlocker zu nutzen. Ich würde mich freuen, wenn du ihn auf dieser Seite deaktivierst und dich davon überzeugst, dass die Werbung hier nicht störend ist.