How to resolve the algorithm Seven-sided dice from five-sided dice step by step in the Kotlin programming language

Published on 22 June 2024 08:30 PM

How to resolve the algorithm Seven-sided dice from five-sided dice step by step in the Kotlin programming language

Table of Contents

Problem Statement

(Given an equal-probability generator of one of the integers 1 to 5 as dice5),   create dice7 that generates a pseudo-random integer from 1 to 7 in equal probability using only dice5 as a source of random numbers,   and check the distribution for at least one million calls using the function created in   Simple Random Distribution Checker.

Implementation suggestion: dice7 might call dice5 twice, re-call if four of the 25 combinations are given, otherwise split the other 21 combinations into 7 groups of three, and return the group index from the rolls. (Task adapted from an answer here)

Let's start with the solution:

Step by Step solution about How to resolve the algorithm Seven-sided dice from five-sided dice step by step in the Kotlin programming language

This Kotlin program simulates rolling a 7-sided die and checks the distribution of the results. Here's a detailed explanation:

  1. Importing Java Libraries:

    import java.util.Random

    Imports the Java Random class for generating random numbers.

  2. Random Number Generation:

    val r = Random()

    Creates an instance of the Random class for generating random numbers.

  3. dice5 Function:

    fun dice5() = 1 + r.nextInt(5)

    Simulates rolling a 5-sided die by generating a random number between 0 and 4 and adding 1 to it, resulting in values from 1 to 5.

  4. dice7 Function:

    fun dice7(): Int {
       while (true) {
           val t = (dice5() - 1) * 5 + dice5() - 1
           if (t >= 21) continue
           return 1 + t / 3
       }
    }

    This function simulates rolling a 7-sided die. It does this by rolling two 5-sided dice and creating a number t between 0 and 20. If t is greater than or equal to 21, it continues rolling the dice. Otherwise, it returns 1 plus the integer division of t by 3, resulting in values from 1 to 7.

  5. checkDist Function:

    fun checkDist(gen: () -> Int, nRepeats: Int, tolerance: Double = 0.5) {
       // ...
    }

    This function is used to check the distribution of the results generated by a given function gen (which takes no arguments and returns an integer). It takes three parameters:

    • gen: A function that generates random numbers.
    • nRepeats: The number of times to roll the dice.
    • tolerance: The acceptable percentage error for each number (default is 0.5%).
  6. Distribution Checking: The checkDist function generates nRepeats random numbers using gen, counts the occurrences of each number, and compares the observed distribution to the expected distribution. It prints the results in a table, showing the integer value, number of occurrences, error, and whether the error is acceptable according to the specified tolerance.

  7. Main Function:

    fun main(args: Array<String>) {
       checkDist(::dice7, 1_400_000)
    }

    In the main function, the checkDist function is called with the dice7 function and 1,400,000 repeats. This simulates rolling a 7-sided die 1,400,000 times and checks the distribution of the results against an expected uniform distribution, with a tolerance of 0.5%. The program prints the results, indicating whether the overall distribution is acceptable within the specified tolerance.

Source code in the kotlin programming language

// version 1.1.3

import java.util.Random

val r = Random()

fun dice5() = 1 + r.nextInt(5)

fun dice7(): Int {
    while (true) {
       val t = (dice5() - 1) * 5 + dice5() - 1
       if (t >= 21) continue
       return 1 + t / 3
    }
}

fun checkDist(gen: () -> Int, nRepeats: Int, tolerance: Double = 0.5) {
    val occurs = mutableMapOf<Int, Int>()
    for (i in 1..nRepeats) {
        val d = gen()
        if (occurs.containsKey(d))
            occurs[d] = occurs[d]!! + 1
        else
            occurs.put(d, 1)
    }
    val expected = (nRepeats.toDouble()/ occurs.size).toInt()
    val maxError = (expected * tolerance / 100.0).toInt()
    println("Repetitions = $nRepeats, Expected = $expected")
    println("Tolerance = $tolerance%, Max Error = $maxError\n")
    println("Integer   Occurrences   Error  Acceptable")
    val f = "  %d        %5d      %5d     %s" 
    var allAcceptable = true
    for ((k,v) in occurs.toSortedMap()) {
        val error = Math.abs(v - expected)
        val acceptable = if (error <= maxError) "Yes" else "No"
        if (acceptable == "No") allAcceptable = false
        println(f.format(k, v, error, acceptable))
    }  
    println("\nAcceptable overall: ${if (allAcceptable) "Yes" else "No"}")
}

fun main(args: Array<String>) {
    checkDist(::dice7, 1_400_000)
}


  

You may also check:How to resolve the algorithm Sieve of Eratosthenes step by step in the Prolog programming language
You may also check:How to resolve the algorithm Matrix multiplication step by step in the Stata programming language
You may also check:How to resolve the algorithm Video display modes step by step in the REXX programming language
You may also check:How to resolve the algorithm Percolation/Mean run density step by step in the Raku programming language
You may also check:How to resolve the algorithm Accumulator factory step by step in the Raku programming language