How to resolve the algorithm Dice game probabilities step by step in the Haskell programming language

Published on 7 June 2024 03:52 AM

How to resolve the algorithm Dice game probabilities step by step in the Haskell programming language

Table of Contents

Problem Statement

Two players have a set of dice each. The first player has nine dice with four faces each, with numbers one to four. The second player has six normal dice with six faces each, each face has the usual numbers from one to six. They roll their dice and sum the totals of the faces. The player with the highest total wins (it's a draw if the totals are the same). What's the probability of the first player beating the second player? Later the two players use a different set of dice each. Now the first player has five dice with ten faces each, and the second player has six dice with seven faces each. Now what's the probability of the first player beating the second player? This task was adapted from the Project Euler Problem n.205: https://projecteuler.net/problem=205

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Dice game probabilities step by step in the Haskell programming language

The code implements a function succeeds that takes two tuples as arguments:

  • p1 = (nFaces1, nDice1): represents the first die, where nFaces1 is the number of faces and nDice1 is the number of dice.
  • p2 = (nFaces2, nDice2): represents the second die, where nFaces2 is the number of faces and nDice2 is the number of dice.

The function succeeds calculates the probability that the sum of the rolls of the first die (p1) is greater than the sum of the rolls of the second die (p2).

Here's a step-by-step breakdown of the code:

  1. The function first calculates the total number of possible outcomes as totalOutcomes = uncurry (^) p1 * uncurry (^) p2. Here, uncurry (^) p1 and uncurry (^) p2 are equivalent to raising the first and second elements of p1 and p2 to the power of their respective second elements. This gives us the total number of possible outcomes when rolling both dice.

  2. The countSums function is then used to count the number of ways to get each possible sum for both p1 and p2. For example, if p1 = (4, 3), the possible sums are 3, 4, 5, 6, 7, 8, 9, 10, 11, and 12. The function countSums returns a list of tuples where each tuple represents a sum and the number of ways to get that sum.

  3. The function f is used to map each possible sum to a tuple containing the sum and the number of ways to get that sum. For example, f [1, 2, 3, 4] might return [(3, 1), (4, 3), (5, 3), (6, 2)].

  4. The function group is used to group together all the sums that are the same. For example, group [(3, 1), (4, 3), (5, 3), (6, 2)] might return [(3, 1), (4, 3), (5, 3), (6, 2)].

  5. The function sort is used to sort the list of sums in ascending order. For example, sort [(3, 1), (4, 3), (5, 3), (6, 2)] might return [(3, 1), (4, 3), (5, 3), (6, 2)].

  6. The function sum is used to sum up the number of ways to get each sum. For example, sum [(3, 1), (4, 3), (5, 3), (6, 2)] might return 10.

  7. The function succeeds then iterates over the list of sums for p1 and p2 and calculates the probability that the sum of p1 is greater than the sum of p2. This is done by dividing the number of ways to get a sum for p1 that is greater than the sum for p2 by the totalOutcomes.

  8. Finally, the main function calls the succeeds function for two different pairs of dice, and prints the results.

Source code in the haskell programming language

import Control.Monad (replicateM)
import Data.List (group, sort)

succeeds :: (Int, Int) -> (Int, Int) -> Double
succeeds p1 p2 =
  sum
    [ realToFrac (c1 * c2) / totalOutcomes
    | (s1, c1) <- countSums p1 
    , (s2, c2) <- countSums p2 
    , s1 > s2 ]
  where
    totalOutcomes = realToFrac $ uncurry (^) p1 * uncurry (^) p2
    countSums (nFaces, nDice) = f [1 .. nFaces]
      where
        f =
          fmap (((,) . head) <*> (pred . length)) .
          group . sort . fmap sum . replicateM nDice

main :: IO ()
main = do
  print $ (4, 9) `succeeds` (6, 6)
  print $ (10, 5) `succeeds` (7, 6)


  

You may also check:How to resolve the algorithm Null object step by step in the Latitude programming language
You may also check:How to resolve the algorithm Sorting algorithms/Merge sort step by step in the Python programming language
You may also check:How to resolve the algorithm Calculating the value of e step by step in the Pascal programming language
You may also check:How to resolve the algorithm S-expressions step by step in the Phix programming language
You may also check:How to resolve the algorithm Iterated digits squaring step by step in the REXX programming language