Homework project for Coursera.org course Programming and the Web for Beginners | www.bit.ly/HowToCreateRandomPuzzlePages Please note: This is a page in process. It is not complete (Suggestions are warmly welcomed) |
The average age of three boys is 15 years. If their ages are in the ratio 3:5:7, what is the age of the youngest boy?
There are ____ people at a _________ meeting.
Except for the youngest and the oldest, they all love ______ puzzles.
Their average age is fifteen.
Their ages have the relative ratio: __________.
How old are the two members who will not solve this puzzle?As you can see, all the blanks can contain random information. In addition, all sentences can have variations if desired.
I learned FORTRAN in 1969, and later learned COBOL, RPG and other languages, but I've been thinking in the old DOS-style BASIC since 1977. I've even dreamed about writing programs, even writing a four-dimensional maze program during a dream one night in the 1980's. (I got up, used that dreamt logic to create a 3D maze, and it worked in real life. Later, I did write the 4D version.) This paragraph is meant to help the reader realize that I took the Coursera course in order to learn Javascript. I already knew BASIC.When I decided to use this for my Coursera project, I stole a puzzle from a friend of mine (with permission) and wrote a QB64.net program to randomly create a few puzzles, to see how it worked. This process will will help me when I get to the point of rewriting the program in Javascript, because I'll already know the logic works. P> The process I went through to write that program is similar to the process you would use to write a program in Javascript, so let's outline the process of writing a program to create the puzzle above. NOTE that my original list of tasks was shorter, but as I tested the program, I found errors I needed to look out for.
Here is the updated QB64 program that includes all of the above:
'COMMENT: (For best readability, expand your page width so that these two comment lines (with all the dashes --------------) '-------: -----------------: appear full width, the indenting and program comments will be much easier to read as a result.) ' DEFINT A-S ' All variables that start with A thru S are integers DEFSTR T-Z ' All variables that start with T thru Z are strings SCREEN _NEWIMAGE(1920, 1080, 256) ' set SCREEN to half of maximum 2880x1630 resolution RANDOMIZE TIMER ' This uses seconds since midnight to randomize the random number generator DIM age(9), ratio(9) ' define arrays to hold random values ' Next 3 lines are the DATA that is used by FUNCTION RandomW$ to pick random info to include in program zg = "TNS,Triple 9 Society,Intertel,OATHS,One in 1000 Society,TOPS,Top One % Society,Brain Society,Mensa," zp = "Math,Number,Arithmetic,Maths,Mathematical,Arithmetical,Algebra,Algebraical,Numeric," zr = "Pizza Hut,Subway,Dominos,Wendys,McDonalds,Sonic,Shoneys,Dennys,Central Park,Burger King,Hardees," group = 0 ' First "group" is random. Choose specific group number with 1-9 after answer DO ' DO all code until we press ESCape after seeing the answers bc = INT(RND * 3) * 8 + 24 ' Random function returns 24, 32 (blue) or 40 (red) background color IF bc < 30 THEN bc = 9 ' Change 24 to 9 (blue) background color (all reasonable dark choices) fc = INT(RND * 6) + 10 ' Random foreground color (all reasonable bright choices) COLOR fc, bc ' set foreground and background colors as randomly generated zGroup = RandomW$(zg, group) ' Pick a random group name (might not be in every puzzle generated) zPlace = RandomW$(zr, 0) ' Pick a random eating place (might not be in every puzzle generated) zPtype = RandomW$(zp, 0) ' Pick a random type of puzzle CLS ' Clear Screen, entire screen white DO ' DO all following statements WHILE final statements are true REDIM k(999) ' reDIM array that checks for too many of one age n = INT(RND * 7) + 3 ' How many people in the group zCount = CountWord$(n) ' Get word to use for number of people in puzzle DO: gcf = INT(RND * 4) + 2 ' Greatest Common Factor of their ages LOOP WHILE GCFactor(n, gcf) > 1 ' Do not allow the number of people and the GCF to share a common factor min = INT(RND * 9 + 5) ' Minimum age in group sum = 0 ' sum for calculating average later FOR a = 1 TO n - 1 ' generate ages for all except one person g = INT(min / gcf) * gcf + INT(RND * 9) ' start with the ratio of their ages ratio(a) = g ' and store that value as an individual ratio g = g * gcf: age(a) = g ' then multiply by the GCF to get the person's age sum = sum + age(a): 'PRINT age(a); ' add up the ages (PRINT was used during debugging to see all tries) NEXT ' do this for all 'N' people g = (sum + n) MOD n ' this is minimum possible age for last person in room WHILE g < min OR g MOD gcf ' WHILE that age is invalid g = g + n ' keep adding 'N' to that age until that age is divisible by 'GCF' WEND ' WEND: This is why we did not let 'N' and 'GCF' have a common factor age(n) = g: ratio(n) = g \ gcf ' store that last age and ratio into their arrays sum = sum + g: avg = sum / n ' and calculate the average age 'PRINT age(n); ":"; sum; avg; gcf ' (PRINT used during debugging to see calculated last age, sum, etc. z = "": EC = 0 ' Set up string to remember the relative ratios, and check for errors FOR i = 1 TO n ' FOR every person in the group FOR j = i + 1 TO n ' FOR every other other person in the group IF ratio(i) > ratio(j) THEN ' IF their ages are out of order SWAP ratio(i), ratio(j) ' SWAP the ratios SWAP age(i), age(j) ' SWAP the ages END IF ' end of IF block NEXT ' NEXT - at end of this loop, person 'I' has the correct age values g = age(i) ' this statement saves a few bytes of memory k(g) = k(g) + 1 ' Count how many of each age is in the sorted array IF k(g) > 2 THEN EC = 1 ' If there are more than 2 people of one age, generate an error code z = z + ":" + LTRIM$(STR$(ratio(i))) ' This string contains all the ratio values for later display NEXT ' NEXT 'this loop finishes work for sorting ages into order LOOP WHILE age(n) > 99 OR sum MOD n OR EC ' LOOP until no centennarians, average is valid, & there are no errors ' PROBLEM || Display puzzle including zGroup (group name), zPtype (Puz Type), PRINT ' PUZZLE || zPlace (restaurant/place), zCount (# of people), z (ratio) with ' PRINT || three different types of situation (meeting, lunch, dinner) ' SECTION || and three different questions that mean the same thing; and ' || give credit to the Coursera Homework development page: ptb = 40 tb = " º" + SPACE$(ptb - 3) + "º" PRINT " É"; STRING$(ptb - 3, 205); "»" ' 'Mathematical, 'Central Park, IF RND < .334 THEN PRINT " º There are "; zCount; " people at a"; TAB(ptb); "º" ' There are three people at a PRINT " º "; zGroup; " meeting."; TAB(ptb); "º" ' One in 1000 Society meeting. ELSE IF RND < .5 AND LEN(zGroup) < 12 AND LEN(zPlace) < 9 THEN PRINT " º "; Cap$(zCount); " "; zGroup; " members"; TAB(ptb); "º" ' Three One in 1000 Society members PRINT " º met at "; zPlace; " for lunch."; TAB(ptb); "º" ' met at Central Park for lunch. ELSE PRINT " º "; Cap$(zCount); " friends met for lunch"; TAB(ptb); "º" ' Three friends met for lunch PRINT " º at "; zPlace; " today."; TAB(ptb); "º" ' at Central Park today. END IF END IF PRINT tb ' º 12345678901234567890123456789012345 º IF RND < .5 THEN PRINT " º Except for the youngest and oldest,"; TAB(ptb); "º" ' Except for the youngest and oldest PRINT " º they all love "; zPtype; " puzzles."; TAB(ptb); "º" ' they all love mathematical puzzles. ELSE PRINT " º The youngest and oldest members"; TAB(ptb); "º" ' The youngest and oldest members PRINT " º do not enjoy "; zPtype; " puzzles."; TAB(ptb); "º" ' do not enjoy mathematical puzzles. END IF PRINT tb PRINT " º Their average age is "; CountWord$(avg); "."; TAB(ptb); "º" ' Their average age is seventy-seven. PRINT tb IF RND < .5 THEN PRINT " º Their ages have the relative ratio: º" ' Their ages have the relative ratio: ELSE PRINT " º The ratio between their ages is: º" ' The ratio between their ages is: PRINT " º "; z; TAB(ptb); "º" END IF PRINT tb SELECT CASE INT(RND * 3) CASE 0 PRINT " º How old are the two people who will º" PRINT " º just ask everyone their ages? º" CASE 1 PRINT " º What are the ages of the members º" PRINT " º who won't solve this puzzle? º" CASE 2 PRINT " º How old are the two people who are º" PRINT " º so woefully puzzle-challenged? º" END SELECT PRINT tb ' º 12345678901234567890123456789012345 º PRINT " º bit.ly/HowToCreateRandomPuzzlePages º" PRINT " ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ" PRINT INPUT$(1) ' Pause after displaying puzzle ' PRINT " Youngest:"; age(1); " Oldest:"; age(n) ' Display answers PRINT FOR i = 1 TO n: PRINT STR$(age(i));: NEXT ' Show all of the ages PRINT ": Sum"; sum; " GCF"; gcf ' Print sum and Greatest Common Factor z = INPUT$(1) ' Pause until (1-9 next group), (ESCape) or (any other key random group) group = VAL(z) ' If key pressed is 1-9, next puzzle will include group # that number LOOP UNTIL z = CHR$(27) ' LOOP: keep generating new puzzles until ESC pressed twice END ' END of main program FUNCTION GCFactor (a, b) FOR c = 1 TO a ' FOR every value of 'c' up to 'a' IF c * (a \ c) = a AND c * (b \ c) = b THEN d = c ' If A and B both divisible by C, then D is GCF of A and B NEXT ' NEXT value of c GCFactor = d ' RETURN the value of the greatest common factor END FUNCTION ' NOTE: If you initialize 'd=1' change FOR loop to '= 2 to a' FUNCTION CountWord$ (a) z = "one,two,three,four,five,six,seven,eight,nine,ten,eleven,twelve,thir,four,fif,six,seven,eigh,nine," y = "twenty ,thirty ,forty ,fifty ,sixty ,seventy,eighty ,ninety" w = "" ' W, the tens word, starts out blank IF a > 19 THEN ' If a ten word is required for 20-something, etc. w = RTRIM$(MID$(y, INT(a / 10) * 8 - 15, 7)) ' W now contains the ten word a = a MOD 10 ' A now contains only the unit digit IF a THEN w = w + "-" ' If A is not zero, add a dash to the tens word END IF ' End of TEN word IF block --> 'W' now contains ten word FOR i = 1 TO a ' FOR thru loop until we get to 'A' value (loop skipped if A=0) k = INSTR(z, ",") ' Look for comma inside 'Z' string x = LEFT$(z, k - 1) ' X is equal to the word before the comma z = MID$(z, k + 1) ' Remove that word from beginning of the 'Z' string NEXT ' NEXT until we get to A --> X now contains unit word (or ten-teen word) IF a > 12 THEN x = x + "teen" ' This line saved 32 characters of data at cost of less length of code.s CountWord$ = w + x ' RETURN the combined word for the original 'A' value END FUNCTION ' END of FUNCTION CALL