|
Post by tsh73 on Oct 8, 2020 17:48:43 GMT
Playing with guess-a-number, I end up with a version that does not have "secret" variable at all.
Instead, for each number user inputs, decision is made (with different probability) to call it "secret" or not. Of course it should keep list of discarded numbers so not to approve number already refused. Program does not know result in advance till last moment.
---- Guess a number ---- I made up a number, (1..9) - you guess it. That's all ;)
No! Not quite. Actually I do not made a number. I will deside on the go.
Make your guess (1..9): 1 Nope, try again Make your guess (1..9): 2 Nope, try again Make your guess (1..9): 3 You did it! -=* thanks for playing *=-
'guessANumber ' idea ' instead of making a number ' we deside on each turn 'of cource we should store numbers tried to say "no" again 'and fix probability according to not tried numbers
'logic: loop ' get a number ' check if number is new ' if it is, ' with probabilty 1/#(numbers left) say Yes and stop ' (or else) store it ' else say No
print "---- Guess a number ----" print "I made up a number, (1..9)" print "- you guess it. That's all ;)" print print "No! Not quite." print "Actually I do not made a number." print "I will deside on the go." print
tried$=""
while 1 Input "Make your guess (1..9): ";guess if guess<1 or guess> 9 or int(guess)<>guess then print "Guess not valid" goto [cont] end if if instr(tried$, str$(guess)) then print "Already tried that" goto [cont] end if numsLeft=9-len(tried$) 'print "1/";numsLeft, 'and the probability is if rnd(0)<1/numsLeft then print "You did it!" exit while end if 'else tried$=tried$;guess print "Nope, try again" [cont] wend print "-=* thanks for playing *=-" end
Now I admit one cannot say if it uses right probabilities then picking numbers. So next program tests it. 10000 tests. And it looks quite good, IMHO.
secret with simple random number --------------------------------- 1072 1179 1102 1067 1114 1088 1137 1086 1155 0.107 0.118 0.110 0.107 0.111 0.109 0.114 0.109 0.116 randomly approving, which move --------------------------------- 1115 1152 1082 1143 1115 1112 1184 1052 1045 0.112 0.115 0.108 0.114 0.112 0.111 0.118 0.105 0.105 randomly approving random guess --------------------------------- 1145 1086 1089 1151 1157 1168 1116 1060 1028 0.115 0.109 0.109 0.115 0.116 0.117 0.112 0.106 0.103
'guessANumber ' idea ' instead of making a number ' we deside on each turn 'Probablilties test
Ntests=10000 dim r(9) 'for 1..9
'making secret with random number test print "secret with simple random number " print "---------------------------------" for k=1 to Ntests secret = int(rnd(0)*9+1) r(secret)=r(secret)+1 next for i = 1 to 9 print using("####",r(i));" "; next print for i = 1 to 9 print using("#.###",r(i)/Ntests);" "; next print
'deciding test #1 print "randomly approving, which move " print "---------------------------------" redim r(9) for k=1 to Ntests 'single test tried$="" move=0 while 1 'random guess move=move+1 numsLeft=9-len(tried$) 'print "1/";numsLeft, 'and the probability is if rnd(0)<1/numsLeft then 'approved guess 'print "You did it!" r(move)=r(move)+1 exit while end if 'else tried$=tried$;guess 'print "Nope, try again" [cont1] wend next for i = 1 to 9 print using("####",r(i));" "; next print for i = 1 to 9 print using("#.###",r(i)/Ntests);" "; next print
'deciding test #2 print "randomly approving random guess " print "---------------------------------" redim r(9) for k=1 to Ntests 'single test tried$="" while 1 'random guess guess = int(rnd(0)*9+1) '0..8 -> 1..9 if instr(tried$, str$(guess)) then 'print "Already tried that" goto [cont2] end if numsLeft=9-len(tried$) 'print "1/";numsLeft, 'and the probability is if rnd(0)<1/numsLeft then 'approved guess 'print "You did it!" r(guess)=r(guess)+1 exit while end if 'else tried$=tried$;guess 'print "Nope, try again" [cont2] wend next for i = 1 to 9 print using("####",r(i));" "; next print for i = 1 to 9 print using("#.###",r(i)/Ntests);" "; next print
end
|
|
|
Post by B+ on Oct 9, 2020 0:22:25 GMT
No secret number, no probability just pure meanness ;-))
tried$=""
while 1 Input "Make your guess (1..9): ";guess if guess<1 or guess> 9 or int(guess)<>guess then print "Guess not valid" goto [cont] end if if instr(tried$, str$(guess)) then print "Already tried that" goto [cont] end if if len(tried$) >= 8 then print "You did it!" exit while end if 'else tried$=tried$;guess print "Nope, but you're getting closer!" [cont] wend print "-=* thanks for playing *=-" end
|
|
|
Post by tsh73 on Oct 9, 2020 6:17:39 GMT
Mean indeed There is a nice cyberpank novel (1997) en.wikipedia.org/wiki/Labyrinth_of_Reflectionsbut I don't think it got translated to English. (I happened to find fun translation. It is surely inofficial and I wonder if language is any good But, chapters are numbered in binary! 001, 010, 011 etc warm lamp feeling ) Near the end they confront game boss (in "real" virtual reality, all that stuff) and there was a line along "AI is cheating. You can choose doors in any order - boss will be behind last one"
|
|
|
Post by B+ on Oct 10, 2020 13:37:19 GMT
Hi all,
I have worked this idea out for the Hi Lo Game where you have to guess a number from 1 to 100 and if your number <> secret then you are told if High or Low. I tried tsh73 probability method without a secret number to see if it plays "right". It was tricky so before I post code, I challenge others to give it a try to appreciate how it gets tricky. Meanwhile I am going to test the distribution of "secret numbers" to see if is stacking up somewhere or leaving holes as tsh73 had done.
Update: OK a nice fairly even distribution of "secret numbers" for answers so a person can not tell if the game is working with a given secret number or making things up as it goes along. Pretty cool, tsh73!
Got nice even distribution even when all my guesses remain 1 less than last guess!
|
|
|
Post by B+ on Oct 12, 2020 15:00:27 GMT
Here is a distribution of "Secret Numbers" finally determined at games end in 10,000 trials:
Secret Numbers results: Program errors = 0 1 92 2 94 3 101 4 111 5 110 6 100 7 114 8 104 9 91 10 89 11 82 12 122 13 97 14 97 15 115 16 109 17 96 18 97 19 91 20 103 21 108 22 95 23 104 24 99 25 99 26 108 27 104 28 91 29 102 30 105 31 97 32 81 33 106 34 101 35 107 36 89 37 99 38 88 39 87 40 102 41 100 42 107 43 92 44 81 45 84 46 103 47 100 48 98 49 89 50 95 51 107 52 102 53 105 54 95 55 110 56 92 57 119 58 110 59 106 60 93 61 92 62 84 63 103 64 113 65 94 66 95 67 99 68 92 69 99 70 110 71 91 72 96 73 95 74 87 75 93 76 95 77 111 78 102 79 101 80 111 81 113 82 110 83 115 84 95 85 105 86 106 87 107 88 92 89 93 90 118 91 95 92 106 93 91 94 104 95 106 96 104 97 98 98 97 99 101 100 106 Total 10000 Lowest count 81 for i = 32 Highest count 122 for i = 12
As you can see no holes and no heavy favorites. This tells me this game plays the same as one in which a secret number is decided before the start of each game or round.
|
|
|
Post by B+ on Oct 12, 2020 16:14:13 GMT
Mean indeed There is a nice cyberpank novel (1997) en.wikipedia.org/wiki/Labyrinth_of_Reflectionsbut I don't think it got translated to English. (I happened to find fun translation. It is surely inofficial and I wonder if language is any good But, chapters are numbered in binary! 001, 010, 011 etc warm lamp feeling ) Near the end they confront game boss (in "real" virtual reality, all that stuff) and there was a line along "AI is cheating. You can choose doors in any order - boss will be behind last one" You know this sounds more like the movie Matrix than Neuromancer, 1984 by William Gibson which a quick Google tells me was the book Matrix was based on but wait here is more in depth answer here www.syfy.com/syfywire/7-classic-sci-fi-influences-on-the-original-the-matrix#:~:text=The%20biggest%20and%20perhaps%20most,%2C%20and%20other%20cyberpunky-stuff. Hey checkout the first screen shot FX, we could do that with JB! Matrix is legendary around here in USA. Update: Huh! I thought I read Neuromancer but don't remember anything like Matrix might have William Gibson confused with another.
|
|
|
Post by B+ on Oct 12, 2020 23:51:21 GMT
I've got a feeling nobody is interested or maybe tsh73 is too busy with real life, so without further ado here is the Hi Lo Game without a secret number established at the beginning of each round:
' Hi Lo Game without Secret Number B+ 2020-10-10 works now
[restart] cls Hi = 101: Lo = 0 '<<<< make these higher and lower than what the secret number can be guesses$ = "" while Hi - Lo > 1 input "Guess Number 1 to 100, Enter your guess "; PlayerGuess 'if PlayerGuess = 0 then goto [restart] ' GOOD! we split first guess of 50 both ways! if PlayerGuess < 1 or PlayerGuess > 100 then print "Your guess is out of range of this game." goto [cont] end if if instr(guesses$, right$("000"+str$(PlayerGuess), 3)) then print "You've guessed that number already." goto [cont] end if guesses$ = guesses$ + "," + right$("000";str$(PlayerGuess), 3) if PlayerGuess > Lo and PlayerGuess < Hi then r = rnd(0) : p = 1/(Hi - Lo - 1) ' must be inside the Lo and Hi range ie not inclusive boundaries. if r <= p then print "You Guessed!" Guessed = 1 exit while else if PlayerGuess = Hi - 1 then 'guess must of been too high print Lo, Hi, "Your guess was too high.", r, p Hi = PlayerGuess else if PlayerGuess = Lo + 1 then print Lo, Hi, "Your guess was too low.", r, p Lo = PlayerGuess else 'toss coin if too high or low if rnd(0) < .5 then print Lo, Hi, "Your guess was too low.", r, p Lo = PlayerGuess else print Lo, Hi, "Your guess was too high.", r, p Hi = PlayerGuess end if end if end if end if else if PlayerGuess >= Hi then Print "Your guess was too high." else print "Your guess was too low." end if [cont] wend if Guessed <> 1 then PRINT "Yikes! Programming error, did not find secret number." print: input "press Enter to go again, any other + Enter to quit ";again$ if len(again$) then end else goto [restart]
and here is code to check frequency distribution of final resulting secret numbers:
' Hi Lo Game wo secret Test Distribution B+ 2020-10-10 works now
dim secrets(100) 'check distribution of answers, also checking if we fail to arrive at answer
[restart] 'cls Hi = 101: Lo = 0 '<<<< make these higher and lower than what the secret number can be guesses$ = "" ALO = 0: AHI = 101 Guessed = 0 while Hi - Lo > 1 scan 'input "Guess Number 1 to 100, Enter your guess "; PlayerGuess
'use AI to guess 'PlayerGuess = int((AHI - ALO)/ 2) + ALO 'OK have removed blunder!
'make all the guesses way too high ie ride the AHI down 1 by 1 PlayerGuess = AHI - 1 'Ah still a very nice ditribution of secrets, no holes nor mountains
'PlayerGuess = int((Hi - Lo )/ 2) + Lo 'debug what the heck is going on with ALO AHI?? 'print "Player Guesses ";PlayerGuess
'if PlayerGuess = 0 then goto [restart] ' GOOD! we split first guess of 50 both ways! if PlayerGuess < 1 or PlayerGuess > 100 then 'print "Your guess is out of range of this game." 'call pause 5000 goto [cont] end if if instr(guesses$, right$("000"+str$(PlayerGuess), 3)) then 'print "You've guessed that number already." 'call pause 5000 goto [cont] end if guesses$ = guesses$ + "," + right$("000";str$(PlayerGuess), 3) if PlayerGuess > Lo and PlayerGuess < Hi then r = rnd(0) : p = 1/(Hi - Lo - 1) ' must be inside the Lo and Hi range ie not inclusive boundaries. if r <= p then 'print "You Guessed!" Guessed = 1 'call pause 5000 exit while else if PlayerGuess = Hi - 1 then 'guess must of been too high 'print Lo, Hi, "Your guess was too high.", r, p Hi = PlayerGuess AHI = PlayerGuess else if PlayerGuess = Lo + 1 then 'print Lo, Hi, "Your guess was too low.", r, p Lo = PlayerGuess ALO = PlayerGuess else 'toss coin if too high or low if rnd(0) < .5 then 'print Lo, Hi, "Your guess was too low.", r, p Lo = PlayerGuess ALO = PlayerGuess else 'print Lo, Hi, "Your guess was too high.", r, p Hi = PlayerGuess AHI = PlayerGuess end if end if end if end if else 'going wrong way with guessing, not narrowing down with current guess 'if PlayerGuess >= Hi then Print "Your guess was too high." else print "Your guess was too low." 'call pause 2000 end if [cont] 'print Lo, Hi, ALO, AHI 'OK that blunder was pretty dumb! 'Input "Press enter to continue..." ; wait$ wend if Guessed <> 1 then print "Yikes! Programming error, did not find secret number." programErrors = programErrors + 1 else secrets(PlayerGuess) = secrets(PlayerGuess) + 1 end if trial = trial + 1 if trial < 10000 then goto [restart]
'report results cls Print "Secret Numbers results:" Print "Program errors = ";programErrors low = 10000 for i = 1 to 100 scan print i, secrets(i) 'that's right in JB you can scroll output screen to review all 100 tot = tot + secrets(i) if secrets(i) < low then low = secrets(i) : saveLowI = i if secrets(i) > high then high = secrets(i) : saveHighI = i
next print "Total ";tot print " Lowest count ";low;" for i = ";saveLowI print "Highest count ";high;" for i = ";saveHighI end
sub pause mil 'tsh version has scan built-in t0 = time$("ms") while time$("ms") < t0 + mil : scan : wend end sub
|
|
|
Post by tsh73 on Oct 13, 2020 14:23:54 GMT
Hello B+ You code really looks correct for me But I added a chart to frequency test - and sometimes it looks weird You put PlayerGuess = AHI - 1 and it looks working OK (I use diferen number of points instead of 100 - now, set MAXX to 20) But should frequency depend on other distributions, at all? So then I uncomment 'kk=kk+1 'PlayerGuess = kk
I got pretty level distibution But then I uncomment 'PlayerGuess = int((Hi - Lo )/ 2) + Lo I got and then I try to use random numbers 'PlayerGuess = int(rnd(0)*MAXX) + 1 I got And this one (going up on edges) shows on different MAXX value ' Hi Lo Game wo secret Test Distribution B+ 2020-10-10 works now
'chart library kind-of-header '(that is, should be included to top) '==================================================== global Chart.xmin, Chart.xmax, Chart.ymin, Chart.ymax global Chart.winW, Chart.winH global Chart.slackX, Chart.slackY global Chart.nPoints, Chart.nSeries, Chart.handle$ global Chart.windowTitle$ global Chart.colors$, Chart.widths$ dim Chart.data(1,1) '----------------------------------------------------- 'include chart.hb to the top 'include chart.lb at the end
dim secrets(100) 'check distribution of answers, also checking if we fail to arrive at answer
[restart] 'cls MAXX=100 MAXX=10 MAXX=20 'MAXX=30
Hi = MAXX+1: Lo = 0 '<<<< make these higher and lower than what the secret number can be guesses$ = "" ALO = 0: AHI = MAXX+1 Guessed = 0 kk=0 while Hi - Lo > 1 scan 'input "Guess Number 1 to 100, Enter your guess "; PlayerGuess
'use AI to guess 'PlayerGuess = int((AHI - ALO)/ 2) + ALO 'OK have removed blunder!
'make all the guesses way too high ie ride the AHI down 1 by 1 '1) PlayerGuess = AHI - 1 'Ah still a very nice ditribution of secrets, no holes nor mountains 'PlayerGuess = ALO + 1 'looks pretty much the same
'2) 'PlayerGuess = int((Hi - Lo )/ 2) + Lo 'debug what the heck is going on with ALO AHI?? '3) PlayerGuess = int(rnd(0)*MAXX) + 1 '4) 'kk=kk+1 'PlayerGuess = kk
'print "Player Guesses ";PlayerGuess
'if PlayerGuess = 0 then goto [restart] ' GOOD! we split first guess of 50 both ways! if PlayerGuess < 1 or PlayerGuess > MAXX then 'print "Your guess is out of range of this game." 'call pause 5000 goto [cont] end if if instr(guesses$, right$("000"+str$(PlayerGuess), 3)) then 'print "You've guessed that number already." 'call pause 5000 goto [cont] end if guesses$ = guesses$ + "," + right$("000";str$(PlayerGuess), 3) if PlayerGuess > Lo and PlayerGuess < Hi then r = rnd(0) : p = 1/(Hi - Lo - 1) ' must be inside the Lo and Hi range ie not inclusive boundaries. if r <= p then 'print "You Guessed!" Guessed = 1 'call pause 5000 exit while else if PlayerGuess = Hi - 1 then 'guess must of been too high 'print Lo, Hi, "Your guess was too high.", r, p Hi = PlayerGuess AHI = PlayerGuess else if PlayerGuess = Lo + 1 then 'print Lo, Hi, "Your guess was too low.", r, p Lo = PlayerGuess ALO = PlayerGuess else 'toss coin if too high or low if rnd(0) < .5 then 'print Lo, Hi, "Your guess was too low.", r, p Lo = PlayerGuess ALO = PlayerGuess else 'print Lo, Hi, "Your guess was too high.", r, p Hi = PlayerGuess AHI = PlayerGuess end if end if end if end if else 'going wrong way with guessing, not narrowing down with current guess 'if PlayerGuess >= Hi then Print "Your guess was too high." else print "Your guess was too low." 'call pause 2000 end if [cont] 'print Lo, Hi, ALO, AHI 'OK that blunder was pretty dumb! 'Input "Press enter to continue..." ; wait$ wend if Guessed <> 1 then print "Yikes! Programming error, did not find secret number." programErrors = programErrors + 1 else secrets(PlayerGuess) = secrets(PlayerGuess) + 1 end if trial = trial + 1 if trial < 10000 then goto [restart]
'report results cls Print "Secret Numbers results:" Print "Program errors = ";programErrors low = 10000 for i = 1 to MAXX scan print i, secrets(i) 'that's right in JB you can scroll output screen to review all 100 tot = tot + secrets(i) if secrets(i) < low then low = secrets(i) : saveLowI = i if secrets(i) > high then high = secrets(i) : saveHighI = i
next print "Total ";tot print " Lowest count ";low;" for i = ";saveLowI print "Highest count ";high;" for i = ";saveHighI
'-- graph code ----------------------- Chart.nSeries = 1 'for ordinary graphs, that will be 'col0 for X, col1 etc to Y1 etc Chart.nPoints = MAXX Chart.nPoints = 100 redim Chart.data(Chart.nSeries, Chart.nPoints) Chart.xmin = 1 Chart.xmax = MAXX
for i = 1 to Chart.nPoints Chart.data(0,i)=i Chart.data(1,i)=secrets(i) next
call chartByArray
end
sub pause mil 'tsh version has scan built-in t0 = time$("ms") while time$("ms") < t0 + mil : scan : wend end sub
'>>include chart.lb at the end 'chart library body 'to be included after main program '(together with header included at top)
'----------------------------------------------------- sub parametricChartByArrayInHandle handle$ 'this sub RETURNS AFTER DRAWING Chart.handle$ = handle$ #Chart.handle$ "down" 'get a chart size #Chart.handle$ "home" #Chart.handle$ "posxy w h" Chart.winW=2*w: Chart.winH=2*h
'now, to get Chart.ymin, Chart.ymax we have to loop Chart.ymin=Chart.data(2,1) Chart.ymax=Chart.ymin for s = 1 to Chart.nSeries for i = 1 to Chart.nPoints y=Chart.data(s*2,i) if Chart.ymin > y then Chart.ymin = y if Chart.ymax < y then Chart.ymax = y next next 'for parametrics, xmax xmin should be calculated too Chart.xmin=Chart.data(1,1) Chart.xmax=Chart.xmin for s = 1 to Chart.nSeries for i = 1 to Chart.nPoints x=Chart.data(s*2-1,i) if Chart.xmin > x then Chart.xmin = x if Chart.xmax < x then Chart.xmax = x next next
colorList$ = Chart.colors$ if colorList$="" then colorList$ = "blue green red cyan pink yellow black lightgray darkblue darkgreen darkred darkcyan darkpink brown darkgray" 'add axis call drawAxes call drawTicks 'and labeling ', before graphs (so then came over text) call drawLabels
'now we just - plot function 'for parametric graphs, that will be 'col1 for X1, col2 etc to Y1, col3 for X2, col4 etc to Y2 etc for s = 1 to Chart.nSeries colr$=word$(colorList$, s) if colr$="" then colr$= "black" #Chart.handle$ "color ";colr$ if Chart.widths$<>"" then w$ = word$(Chart.widths$, s) if w$<>""then #Chart.handle$ "size ";w$ end if x=Chart.data(s*2-1,1) y=Chart.data(s*2,1) #Chart.handle$ "set ";sx(x);" ";sy(y) 'just set first dot for i = 1 to Chart.nPoints x=Chart.data(s*2-1,i) y=Chart.data(s*2,i) #Chart.handle$ "goto ";sx(x);" ";sy(y) 'then connect dots next next
#Chart.handle$ "flush" end sub
sub chartByArrayInHandle handle$ 'this sub RETURNS AFTER DRAWING Chart.handle$ = handle$ #Chart.handle$ "down" 'get a chart size #Chart.handle$ "home" #Chart.handle$ "posxy w h" Chart.winW=2*w: Chart.winH=2*h
'now, to get Chart.ymin, Chart.ymax we have to loop Chart.ymin=Chart.data(1,1) Chart.ymax=Chart.ymin for s = 1 to Chart.nSeries for i = 1 to Chart.nPoints y=Chart.data(s,i) if Chart.ymin > y then Chart.ymin = y if Chart.ymax < y then Chart.ymax = y next next
colorList$ = Chart.colors$ if colorList$="" then colorList$ = "blue green red cyan pink yellow black lightgray darkblue darkgreen darkred darkcyan darkpink brown darkgray" 'add axis call drawAxes call drawTicks
'and labeling ', before graphs (so then came over text) call drawLabels
'now we just - plot function 'for ordinary graphs, that will be 'col0 for X, col1 etc to Y1 etc for s = 1 to Chart.nSeries colr$=word$(colorList$, s) if colr$="" then colr$= "black" #Chart.handle$ "color ";colr$ if Chart.widths$<>"" then w$ = word$(Chart.widths$, s) if w$<>""then #Chart.handle$ "size ";w$ end if y=Chart.data(s,1) #Chart.handle$ "set ";sx(Chart.xmin);" ";sy(y) 'just set first dot for i = 1 to Chart.nPoints x=Chart.data(0,i) y=Chart.data(s,i) #Chart.handle$ "goto ";sx(x);" ";sy(y) 'then connect dots next next
#Chart.handle$ "flush" end sub
sub parametricChartByArray 'this sub OPENS MODAL WINDOW and STAYS UNTIL IT CLOSED call genericChartByArray 1 end sub
sub chartByArray 'this sub OPENS MODAL WINDOW and STAYS UNTIL IT CLOSED call genericChartByArray 0 end sub
sub genericChartByArray isParametric oldWindowWidth = WindowWidth oldWindowHeight = WindowHeight gosub [getSlack] WindowWidth=oldWindowWidth:WindowHeight=oldWindowHeight textbox #chart.track, 1, 1, WindowWidth-Chart.slackX, 25 graphicbox #chart.gr, 1, 25, WindowWidth-Chart.slackX, WindowHeight-Chart.slackY-25 title$=Chart.windowTitle$ if title$="" then title$="(modal) Chart window" open title$ for dialog_modal as #chart #chart "trapclose [quitChart]" #chart.track "left mouse button move for tracking" if isParametric then call parametricChartByArrayInHandle "#chart.gr" else call chartByArrayInHandle "#chart.gr" end if #chart.gr "when leftButtonMove [track]" wait
[track] #chart.track ex(MouseX); " "; ey(MouseY) wait
[getSlack] if Chart.slackX <>0 then return WindowWidth=200:WindowHeight=200 open "" for graphics_nsb as #t:#t,"home;posxy x y":close#t Chart.slackX=WindowWidth-2*x:Chart.slackY=WindowHeight-2*y return
[quitChart] close #chart end sub
sub parametricChartByFunc x$,y$,tmin,tmax 'this sub OPENS MODAL WINDOW and STAYS UNTIL IT CLOSED nPointsWasEmpty = (Chart.nPoints=0) if nPointsWasEmpty then Chart.nPoints=1000 'default call fillArrForParametricFunc x$,y$,tmin,tmax call parametricChartByArray if nPointsWasEmpty then Chart.nPoints=0 'reset end sub
sub parametricChartByFuncInHandle handle$, x$,y$,tmin,tmax 'this sub RETURNS AFTER DRAWING nPointsWasEmpty = (Chart.nPoints=0) if nPointsWasEmpty then Chart.nPoints=1000 'default call fillArrForParametricFunc x$,y$,tmin,tmax call parametricChartByArrayInHandle handle$ if nPointsWasEmpty then Chart.nPoints=0 'reset end sub
sub chartByFunc f$,xmin,xmax 'this sub OPENS MODAL WINDOW and STAYS UNTIL IT CLOSED nPointsWasEmpty = (Chart.nPoints=0) if nPointsWasEmpty then Chart.nPoints=300 'default call fillArrForFunc f$,xmin,xmax call chartByArray if nPointsWasEmpty then Chart.nPoints=0 'reset end sub
sub chartByFuncInHandle handle$, f$,xmin,xmax 'this sub RETURNS AFTER DRAWING nPointsWasEmpty = (Chart.nPoints=0) if nPointsWasEmpty then Chart.nPoints=300 'default call fillArrForFunc f$,xmin,xmax call chartByArrayInHandle handle$ if nPointsWasEmpty then Chart.nPoints=0 'reset end sub
sub fillArrForFunc f$,xmin,xmax 'copy to globals first Chart.xmin = xmin Chart.xmax = xmax 'reality/default check if Chart.xmin=Chart.xmax then Chart.xmin = Chart.xmin-10 Chart.xmax = Chart.xmax+10 end if
Chart.nSeries = 1 'for ordinary graphs, that will be 'col0 for X, col1 etc to Y1 etc redim Chart.data(Chart.nSeries, Chart.nPoints) for i = 1 to Chart.nPoints x = i*(Chart.xmax-Chart.xmin)/Chart.nPoints+Chart.xmin Chart.data(0,i)=x Chart.data(1,i)=evalFuncX(f$,x) next end sub
sub fillArrForParametricFunc x$,y$,tmin,tmax 'reality/default check if tmin=tmax then tmin = tmin-10 tmax = tmax+10 end if
Chart.nSeries = 1 'for parametric graphs, that will be 'col1 for X1, col2 etc to Y1, col3 for X2, col4 etc to Y2 etc redim Chart.data(Chart.nSeries*2, Chart.nPoints) for i = 1 to Chart.nPoints t = i*(tmax-tmin)/Chart.nPoints+tmin Chart.data(1,i)=evalFuncX(x$,t) Chart.data(2,i)=evalFuncX(y$,t) next end sub
'-----------------------------------------------------
'function f(x) evaluation function evalFuncX(f$,x) 'for LB apparently 'evalFuncX = eval(f$) 'exit function
'now, for lowly JB select case f$ case "1.5*x^2-2*sin(5*x)" 'single function testing evalFuncX = 1.5*x^2-2*sin(5*x) case "2*cos(x)-cos(2*x)" 'parametric, cardioid X of x[0..2pi] evalFuncX = 2*cos(x)-cos(2*x) case "2*sin(x)-sin(2*x)" 'parametric, cardioid Y of x[0..2pi] evalFuncX = 2*sin(x)-sin(2*x) case else evalFuncX = x 'so you clearly see it works, and works wrong end select end function
'To translate X from interval [a,b] to [c,d] we'll do (X-a)/(b-a)*(d-c)+c. 'create two functions: sx(x) and sy(y) function sx(x) sx=(x-Chart.xmin)/(Chart.xmax-Chart.xmin)*Chart.winW end function function sy(y) sy=Chart.winH-(y-Chart.ymin)/(Chart.ymax-Chart.ymin)*Chart.winH 'Y is inverted, so Chart.winH-... end function 'now, two back functions for mouse tracking function ex(x) ex=(x-0)/Chart.winW*(Chart.xmax-Chart.xmin)+Chart.xmin end function function ey(y) ey=Chart.ymin-(y-Chart.winH)/Chart.winH*(Chart.ymax-Chart.ymin) 'Y is inverted, so Chart.winH-... end function
'----------------------------------------------------- sub drawAxes #Chart.handle$ "color black" #Chart.handle$ "size 1" #Chart.handle$ "line ";sx(Chart.xmin);" ";sy(0);" ";sx(Chart.xmax);" ";sy(0) #Chart.handle$ "line ";sx(0);" ";sy(Chart.ymin);" ";sx(0);" ";sy(Chart.ymax) end sub
sub drawLabels 'default: numbers 7x16 pixels CharW=7 CharH=16 call textAt sx(0)+5,sy(0)-5,"0,0" call textAt sx(Chart.xmax)-20,sy(0)-5,"X" call textAt sx(0)+5,sy(Chart.ymax)+20,"Y"
call numAt sx(Chart.xmin)+20,sy(Chart.ymin)-5,Chart.xmin call numRightAt sx(Chart.xmax),sy(Chart.ymin)-5,Chart.xmax
call numAt sx(Chart.xmin),sy(Chart.ymin)-20,Chart.ymin call numAt sx(Chart.xmin),sy(Chart.ymax)+15,Chart.ymax end sub
sub drawTicks 'tbd end sub
'----------------------------------------------------- sub textAt x,y,text$ #Chart.handle$ "place ";x;" ";y #Chart.handle$ "\";text$ end sub
sub numAt x,y,n text$ = formatG$(n,1) call textAt x,y,text$ end sub
sub numRightAt x,y,n 'default: numbers 7x16 pixels CharW=7 text$ = formatG$(n,1) call textAt x-len(text$)*CharW,y,text$ end sub
'----------------------------------------------------- 'scientific USING function. '(keep in mind that there are no more then 16 digits stored in real number (Double data type)). function usingS$(n,prec) if n = 0 then usingS$="0e+0":exit function fmt$ = "#"+left$(".",prec>0)+left$("#################",prec) 'fmt of mantissa s$=left$("-",n<0) n=abs(n) log10=log(n)/log(10) e=int(log10)-(log10<0) 'QB like INT. Makes mantissa for negative exponents start from digit (not 0 as JB do) p=10^e if left$(using(fmt$,n/p),1)="%" then p=p*10:e = e+1 usingS$=s$+using(fmt$,n/p) +"e"+left$("+",e>0) +str$(e) 'Excel always shows "+" for exponent end function
'there 'scientific' just not needed? function formatG$(n,prec) a$=usingS$(n,prec) fmt$ = "#"+left$(".",prec>0)+left$("#################",prec) 'fmt of mantissa b$=using(fmt$,n) if left$(b$,1)="%" then b$=mid$(b$,2) formatG$=a$ if len(b$)<len(a$) _ 'nice try but 1e-3 turns to 0.000 with prec=3 - ?? and abs(n)>1 then formatG$=b$ end function
|
|
|
Post by B+ on Oct 13, 2020 16:16:03 GMT
tsh73 Thanks for looking into this. Hmm... I never tested just completely random guesses. Not sure what you are doing with chart. I will play with pure random guessing and different Hi Lo starts too? If I get nothing new, I will come back to your chart thing and study what might be happening there, specially the Smiley graph! ;-))
|
|
|
Post by B+ on Oct 13, 2020 22:46:33 GMT
tsh73 Yep! My independent tests confirm the Giant's smile: ' Hi Lo Game WO Secret Number Test Random Guessing Distribution B+ 2020-10-13
' Check tsh73 report of wackiness for pure random guessing. ' So we aren't here all day waiting for results of 1000 tests ' let us store all the guess numbers into a deck. ' Shuffle the deck before each round and use 100 numbers WITHOUT REPEAT ' to get that secret number established! That should save us a ship load ' of time and still produce results of pure random guesses.
dim secrets(100) ' Check distribution of answers, also checking if we fail to arrive at answer. dim rg(100) ' Get our random guesses in a row! Here is our Deck! for i = 1 to 100 ' Create our deck of random numbers to test, rg stands for Random Guess rg(i) = i next
[restart] ' reinitialize all that is necessary start by reshuffle rg() for i = 100 to 2 step -1 'forget about 0 leave it alone tmp = rg(i) r = int(rnd(0) * i) + 1 rg(i) = rg(r) rg(r) = tmp next rIdx = 1 'reset deck index Hi = 101: Lo = 0 ' reset, make these higher and lower than what the secret number can be guesses$ = "" ' track what has been guessed Guessed = 0 ' flag the number has been established!
while Hi - Lo > 1 ' Begin rounds of guesses for number scan
PlayerGuess = rg(rIdx) ' 1 of 100 pure random guesses rIdx = rIdx + 1 'print "Player Guesses ";PlayerGuess
'if PlayerGuess = 0 then goto [restart] ' GOOD! we split first guess of 50 both ways! if PlayerGuess < 1 or PlayerGuess > 100 then 'not going to happen goto [cont] end if if instr(guesses$, right$("000"+str$(PlayerGuess), 3)) then 'not going to happen goto [cont] end if guesses$ = guesses$ + "," + right$("000";str$(PlayerGuess), 3) 'wasting time but... if PlayerGuess > Lo and PlayerGuess < Hi then r = rnd(0) : p = 1/(Hi - Lo - 1) ' must be inside the Lo and Hi range ie not inclusive boundaries. if r <= p then 'print "You guessed it!" Guessed = 1 exit while else if PlayerGuess = Hi - 1 then 'guess must of been too high 'print Lo, Hi, "Your guess was too high.", r, p Hi = PlayerGuess else if PlayerGuess = Lo + 1 then 'print Lo, Hi, "Your guess was too low.", r, p Lo = PlayerGuess else 'toss coin if too high or low if rnd(0) < .5 then 'print Lo, Hi, "Your guess was too low.", r, p Lo = PlayerGuess else 'print Lo, Hi, "Your guess was too high.", r, p Hi = PlayerGuess end if end if end if end if else 'going wrong way with guessing, not narrowing down with current guess this will happen allot!!! if PlayerGuess >= Hi then 'Print "Your guess was too high." else 'print "Your guess was too low." end if end if [cont] 'Input "Press enter to continue..." ; wait$ wend if Guessed <> 1 then print "Yikes! Programming error, did not find secret number." programErrors = programErrors + 1 else secrets(PlayerGuess) = secrets(PlayerGuess) + 1 end if trial = trial + 1 if trial < 1000 then goto [restart]
'report results cls Print "Secret Numbers results:" Print "Program errors = ";programErrors low = 1000 for i = 1 to 100 scan print i, secrets(i) 'that's right in JB you can scroll output screen to review all 100 tot = tot + secrets(i) if secrets(i) < low then low = secrets(i) : saveLowI = i if secrets(i) > high then high = secrets(i) : saveHighI = i next print "Total ";tot print " Lowest count ";low;" for i = ";saveLowI print "Highest count ";high;" for i = ";saveHighI end
Output: Secret Numbers results: Program errors = 0 1 66 2 24 3 23 4 14 5 9 6 11 7 13 8 12 9 12 10 18 11 10 12 7 13 8 14 16 15 6 16 12 17 8 18 5 19 5 20 8 21 9 22 5 23 11 24 5 25 11 26 12 27 11 28 8 29 5 30 3 31 5 32 2 33 5 34 6 35 5 36 3 37 9 38 9 39 6 40 7 41 7 42 6 43 4 44 5 45 7 46 5 47 8 48 4 49 12 50 7 51 11 52 5 53 7 54 4 55 7 56 7 57 5 58 10 59 3 60 2 61 5 62 11 63 5 64 7 65 4 66 9 67 10 68 5 69 4 70 7 71 4 72 12 73 6 74 7 75 4 76 8 77 8 78 8 79 14 80 14 81 4 82 6 83 11 84 18 85 12 86 14 87 9 88 12 89 11 90 11 91 8 92 12 93 13 94 11 95 16 96 12 97 21 98 19 99 29 100 49 Total 1000 Lowest count 2 for i = 32 Highest count 66 for i = 1
So the phenomena is definitely not just an artifact of your chart. So what the heck??? Those boundaries are significantly favored.
|
|
|
Post by B+ on Oct 15, 2020 0:55:08 GMT
OK back from the Drawing Board and I think I have it now.
Here's why, frequency distribution of 100,000 trials:
Secret Numbers results: Program errors = 0 1 1125 2 950 3 1065 4 976 5 1085 6 978 7 1091 8 905 9 980 10 964 11 1110 12 1017 13 1072 14 940 15 1098 16 953 17 1074 18 1104 19 1121 20 968 21 988 22 877 23 971 24 949 25 1093 26 951 27 1070 28 1074 29 1090 30 964 31 923 32 956 33 1022 34 937 35 1054 36 966 37 1000 38 910 39 1039 40 1088 41 1035 42 951 43 1018 44 1033 45 1109 46 966 47 940 48 1010 49 939 50 958 51 1083 52 909 53 971 54 927 55 1053 56 932 57 1169 58 955 59 1016 60 904 61 1073 62 976 63 1121 64 978 65 993 66 936 67 1002 68 1104 69 1062 70 957 71 977 72 911 73 915 74 914 75 967 76 933 77 1076 78 945 79 1058 80 948 81 957 82 955 83 1100 84 1023 85 919 86 966 87 972 88 1008 89 917 90 1017 91 974 92 1051 93 989 94 1070 95 993 96 1096 97 990 98 939 99 952 100 890 Total 100000 Lowest count 877 for i = 22 Highest count 1169 for i = 57
Here is the new version of Game:
' Hi Lo Game without Secret Number v2 B+ 2020-10-14 ' OK the first version gets really wierd results around the boundaries 1 and 100. ' The frequency of established secret numbers jumps up very significantly! ' Back to the drawing board :)
' 2020-10-14 This time I developed the game code in the Random Number Guess Frequency Tester. ' This game has very level frequency from 1 to 100 and regular game feels right.
[restart] cls Hi = 101: Lo = 0 '<<<< make these higher and lower than what the secret number can be guesses$ = "" while Hi - Lo > 1 input "Guess Number 1 to 100, Enter your guess "; PlayerGuess 'if PlayerGuess = 0 then goto [restart] ' GOOD! we split first guess of 50 both ways! if PlayerGuess < 1 or PlayerGuess > 100 then print "Your guess is out of range of this game." goto [cont] end if if instr(guesses$, right$("000"+str$(PlayerGuess), 3)) then print "You've guessed that number already." goto [cont] end if guesses$ = guesses$ + "," + right$("000" + str$(PlayerGuess), 3) if PlayerGuess > Lo and PlayerGuess < Hi then r = rnd(0) : p = 1/(Hi - Lo - 1) ' must be inside the Lo and Hi range ie not inclusive boundaries. if r <= p then print "You Guessed!" Guessed = 1 exit while else if PlayerGuess = Lo + 1 then print "Your guess was low." Lo = Lo + 1 else if PlayerGuess = Hi - 1 then print "Your guess was high." Hi = Hi - 1 else 'p < guess = (guess - lo -1) / range range = Hi - Lo - 1 if rnd(0) * range <= PlayerGuess - Lo -.5 then Print Lo, Hi, "Your guess was too high." Hi = PlayerGuess else print Lo, Hi, "Your guess was too low." Lo = PlayerGuess end if end if end if end if else if PlayerGuess >= Hi then Print "Your guess was too high." else print "Your guess was too low." end if [cont] wend if Guessed <> 1 then PRINT "Yikes! Programming error, did not find secret number." print: input "press Enter to go again, any other + Enter to quit ";again$ if len(again$) then end else goto [restart]
Here is code that produced the above frequency table (It has 2 tests actually one that chooses the middle of known High's and Low's like a good AI would, the other test systematically goes down 1 number at each guess commented out):
' Hi Lo Game wo secret Test Distribution B+ 2020-10-10 works now
dim secrets(100) 'check distribution of answers, also checking if we fail to arrive at answer
[restart] 'cls Hi = 101: Lo = 0 '<<<< make these higher and lower than what the secret number can be guesses$ = "" Guessed = 0 player = 101 while Hi - Lo > 1 scan 'input "Guess Number 1 to 100, Enter your guess "; PlayerGuess
'make all the guesses way too high ie ride the AHI down 1 by 1 'player = player - 1 'PlayerGuess = player 'Ah still a very nice ditribution of secrets, no holes nor mountains
PlayerGuess = int((Hi - Lo )/ 2) + Lo 'debug what the heck is going on with ALO AHI?? 'print "Player Guesses ";PlayerGuess
'if PlayerGuess = 0 then goto [restart] ' GOOD! we split first guess of 50 both ways! if PlayerGuess < 1 or PlayerGuess > 100 then print "Your guess is out of range of this game." goto [cont] end if if instr(guesses$, right$("000"+str$(PlayerGuess), 3)) then print "You've guessed that number already." goto [cont] end if guesses$ = guesses$ + "," + right$("000";str$(PlayerGuess), 3) if PlayerGuess > Lo and PlayerGuess < Hi then r = rnd(0) : p = 1/(Hi - Lo - 1) ' must be inside the Lo and Hi range ie not inclusive boundaries. if r <= p then 'print "You Guessed!" Guessed = 1 exit while else if PlayerGuess = Lo + 1 then 'print "Your guess was too low." Lo = Lo + 1 else if PlayerGuess = Hi - 1 then 'print "Your guess was too high." Hi = Hi - 1 else 'p < guess = (guess - lo -1) / range range = Hi - Lo - 1 if rnd(0) * range <= PlayerGuess - Lo -.5 then ' Print Lo, Hi, "Your guess was too high." Hi = PlayerGuess else 'print Lo, Hi, "Your guess was too low." Lo = PlayerGuess end if end if end if end if else 'going wrong way with guessing, not narrowing down with current guess if PlayerGuess >= Hi then Print "Your guess was high." else print "Your guess was low." end if [cont] 'Input "Press enter to continue..." ; wait$ wend if Guessed <> 1 then print "Yikes! Programming error, did not find secret number." programErrors = programErrors + 1 else secrets(PlayerGuess) = secrets(PlayerGuess) + 1 end if trial = trial + 1 if trial < 100000 then goto [restart]
'report results cls Print "Secret Numbers results:" Print "Program errors = ";programErrors low = 10000 for i = 1 to 100 scan print i, secrets(i) 'that's right in JB you can scroll output screen to review all 100 tot = tot + secrets(i) if secrets(i) < low then low = secrets(i) : saveLowI = i if secrets(i) > high then high = secrets(i) : saveHighI = i next print "Total ";tot print " Lowest count ";low;" for i = ";saveLowI print "Highest count ";high;" for i = ";saveHighI end
And here is code I used to actually develop the new improved version of the Hi Lo Game Without Secret Number, the frequency distribution test for Random number guess. This is the test that pointed out the serious flaw in previous version of Hi Lo Without Secret Number:
' Hi Lo Game WO Secret Number Test Random Guessing Distribution B+ 2020-10-13
' Check tsh73 report of wackiness for pure random guessing. ' So we aren't here all day waiting for results of 1000 tests ' let us store all the guess numbers into a deck. ' Shuffle the deck before each round and use 100 numbers WITHOUT REPEAT ' to get that secret number established! That should save us a ship load ' of time and still produce results of pure random guesses. ' 2020-10-13 post https://justbasiccom.proboards.com/thread/567/guess-number-secret
dim secrets(100) ' Check distribution of answers, also checking if we fail to arrive at answer. dim rg(100) ' Get our random guesses in a row! Here is our Deck! for i = 1 to 100 ' Create our deck of random numbers to test, rg stands for Random Guess rg(i) = i next
[restart] ' reinitialize all that is necessary start by reshuffle rg() for i = 100 to 2 step -1 'forget about 0 leave it alone tmp = rg(i) r = int(rnd(0) * i) + 1 rg(i) = rg(r) rg(r) = tmp next rIdx = 1 'reset deck index Hi = 101: Lo = 0 ' reset, make these higher and lower than what the secret number can be guesses$ = "" ' track what has been guessed Guessed = 0 ' flag the number has been established!
while Hi - Lo > 1 ' Begin rounds of guesses for number scan
PlayerGuess = rg(rIdx) ' 1 of 100 pure random guesses rIdx = rIdx + 1 'print "Player Guesses ";PlayerGuess
'if PlayerGuess = 0 then goto [restart] ' GOOD! we split first guess of 50 both ways! if PlayerGuess < 1 or PlayerGuess > 100 then 'not going to happen goto [cont] end if if instr(guesses$, right$("000"+str$(PlayerGuess), 3)) then 'not going to happen goto [cont] end if guesses$ = guesses$ + "," + right$("000";str$(PlayerGuess), 3) 'wasting time but... if PlayerGuess > Lo and PlayerGuess < Hi then r = rnd(0) : p = 1/(Hi - Lo - 1) ' must be inside the Lo and Hi range ie not inclusive boundaries. if r <= p then 'print "You guessed it!" Guessed = 1 exit while else
if PlayerGuess = Lo + 1 then 'print "Your guess was low." Lo = Lo + 1 else if PlayerGuess = Hi - 1 then 'print "Your guess was high." Hi = Hi - 1 else 'p < guess = (guess - lo -1) / range range = Hi - Lo - 1 if rnd(0) * range <= PlayerGuess - Lo -.5 then 'Print Lo, Hi, "Your guess was too high." Hi = PlayerGuess else 'print Lo, Hi, "Your guess was too low." Lo = PlayerGuess end if end if end if end if
else 'going wrong way with guessing, not narrowing down with current guess this will happen allot!!! if PlayerGuess >= Hi then 'Print "Your guess was too high." else 'print "Your guess was too low." end if end if [cont] 'Input "Press enter to continue..." ; wait$ wend if Guessed <> 1 then print "Yikes! Programming error, did not find secret number." programErrors = programErrors + 1 else secrets(PlayerGuess) = secrets(PlayerGuess) + 1 end if trial = trial + 1 if trial < 10000 then goto [restart]
'report results cls Print "Secret Numbers results:" Print "Program errors = ";programErrors low = 1000 for i = 1 to 100 scan print i, secrets(i) 'that's right in JB you can scroll output screen to review all 100 tot = tot + secrets(i) if secrets(i) < low then low = secrets(i) : saveLowI = i if secrets(i) > high then high = secrets(i) : saveHighI = i next print "Total ";tot print " Lowest count ";low;" for i = ";saveLowI print "Highest count ";high;" for i = ";saveHighI end
And here is a sample run of that distribution:
Secret Numbers results: Program errors = 0 1 127 2 111 3 124 4 109 5 112 6 105 7 109 8 110 9 100 10 125 11 106 12 87 13 105 14 97 15 87 16 110 17 111 18 115 19 114 20 101 21 115 22 95 23 89 24 110 25 104 26 87 27 86 28 97 29 105 30 100 31 98 32 106 33 95 34 100 35 99 36 89 37 104 38 110 39 99 40 89 41 100 42 91 43 107 44 114 45 120 46 76 47 103 48 109 49 96 50 103 51 93 52 88 53 79 54 91 55 85 56 82 57 94 58 107 59 96 60 131 61 111 62 88 63 94 64 89 65 81 66 124 67 82 68 112 69 105 70 101 71 94 72 111 73 97 74 95 75 68 76 93 77 118 78 99 79 106 80 101 81 87 82 89 83 96 84 110 85 91 86 99 87 98 88 104 89 88 90 105 91 83 92 109 93 83 94 97 95 81 96 97 97 106 98 95 99 112 100 94 Total 10000 Lowest count 68 for i = 75 Highest count 131 for i = 60
|
|