import System.Random (newStdGen, randomRs)

dataBinCounts :: [Float] -> [Float] -> [Int]
dataBinCounts thresholds range =
  let sampleSize = length range
      xs = ((-) sampleSize . length . flip filter range . (<)) <$> thresholds
  in zipWith (-) (xs ++ [sampleSize]) (0: xs)

main :: IO ()
main = do
  g <- newStdGen
  let fractions = recip <$> [5 .. 11] :: [Float]
      expected = fractions ++ [1 - sum fractions]
      actual =
        ((/ 1000000.0) . fromIntegral) <$>
        dataBinCounts (scanl1 (+) expected) (take 1000000 (randomRs (0, 1) g))

      piv n = take n . (++ repeat ' ')

  putStrLn "       expected     actual"
  mapM_ putStrLn $
    zipWith3
      (\l s c -> piv 7 l ++ piv 13 (show s) ++ piv 12 (show c))
      ["aleph", "beth", "gimel", "daleth", "he", "waw", "zayin", "heth"]
      expected
      actual