/* * The "Halbkreis" problem, see FHK\Spiele-Simu\Halbkreis\Halbkreis.html & Halbkreis-loesung.docx. * * Three blue points on a circle are randomly selected. What is the probability that these three * points can be covered by a suitable semi-circle? (The correct answer is 75%.) * * This program simulates the problem with many random trials ("rounds"), where a suitable semi-circle * is found auctomatically ("test"). After multiple rounds, the hit frequency approximates better * and better the sought probability. * * Author: Wolfgang Konen, Cologne Univ. of Applied Sciences, 09/2013 * (original idea goes back to Timm Grams, FH Fulda, 1999) */ int x0, y0; // center circle int r=70; // raduis circle int dr=r/10; // radius blue dots int t=180; int a[]={0, 0, 0, 0}; //a[1..3] the three blue dots //a[0] first point of semi-circle int i,a0; int count, hit; // number of trials, number of hits float hitrate=0.0; int state; // The simulation is modeled as a state machine: // 0: new round, test is running // 1: test just ready // 2: test (longer) ready int incr=1; // increment of semi-circle during test boolean ok; // whether a hit has been detected in the current round boolean showHelp=true; // toggle help text boolean contMode=true; // toggle continuous mode vs. user-controlled mode (SPACE bar) int mil=0; // a timer is started when the simulation goes from state==1 to state==2 color fg1 = color(0,0,255); // blue: dots color fg2 = color(245,245,82); // yellow: circle, semi-circle PFont mainFont,helpFont; void setup() { size(310, 210, JAVA2D); // Uncomment the following line to see the available fonts: //String[] fontList = PFont.list(); println(fontList); //helptextLabel helpFont = createFont("Georgia",20, true); mainFont = createFont("Georgia",20, true); newRound(); } void setPoints(){ a[0]=0; a0=a[0]; for (i=1;i<4;i++) a[i]=(int)Math.floor(2*t*Math.random()); } //test returns true, if b is on the semi-circle starting at a boolean test(int a, int b) { return (b-a+360) % 360 <= 180; } void newRound() { setPoints(); ok=false; state=0; } void processRound() { if (state==0) // hit test underway { if (!(test(a[0],a[1])&&test(a[0],a[2])&&test(a[0],a[3]))) { // if not a hit yet, increment semi-circle location a[0]=(a[0]+incr)%360; } else { ok=true; // we have a semi-circle with a hit state=1; } if (a[0]==a0) { // one round without any "OK" --> "NO HIT" state=1; } } else if (state==1) // hit test just ready { count++; if (ok) hit++; hitrate = (float)hit/count; println("ok = " + ok + ", count=" + count + ", hit="+hit + " (" + (hitrate*100) + "%)"); mil=millis(); // start the timer state=2; } else if (state==2) // hit test longer ready { if (contMode) { // if continuous mode: sleep a while, then start next round if (millis()>mil + 1000) // equivalent to former delay(1000); newRound(); } } // state } void draw() { processRound(); x0=height/2; y0=height/2; background(150); // light gray background noFill(); stroke(fg2); ellipse(x0, y0, 2*r, 2*r); strokeWeight(7); arc(x0,y0,2*r,2*r,a[0]*PI/t,a[0]*PI/t+PI); // the semi-circle fill(fg1); strokeWeight(1); for (i=1;i<4;i++) ellipse(x0+r*cos(PI/t*a[i]), y0+r*sin(PI/t*a[i]),2*dr,2*dr); drawText(); } void drawText() { textAlign(RIGHT); fill(40); // text color dark grey textFont(mainFont); if (count>0) { text("hits: "+hit, 300,160); text("trials: "+count, 300,180); text("hit rate: "+nf(hitrate*100,3,1)+"%", 300, 200); } if (state>0) { if (ok) text("OK",300,140); else text("NO HIT",300,140); } if (showHelp) { textFont(helpFont); text(": new round",300,20); text("c: continuous mode",300,20+18); text("h: toggle help",300,20+2*18); text(": exit",300,20+3*18); } } void keyPressed() { switch(key) { case ESC: exit(); break; case ' ': if (state>0) newRound(); break; case 'c': contMode = !contMode; break; case 'h': showHelp = !showHelp; break; } }