Hi,
  Please see below the code. It does not check for integer values yet and the 
algorithm is based on the suggestion made in moritz's post.
diff --git a/src/core/Hash.pm b/src/core/Hash.pmindex 0365dfc..b2fa0ae 
100644--- a/src/core/Hash.pm+++ b/src/core/Hash.pm@@ -96,6 +96,69 @@ role Hash 
is EnumMap {     multi method sort(&by = &infix:<cmp>) {         
self.pairs.sort(&by)     }+    +    multi method pick() {+        my @weights = 
[\+] self.values;+        my $value = @weights[*-1].rand;+        return 
self.keys[0] if @weights[0] > $value;+        my ($l, $r) = (0, 
@weights.elems-1);+        my $middle = $l + floor( ($r-$l)/2);+        while 
($middle > $l) {+            if @weights[$middle] < $value {+                $l 
= $middle;+            }+            else {+                 $r = $middle;+     
       }+            $middle = $l + floor( ($r-$l)/2);+        }+        
self.keys[$r];+    }++    multi method pick($num is copy = 1, :$replace) {+     
   if ($num == 1) {+            my
 @weights = [\+] self.values;+            my $value = @weights[*-1].rand;+      
      return self.keys[0] if @weights[0] > $value;+            my ($l, $r) = 
(0, @weights.elems-1);+            my $middle = $l + floor( ($r-$l)/2);+        
    while ($middle > $l) {+                if @weights[$middle] < $value {+     
               $l = $middle;+                }+                else {+          
           $r = $middle;+                }+                $middle = $l + 
floor( ($r-$l)/2);+            }+            return self.keys[$r];+        }++  
      if $replace {+            gather {+                while $num > 0 {+      
              take self.pick();+                    $num--;+                }+  
          }+        } else {+            my %copyHash = self;+            
gather {+
                while $num > 0 && %copyHash {+                    my $picked;+  
                  take $picked = %copyHash.pick();+                    unless 
--%copyHash{$picked} {+                        %copyHash.delete($picked);+      
              }+                    $num--;+                }+            }+    
    }+    }++    multi method pick(Whatever, :$replace) {+        
self.pick(Inf, :$replace);+    }
}


      

Reply via email to