Skip to content

Instantly share code, notes, and snippets.

@mayonesa
Last active December 12, 2018 14:40
Show Gist options
  • Save mayonesa/80511b0456917276288d to your computer and use it in GitHub Desktop.
Save mayonesa/80511b0456917276288d to your computer and use it in GitHub Desktop.
Shows 2-Die Histogram
import util.Random.nextInt
/**
Dice
Write a program that simulates throwing two six-sided dice 200 times, and creates a histogram of the results, like this:
2: XXXX
3: XXXXXXXXXX
4: XXXXXXXXXXXXXXXXXXXXXX
5: XXXXXXXXXXXXXXXXXXXXX
6: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
8: XXXXXXXXXXXXXXXXXXXXXXXXXX
9: XXXXXXXXXXXXXXXXXXXXX
10: XXXXXXXXXXXXXX
11: XXXXXXXXXXXX
12: XXXX
**/
object DiceHistogrammer extends App {
println(DiceHist.roll(200))
}
trait DiceHist {
def roll(): DiceHist
}
object DiceHist {
private val IndOffset = 2
private val NRows = 11
private def apply(rolls: IndexedSeq[Int]) = new DiceHistImpl(rolls)
private def empty: DiceHist = DiceHist(IndexedSeq.fill(NRows)(0))
def roll(times: Int): DiceHist =
(1 to times).foldLeft(empty) { (hist, _) =>
hist.roll()
}
private class DiceHistImpl(rolls: IndexedSeq[Int]) extends DiceHist {
def roll(): DiceHist = {
val rollRes = Dice.roll() + Dice.roll()
val i = rollRes - IndOffset
DiceHist(rolls.updated(i, rolls(i) + 1))
}
override def toString =
rolls.zipWithIndex.map { case (rollCardinality, i) =>
val rollRes = i + IndOffset
f"$rollRes%2d: " + ("X" * rollCardinality)
}.mkString("\n")
}
}
object Dice {
def roll(): Int = nextInt(6) + 1
}
@stephen-lazarionok
Copy link

Well as you want me to put my comments then I will try to be very captiousness and strict :)

  1. A dice might have not only 6 sides.. (http://www.awesomedice.com/image/cache/data/7-dice-set-premium-gemini-black-shell2-500x500.jpg)

  2. Method def roll = .... If I didn't see the implementation then I would doubt what it returns... Consider the result type of ball.roll() or ship.turnAround() I would say that they just change the state of the object and return Unit rather than return some value...

  3. Naming conventions... camelCase

  private val VecOffset = 2
  private val NStates = 11
  1. Actually you do not need to have Vector as the algorithm for creating histograms does not require random access.

  2. Too many string concatenation operations DiceHist(vec updated (i, vec(i) + 'X'))

  3. Simulation & building histogram are tightly coupled. What if I just want to reuse your component to output histogram by my results that I got from somewhere else? Or just wanna get the results of your dice simulation and then put them into some Excel spreadsheet?...

  4. Class/object/trait responsibility...

trait DiceHist {
  def roll: DiceHist
}

diceHistogram.roll().... I do not know what will happen if I roll some diagram :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment