Odds beräkning med 6 tärningar

Trädvy Permalänk
Medlem
Plats
Skövde
Registrerad
Sep 2005

Odds beräkning med 6 tärningar

Jag har lite av ett problem, jag fick för mig att räkna ut det här men klarar inte av det.

du har 6st 6-sidiga tärningar.
du slår alla 6 samtidigt
vad är chansen att du kan kombinera ett par av dessa tärningar till värdet 7?
vad är chansen att du kan kombinera två par av dessa tärningar till värdet 7?
vad är chansen att du kan kombinera tre par av dessa tärningar till värdet 7?

det är ingen läxa, utan det är till ett eget hemmagjort brädspel som jag arbetar på.

Censorship is for the weak
----------------------------------
i5 6600K @ 4.7 | MSI GeForce GTX 980 Ti 6GB Gaming | ASUS Z170 PRO GAMING | 16GB 2400mhz | 850 EVO 250GB SSD | 2+1+1TB HDD | NH-U12P SE2 | Define S | XL2411Z 144Hz | Qpad MK-50 | Deathadder 2013

Trädvy Permalänk
Hedersmedlem
Plats
Wasserburg
Registrerad
Jul 2001

Ett tips är att angripa problemet omvänt:
Vad krävs t ex för att du inte ska kunna bilda ett enda par med summan 7, om du har sex tärningar?

Om du inte orkar pilla med kombinatoriken kan du ju alltid skriva ett litet program som räknar upp alla kombinationer av 6 tärningar, de är bara 46656 till antalet.

Religion och vidskepelse är smittsamma psykiska sjukdomar, den biologiska motsvarigheten till datorvirus.
"-Pappa, pappa, idag firade vi födelsedag och hela dagis fick gå på McDonalds. - Vems födelsedag då? - En farbror som hette Lenin."

Trädvy Permalänk
Forumledare
Registrerad
Okt 2002

Tänkte först: "Är det en trickfråga?" då jag tolkade "par" som "två tärningar med samma värde", och ett jämnt antal tärningar med heltalsvärden aldrig kan ha en ojämn summa . Men du måste mena att 2/4/6 av dessa 6 tillsammans ska ha totalsumman 7.

För att alla 6 tillsammans ska ha totalsumma 7 så finns det 6 möjligheter: 5 tärningar har värde 1, och 1 har värde 2. Det finns 6⁶ = 46656 möjligheter totalt, så sannolikheten för detta är 6/6⁶ = 1/6⁵ = 1/7776 = 0.0129 %.

För att fyra tillsammans ska ha totalsumma 7 så finns det fler möjligheter. För fyra tärningar:

   1 1 1 4 — 4 möjligheter
   1 2 2 2 — 4 möjligheter
   1 1 2 3 — 4 ⋅ 3 möjligheter

dvs 4 + 4 + 12 = 20 möjligheter för att en viss 4-kombination av tärningar har summa 7. Övriga två tärningar kan väljas hur som helst, men här får man se upp: om man inte tänker till så kommer man dubbelräkna många kast, eftersom ett kast kan ha fler än en möjlighet att hitta en 4-kombination som blir 7, men ändå ska detta kast bara räknas som "ett uppfyllande utfall". Exempelvis slaget [1 1 1 2 3 4] (och dess permutationer) räknas in i både kombination 1 och kombination 3 ovan, och [1 1 2 2 2 3] (och dess permutationer) räknas in i både 2 och 3. Dessutom räknas t ex [1 1 1 1 1 4] in flera gånger i kombination 1, och man ser snabbt att det blir tråkigt att räkna (men möjligt, så klart — bara att räkna ut hur många överlappande kombinationer som finns och dra bort dem).

Utan att räkna bort dessa kombinationer kan man lätt få den "övre gränsen" 20 ⋅ 2⁶ ⋅ 15 / 6⁶ = 10800/46656 = 25/108 = 23.1 % (men fäst ingen större vikt vid den, vilket demonstreras senare. Faktorn 15 är binomialkoefficienten för 6 över 4), men faktum är att, efter att dubbelräkningar kompenserats (enligt mitt program nedan, reservation för buggar), den korrekta sannolikheten är 5962/46656 = 12.8 %.

Samma problem uppstår då 2 tärningar ska väljas, men i än högre grad. Här blir det så många överlappande kombinationer att man trivialt ser att det finns fler totalt möjligt antal kombinationer än det finns möjliga tärningskast (varje kombination lämnar 4 tärningar fria att välja, vari två andra möjliga kombinationer definitivt kan finnas), så "övre gränsen" blir en sannolikhet långt över 100 %, vilket så klart är nonsens.

I stället låter man datorn bruteforcea:

#!/usr/bin/env python3 import itertools def generate_outcomes(sides, dice): """Generate possible outcomes of a dice throw. Args: sides: Number of sides on dice dice: Number of dice """ return itertools.product(range(1, sides+1), repeat=dice) def generate_combinations(outcome, dice_to_combine): """Generate possible combination sums of subsets of dice in a throw. Args: outcome: List of dice face numbers in outcome. dice_to_combine: Number of dice to combine for the sum. """ return itertools.combinations(outcome, dice_to_combine) def good_outcome(outcome, dice_to_combine, want_sum): """Return whether a dice throw outcome contains the wanted subset sum. Args: outcome: List of dice face numbers in outcome. dice_to_combine: Number of dice to combine for the sum. want_sum: The subset sum that is wanted. """ return bool( sum( want_sum == sum(combination) for combination in generate_combinations(outcome, dice_to_combine) ) ) def combination_counter(dice_to_combine, dice, sides, want_sum): """Return amount of outcomes that contain a subset with a certain number sum in a dice throw. Args: dice_to_combine: Number of dice to combine for the sum. dice: Number of dice sides: Number of sides on dice want_sum: The subset sum that is wanted. """ return sum( good_outcome(outcome, dice_to_combine, want_sum) for outcome in generate_outcomes(sides, dice) ) def pretty_print(dice_to_combine, dice, sides, want_sum): """Print combinatoric information of possible dice throw outcomes for a certain number of dice; specifically the amount and proportion of outcomes that contain a subset with a certain number sum in a dice throw. Args: dice_to_combine: Number of dice to combine for the sum. dice: Number of dice sides: Number of sides on dice want_sum: The subset sum that is wanted. """ good_outcomes = combination_counter(dice_to_combine, dice, sides, want_sum) total_outcomes = sides**dice print( '{:>2} tärningar, ' 'kombinera {:>2} till summa {:>2}: ' '{:>5}/{:>5} = {:>8.4%}'.format( dice, dice_to_combine, want_sum, good_outcomes, total_outcomes, good_outcomes/total_outcomes ) ) def main(): """Print combinatoric information of possible dice throw outcomes for some certain number of dice; specifically the amount and proportion of outcomes that contain a subset with a certain number sum in a dice throw. """ dice = 6 sides = 6 want_sum = 7 for dice_to_combine in 2, 4, 6: pretty_print(dice_to_combine, dice, sides, want_sum) if __name__ == '__main__': main()

Dold text

$ ./tarning.py 6 tärningar, kombinera 2 till summa 7: 41586/46656 = 89.1332% 6 tärningar, kombinera 4 till summa 7: 5962/46656 = 12.7786% 6 tärningar, kombinera 6 till summa 7: 6/46656 = 0.0129%

Möjligen finns det ett klurigt sätt att automatiskt undvika dubbelräkning i mitt manuella kombinatorikförsök ovan, men det skulle ta längre tid för mig att lista ut detta än att skriva ett generellt program som räknar ut specifika exempel på bråkdelen av en sekund.

Sentida redigering: Jag hittade detta inlägg och skrev om koden i mer förståelig form som lördagsnöje. Den gamla varianten jag skrev såg nästan ut att vara kodgolf, och även om den nya med kommentarer är många gånger längre så är den åtminstone läsbar. Jag behöll samma utskriftsformat.

Bara för att det går att göra ovanstående på typ fem rader så betyder inte det att man bör .

Gällande att räkna kombinationer matematiskt så skrev jag efter att jag svarade i denna tråd ett svar på en uppgift som åtminstone är inom samma område. Länkar den som referens för att visa hur mycket arbete som kan krävas att lösa liknande uppgifter analytiskt (uppgiften i denna tråd är nog än mer komplex än i mitt svar i andra tråden).

Uppdatering av program; se notis i texten.

Nu med kortare användarnamn, men fortfarande bedövande långa inlägg.