CSC323 2010S, Class 12: Tools: Project Management with Make Overview: * Use Cases: iSimGrinL. * Beautiful Code: Bentley. * Beautiful Code: Subversion's Delta Trees. * About Make. * Hands-on Make. Admin: * Reading for Tuesday: BC 32 (Code in Motion). * It looks like we won't have time for everything I have planned today. Expect the Make stuff to turn into an assignment that we will discuss on Tuesday. * EC for the StatsGames talk today. * EC for CS Table tomorrow. Project Consideration: Use Cases * Narrate * Discuss * Repeat * Choose overall structure Use Case one: Grinellmonsters * Eight use cases + Create + Battle/Argue + Train + New attacks (e.g., postmodernism) + Breed + Apply objects to + Revive (Lyle's) + Morph (first year to second year and beyond) * Create a creature + System presents list of types of creates + User selects a type of creature to create + Choose useless attributes, like name and color + System shows a list of skills + Side path: User can 'redraw' + User confirms creation of creature Use Case two: * Note: A simulated version of Grinnell * Use case for creation of a student + Series of lists of attributes + User selects + User enters height and weight + System computes alcohol tolerance and eating disorders and other disorders + System displays options for gender orientation + User selects + System displays options for major and academic interest + User selects + System displays options for lifestyle + User selects + System updates characteristics such as need for sleep or requirements to participate in certain activities Use case three: Battle Royale, Grinnell style * Everyone tries to kill each other; a most one person survives * Use case: Getting started + User signs in [Sam notes that we'll need to write a client and server] + Scrape Stalkerbook/Facenet for pictures + System places them in starting place (e.g., dorm) + System gives them random weapons (spoon, chainsaw, RKO's red swimsuit, etc.) + Start "wander around Grinnell" use case * Use case: Encouter + TBD Use case four: R King O * A turn-based game in which president makes admin. decisions; we do a semester at a time * Use case: User ends term + User clicks "Next semester" button + Net expenses removed, net income added to coffers + Effects of policies on size and happiness of population are calculated (E.g., raise in professor pay raises professor happiness) (E.g., raise in tuition decreases student happiness) + Generate random events (hate crime, student granted award, faculty petition, resignation, etc.) + Time advances to next semester + Iconic and textual description of problem to address - If user clicks on icon, gets more detailed information - User clicks on back button + User clicks "Continue" button + User returns to "Main Game Play" screen Model five: iSimGrinL * Four kinds of characters: Student, Professor, Animal, Other * Accumulate "action points" * Initial characteristics/stats * Can use action points to do activities that increase points * Ranking system keeps track of who has the highest score, but it's not possible to tell what score/stats someone has * Messaging system between players * Potential ladder system (it is March, after all) * Accumulate other abilities Model six: iSimGrinL * Assumption: We create students (name, age, class year, GPA, etc.) * Each user has a sidekick, which is an animal * Select attack moves * Users wander around - Users and their animals fight * At the end of the semester, points get totaled Next model: * Start a game or join a game * Use case: Start a game * Create a situation in which students, faculty, animals cohabit naturally * Use case: Join a gain * Disrupt the situation by creating No Limits or Outtakes or Ultimate * Aren't permitted to see the settings of the situation Next model: The Game of Life * Use case: Make a grid * Player selects width and height * Player selects cells + Individually + From a preset group of templates * Use case: Create rules * Use case: Make template * Use case: Competition * Make a grid (see use case) * Connect to server * Server pairs players (or groups of players) * Server merges grids * Each round + Player can make one "move" (see use case) + System updates + System checks for winners * System reports winner Next model: Alter Ego * Whoops .. less coding, more writing Next model: Life with Grinnell characteristics * Different kinds of cell contents that represent the different kinds of things we have on campus: * Fixed things, like ice or buildings * "Live" things, like scholars, students, staff, and squirrels * Ideas: The things that live, propagate, die (age?) Choose a version of the project: * Pocket Grinnelians - 8 * Narrative scenario - 2 * Battle Russell - 1 * Russell for a day - 3 * Competitively narrative Grinnell - 2 * Make PETA mad - 0 * Gadfly! Destabilize the system - 2 * The Game of Life, or some variant thereof - 8 * Sam's Stupid Scenario - 6 Three choices left * Pocket Grinnelians * Anti: * Making it a fun game will require tedious busywork in balancing details * Pro: * We could build a framework as well as the tedious busywork * Some GUI work, but that doubles your work * Accessible to non CS/math geeks * Thoughts: * We want something we can play! * The Game of Life, or Sam's stupid variant thereof * Anti: * There are approximately 23,011 life simulators available on the Web * Doesn't seem to have natural subclassing; that may be similar tedious busywork * Pro: * Need to process large grids efficiently. * Rule sets might be subclassing. * Template system could use subclassing. * Some GUI work * Thoughts: * Ooh, Pretty colors * Sam's Stupid Scenario * Anti: * Also likely to have tedious busywork to make it fun. * Pro: * Some GUI work * Thoughts: HAPPY BIRTHDAY UNNAMED STUDENT. YOU MUST SING YOUR OWN BIRTHDAY SONG. The Most Beautiful Code that Jon Bentley Never Wrote * Initially, we have Quicksort, in a wicked compact version * Key ideas in Quicksort * Divide and conquer * Randomness is your friend * In-place sorting * Unstable void quicksort (int l, int u) { int i, m if (l >= u) return; swap (l, randint (l, u)); m - l for (i = l+1, i <=u; i++) { if (x[i] < x[l]) { swap (++m, i); } // if } // for swap(l, m); quicksort (l, m-1); quicksort (m+1, u); } What do you choose as the pivot? * In this case, a random element of the array * Easier to analyze * Some folks choose median of (x[l], x[u], x[(l+u)/2]) * Likely to be closer to the actual median of the values in the array * In practice, both have the same asymptotic behavior, and only slightly different constant multipliers Goal: To experimentally analyze the average case of Quicksort. (In terms of number of comparisons.) Example 3-2: The first version * Adds a comps++ before the comparison, which lets us count the number of comparisons for (i = l+1; i <=u; i++) { comps++; if (x[i] < x[l]) swap (++m, i); } Example 3-3: Move code out of the inner loop (good coding practice) comps += (u-l); for (i = l+1; i <=u; i++) { if (x[i] < x[l]) swap (++m, i); } Example 3-4: Notes that comparisons are no longer necessary for the actual counting void quickcount(int l, int u) { ... comps += (u-l); quickcount (l, m-1); quickcount (m+1, u); } Example 3-5: Remove lower bounds and upper bounds, since all that matters in the computation is the size of the array void qc(int n) { ... comps += n-1; qc(m-1); qc(n-m); } Example 3-6: Return the count, rather than using a global variables int cc(int n) { ... return n-1 + cc(m-1) + cc(n-m); } Example 3-7: Given an array of size n, find the average number of comparisons required to sort the array of size n. float c(int n) { if (n <= 1) return 0; sum = 0; for (m = 1; m <= n; m++) sum += n-1 + c(m-1) + c(n-m); return sum/n; } * Note: Sam would use for (m = 0; i < n; m++) Example 3-8: Apply Dynamic Programming * If you find yourself computing values for an integer-parameter pure function, it's often useful to cache those values in an array * Makes it much more efficient: From O(3^n) to O(n^2) t[0] = 0; for (n = 0; n <= N; n++) c(n); float c(int n) { if (n <= 1) return 0; sum = 0; for (m = 1; m <= n; m++) sum += n-1 + t[m-1] + t[n-m]; t[n] = sum/n; } Example 3-9: Move code out of inner loop float c(int n) { if (n <= 1) return 0; sum = 0; for (m = 1; m <= n; m++) sum += t[m-1] + t[n-m]; t[n] = n-1 + sum/n; } Example 3-10: Take advantage of symmetry t[0] = 0; for (n = 1; n <= N; n++) { sum = 0; for (i = 0; i < n; i++) { sum += 2 * t[i]; } t[n] = n-1 + sum/n; } Example 3-11: Close look at the code reveals a better way to do the inner loop t[0] = 0; sum = 0; for (n = 1; n <= N; n++) { sum += 2*t[n-1] t[n] = n-1 + sum/n; } Example 3-12: Final Version * Dynamic programming strategy: If the only thing you depend upon is the previous value in the cached array, you can subsitute a single variable t = 0; sum = 0; for (n = 1; n <= N; n++) { sum += 2*t t = n-1 + sum/n; } Okay, what's with all the math? * It's a straightforward translation of the code What was beautiful to you? * Short code that does a lot. (Only comprehensible with twenty pages of text, but ...) * Inspirational quotes/aphorisms * Carefully laid out progression * Important tips for code design: + Move stuff out of loops + Use dynamic programming + Repeatedly try to improve your code + Sometimes try to solve a harder problem What was ugly? * It's C; raw C with no comments can be hard to understand. * It may be pseudo-C, but it's close enough to real C to share C's terseness * Lowercase l is a hideous variable, at least in this font. * n <= N * Sudden jumps * Global variables (x, count, etc.) What lessons did you learn? * See above.