Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate # Pie Chart Probability

25 replies to this topic • Members
• 52 posts
• Last active: Aug 15 2009 01:47 AM
• Joined: 20 Nov 2008
Imagine I have a pie chart with a spinner in the center. The pie chart has 4 different colors on it, Red, Green, Blue, Yellow. Each color takes up a certain amount of space on the pie chart, and the amount changes for each situation. If I were to spin the spinner how would I determine where the spinner would land, factoring in the probability of each color (size of slice).

The way I have my information is setup differently, but it uses the exact same concept. If you have any questions please let me know. • Guests
• Last active:
• Joined: --
```red_probability=25

green_probability=25

blue_probability=25

yellow_probability=25

random, spinner, 0, 100

if spinner between 0 and %red_probability%

msgbox, RED_%spinner%

bound_lower1:= red_probability

bound_upper1:= red_probability + green_probability

if spinner between %bound_lower1% and %bound_upper1%

msgbox, GREEN_%spinner%

bound_lower2:= bound_upper1

bound_upper2:= bound_upper1 + blue_probability

if spinner between %bound_lower2% and %bound_upper2%

msgbox, BLUE_%spinner%

bound_lower3:= bound_upper2

bound_upper3:= bound_upper2 + yellow_probability

if spinner between %bound_lower3% and %bound_upper3%

msgbox, YELLOW_%spinner%``` • Members
• 52 posts
• Last active: Aug 15 2009 01:47 AM
• Joined: 20 Nov 2008
Thanks that helps. However, in my situation I have upwards of 20 different "slices" and the number of slices may change. So is there a way to make a function of a sorts that allows for a changing number of slices?

Again thank you • Moderators
• 6367 posts
• Last active: Nov 30 2018 08:50 PM
• Joined: 18 Mar 2008
Something like this?

```Spinner(num) {

Random, var, 0, % num * 10
Loop % num {
slice := A_Index * num
if var between 0 and %slice%
{
MsgBox, Slice %A_Index% was randomly selected
break
}
}

}

#v::Spinner(7)
;Spinner(11)
;Spinner(24)``` • Moderators
• 4323 posts
• Last active: Jan 28 2016 01:38 AM
• Joined: 08 Apr 2009
sinkfaze, your code considers that all slices have the same probability, right?
(If so, I suppose a one-line random command would be enough)

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Antonio França -- git.io -- github.com -- ahk4.net

Member of the AHK community since 08/Apr/2009. Moderator since mid-2012. • Members
• 52 posts
• Last active: Aug 15 2009 01:47 AM
• Joined: 20 Nov 2008

Something like this?

```Spinner(num) {

Random, var, 0, % num * 10
Loop % num {
slice := A_Index * num
if var between 0 and %slice%
{
MsgBox, Slice %A_Index% was randomly selected
break
}
}

}

#v::Spinner(7)
;Spinner(11)
;Spinner(24)``` • Members
• 52 posts
• Last active: Aug 15 2009 01:47 AM
• Joined: 20 Nov 2008

sinkfaze, your code considers that all slices have the same probability, right?
(If so, I suppose a one-line random command would be enough)

In my situation they all have different probabilities • Members
• 52 posts
• Last active: Aug 15 2009 01:47 AM
• Joined: 20 Nov 2008
I might try to give some more insight for what I am looking for. A while ago I tried making a genetic algorithm with AHK, Sinkfaze actually helped me with it. However, I never got it working, so I gave up. I decided to try and make another one, with less work-arounds and hopefully functional.

My current script is this:
```#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
CoordMode , Mouse, Screen

StartX := A_ScreenWidth/2
Loop
{
StringRight , LastChar, StartX, 1
If LastChar = 0
StringTrimRight , StartX, StartX, 1
Else
{
Break
}
}
Loop
{
StringRight , LastChar, StartX, 1
If LastChar = .
StringTrimRight , StartX, StartX, 1
Else
{
Break
}
}
StartY := A_ScreenHeight/2
Loop
{
StringRight , LastChar, StartY, 1
If LastChar = 0
StringTrimRight , StartY, StartY, 1
Else
Break
}
Loop
{
StringRight , LastChar, StartY, 1
If LastChar = .
StringTrimRight , StartY, StartY, 1
Else
Break
}
Gui, Add, Text, x16 y23 w50 h20 , Target X:
Gui, Add, Edit, x66 y20 w90 h20 vPrimeX, %StartX%
Gui, Add, Text, x166 y23 w50 h20, Target Y:
Gui, Add, Edit, x216 y20 w90 h20 vPrimeY, %StartY%
Gui, Add, Button, x316 y15 w50 h30 , Test

Gui , Add, Text, x16 y62 w80 h20 , Population Size:
Gui , Add, Edit, x106 y60 w80 h20 vNumberSeeds, 20

Gui , Add, Text, x196 y62 w70 h20 , Seed Length:
Gui , Add, Edit, x276 y60 w90 h20 vSeedLength, 10

Gui , Add, Text, x16 y102 w90 h20 , Mutation Rate (`%):
Gui , Add, Edit, x116 y100 w70 h20

Gui , Add, Text, x196 y102 w100 h20 , Crossover Rate (`%):
Gui , Add, Edit, x296 y100 w70 h20

Gui , Add, Button, x16 y140 w90 h30 +Default vStart, Start
Gui , Add, Button, x16 y140 w90 h30 +Hidden vNext, Next
Gui , Add, Button, x146 y140 w90 h30 , Pause
Gui , Add, Button, x276 y140 w90 h30 , Cancel

Gui , Add, Tab, x8 y180 w373 h290 , Seeds|Generations
Gui , Tab, 1
Gui , Tab, 2
Gui , Add, ListView, w350 h250 +ReadOnly +NoSortHdr vGenerations, Generation|Avg Fit|Best Fit|X|Y

Gui, Show, x322 y188 h489 w391, Mouse Genetic Algorithm
Return

ButtonCancel:
GuiClose:
ExitApp

ButtonHere:
MsgBox , Yes here, but doesn't mean you have to click on it :)
Return

ButtonPause:
Pause
Return

ButtonTest:
Gui , Submit, NoHide
Random , Rans, 1, 10
MouseMove , PrimeX, PrimeY, Rans
Return

RandI(min, max) ; Random integer (< 53-bit) from Globally Unique ID  ;This Takes a little time to run
{
VarSetCapacity(A,16)
DllCall("rpcrt4\UuidCreate","Str",A)
r = 0
Loop 8
Return min + Floor(r*(max-min+1))
}
;;RandI(min, max)  ;Doesn't seem to work, probably because of delay
;{
;	High := max ;+1,000,000,000 is limit
;	Low := min ;-1,000,000,000 is limit
;	Return random
;}

;RandI(Min, Max)
;{
;   Random , Number, Min, Max
;   Return Number
;}

FirstGen(NumberSeeds, SeedLength)
{
loop , 1000
{
r := RandI(0,9)
f := RandI(0,3)
d%r% .= f
}
n := RandI(0,9)
m := d%n%
Length := SeedLength*6
StringRight , Seed, m, %Length%
Return Seed
}

ProteinSynthesis(Seed, SeedLength, Temp)
{
Result =
Protein =
Loop , 2
{
Result =
Loop , %SeedLength%
{
CodonIndex := A_Index
Trim := (CodonIndex-1)*3
StringTrimRight , ProteinCodon, SeedCodon, %Trim%
if ProteinCodon between 000 and 003
Protein .= "0"
else if ProteinCodon between 010 and 013
Protein .= "1"
else if ProteinCodon between 020 and 023
Protein .= "2"
else if ProteinCodon between 030 and 033
Protein .= "3"
else if ProteinCodon between 040 and 043
Protein .= "4"
else if ProteinCodon between 100 and 103
Protein .= "5"
else if ProteinCodon between 110 and 113
Protein .= "6"
else if ProteinCodon between 120 and 123
Protein .= "7"
else if ProteinCodon between 130 and 133
Protein .= "8"
else if ProteinCodon between 200 and 203
Protein .= "9"
else if ProteinCodon between 210 and 213
Protein .= "+"
else if ProteinCodon between 220 and 223
Protein .= "-"
else if ProteinCodon between 230 and 233
Protein .= "*"
else if ProteinCodon between 300 and 303
Protein .= "/"
}
Protein := RegExReplace(RegExReplace(Protein,"([\+\*/-])[\+\*/-]+","\$1"),"([\+\*/-])","\$1")
Protein := RegExReplace(RegExReplace(Protein,"^[\*\+/-0]+(.*)","\$1"),"(.*)[\*\+/-]+\$","\$1")
FileDelete , %Temp%
FileAppend , #NoTrayIcon`nFileDelete %Temp%`nFileAppend `% %Protein%`, %Temp%, %Temp%
RunWait , %Temp%
FileDelete , %Temp%
Result := Abs(Result)
Loop
{
StringRight , LastChar, Result, 1
If LastChar = 0
StringTrimRight , Result, Result, 1
Else
Break
}
Loop
{
If LasChar = .
StringTrimRight , Result, Result, 1
Else
Break
}
If Result =
Result = 0
If A_Index = 1
{
Result .= "X"
ResultX := Result
}
Else If A_Index = 2
{
Result .= "Y"
ResultY := Result
}
}
Result := ResultX . ResultY
Return Result
}

FillSeeds(Result, Num, GenerationIndex)
{
Gui , ListView, Seeds
StringGetPos , Pos, Result, X
StringLeft , ValueX, Result, %Pos%
Pos += 1
StringTrimLeft , ValueY, Result, %Pos%
StringGetPos , Pos, ValueY, Y
StringLeft , ValueY, ValueY, %Pos%
}

FillGenerations(NumberSeeds, GenerationIndex)
{
Gui , ListView, Seeds
Prime := LV_GetCount()-NumberSeeds
AllFitness = 0
BestFitness = 0
Loop , %NumberSeeds%
{
Start := Prime+A_Index
LV_GetText(Fitness, Start, 5)
AllFitness += Fitness
If (Fitness > BestFitness)
{
BestFitness := Fitness
LV_GetText(ValueX, Start, 3)
LV_GetText(ValueY, Start, 4)
}
}
AvgFitness := AllFitness/NumberSeeds
Gui , ListView, Generations
LV_Add("", GenerationIndex, AvgFitness, BestFitness, ValueX, ValueY)
Random , RanS, 0, 100
MouseMove , ValueX, ValueY, RanS
}

Fitness(PrimeX, PrimeY, NumberSeeds, GenerationIndex)
{
Gui , ListView, Seeds
Prime := LV_GetCount()-NumberSeeds
Loop , %NumberSeeds%
{
Start := Prime+A_Index
LV_GetText(ValueX, Start, 3)
LV_GetText(ValueY, Start, 4)
ValueX := Abs(PrimeX-ValueX)
ValueY := Abs(PrimeY-ValueY)
If ValueX =
ValueX := 0
If ValueY =
ValueY := 0
ValueX := 1/ValueX
ValueY := 1/ValueY
If ValueX =
ValueX := 0
If ValueY =
ValueY := 0
}
Loop , %NumberSeeds%
{
Start := Prime+A_Index
LV_GetText(ValuePrimeX, Start, 3)
LV_GetText(ValuePrimeY, Start, 4)
ValueX := Abs(PrimeX-ValuePrimeX)
ValueY := Abs(PrimeY-ValuePrimeY)
If ValueX =
ValueX := 0
If ValueY =
ValueY := 0
If FitnessX =
FitnessX := 0
If FitnessY =
FitnessY := 0
Fitness := (FitnessX+FitnessY)/2
If Fitness =
Fitness := 0
Seed := (Start+NumberSeeds)-LV_GetCount()
LV_Modify(Start, "", GenerationIndex, Seed, ValuePrimeX, ValuePrimeY, Fitness)
}
}

ButtonStart:
Gui , Submit, NoHide
GuiControl , Hide, Start
GuiControl , Show , Next
GuiControl , +Default, Next
CoordMode , Mouse, Screen
SetFormat , Float, 4.18 ;In accordance with RandomI including DLLCall
GenerationIndex = 1
Temp = %A_ScriptDir%\\$Temp\$.ahk
FileDelete , Generation%GenerationIndex%.txt
FileDelete , Result%GenerationIndex%.txt

Num = 0
GuiControl , -Redraw, Seeds
Loop , %NumberSeeds%
{
Num += 1
SeedIndex := A_Index
Seed := FirstGen(NumberSeeds, SeedLength)
Result := ProteinSynthesis(Seed, SeedLength, Temp)
FillSeeds(Result, Num, GenerationIndex)
FileAppend , %Seed%`r`n, Generation%GenerationIndex%.txt
FileAppend , %Result%`r`n, Result%GenerationIndex%.txt
}
Fitness(PrimeX, PrimeY, NumberSeeds, GenerationIndex)
Gui , ListView, Seeds
LV_ModifyCol(3)
LV_ModifyCol(4)
LV_ModifyCol(5)
GuiControl , +Redraw, Seeds
FillGenerations(NumberSeeds, GenerationIndex)
Gui , ListView, Generations
LV_ModifyCol(2)
LV_ModifyCol(3)
LV_ModifyCol(4)
LV_ModifyCol(5)```
The code is big long and probably not helpful for you, however, it help me explain what I need. (P.S. this script contains no attempt at a spinner function)

In the Genetic Algorithm (GA) I have some values generated and then they are given a fitness (how close they are to the target). Their fitness determines the size of their "Slice". The size of the slices is completely random, and the number of slices is determined at the beginning of the script. I want to be able to randomly choose one of the values, the closer they are to the target the higher chance of being picked they will have (aka bigger slice).

Thank you • Members
• 52 posts
• Last active: Aug 15 2009 01:47 AM
• Joined: 20 Nov 2008
In my first attempt a the GA for the spinner function I used a txt file.
Say I have the colors: green, blue, red, yellow

Blue = 36
green = 2
red = 13
yellow = 49

So I had the function write 36 blue line by line, then 2 greens, the 13 reds, then 49 yellows. Then I randomly chose one line from the file, which ever color I ended up with was the selected color. However, I thought this was a work-around and that there should be a way i can do it without writing to a file.

Thank you • Members
• 52 posts
• Last active: Aug 15 2009 01:47 AM
• Joined: 20 Nov 2008

Something like this?

```Spinner(num) {

Random, var, 0, % num * 10
Loop % num {
slice := A_Index * num
if var between 0 and %slice%
{
MsgBox, Slice %A_Index% was randomly selected
break
}
}

}

#v::Spinner(7)
;Spinner(11)
;Spinner(24)```

I do not need this explained anymore, I get it now thanks.
And like MasterFocus wrote, this considers that all slices have the same probability, which i do not need

Thank you though • Moderators
• 4323 posts
• Last active: Jan 28 2016 01:38 AM
• Joined: 08 Apr 2009
Good. Let me test a few things and see what I can do.

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Antonio França -- git.io -- github.com -- ahk4.net

Member of the AHK community since 08/Apr/2009. Moderator since mid-2012. • Members
• 52 posts
• Last active: Aug 15 2009 01:47 AM
• Joined: 20 Nov 2008

Good. Let me test a few things and see what I can do.

Thanks • Moderators
• 4323 posts
• Last active: Jan 28 2016 01:38 AM
• Joined: 08 Apr 2009
EDIT:
Solution provided here.
Thanks to [VxE] for the original code (next post).

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Antonio França -- git.io -- github.com -- ahk4.net

Member of the AHK community since 08/Apr/2009. Moderator since mid-2012. • Moderators
• 3622 posts
• Last active: Dec 24 2015 02:21 AM
• Joined: 07 Oct 2006
A random selection from a weighted set is easily calculated by choosing a random weight between zero and the total weight, then removing items one at a time until the weight of the items removed exceeds the randomly chosen weight. Then the last item removed is the one selected.

```Random,, % A_Now ^ A_TickCount ; as good as any seed
Blue = 36
green = 2
red = 13
yellow = 49
VarsListItDo =
( ltrim
Blue
Green
Red
Yellow
)
F5::MsgBox % WeightedRandomVarName(VarsListItDo)

WeightedRandomVarName( list )
{
Local R := 0 ; Global everything else
Loop, Parse, list, `n, `r %A_Tab%
R += Abs(%A_LoopField%) ; Abs() was required here... I don't know why
Random, R, 0, % R
Loop, Parse, list, `n, `r %A_Tab%
If ( 0 >= R -= %A_LoopField% )
Return A_LoopField
}```
Aah yes... floating numbers are just fine in this code. • Guests
• Last active:
• Joined: --
```red = 11

blue = 22

green = 33

teal = 44

yellow = 55

loop %red%

list = %list%`nred

loop %blue%

list = %list%`nblue

loop %green%

list = %list%`ngreen

loop %teal%

list = %list%`nteal

loop %yellow%

list = %list%`nyellow

sort, list, random

Loop, parse, list, `n

{

if A_LoopField !=

{

chosen = %A_LoopField%

break

}

}

msgbox, % chosen

msgbox, % list```