CS60 Mid-Term Solutions, Fall 1994 #1: find_node([], T) => T. %% [] addresses the whole tree find_node([A | X], T) => find_node(X, select(A, T)). %% address Ath subtree select(0, [A | L]) => A. %% select subtree select(N+1, [_ | L]) => select(N, L). ----------------------------------------------------------------------------- #2: find_address(Node, Node) => []. %% Thing to be found *is* the tree find_address(Node, X) => %% Atomic tree didn't match search argument atomic(X)? 0. find_address(Node, []) => 0. %% failed to find node find_address(Node, Tree) => find_address(Node, Tree, 0). %% 3-argument function, third argument is accumulator find_address(_Node, [], _Offset) => 0. %% failed to find node, empty tree find_address(Node, [A | X], Offset) => D = find_address(Node, A), %% try to find in A D == 0 ? find_address(Node, X, Offset+1) %% If not found, try in X : [Offset | D]. %% If found, use A's offset in address ----------------------------------------------------------------------------- #3: Grammar: (using the clarification that there must be at least one domain) S is the start symbol L is a list of domains separated by .'s, starting with a . U is a non-empty list of letters A is a letter S -> U @ U . U L L -> . U L | empty U -> A M M -> A M | empty A -> a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z Syntax diagram: S: ----> U ----> @ ----> U ----> . ----> U --------> ^ | | | ------------------ U: -----> A -----> ^ | A: -----> a -----> | | ^ | -------- |<-- b ---| etc. ----------------------------------------------------------------------------- #4: U() is the unit parser from unicalc // Effectively S -> U @ U . U (. U)* parse S() { parse u; list result = NIL; u = U(); if( failed(u) ) return failure; result = cons(u, result); if( !match('@') ) return failure; u = U(); if( failed(u) ) return failure; result = cons(u, result); if( !match('.') ) return failure; u = U(); if( failed(u) ) return failure; result = cons(u, result); char c; while( cin.good() && match('.') ) { u = U(); if( failed(u) ) return failure; result = cons(u, result); } return result; } ----------------------------------------------------------------------------- #5 Use an array of lists. The array indices correspond to rows. The lists contain cells, where each in the list is a column index and a coefficient value. Only non-zero coefficients are stored. Coefficients that are zero are implicit by knowing the size of the array. For example, for the coefficient array 0 1.0 0 0 1.0 0 0 0 0 1.0 0 1.0 0 0 1.0 0 we would have the following structure: row _______ __________ 0 | ---|---->| null | < pointer to next element | | | 1 | < column index | | | 1.0 | < coefficient value | | |__________| |_______| ___________ 1 | ---|---->| null | | | | 0 | | | | 1.0 | | | |__________| |_______| ___________ ___________ 2 | ---|---->| ---|---->| null | | | | 1 | | 3 | | | | 1.0 | | 1.0 | | | |__________| |___________| |_______| ___________ 3 | ---|---->| null | | | | 2 | | | | 1.0 | | | |__________| |_______| The declarations would be: struct coefficient // type of coefficient cell { long column; double value; coefficient *next; }; coefficient **a; // type of array of pointers to cells