1 / 22

Applied Algorithms

Applied Algorithms. Lecture #2 Overall program structure, Representing graphs, finding bugs. Solution to the 3n+1 problem. /* The 3n+1 problem */ #include<stdio.h> /* Given a number, return the next number in the sequence */ int formula (int x)

livingstonm
Download Presentation

Applied Algorithms

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Applied Algorithms Lecture #2 Overall program structure, Representing graphs, finding bugs

  2. Solution to the 3n+1 problem /* The 3n+1 problem */ #include<stdio.h> /* Given a number, return the next number in the sequence */ int formula (int x) { return ( ((x % 2) == 0) ? (x / 2) : ((3*x)+1) ); } /* Find the length of a sequence starting at "x" */ /* tests: onecycle(1,1) = 4 onecycle(2,1) = 2 */ int onecycle(int x,int count) { int next; next = formula(x); while (next != 1) { next = formula(next); count = count + 1; } return count+1; } Use conditional expression, its short and clear Include tests when their might be some ambiguity

  3. Document assumptions /* do many cycles, 1 for each number between "i" and "j“ Assume “i <= j”, and "big" is the longest cycle found so far */ int manycycles (int i, int j, int big) { int candidate; while ( i <= j ) { candidate = onecycle(i,1); if (candidate > big) big = candidate; i = i+1; } return big; } /* find the longest cycle between "n" and "m" and print the result */ void oneline (int n, int m) { int i; int j; int big; if (n <= m) { i = n; j = m; } /* make sure i <= j */ else { i = m; j = n; }; big = manycycles(i,j,1); printf("%ld %ld %ld\n",n,m,big); } int main () { int n; int m; while ( scanf("%ld %ld",&n, &m) != EOF ) oneline(n,m); return 0; } Use meaningful variable names Use clear logic, and comments to annotate strange code Break program up into clear units with single purpose Main should only have the toplevel structure

  4. Goals in program design • Simplicity • Small size • Clarity • Structure • Elegance

  5. Solution to the Family Tree Problem /* potential family trees */ #include<stdio.h> #define TRUE 1 #define FALSE 0 typedef int Bool; typedef int Status; Status M = 0; /* mother */ Status F = 1; /* father */ Status Un = 2; /* unknown */ /* --------------------------------------------------------*/ /* Arrays or tables that store information about the trees */ Status assignment[15]; int parentCount[15]; int parent1[15]; int parent2[15]; Use logical names, and define new types to clarify how the data is being used. Declare logically related data structures together so the reader can get the big picture.

  6. Write initialization and input functions to logically separate the different phases of the program /* --------------------------------------------------- */ /* initialize and reading the tables */ void initTables() { int i; for (i=1;i<=14;i++) { assignment [i] = Un; parentCount[i] =0; parent1[i] =(-1); parent2[i] =(-1); }} void readTables(int i) { int parent; int child; int n; scanf("%ld %ld",&parent,&child); n = parentCount[child]; parentCount[child] = (n+1); switch(n) { case 0: parent1[child]= parent; break; case 1: parent2[child]= parent; break; default: break; }} Use sentinel data to indicate out of bounds or impossible cases Use switch statements for n-way branches on unstructured data. Don’t forget the “break”s

  7. If a function is the “key” or “workhorse” for solving a problem, say so. Use comments to describe its role. // ----------------------------------------------------------------- // The key function that given the two parents of a node // determines if they are unknown, consistent, or inconsistent // if one parents' status is unknown, but can be updated to remain // consistent, then that update is made. Bool updateStatus(int parent1, int parent2) { Status status1,status2; status1 = assignment[parent1]; status2 = assignment[parent2]; if (status1==Un && status2==Un) return TRUE; else if (status1==Un && status2==M ) {assignment[parent1]=F; return TRUE;} else if (status1==Un && status2==F ) {assignment[parent1]=M; return TRUE;} else if (status1==M && status2==Un) {assignment[parent2]=F; return TRUE;} else if (status1==F && status2==Un) {assignment[parent2]=M; return TRUE;} else if (status1==F && status2==M ) return TRUE; else if (status1==M && status2==F ) return TRUE; else if (status1==M && status2==M ) return FALSE; else if (status1==F && status2==F ) return FALSE; } Use white space and indentation to layout programs so programs with regular structure appear that way. It makes it easier to see the pattern, to be sure coverage is exhaustive and to find bugs.

  8. /* -------------------------------------------------------- */ /* for each node in the tables, update that nodes status */ Bool updateTableEntries(int low, int high) { int i; int count; int p1; int p2; for (i=low;i<=high;i++) { count = parentCount[i]; p1 = parent1[i]; p2 = parent2[i]; /* failure at any node causes the loop to exit an */ /* the whole function to return FALSE */ switch(count) { case 0: break; case 2: { if (updateStatus(p1,p2) != TRUE) return FALSE; else break; } default: return FALSE; } } } Give names to important intermediate results Use return and break for unusual control flow. Document unusual control flow

  9. /* ------------------------------------------------------------ */ /* Read the status of the "n"th node, if it is unknown then */ /* choose an assignment for it. Then make all other nodes */ /* consistent with this choice. */ Bool makeNthAssignment(int i, int j, int n) { Status st; st = assignment[n]; if (st==Un) assignment[n] = F; return updateTableEntries(i,j); } int main() { int nodes; int edges; int i; int j; Bool valid; while (scanf("%ld %ld",&nodes,&edges) != EOF) { initTables(); for (i=1;i<=edges;i++) readTables(i); valid = TRUE; /* break out of loop is any assignment fails */ for (j=1;j<=nodes && valid;j++) valid = makeNthAssignment(1,nodes,j); if (valid) printf("valid\n\n"); else printf("invalid\n\n"); } } Document unusual control flow Main should only have the toplevel structure

  10. Writing Contest Programs • In Contest problems, speed is often important. • To get started write away, imagine the top-level structure. • Write main first, and call stubs to get started. • Write a input data file, and test that main processes it correctly.

  11. Define, and use stubs to get started int main () { int n; int m; while ( scanf("%ld %ld",&n, &m) != EOF ) oneline(n,m); return 0; } int main() { int nodes; int edges; int i; int j; Bool valid; while (scanf("%ld %ld",&nodes,&edges) != EOF) { initTables(); for (i=1;i<=edges;i++) readTables(i); valid = TRUE; for (j=1;j<=nodes && valid;j++) valid = makeNthAssignment(1,nodes,j); if (valid) printf("valid\n\n"); else printf("invalid\n\n"); } }

  12. Representing Graphs • Graphs are ubiquitous, they appear in many problems. • Best to have some canned strategies for thinking about graphs. • Separate in your mind the logical descriptions of graphs, form the physical representations • Functions • Arrays • Matrices • Pointers

  13. a b c d Graphs: • A graph is a pair (V,E) where • V is a set of vertices; • E is a set of edges {u,v}, where u,v are distinct vertices from V. • For example: • G = ({a,b,c,d}, {{a,b}, {a,c}, {a,d}, {b,d}}) • Examples: computer networks, street layout, etc…

  14. Variations: • There are many variations on this theme. For example, in some cases we may want to allow: • Self loops {v,v}; • Multiple edges between two vertices (multigraphs); • Labels attached to vertices by a function V  A; • Labels attached to edges by a function E  B; • Hyperedges that connect multiple vertices (hypergraphs); • etc…

  15. Representing graphs: • Function: Define a function that when applied to vertex v, returns a set of children (or a set of parents). Each child is a node where (v,c) is in the set of edges. • Adjacency list: for each vertex v, we store a linked list of the vertices u that it connects to by a single edge. • Adjacency matrix: a two dimensional array g[i][j]. An entry of 1 means that there is an edge between vertices i and j. • Pointers: actually construct a heap object where edges are implemented by pointers

  16. a b c d Adjacency matrix representation: • A simple example: • Uses O(|V|2) space, much of which will be wasted if the graph is sparse (i.e., relatively few edges). • Easily adapted to store information about each edge in the entries of the matrix. • Alternatively, if all we need is 0/1, then a single bit will do!

  17. a b c d 0 b a d 0 c a 0 d a b 0 a b c d Adjacency list representation • A simple example: • Uses O(|V|+|E|) space, good for sparse graphs, more expensive for dense case (i.e., many edges). • Easily adapted to store information about each edge in each part of the linked lists. • Testing to see if there is an edge (u,v) is not O(1); we must search the adjacency list of u for v.

  18. a b c d Function representation • Best when we have directed graphs. I.e. edges have an orientation. • A simple example: list graph(node x) { if (node==a) return [b,c,d] else if (node==b) return [d] else if (node==c) return [] else if (node==d) return [] else return [] }

  19. c d a b 3 ? ? d 1 b ? c 1 0 ? 0 ? ? d ? a b c d Arrays • When a graph has fixed in-degree (or out degree) the function representation has an especially nice implementation as a set of parallel arrays. list graph(node x) { if (node==a) return [b,c,d] else if (node==b) return [d] else if (node==c) return [] else if (node==d) return [] else return [] } int count [5] node child1 [5] node child2 [5] node child3 [5]

  20. Bug search • Go to the home page • http://www.cs.pdx.edu/~sheard/course/appliedalg • Under “Lecture Notes”, under today’s lecture “Lecture 2” is a clickable link that leads to a file with a solution to the 3n+1 problem, with a bug. • Upload the file. • Find and fix the bug.

  21. In Class Problem • Minesweeper • Page 16 of the text • Keeping in mind the rules we discussed in class, break into teams of two, and solve the problem. • Pick a different partner than you used last time. • Use pair programming. One person “drives” the other observes.

  22. Today’s Assignments Read for next time Chapter 2 of the text. pp 27-55 Be prepared to answer questions in class next Friday from the reading. Programming assignment 1.6.7 Check the Check Page 23-24 Write a solution Submit your solution (until you get it right) Hand in both your program, and the judge output. Those who volunteer to discuss their program get class participation points. Email me solutions before noon on Friday, April 15.

More Related