Presentation is loading. Please wait.

Presentation is loading. Please wait.

review combinatorics bignum OCAML rapid tour, day 3

Similar presentations


Presentation on theme: "review combinatorics bignum OCAML rapid tour, day 3"— Presentation transcript:

1 review combinatorics bignum OCAML rapid tour, day 3
Class 19 review combinatorics bignum OCAML rapid tour, day 3

2 Review Big ideas (for developing recursive programs)
Recursive diagrams sometimes help Adding an argument sometimes helps Methodically splitting into "cases" helps (e.g., argument is empty vs. cons list)

3 Combinatorial Programs

4 Combinatorial programs
Used to count or enumerate things "all triples of int between 0 and 10 whose sum is no more than 7" "all increasing sequences of numbers between 0 and 20" "The number of ways to partition a regular n-gon into triangles" Today we're going to look at one in detail: Stars-and-stripes: "Find all strings containing only "*" and "-", and which contain exactly n stars and n stripes." Input: n, a natural number Output: a list of strings

5 ;; ss: int -> (string list)
;; intput: an integer n ;; output: a list of all strings made up from exactly ;; n asterisks and n dashes (define (ss n) ( … ) (check-expect (ss 0) empty) (check-expect (ss 1) (list "*-" "-*") (check-expect (ss 2) (list "**--" "*-*-" "*--*" "-**-" "-*-*" "--**") Problem: what if they're in a different order? We really need to compare the results as sets.

6 ;; ss: int -> (string list) ;; intput: an integer n ;; output: a list of all strings made up from exactly ;; n asterisks and n dashes (define (ss n) (check-expect (ss 0) empty) (check-expect (set-equal? (ss 1) (list "*-" "-*")) true) (check-expect (set-equal? (ss 2) (list "**--" "*-*-" "*--*" "-**-" "-*-*" "--**")) true)

7 What next? Draw a recursive diagram! Then write a template and some code.

8 Ideas? Recursive result doesn't actually seem very helpful
Have to "put an extra star and an extra stripe" in every possible position Ends up producing duplicates, too Solution: make the problem harder, so the recursive result can be more useful!

9 Revised stars-n-stripes problem: more general
Given n, k, create all strings containing n “*”s and k “-”s, in any order. (sns 2 0) => (list “**”) (sns 2 1) => (list “-**” “*-*” “**-”)

10 Recursive diagram OI: 1 2 RI 0 2 RO -- idea: stick a star in every possible “slot” OO: *-- -*- --*

11 Another diagram OI: 0 2 RI 0 1 RO – idea: you can’t stick a stripe in every slot – duplicates! OO: --

12 Some ideas Idea: Go ahead and produce duplicates, but filter them out later. Slow. Idea: Maybe there are many base-cases, like 0 0, 0 n, and n 0.

13 Combinatorics approach
A surprisingly general approach to (beginning) combinatorial problems is this: Divide the things you're trying to produce (or count) into two disjoint piles and work on each one Disjoint means “Not sharing any items” Sometimes we divide into 3 or 4 piles, but 2 is often enough Being certain they’re disjoint is essential, and sometimes tricky. An application of “divide and conquer”, a general idea in CS

14 Stars-n-stripes 2 2 **-- --** *-*- *--* -**- -*-* How can we divide these into disjoint groups? (preferably of about equal size)

15 Divide into piles based on the “starting letter”!
**-- --** *-*- *--* -**- -*-* Groups are obviously disjoint.

16 Continuing with the plan
Divide the things your trying to produce (or count) into two disjoint piles and work on each one Q: How can we produce these? **-- *-*- *--* A: By prepending a “*” on each of these: *-- -*- --* How can we produce those? A recursive call! Summary Make two recursive calls, reducing the number of stars in one, the number of stripes in the other Prepend a * on each item in the first result; prepend a – on each item in the second result Append the two resulting lists

17 Summary Make two recursive calls, reducing the number of stars in one, the number of stripes in the other Prepend a * on each item in the first result; prepend a – on each item in the second result Append the two resulting lists (define (sns n k) (let ((alos1 (map (lambda (x) (string-append "*" x)) (sns (- n 1) k))) (alos2 (map (lambda (x) (string-append "-" x)) (sns n (- k 1))))) (append alos1 alos2))) Doesn’t work…we need base cases, helpers, etc.

18 Base cases! (define (sns n k) (cond
[(zero? n) (list (replicate "-" k))] [(zero? k) (list (replicate "*" n))] [(and (succ? n) (succ? k) (sns-helper n k)])) (define (sns-helper n k) (let ((alos1 (map (lambda (x) (string-append "*" x)) (sns (- n 1) k))) (alos2 (map (lambda (x) (string-append "-" x)) (sns n (- k 1))))) (append alos1 alos2)))) (define (replicate str n) [(zero? n) ""] [(succ? n) (string-append str (replicate str (- n 1)))]))

19 ; sns-helper: int*int -> (str list) ; Inputs: ; n, a positive int, saying how many stars ; k, a positive int, saying how many stripes ; output: ; a complete list (with no duplicates) of all strings containing ; only * and - , where each string has exactly n stars and k stripes (define (sns-helper n k) (let ((alos1 (map (lambda (x) (string-append "*" x)) (sns (- n 1) k))) (alos2 (map (lambda (x) (string-append "-" x)) (sns n (- k 1))))) (append alos1 alos2))) Check-expects here

20 ; sns: int*int -> (str list) ; Inputs: ; n, a natural number, saying how many stars ; k, a natural number, saying how many stripes ; output: ; a complete list (with no duplicates) of all strings containing ; only * and - , where each string has exactly n stars and k stripes (define (sns n k) (cond [(and (zero? n) (zero? k)) empty] [(zero? n) (list (repeat "-" k))] [(zero? k) (list (repeat "*" n))] [(and (succ? n) (succ? k)) (sns-helper n k)])) (check-expect (sns 0 0) empty) (check-expect (sns 1 0) (list "*")) (check-expect (sns 0 3) (list "---")) ; (check-expect (set-equal? (sns 1 2) (list "*--" "-*-" "--*")) true)

21 It’s still wrong! Can you think of a string that contains no characters other than *s and -s, and which contains zero of each of these? What should (sns 0 0) be? (list "") Have to change the check-expect, too!

22 A more compact solution
(define (sub1 n) (- n 1)) (define (sns num-stars num-stripes) (cond [(and (zero? num-stars) (zero? num-stripes)) (list "")] [(and (zero? num-stars) (succ? num-stripes)) (map (lambda (x) (string-append "-" x )) (sns 0 (sub1 num-stripes)))] [(and (succ? num-stars) (zero? num-stripes)) (map (lambda (x) (string-append "*" x)) (sns (sub1 num-stars) 0))] [(and (succ? num-stars) (succ? num-stripes)) (append (map (lambda (x) (string-append "*" x)) (sns (sub1 num-stars) num-stripes)) (map (lambda (x) (string-append "-" x)) (sns num-stars (sub1 num-stripes))))]))

23 Review review Big ideas (for developing recursive programs)
Recursive diagrams sometimes help Adding an argument sometimes helps Methodically splitting into "cases" helps (e.g., argument is empty vs. cons list) Small (but big) ideas Your base case is the only one involved in every possible invocation of your procedure; get it right! Sometimes there are multiple base cases

24 More Ocaml

25 Interacting with Ocaml

26 When are we ready to evaluate?
Racket: 4 (+ 3 2) Ocaml 3 + 2 could be the start of 4 + 7 * 9 3 + 2 – 11 Use double-semicolon to say "Please evaluate what you can up to now!"

27 Do lines in Ocaml have to end with double semicolons?
Perfectly OK: let x = 4 let y = 2;; x + y;; OK because when parser sees the keyword "let", it knows the previous expression is finished Double-semicolons after the "let y" says "I'm done telling you what y is, and the next thing you see will start a new expression." Without it, OCaml sees "let y = 2 x + y", and thinks that "2" is a function that should be applied to x!

28 Useful beginner's rule Go ahead and end lines with a double-semicolon
Except Multi-line lets, like let x = 4 and y = 2 and … and t = 4;; Multi-line function definitions let f x = match x with | [] -> … | hd::tl -> … any semicolon here would end the "match" expression let … in expressions

29 File inclusion #use "myFile.ml" ;;
Means "go to the filesystem and locate "myFile.ml"; read each line of that file as if I had typed it into OCaml. The file must be located in the same folder/directory as the file you're currently working on (or the folder in which you started ocaml) Can replace by "full pathname", as in #use "/course/cs017/src/helpers.ml" ;; which works on the CS filesystem…but not on your home computer, because you don't have a folder called "/course", for instance.

30 Applying the OCaml we've seen

31 Bignum solution (in ocaml)
[omitted]

32 A bit more OCaml

33 Multi-argument procedures
In Ocaml fun x y -> x + y + 1 looks like a 2-arg function. It’s not. Let’s see: # fun x y -> x + y + 1;; - : int -> int -> int = <fun> The truth: it’s really syntactic sugar for # fun x -> (fun y -> x + y + 1);; : int -> int -> int = <fun> Rewriting multi-arg functions as nested one-arg functions is called « Currying »

34 A (bad) alternative Let’s see: # fun (x, y) -> x + y + 1;;
In Ocaml fun (x, y) -> x + y + 1 is a 1-arg function whose sole input is a pair Almost never what you want Let’s see: # fun (x, y) -> x + y + 1;; - : int*int -> int = <fun> That looks more familiar, but it’s not at all idiomatic. Avoid it.

35 With only single-arg functions, it's easy to get confused
Parentheses often help: if you want to apply f to x, go ahead and write f (x) or (f (x)) to make that clear. Example: length hd::tl Does that compute the length of "hd" and cons that number onto tl? Or does it cons hd to tl, and compute the length of the resulting list? If you want to be sure you're getting the second, write length (hd::tl) (length (hd::tl))

36 Contains17? Remember this proc? (define (contains17? aloi) (cond
[(empty? aloi) false] [(cons? aloi) (or (= 17 (first aloi)) (contains17? (rest aloi)))]))

37 contains17? (ocaml) [3 forms, all good]
let rec contains17 (lst: int list) = match lst with | [] -> false | hd::tl -> (hd == 17) || (contains7 tl) let rec contains7:(int list -> bool) = function let rec contains17:(int list -> bool) = function | 17::tl -> true | _::tl -> contains17 tl

38 Dictionaries Represent a function 𝑓
Sometimes thought of as key-value pairs, where 𝑓(key) = value. Examples: Phone book, a dictionary from names to phone numbers English-french dictionary, a dict from english words to french ones Environment: a dictionary from identifiers to values Usual operations: Is this key in the dictionary? What value is associated with this key add key-value pair replace key-value-pair delete key-value-pair

39 A simple dictionary “data structure”: a list of pairs.
my_dict = [(“I”, “je”); (“you”, ”tu”); (“dog”, “chien”); … ] : (string*string) list let rec lookup key:string dict:(string*string list):string = match dict with | [] -> ??? | (k, v) :: tl -> if (key == k) then v else lookup key tl

40 A builtin type for handling success/failure cases!
type ‘a option = Some of ‘a | None Intended use: “None” means something like “I didn’t find an answer” or “your item isn’t in the data”, etc. “Some x” means “I found an answer, and it was x” Requires new type-signature for most functions f: int -> int becomes f: int -> int option For recursive procs, adds slight complexity

41 Small example let rec lookup key:string dict:(string*string list):(string option) = match dict with | [] -> None | (k, v) :: tl -> if (key == k) then (Some v) else lookup key tl Parens around "Some v" not really necessary, but clarify things.

42 Annoyance When you look up "dog", you get Some "chien" not "chien"
Solution forthcoming…


Download ppt "review combinatorics bignum OCAML rapid tour, day 3"

Similar presentations


Ads by Google