"Searching Algorithms / Binary Trees" for QB Express #24 Written by Dean Menezes Let's say you have a guess the number program where the computer tries to find the human's number (pseudo-code): FOR i = 1 TO 31 ask the user if their number is i if their number is i, print "I got it in"; i; "guesses"; end end if NEXT Clearly, if the user's number is N, the program will take N guesses to arrive at this result (max of 31 guesses). See if you can make a more efficient algorithm. 16 8 24 4 12 20 28 / \ / \ / \ / \ 2 6 10 14 18 22 26 30 /\ /\ /\ /\ /\ /\ /\ /\ 1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 More efficient algorithm using binary tree: 1. Start at the top of the binary tree 2. Ask the user if their number is (current number) 3. If their number is the current number then stop 4. Else, ask them if their number is higher or lower than the current number 5. If higher, go right on the tree. If lower, go left on the tree. 6. Go to step 2 This will need a maximum of 5 guesses, making it much more efficent than the first method. Here is an implementation of QBASIC: DECLARE SUB logic (low!, high!, numturns!) CLS PRINT "Think of an integer x such that 1 "; CHR$(243); " x "; CHR$(243); " 31" PRINT "Press any key when ready." WHILE INKEY$ = "" 'Dummy press any key routine WEND CALL logic(1, 31, 0) SUB logic (low, high, numturns) num = (low + high) / 2 DO PRINT "Is your number"; num INPUT answer$ IF UCASE$(LEFT$(answer$, 1)) = "Y" THEN PRINT "I got it in"; numturns; "turns": EXIT SUB IF UCASE$(LEFT$(answer$, 1)) = "N" THEN EXIT DO PRINT "Please answer the question." LOOP DO PRINT "Is your number higher or lower than"; num INPUT answer$ IF UCASE$(LEFT$(answer$, 1)) = "H" THEN CALL logic(num + 1, high, numturns + 1): EXIT SUB IF UCASE$(LEFT$(answer$, 1)) = "L" THEN CALL logic(low, num - 1, numturns + 1): EXIT SUB PRINT "Please answer the question." LOOP END SUB Here is another example of where a binary tree could make a program more efficient. INPUT "num? ", num INPUT "accuracy? ", acc FOR i = 0 TO num STEP acc IF i * i >= num THEN PRINT i: END NEXT This is a program to find the square root of a number to a certain accuracy. It does this by increminting a variable until the varialbe squared is greater than the number. Can you write a faster version of this program? Here is the fast version: INPUT "num? ", num INPUT "accuracy? ", acc g1 = 1 DO g2 = num / g1 IF ABS(g2 - g1) < acc THEN PRINT "val is between"; g1; "and"; g2: END g1 = (g1 + g2) / 2 LOOP Here's how the fast program works: 1. it starts out with this range: 0 ......... n 2. then is gets an initial guess (always picks 1 in example). the range is now g0 .... 1/g0 3. then it picks the average of the two bounds as the new guess g1 .. 1/g1 4. it repeats step 3 until the range is within the desired accuracy (small range = more accurate).