My friend wrote a program which compares random arrangements of die faces to find the one with the most evenly distributed faces - especially when the faces are not a mere sequence.
I translated his program into haskell because I've been looking for a reason to talk someone's ear off about how cool haskell is. However, I am not very proficient with haskell (it took me forever to write this and it has undergone a couple giant refactorings) and so I have two problems.
This is the most relevant code:
-- _CENTERS :: [{ x :: Float, y :: Float, z :: Float}]
-- _VALUES :: [Num]
-- Basically just (repeat $ map rand [0.._SIDES]), but never using a seed twice
randstates from = (take _SIDES (infrand from)) : randstates newseed
where infrand seed = seed : infrand (shuffle seed)
newseed = (infrand from) !! (_SIDES + 1)
-- yates shuffle
yates _ (last:[]) = [last]
yates (rand:pass) (swap:order) = choice:yates pass rorder
where choice = order !! index
index = (randfrom rand) `mod` (length order)
rorder = take (index) order ++ swap : drop (index + 1) order
arrangements seed = map arrange $ randstates seed
where arrange rands = yates rands [0.._SIDES - 2]
-- fns comparing arrangements --
arcLength i j = 1 / (1 + _WEIGHT * acos(dot3D / _VEC_LEN_SQUARED))
where dot3D = apply x + apply y + apply z
apply fn = (fn i) * (fn j)
matrix arr = map crosscmp arr
where crosscmp s1 = [ value s1 * (distance s1 s2) | s2 <- arr ]
distance a b = arcLength (_CENTERS !! a) (_CENTERS !! b)
value s = fromInteger $ _VALUES !! s
variance arr = sum $ map perside (matrix arr)
where perside s = (sum s - mean) ^ 2
mean = (sum (concat $ matrix arr)) / (sides + 1)
sides = fromInteger $ toInteger _SIDES
maxDistr = maximumBy (\a b -> variance a `compare` variance b)
Main is basically just
print $ maxDistr $ take _TRIALS $ arrangements seed
As the comments note, it can't scale linearly as indexing into a list is O(index). You will need to move to an array structure to begin to see improvements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With