Ask Your Question

Random value from array? (Also: ™Bells+Whistles)

asked 2016-08-10 09:34:12 -0500

danielmkarlsson gravatar image

How do I make an array of values and then choose randomly from that array?

Next I'd like to add weights. In SC that would be Pwrand. Next I'd like to empty out all values before putting all values back in the array and then choosing randomly again. In sc that would be Pshuf. Next I'd like make sure there are no repeats of values ever. Not even when comparing the last value with the first value of a new shuffling. I don't know how to do that in SC.

edit retag flag offensive close merge delete


for posterity... referencing my partial answer on Twitter, but I don't think it fully answers your question:

kindohm gravatar imagekindohm ( 2016-08-10 09:58:43 -0500 )edit

Can bgold's answer be accepted?

kindohm gravatar imagekindohm ( 2016-11-14 08:32:48 -0500 )edit

2 answers

Sort by » oldest newest most voted

answered 2016-08-17 15:12:15 -0500

bgold gravatar image

Choose random array values:

choose ["a", "b", "c"]

With integer weights:

choose $ concat $ zipWith replicate [1,2,3] ["a", "b", "c"]

With real weights is possible, but not as a one-liner. I think you'd need to take a cumulative sum of the weights and use rand to index, basically.

If I understand Pshuf correctly I think it's a little awkward in Haskell/Tidal. You can try a function like this:

let randperm t xs = pxs !! (floor $ timeToRand t * (fromIntegral $ length pxs)) where pxs = permutations xs

so randperm 0 ["a", "b", "c"] will give you some random (but always the same if you use 0 as the first argument) permutation of the list. That'll be a list not a Pattern, but you could then use listToPat, preplace, etc...

I'm not sure what you mean by "no repeats of values ever". If there's only 3 things in the list, what happens after the 3rd is taken?

edit flag offensive delete link more

answered 2016-11-15 05:02:23 -0500

danielmkarlsson gravatar image

Oh yes, choose is great. I've used that.

d1 $ s "rave2*8" # n (choose [1, 2, 3]) # cut "1"

Your solution here is great. Thank you so much. Very useful and superFunzees to mess around w/:

d1 $ s "rave2*8" # n (choose $ concat $ zipWith replicate [1, 2, 3] [1, 2, 3]) # cut "1"

Much more elegant than my clunky workaround that I've been using up until now:

d1 $ s "rave2*8" # n (choose [1, 2, 2, 3, 3, 3]) # cut "1"

Less chars and easy to read w/ that particular example but possibly infinitely more amount of chars and definitely harder to read with very large arrays.

This bit went over my head. It looks cool though:

let randperm t xs = pxs !! (floor $ timeToRand t * (fromIntegral $ length pxs)) where pxs = permutations xs

I got it to evaluate ok and I can also run randperm 0 ["a", "b", "c"] ok. But that last bit about turning the list into a pattern I would love to be able to do on my own but sadly I lack the experience w/ Haskell.

I tried looking up mentions of listtoPat in Learn you a Haskell.

I found some mentions of it here:

I dunno, could @bgold or someone else maybe help me out some more?

edit flag offensive delete link more


listToPat just turns a list into a basic pattern, which repeats each cycle and with each entry in the list taking up an equal part. So `n (listToPat [1,2,3])` is exactly the same as `n "1 2 3"`

bgold gravatar imagebgold ( 2016-11-15 07:27:22 -0500 )edit

Question Tools

1 follower


Asked: 2016-08-10 09:34:12 -0500

Seen: 92 times

Last updated: Nov 15 '16