Você está na página 1de 9

CS 135 Fall 2012 Ali,Fraser,Goldberg,Hoey, Kaplan,Kogan,Petrick,Tompkins

Assignment: 10
Due: Tuesday, 27 November 2012, 9:00 pm Language level: Intermediate Student with lambda Allowed recursion: Pure structural, generative, or accumulative, except where otherwise
noted. Files to submit: skyscrapers.rkt, skyscrapers-bonus.rkt (bonus), curry.rkt (bonus) Warmup exercises: HtDP 28.1.6, 28.2.1, 30.1.1, 31.3.1, 31.3.3, 31.3.6, 32.3.1 Practise exercises: HtDP 28.1.4, 28.2.2, 28.2.3, 28.2.4, 31.3.7, 32.3.2, 32.3.3 A Skyscrapers puzzle is a variety of logic puzzle that has some features in common with its more popular cousin Sudoku. In the simplest form of the puzzle, we begin with an empty n n grid with numbers between 1 to n (the clues) written around the outside. Lets use this simple 4 4 puzzle as an example:

1 1 3 2 2 2

3 3 2 2 1

The goal is to ll in every space in the grid with a number from 1 to n so that they satisfy three conditions: Every number appears exactly once in each row; Every number appears exactly once in each column; and If a number k in the grid is converted into a tower of height k , then a clue on the outside of the grid corresponds to the number of towers visible from that location along that row or column.

CS 135 Fall 2012

Assignment 10

The nal condition is what gives Skyscrapers its name, and it deserves a bit more explanation. Imagine standing on one of the clues around the outside of the grid, looking in along the row or column at the towers mentioned above. A tower of height k will shadow all towers of height less than k that are placed beyond it in the grid. The visibility number at any point along the outside of the grid is the number of towers that arent shadowed when looking in from that point along a row or column. Every row has two visibility numbers: one when read from the left, and one when read from right. Here is an example of a row of ve towers with heights (4 2 1 5 3), with visibility number 2 when viewed from either end.

Similarly, every column has two visibility numbers. A lled-in grid is a correct solution when, in addition to the rst two Sudoku-like conditions above, the clues are the correct visibility numbers for the lled-in tower heights. So, for example, the top-left cell in the grid must contain a 4 (if it were 1, 2 or 3, then a 4 would have to occur later in the rst row, guaranteeing that the row would have a visibility number greater than 1 when viewed from the left). Similarly, the bottom-right cell must be 4. The bottom-left cell must then be 3, for if it were 1 or 2 then the bottom row would have visibility number greater than 2. And so on. Here is the same puzzle with the solution lled in. You can verify that it satises the conditions above.

1 1 3 2 2 4 2 1 3 2
CS 135 Fall 2012

3 1 3 4 2 2

2 3 4 2 1 3

3 2 1 3 4 1
2

3 2 2 1

Assignment 10

In this assignment you will write a Scheme program to solve Skyscrapers puzzles, based on the search-with-backtracking approach presented in Module 12 of the lecture notes (see in particular the material beginning on Slide 12-26). You are not required to be able to solve Skyscrapers puzzles by hand, but it doesnt hurt to try a few to build your intuition. You can nd an implementation of Skyscrapers in Simon Tathams Portable Puzzle Collection (http://www.chiark. greenend.org.uk/sgtatham/puzzles/)its called Towers there. Theres also a version at BrainBashers (http://www.brainbashers.com/skyscrapers.asp). In order to use the search-with-backtracking approach of Module 12 to move from an initially empty puzzle to a solved one (or to determine that no solution exists), we need a few data denitions to describe a state (a node in the implicit graph well be searching). ;; A Cell is a (union Nat[>0] ?) ;; A Grid is a (ne-listof (ne-listof Cell)) ;; A ClueSet is a (ne-listof Nat[>0]) (dene-struct state (grid left right top bottom)) ;; A State is a (make-state Grid ClueSet ClueSet ClueSet ClueSet) (Do not copy and paste these data denitions into an empty source le! We are providing you with skeleton code to get started; see the note about Template Code at the end of the required questions.) The intention is that a Grid is an n n grid represented as a list of n n-element lists. An element is either one of the numbers from 1 to n, or the symbol ? indicating that the given cell hasnt been lled in yet. The ClueSets are n-element lists representing the clues along the outside of the grid; the top and bottom ClueSets are read left-to-right, and the left and right ClueSets are read top-to-bottom. With that in mind, the initial and solved States of the sample puzzle are: (make-state ((? ? ? ?) (? ? ? ?) (? ? ? ?) (? ? ? ?)) (1 3 2 2) (3 2 2 1) (1 3 2 3) (2 2 3 1)) (make-state ((4 1 3 2) (2 3 4 1) (1 4 2 3) (3 2 1 4)) (1 3 2 2) (3 2 2 1) (1 3 2 3) (2 2 3 1))

The goal will be to construct an initial State (as in the example on the left), and use repeated applications of a neighbours function to discover a route from that starting point to a lled in puzzle. If no such route exists, then the puzzle is unsolvable. We will assume that a puzzle will have at most one solutionyou do not need to worry about multiple distinct solutions for the same set of clues. There are many ways to write an algorithm to solve Skyscrapers puzzles. In this assignment we will build up a solution in one particular way. When searching for the neighbours of a given State, CS 135 Fall 2012 Assignment 10 3

we nd the rst empty cell in the grid (i.e., the leftmost empty cell in the rst row that has any). We then produce a list of neighbouring states in which that cell has been lled with all possible legal values that do not obviously violate the rules for a completed puzzle. You must follow this approach in order to receive full marks, even if you have ideas for alternatives. The benet is that we can mark the individual parts of the solution, and award part marks even if you dont get everything working. With that in mind, you must solve the individual questions below. Place your solution in the le skyscrapers.rkt. 1. Write a Scheme function visibility-number that consumes a list of Cells. It produces a natural number corresponding to the lists visibility number, as dened above, when standing at the start of the list and looking towards the end. Any occurrences of ? can be ignored when computing visibility. For example, looking at the three-dimensional towers on Page 2, we would expect (visibility-number (4 2 1 5 3)) 2. On the other hand, (visibility-number (? 4 ? 5 6 ?)) 3. A list consisting entirely of blanks should have a visibility number of zero. (Hint: the simplest way to write this function is using accumulative recursion.) 2. Sometimes, it is possible to determine that a partially lled-in row or column cannot be completed in a way that satises the visibility clues at either end. For example, if a row currently contains (1 2 ? ?) then its left visibility number must be at least 3. If the clue on the rows left is 2, then we know weve reached a dead end in the search and should backtrack. Write a Scheme predicate feasible-visibility? that consumes two values: a list lov of Cells, and a visibility number vis. This predicate answers true if and only if there is at least one way to ll in the blanks in the list so that the result uses the numbers from 1 to n and has (left) visibility number vis, where n is the length of the list lov. Remember that the numerical elements of the list will be a subset of the numbers from 1 to n, with no duplicates. You should not solve this question by testing all possible ways to ll the empty spaces of lov with numbersthats far too inefcient. Instead, we will simplify this question by recognizing that according to our solving strategy, any lled-in numbers in lov will be in a contiguous block at the start or end of the list. In that case, the following simple approach will answer the question. Let n be the length of the list lov, and let S represent the set of numbers between 1 and n that do not currently appear in lov. Compute the maximum possible visibility number vmax by placing the elements of S in sorted order in the empty spaces of lov and using the visibility-number function dened previously. Similarly, compute the minimum possible visibility number vmin by placing the elements of S in reverse-sorted order. The row is still feasible as long as vmin vis vmax . 3. Write a Scheme predicate valid-state? that consumes a State and determines whether it is a legal intermediate state of a Skyscrapers puzzle, i.e., one that could still lead to a legal solution. You should check that every row has a feasible visibility (in the sense of the previous question) for the clues at its left and right ends; similarly, you should check every column against the clues at its top and bottom. Finally, you should verify that no row or column CS 135 Fall 2012 Assignment 10 4

contains any duplicated numbers. You can assume that the rows and columns all satisfy the condition of the previous question: the non-blank entries form continuous blocks at the starts or ends. 4. Write a Scheme predicate complete-state? that determines whether a given State represents a nished puzzle (i.e., a puzzle in which every spot in the grid has been lled in). You only need to check that the grid is full; you can assume that it doesnt break any of the rules of a legal solution. For full marks, your solution should be a one-liner a short function with no explicit recursion, no use of cond, and no use of user-dened helper functions. (Hint: use andmap twice.) 5. Write a Scheme function neighbours that consumes a State as input and produces a list of valid neighbouring states as output. Your implementation must use the following logic: Find the rst unlled cell in the grid (i.e., the leftmost empty cell in the topmost row that has empty cells). You can assume that neighbours will only be called on States that have at least one empty cell. Speculatively generate n candidate neighbouring States, one for each possible natural number that could be placed in the empty cell (assuming the puzzle is of size n n). Throw away the candidate States that do not pass the valid-state? test above. (Hint: use an abstract list function.) The list of remaining States are the neighbours of the input. You can produce them in any order. 6. 5% Bonus. If you tried out some of the puzzles on brainbashers.com, you will have noticed that they take a broader view of the starting point for Skyscrapers puzzles. In particular, they allow some of the clues to be left out, but they also sometimes provide a few of the initial values in the grid. Here, for example, is a 4 4 puzzle that is no less solvable than the one given at the start of this assignment:

2 1 3

1 2

CS 135 Fall 2012

Assignment 10

Adapt your solution above so that it can handle partial clue lists and partially lled-in grids. The rst part is easy: you must change the data denition for a ClueSet to allow blanks (represented via the symbol ?), and take those into account when checking the feasibility of a row or column. (Note that you do not need to change these ClueSets blank clues should remain blank, even in a solved puzzle.) Handling partially lled-in grids is much harder. We can no longer assume that feasible-visibility? needs to deal only with rows that are partially lled-in at the start or end; lled-in values can occur anywhere in the list. Its a challenge to check whether the list can be completed to achieve a given visibility number under these conditions, or at least to do so efciently. As above, you should not simply create a modied feasible-visibility? that tests all possible ways to ll the empty spaces of the passed-in list with numbers. To receive bonus marks you must use an efcient algorithm, where the meaning of efcient will be determined by the course staff. We suggest that you do not attempt this bonus question until you have completed the nonbonus part of the assignment to your satisfaction. If you do attempt it, keep it entirely distinct from your code in skyscrapers.rkt. Even if your bonus solution is capable of solving non-bonus puzzles, for Question 2 please submit a version of feasible-visibility? that follows the algorithm outlined there. For this bonus, create a new le skyscrapers-bonus.rkt with the extended code in it. You are welcome to re-use any portions of your non-bonus code that you want, in which case you should simply copy them into the new le. Template code: To help you get started, we are providing you with a skeleton version of the le skyscrapers.rkt. You will see that the data and structure denitions, contracts, purposes, examples, and function headers have been lled in. The function bodies are left as stubs, functions that do (almost) nothing. You must ll in the function bodies, making use of as many helper functions as you want (at the top level or within locals), and give each function an adequate number of tests. If you add any top-level helper functions, they need a complete design recipe too, of course. The le also contains a few test puzzles transcribed from the website and software mentioned earlier. You should test your code on these puzzles, together with additional puzzles that you transcribe (or construct) yourself. For this assignment you are permitted to use all forms of recursion discussed this term, and all regular and higher-order functions that are available in Intermediate Student with Lambda (including reverse). This concludes the list of questions for which you need to submit solutions. Dont forget to always check your email for public test results after making a submission.

7. 5% Bonus: Currying is an elegant method of creating functions that can be partially evaluated. Currying transforms a function of n parameters in a chain of nested functions each of one parameter. So, for example, we might imagine the following hypothetical sequence of interactions in Scheme: (dene (f x y) ( x (+ y 5))) CS 135 Fall 2012 Assignment 10 6

(dene curry-f (curry f )) (f 2 3) 16 (curry-f 2) (lambda (y) ( 2 (+ y 5))) ((curry-f 2) 3) 16 This question will explore two approximations of the curry function hinted at above. For this question you do not need to provide any parts of the design recipe apart from the denition. Place your solutions in the le curry.rkt. (a) Write a Scheme function curry-three that consumes a function of three arguments, and produces a curried version of the same function. So, for example, ((((curry-three substring) coffee) 1) 4) off. (b) Write a Scheme function curry-n that consumes two arguments: a natural number n greater than zero, and a function of n arguments. It should produce the curried equivalent of any function, as long as the required number of arguments are passed in. All of the following should work as examples: ((curry-n 1 string->number) 54) 54 (((curry-n 2 expt) 6) 2) 36 ((((curry-n 3 substring) scurrying) 1) 6) curry ((((curry-n 3 foldr) +) 0) (4 5 6 7)) 22 (((((curry-n 4 <) 1) 2) 3) 4) true You will want to use the built-in Scheme function apply to solve this problem, and probably also reverse. (Note: the need to specify the number of parameters of the passed-in function explicitly is annoyingit would be much nicer to be able to ask Scheme to tell you. If youre interested, you can look at the built-in function procedurearity, which is part of Racket but not any of the teaching languages. Dont use it here, but in theory it would allow you to write a more elegant solution.)

Enhancements: Reminderenhancements are for your interest and are not to be handed in. It is perhaps stretching to call what we are about to look at an articial intelligence application. It is a program which mimics a human psychologist in an extremely simple way. The idea comes from Joseph Weizenbaum, who wrote a similar program and reported on it in the January 1966 issue of Communications of the ACM. A typical interaction might look like this: eliza> human> eliza> human> eliza> Hello, how are you? I feel really tired today. Why do you feel really tired today? I stayed up all night doing CS 135. You stayed up all night doing CS 135? Assignment 10 7

CS 135 Fall 2012

human> eliza> human> eliza>

They make us work too hard. Can you be more specific? Assignment 8 was a killer. Tell me more about Assignment 8.

You can see how it wouldnt take a lot of processing to do this. In fact, we are going to do even less processing than Weizenbaums program, which remembered past interactions in a certain way and could bring up phrases from them. Our program will treat every input from the human in isolation. To avoid dealing with the complexities of parsing strings, we will assume the input and output are lists of symbols: > (eliza (I feel really tired today)) (Why do you feel really tired today) Were not going to bother with punctuation, either. Since this is an enhancement, you can put the ability to handle strings with punctuation instead of lists of symbols into your implementation if you wish. (To get output that uses quote notation, select Details in the Choose Language dialog, and choose quasiquote.) The key to writing an eliza procedure lies in patterns. The patterns we use in eliza allow the use of the question mark ? to indicate a match for any one symbol, and the asterisk to indicate a match for zero or more symbols. For example: (I ? you) matches (I love you) and (I hate you), but not (I really hate you). (I your ?) matches (I like your style) and (I really like your style), but not (I really like your coding style). We can talk about the parts of the text matched by the pattern; the asterisk in (I your ?) matches (really like) in the second example in the previous paragraph. Note that there are two different uses of the word match: a pattern can match a text, and an asterisk or question mark (these are called wildcards) in a pattern can match a sublist of a text. What to do with these matches? We can create rules that specify an output that depends on matches. For instance, we could create the rule (I your ?) (Why do you 1 my 2) which, when applied to the text (I really like your style), produces the text (Why do you really like my style). So eliza is a program which tries a bunch of patterns, each of which is the left-hand side of a rule, to nd a match; for the rst match it nds, it applies the right-hand side (which we can call a response) to create a text. Note that we cant use numbers in a response (because they refer to matches with the text) but we can use an asterisk or question mark; we cant use an asterisk or

CS 135 Fall 2012

Assignment 10

question mark in a pattern except as a wildcard. So we could have added the question mark at the end of the response in the example above. A text is a list of symbols, as is a pattern and a response; a rule is a list of pairs, each pair containing a pattern and a response. Heres how we suggest you start writing eliza. First, write a function that compares two lists of symbols for equality. (This is basic review.) Then write the function match-quest which compares a pattern that might contain question marks (but no asterisks) to a text, and returns true if and only if there is a match. Next, write the function extract-quest, which consumes a pattern without asterisks and a text, and produces a list of the matches. For example, (extract-quest (CS ? is ? fun) (CS 135 is really fun)) ((135) (really)) You are going to have to decide whether extract-quest returns false if the pattern does not match the text, or if it is only called in cases where there is a match. This decision affects not only how extract-quest is written, but other code developed after it. Next, write match-star and extract-star, which work like match-quest and extract-quest, but on patterns with no question marks. Test these thoroughly to make sure you understand. Finally, write the functions match and extract, which handle general patterns. Next we must start dealing with rules. Write a function nd-match that consumes a text and a list of rules, and produces the rst rule that matches the text. Then write the function apply-rule that consumes a text and a rule that matches, and produces the text as transformed by the right-hand side of that rule. Now you have all the pieces you need to write eliza. Weve provided a sample set of starter rules for you, but you should feel free to augment them (they dont include any uses of question marks in patterns, for example). Prabhakar Ragde adds a personal note: a version was available on the computer system that he used as an undergraduate, and he knew fellow students who would occasionally talk to it about things they didnt want to discuss with their friends. Weizenbaum reports that his secretary, who knew perfectly well who created the program and how simplistic it was, did the same thing. Its not a substitute for advisors, counsellors, and other sources of help, but you can try it out at the following URL: http://www-ai.ijs.si/eliza/eliza.html The URL below discusses Eliza-like programs, including a classic dialogue between Eliza and another program simulating a paranoid. http://www.stanford.edu/group/SHR/4-2/text/dialogues.html

CS 135 Fall 2012

Assignment 10

Você também pode gostar