mark.warren
2019-2-22 10:08:43

This is a bit of an odd question, but I wondered if someone had come across something like it before. I have a list of lists of a string and a weight value i.e. '(("a" 1) ("b" 4)) and I need to randomly select one of the strings based on the weight. So in the above example I should get "a" 20% of the time and "b" 80% of the time. I’m not asking for code to do this, just some hints as to an approach, as all my ideas so far are far from nice.


hoshom
2019-2-22 10:10:19

I’d just convert it into a list without weights and randomly select


hoshom
2019-2-22 10:10:51

like, make duplicates according to weights, basically


mark.warren
2019-2-22 10:12:06

That could work, could get quite large if there are a lot of choices but I guess it might not be too bad.


hoshom
2019-2-22 10:12:22

Alternatively, use the weights to make a map of ranges to strings, where no range overlaps and the size of the range is proportional to the weight, and then randomly select between the overall range and look up the map


mark.warren
2019-2-22 10:13:22

That would keep the potential size down, I quite like that.


mark.warren
2019-2-22 10:23:09

@hoshom I like your second idea, I’ll give that a go, Thanks.


hoshom
2019-2-22 10:30:56

Is there any way for DrRacket to show test coverage info for normal #lang racket or typed racket programs? It does show coverage for student languages


hoshom
2019-2-22 10:34:36

I found a package for coverage, I wonder if it integrates with DrRacket


diego
2019-2-22 13:35:12

@mark.warren another idea would be to convert the list to a cumulative-weight list, choose a random value within the range of the maximum cumulative weight, and do a search for the corresponding element. In your example, the cumulative list would be (("a" 1) ("b" 5))


mark.warren
2019-2-22 14:06:05

@diego Thanks for that idea, I have implemented the second idea from @hoshom and it’s working nicely. I might implement your idea as well and see which works best though.


greg
2019-2-22 15:23:49
#lang racket/base

(define (silly-random-by-weight vals+weights)
  (apply sync
         (for*/list ([v+w (in-list vals+weights)]
                     [v   (in-value (car v+w))]
                     [w   (in-value (cadr v+w))]
                     [n   (in-range w)])
           (define ch (make-channel))
           (thread (λ ()
                     (sleep (random))
                     (channel-put ch v)))
           ch)))

:smile:


greg
2019-2-22 15:24:55

is in a Friday mood


jerome.martin.dev
2019-2-22 15:26:02

ahahah


greg
2019-2-22 15:27:45

What? It’s kind of like “sleep sort”. You know, from The Little Book of Abusing Threads and Sleep.


jerome.martin.dev
2019-2-22 15:28:51

I guess I’ll gain enlightment by.. sleeping on it.


mark.warren
2019-2-22 15:39:06

@greg Wow, thanks


soegaard2
2019-2-22 20:30:47

@greg Next up. A silly-sort.


andreiformiga
2019-2-23 00:19:37

@mark.warren what you’re doing is the same as sampling from a discrete (not necessarily uniform) probability distribution. the suggestion by @diego is how this is usually done


notjack
2019-2-23 00:28:12

I think the math libraries include a probability distribution module, maybe using that would be easy?


javicasma
2019-2-23 01:43:37

@javicasma has joined the channel