Australian researchers develop typeface they say can boost memory, that could help students cramming for exams.

Similar documents
Fall Recursion and induction. Stephen Brookes. Lecture 4

Fall 2018 Lecture 1

CSE 341 Section 5. Winter 2018

Fall Lecture 3 September 4. Stephen Brookes

Fall Lecture 13 Thursday, October 11

Higher-Order Functions

F28PL1 Programming Languages. Lecture 14: Standard ML 4

Exercises on ML. Programming Languages. Chanseok Oh

A Third Look At ML. Chapter Nine Modern Programming Languages, 2nd ed. 1

Fall Lecture 8 Stephen Brookes

Mini-ML. CS 502 Lecture 2 8/28/08

Homework 7: Subsets Due: 11:59 PM, Oct 23, 2018

Lecture 3: Recursion; Structural Induction

Fall 2018 Lecture N

Lecture Programming in C++ PART 1. By Assistant Professor Dr. Ali Kattan

15 150: Principles of Functional Programming. Exceptions

CSci 4223 Principles of Programming Languages

SCHEME 7. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. October 29, 2015

COS 126 Exam Review. Exams overview Example programming exam Example written exam questions (part 1)

F28PL1 Programming Languages. Lecture 12: Standard ML 2

A quick introduction to SML

The type checker will complain that the two branches have different types, one is string and the other is int

Lecture 6: Sequential Sorting

15 150: Principles of Functional Programming Sorting Integer Lists

Redefinition of an identifier is OK, but this is redefinition not assignment; Thus

Fall 2017 Discussion 7: October 25, 2017 Solutions. 1 Introduction. 2 Primitives

CSE341, Fall 2011, Midterm Examination October 31, 2011

Processadors de Llenguatge II. Functional Paradigm. Pratt A.7 Robert Harper s SML tutorial (Sec II)

Programming Languages and Techniques (CIS120)

CSE341 Autumn 2017, Midterm Examination October 30, 2017

SCHEME 8. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. March 23, 2017

Types, Expressions, and States

General Computer Science (CH ) Fall 2016 SML Tutorial: Practice Problems

CMSC 330: Organization of Programming Languages. Operational Semantics

Practice Problems for the Final

CS558 Programming Languages

CS115 - Module 9 - filter, map, and friends

1 Dynamic Programming

MIDTERM EXAMINATION Douglas Wilhelm Harder EIT 4018 x T09:30:00P1H20M Rooms: RCH-103 and RCH-302

CS 340 Spring 2019 Midterm Exam

Lecture Notes on Induction and Recursion

Questions & Answers 28 Sept.

CSE341, Fall 2011, Midterm Examination October 31, 2011

CS2500 Exam 2 Fall 2011

CS153: Compilers Lecture 15: Local Optimization

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

Begin at the beginning

UNIVERSITY OF TORONTO Faculty of Arts and Science. Midterm Sample Solutions CSC324H1 Duration: 50 minutes Instructor(s): David Liu.

Cornell University 12 Oct Solutions. (a) [9 pts] For each of the 3 functions below, pick an appropriate type for it from the list below.

CSC324- TUTORIAL 5. Shems Saleh* *Some slides inspired by/based on Afsaneh Fazly s slides

CSE 341, Autumn 2005, Assignment 3 ML - MiniML Interpreter

Week 5 Tutorial Structural Induction

Sample Exam; Solutions

ML Built-in Functions

Homework 6: Higher-Order Procedures Due: 11:59 PM, Oct 16, 2018

Functional Programming - 2. Higher Order Functions

CITS3211 FUNCTIONAL PROGRAMMING. 6. Folding operators

CS 112 Midterm Exam Fall 2016

Names and Functions. Chapter 2

Learning Recursion. Recursion [ Why is it important?] ~7 easy marks in Exam Paper. Step 1. Understand Code. Step 2. Understand Execution

Functional abstraction. What is abstraction? Eating apples. Readings: HtDP, sections Language level: Intermediate Student With Lambda

Functional abstraction

CS558 Programming Languages

Hey there, I m (name) and today I m gonna talk to you about rate of change and slope.

APCS Semester #1 Final Exam Practice Problems

Section 1: True / False (2 points each, 30 pts total)

CSE341: Programming Languages Lecture 9 Function-Closure Idioms. Dan Grossman Winter 2013

CS153: Compilers Lecture 14: Type Checking

Inductive Data Types

Lecture 2: SML Basics

Recap from last time. Programming Languages. CSE 130 : Fall Lecture 3: Data Types. Put it together: a filter function

Spring 2018 Discussion 7: March 21, Introduction. 2 Primitives

CS 135 Fall 2018 Final Exam Review. CS 135 Fall 2018 Final Exam Review 1

CSE-321 Programming Languages 2012 Midterm

If we have a call. Now consider fastmap, a version of map that uses futures: Now look at the call. That is, instead of

Computational Expression

Side note: Tail Recursion. Begin at the beginning. Side note: Tail Recursion. Base Types. Base Type: int. Base Type: int

Programming Languages

Problem Set 2 Solutions

Tail Recursion: Factorial. Begin at the beginning. How does it execute? Tail recursion. Tail recursive factorial. Tail recursive factorial

News. Programming Languages. Recap. Recap: Environments. Functions. of functions: Closures. CSE 130 : Fall Lecture 5: Functions and Datatypes

Preliminary Examination I Computer Science 312, Cornell University 6 March 2003

CIS 110 Introduction to Computer Programming 8 October 2013 Midterm

Midterm 1 Exam Principles of Imperative Computation. Thursday 6 th October, This exam is closed-book with one sheet of notes permitted.

Fall 2018 Discussion 8: October 24, 2018 Solutions. 1 Introduction. 2 Primitives

MoreIntro.v. MoreIntro.v. Printed by Zach Tatlock. Oct 07, 16 18:11 Page 1/10. Oct 07, 16 18:11 Page 2/10. Monday October 10, 2016 lec02/moreintro.

COS 320. Compiling Techniques

More About Recursive Data Types

CSE 130 [Winter 2014] Programming Languages

APCS-AB: Java. Recursion in Java December 12, week14 1

COSE212: Programming Languages. Lecture 3 Functional Programming in OCaml

Text Input and Conditionals

Discussion 2C Notes (Week 5, February 4) TA: Brian Choi Section Webpage:

A Brief Introduction to Standard ML

CSU211 Exam 2 Fall 2007

Programming Paradigms

(ii) Define a function ulh that takes a list xs, and pairs each element with all other elements in xs.

Student Number: UTORid: Question 0. [1 mark] Read and follow all instructions on this page, and fill in all fields.

A First Look at ML. Chapter Five Modern Programming Languages, 2nd ed. 1

02157 Functional Programming Tagged values and Higher-order list functions

Transcription:

Font of all knowledge? Australian researchers develop typeface they say can boost memory, that could help students cramming for exams. About 400 university students took part in a study that found a small increase in the amount participants remembered 57% of text written in Sans Forgetica, only 50% in plain Arial. The font has a seven-degree back slant to the left and gaps in letters. The mind will naturally seek to complete those shapes and that slows the reading and triggers memory. The concept of desirable difficulty underpinned the font s design. It s good to have an obstruction added to the learning process because if something is too easy it doesn t create a memory trace.

15-150 Fall 2018 Lecture 12 Stephen Brookes Thursday, October 4

Midterm Exam 1 In class, Tuesday October 9 Write with pen, NOT pencil You can refer to ONE page of written notes If you have permission for extra time, please schedule with Disability Services (and check with me)

and now Generalizing the subset-sum problem Developing specs and code together Another lesson in program design

making change Given a non-negative integer n, a list of positive integers L, and a constraint p : int list -> bool Is there a sublist of L that satisfies p and adds up to n?

using folds Choose an appropriate base value, a sensible combining function, and pay attention to combination order fun sublists L = foldr (fn (x, S) => S @ (map(fn (fn A => => x::a) S)) S)) [ ][ ] ] L val sublists = fn : 'a list -> 'a list list val sublists = fn : 'a list -> 'a list list - sublists [1,2,3]; - sublists val it = [1,2,3]; [] : int list list val it = [[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]] : int list list What happens with foldl instead of foldr?

badchange badchange : int * int list -> (int list -> bool) -> bool fun badchange (n, L) p = exists (fn A => sum A = n andalso p A) (sublists L) A non-recursive function that returns a boolean fun exists q = foldl (fn (x, t) => q x orelse t) false fun sum A = foldl (op +) 0 A sublists [1,2,3] = [[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]] badchange satisfies the spec

critique badchange (300, [1,2,3,...,24]) (fn _ => true) ========>* true brute force search generates the list of all sublists (2 24 ) tests them sequentially only the final sublist will work! 1 + 2 + + 24 = 300

evenworsechange An even worse* function with the same spec fun evenworsechange (n, L) p = exists (fn A => p A andalso sum A = n) (sublists L) checks p A on all sublists A of L, even when sum A <> n * even worse, when p A is expensive to evaluate

specification can we make change for (n, L) that satisfies p change : int * int list -> (int list -> bool) -> bool REQUIRES p is total, n 0, L a list of positive integers ENSURES change (n, L) p = true if there is a sublist A of L with sum A = n and p A = true change (n, L) p = false, otherwise + must be faster!

a better strategy Avoid building the list of sublists only call p on sublists with the correct sum Deal with special cases first n = 0 n > 0, L = [ ] For n > 0, L = x::r, use recursion... the spec suggests this might be feasible!

change A recursive function that returns a boolean fun change (0, L) p = change (n, [ ]) p = false change (n, x::r) p = if x <= n p [ ] then change (n-x, R) (fn A => p(x::a)) orelse change (n, R) p else change (n, R) p change (300, [1,2,3,...,24]) (fn _ => true) => (very fast) true

equivalently fun change (0, L) p = p [ ] change (n, [ ]) p = false change (n, x::r) p = if x <= n then case change (n-x, R) (fn A => p(x::a)) of true => true false => change (n, R) p else change (n, R) p (if you don t like nested if-then-else)

requirements check fun change (0, L) p = p [ ] change (n, [ ]) p = false change (n, x::r) p = if x <= n then change (n-x, R) (fn A => p(x::a)) orelse change (n, R) p else change (n, R) p REQUIRES p is total, n 0, L a list of positive integers MUST CHECK if requirements hold for (n, L, p) and change (n, L) p calls change (n,l ) p then requirements hold for (n, L, p )

correctness? For all positive integer lists L, n 0, and total functions p : int list -> bool, change (n, L) p = true if there is a sublist A of L with sum A = n and p A = true change (n, L) p = false, otherwise PROOF: induction on L why?

change change : int * int list -> (int list -> bool) -> bool fun change (0, L) p = p [ ] change (n, [ ]) p = false change (n, x::r) p = if x <= n then change (n-x, R) (fn A => p(x::a)) orelse change (n, R) p else change (n, R) p

examples change (10, [5,2,5]) (fn _ => true) = true change (210, [1,2,3,...,20]) (fn _ => true) =>* true (FAST!) change (10, [10,5,2,5]) (fn A => length(a)>1) = true change (10, [10,5,2]) (fn A => length(a)>1) = false

the right question? change : int * int list -> (int list -> bool) -> bool Is there a sublist of L YES! that? You What is it? didn t ask

boolean blindness By returning only a truth value we only get a small amount of information (true or false) From the context, we know this tells us if it is possible to make change... But what if we want more information? a way to make change, if there is one needed: a recursive function that computes a suitable sublist, if there is one plan: use result type (int list) option

mkchange A recursive function that returns an (int list) option mkchange : int * int list -> (int list -> bool) -> int list option REQUIRES n >= 0, L is a list of positive integers, p is total ENSURES mkchange (n, L) p = SOME A, where A is a sublist of L with sum A = n and p A = true, if there is such a sublist mkchange (n, L) p = NONE, otherwise

mkchange fun mkchange (0, L) p = if p [ ] then SOME [ ] else NONE mkchange (n, [ ]) p = NONE mkchange (n, x::r) p = if x <= n then case mkchange (n-x, R) (fn A => p(x::a)) of else SOME A => SOME (x::a) NONE => mkchange (n, R) p mkchange (n, R) p

correctness? For all positive integer lists L, n 0, and total functions p : int list -> bool, mkchange (n, L) p = SOME A where A is a sublist of L with sum A = n and p A = true, if there is one mkchange (n, L) p = NONE, otherwise PROOF: induction on L (similar to the proof of change)

mkchange fun mkchange (0, L) p = if p [ ] then SOME [ ] else NONE mkchange (n, [ ]) p = NONE mkchange (n, x::r) p = if x <= n then case mkchange (n-x, R) (fn A => p(x::a)) of SOME A => SOME (x::a) NONE => mkchange (n, R) p else mkchange (n, R) p

assessment We ve defined change : int * int list -> (int list -> bool) -> bool mkchange : int * int list -> (int list -> bool) -> int list option The function definitions have similar control flow fun change (0, L) p = if p [ ] then else change (n, [ ]) p = change (n, x::r) p = if x <= n then case change (n-x, R) (fn A => p(x::a)) of true => false => change (n, R) p else change (n, R) p fun mkchange (0, L) p = if p [ ] then else mkchange (n, [ ]) p = mkchange (n, x::r) p = if x <= n then case mkchange (n-x, R) (fn A => p(x::a)) of SOME A => NONE => mkchange (n, R) p else mkchange (n, R) p

assessment What if the boss decides he wants yet another type of answer How could we avoid the re-doing the code design all over again?

go polymorphic... Design a very flexible function Instead of returning a bool or int list option, use a type variable a for the answer type and use function parameters s and k to implement success and failure (to be chosen later) s : int list -> a k : unit -> a call s if you find a solution call k if you fail

more flexible changer : int * int list -> (int list -> bool) -> (int list -> 'a) -> (unit -> 'a) -> 'a changer (n, L) p s k : t : int list -> t : unit -> t this recipe works for any type t of answers

success s : int list -> t is a success continuation

failure k : unit -> t is a failure continuation

more flexible spec changer : int * int list -> (int list -> bool) -> (int list -> 'a) -> (unit -> 'a) -> 'a REQUIRES n>=0, L a list of positive integers, p total ENSURES changer (n, L) p s k = s A where A is a sublist of L such that sum A = n and p A = true, if there is one changer (n, L) p s k = k ( ) otherwise success, call s fail, call k

changer fun changer (0, L) p s k = if p [ ] then s [ ] else k( ) changer (n, [ ]) p s k = k( ) changer (n, x::r) p s k = if x <= n then changer (n-x, R) (fn A => p(x::a)) (fn A => s(x::a)) (fn ( ) => changer (n, R) p s k) else changer (n, R) p s k

examples -changer (12, [1,1,1,1,1,1,1,2,4,6]) (fn _ => true) SOME (fn () => NONE); val it = SOME [1,1,1,1,1,1,2,4] : int list option -changer (12, [1,1,1,1,1,1,1,2,4,6]) (fn A => length A < 4) SOME (fn () => NONE); val it = SOME [2,4,6] : int list option

correctness? For all lists L of positive integers, n 0, total functions p : int list -> bool, all types t and all s : int list -> t, k : unit -> t changer (n, L) p s k = s A where A is a sublist of L with sum A = n and p A = true, if there is one changer (n, L) p s k = k( ), otherwise PROOF Use induction on structure of L (similar to the proofs for )

verbose? For all types t, all total functions p, yada yada yada We make argument assumptions explicit We indicate flexibility of result type We use accurate math notation The requirements are clear and precise

utility changer : int * int list -> (int list -> bool) -> (int list -> 'a) -> (unit -> 'a) -> 'a change : int * int list -> (int list -> bool) -> bool fun change (n, L) p = changer (n, L) p (fn _ => true) (fn ( ) => false) mkchange : int * int list -> (int list -> bool) -> int list option fun mkchange (n, L) p = changer (n, L) p SOME (fn ( ) => NONE)

robust There s no need to re-do the code if the manager decides to change the spec again, e.g. by giving an extra penny generous_change : int * int list -> (int list -> bool) -> int list fun generous_change (n, L) p = changer (n, L) p (fn A => 1::A) (fn ( ) => [1]) - generous_change (12, [5,5,2,42]) (fn _ => true) val it = [1,5,5,2] : int list

next Using continuations to implement backtracking