The Countdown Problem in Haskell Programming

 
0
 
P
R
O
G
R
A
M
M
I
N
G
 
I
N
 
H
A
S
K
E
L
L
 
Chapter 9 - The Countdown Problem
 
1
 
What Is Countdown?
 
z
A popular 
quiz programme
 on British television
that has been running since 1982.
 
z
Based upon an original 
French
 version called
"Des Chiffres et Des Lettres".
 
z
Includes a numbers game that we shall refer
to as the 
countdown problem
.
 
2
 
Example
 
Using the numbers
 
and the arithmetic operators
765
 
construct an expression whose value is
 
3
 
Rules
 
z
All the numbers, including intermediate results,
must be 
positive naturals
 (1,2,3,…).
 
z
Each of the source numbers can be used at
most once
 when constructing the expression.
 
z
We 
abstract
 from other rules that are adopted
on television for pragmatic reasons.
 
4
 
For our example, one possible solution is
 
z
There are 
780
 solutions for this example.
 
z
Changing the target number to          gives
an example that has 
no
 solutions.
 
Notes:
831
 
5
 
Evaluating Expressions
 
Operators:
data Op = Add | Sub | Mul | Div
 
Apply an operator:
apply :: Op 
 Int 
 Int 
 Int
apply Add x y = x + y
apply Sub x y = x - y
apply Mul x y = x * y
apply Div x y = x `div` y
 
6
 
Decide if the result of applying an operator to two
positive natural numbers is another such:
valid :: Op 
 Int 
 Int 
 Bool
valid Add _ _ = True
valid Sub x y = x > y
valid Mul _ _ = True
valid Div x y = x `mod` y == 0
 
Expressions:
data Expr = Val Int | App Op Expr Expr
 
7
eval :: Expr 
 [Int]
eval (Val n)     = [n | n > 0]
eval (App o l r) = [apply o x y | x 
 eval l
                                , y 
 eval r
                                , valid o x y]
 
Return the overall value of an expression, provided
that it is a positive natural number:
Either succeeds and returns a singleton
list, or fails and returns the empty list.
 
8
 
Formalising The Problem
 
Return a list of all possible ways of choosing zero
or more elements from a list:
choices :: [a] 
 [[a]]
 
For example:
> choices [1,2]
 
[[],[1],[2],[1,2],[2,1]]
 
9
 
Return a list of all the values in an expression:
values :: Expr 
 [Int]
values (Val n)     = [n]
values (App _ l r) = values l ++ values r
 
Decide if an expression is a solution for a given list
of source numbers and a target number:
solution :: Expr 
 [Int] 
 Int 
 Bool
solution e ns n = elem (values e) (choices ns)
                  && eval e == [n]
 
10
 
Brute Force Solution
 
Return a list of all possible ways of splitting a list
into two non-empty parts:
split :: [a] 
 [([a],[a])]
 
For example:
> split [1,2,3,4]
 
[([1],[2,3,4]),([1,2],[3,4]),([1,2,3],[4])]
 
11
 
Return a list of all possible expressions whose values
are precisely a given list of numbers:
exprs :: [Int] 
 [Expr]
exprs []  = []
exprs [n] = [Val n]
exprs ns  = [e | (ls,rs) 
 split ns
               , l       
 exprs ls
               , r       
 exprs rs
               , e       
 combine l r]
The key function in this lecture.
 
12
combine :: Expr 
 Expr 
 [Expr]
combine l r =
   [App o l r | o 
 [Add,Sub,Mul,Div]]
 
Combine two expressions using each operator:
solutions :: [Int] 
 Int 
 [Expr]
solutions ns n = [e | ns' 
 choices ns
                    , e   
 exprs ns'
                    , eval e == [n]]
 
Return a list of all possible expressions that solve an
instance of the countdown problem:
 
13
 
How Fast Is It?
 
System:
 
Compiler:
 
Example:
 
One solution:
 
All solutions:
solutions [1,3,7,10,25,50] 765
 
2.8GHz Core 2 Duo, 4GB RAM
 
GHC version 7.10.2
 
 
0.108 seconds
 
12.224 seconds
 
14
 
z
Many of the expressions that are considered
will typically be 
invalid
 - fail to evaluate.
 
z
For our example, only around 
5 million
 of the
33 million possible expressions are valid.
 
z
Combining generation with evaluation would
allow 
earlier rejection
 of invalid expressions.
 
Can We Do Better?
 
15
results :: [Int] 
 [Result]
results ns = [(e,n) | e 
 exprs ns
                    , n 
 eval e]
type Result = (Expr,Int)
 
Valid expressions and their values:
 
We seek to define a function that fuses together
the generation and evaluation of expressions:
 
Fusing Two Functions
 
16
results []  = []
results [n] = [(Val n,n) | n > 0]
results ns  =
   [res | (ls,rs) 
 split ns
        , lx      
 results ls
        , ry      
 results rs
        , res     
 combine' lx ry]
 
This behaviour is achieved by defining
combine' :: Result 
 Result 
 [Result]
 
where
 
17
solutions' :: [Int] 
 Int 
 [Expr]
solutions' ns n =
   [e | ns'   
 choices ns
      , (e,m) 
 results ns'
      , m == n]
 
New function that solves countdown problems:
combine
 (l,x) (r,y) =
   [(App o l r, apply o x y)
      | o 
 [Add,Sub,Mul,Div]
      , valid o x y]
 
Combining results:
 
18
 
How Fast Is It Now?
 
Example:
 
 
 
One solution:
 
 
 
All solutions:
solutions' [1,3,7,10,25,50] 765
 
0.014 seconds
 
 
 
1.312 seconds
Around 10
times faster in
both cases.
 
19
 
z
Many expressions will be 
essentially the same
using simple arithmetic properties, such as:
 
z
Exploiting such properties would considerably
reduce
 the search and solution spaces.
 
Can We Do Better?
20
Exploiting Properties
Strengthening the valid predicate to take account
of commutativity and identity properties:
valid :: Op 
 Int 
 Int 
 Bool
valid Add x y  = True
valid Sub x y  = x > y
valid Mul x y  = True
valid Div x y  = x `mod` y == 0
x 
 y
x 
 y && x 
 1
x 
 y && x 
 1 && y 
 1
x 
 y
&& y 
 1
 
21
 
How Fast Is It Now?
 
Example:
 
 
 
Valid:
 
 
 
Solutions:
solutions'' [1,3,7,10,25,50] 765
 
250,000 expressions
 
 
 
49 expressions
Around 20
times less.
Around 16
times less.
 
22
 
One solution:
 
 
 
 
All solutions:
 
0.007 seconds
 
 
 
 
0.119 seconds
Around 2
times faster.
Around 11
times faster.
 
More generally, our program usually returns all
solutions in a fraction of a second, and is around
100 times faster that the original version.
Slide Note
Embed
Share

The Countdown problem, popularized by a British television quiz show, challenges players to use given numbers and arithmetic operators to reach a target number. This Haskell programming chapter explores evaluating expressions, applying operators, and formalizing the problem. Learn how to construct expressions and determine if the result is a positive natural number.

  • Haskell Programming
  • Countdown Problem
  • Arithmetic Operators
  • Formalizing
  • Expressions

Uploaded on Oct 06, 2024 | 0 Views


Download Presentation

Please find below an Image/Link to download the presentation.

The content on the website is provided AS IS for your information and personal use only. It may not be sold, licensed, or shared on other websites without obtaining consent from the author. Download presentation by click this link. If you encounter any issues during the download, it is possible that the publisher has removed the file from their server.

E N D

Presentation Transcript


  1. PROGRAMMING IN HASKELL PROGRAMMING IN HASKELL Chapter 9 - The Countdown Problem 0

  2. What Is Countdown? z A popular quiz programme on British television that has been running since 1982. z Based upon an original French version called "Des Chiffres et Des Lettres". z Includes a numbers game that we shall refer to as the countdown problem. 1

  3. Example Using the numbers 1 3 7 10 25 50 and the arithmetic operators + - construct an expression whose value is 765 2

  4. Rules z All the numbers, including intermediate results, must be positive naturals (1,2,3, ). z Each of the source numbers can be used at most once when constructing the expression. z We abstract from other rules that are adopted on television for pragmatic reasons. 3

  5. For our example, one possible solution is = (25-10) (50+1) 765 Notes: z There are 780 solutions for this example. z Changing the target number to gives an example that has no solutions. 831 4

  6. Evaluating Expressions Operators: data Op = Add | Sub | Mul | Div Apply an operator: apply :: Op Int Int Int apply Add x y = x + y apply Sub x y = x - y apply Mul x y = x * y apply Div x y = x `div` y 5

  7. Decide if the result of applying an operator to two positive natural numbers is another such: valid :: Op Int Int Bool valid Add _ _ = True valid Sub x y = x > y valid Mul _ _ = True valid Div x y = x `mod` y == 0 Expressions: data Expr = Val Int | App Op Expr Expr 6

  8. Return the overall value of an expression, provided that it is a positive natural number: eval :: Expr [Int] eval (Val n) = [n | n > 0] eval (App o l r) = [apply o x y | x eval l , y eval r , valid o x y] Either succeeds and returns a singleton list, or fails and returns the empty list. 7

  9. Formalising The Problem Return a list of all possible ways of choosing zero or more elements from a list: choices :: [a] [[a]] For example: > choices [1,2] [[],[1],[2],[1,2],[2,1]] 8

  10. Return a list of all the values in an expression: values :: Expr [Int] values (Val n) = [n] values (App _ l r) = values l ++ values r Decide if an expression is a solution for a given list of source numbers and a target number: solution :: Expr [Int] Int Bool solution e ns n = elem (values e) (choices ns) && eval e == [n] 9

  11. Brute Force Solution Return a list of all possible ways of splitting a list into two non-empty parts: split :: [a] [([a],[a])] For example: > split [1,2,3,4] [([1],[2,3,4]),([1,2],[3,4]),([1,2,3],[4])] 10

  12. Return a list of all possible expressions whose values are precisely a given list of numbers: exprs :: [Int] [Expr] exprs [] = [] exprs [n] = [Val n] exprs ns = [e | (ls,rs) split ns , l exprs ls , r exprs rs , e combine l r] The key function in this lecture. 11

  13. Combine two expressions using each operator: combine :: Expr Expr [Expr] combine l r = [App o l r | o [Add,Sub,Mul,Div]] Return a list of all possible expressions that solve an instance of the countdown problem: solutions :: [Int] Int [Expr] solutions ns n = [e | ns' choices ns , e exprs ns' , eval e == [n]] 12

  14. How Fast Is It? System: 2.8GHz Core 2 Duo, 4GB RAM Compiler: GHC version 7.10.2 Example: solutions [1,3,7,10,25,50] 765 One solution: 0.108 seconds All solutions: 12.224 seconds 13

  15. Can We Do Better? z Many of the expressions that are considered will typically be invalid - fail to evaluate. z For our example, only around 5 million of the 33 million possible expressions are valid. z Combining generation with evaluation would allow earlier rejection of invalid expressions. 14

  16. Fusing Two Functions Valid expressions and their values: type Result = (Expr,Int) We seek to define a function that fuses together the generation and evaluation of expressions: results :: [Int] [Result] results ns = [(e,n) | e exprs ns , n eval e] 15

  17. This behaviour is achieved by defining results [] = [] results [n] = [(Val n,n) | n > 0] results ns = [res | (ls,rs) split ns , lx results ls , ry results rs , res combine' lx ry] where combine' :: Result Result [Result] 16

  18. Combining results: combine (l,x) (r,y) = [(App o l r, apply o x y) | o [Add,Sub,Mul,Div] , valid o x y] New function that solves countdown problems: solutions' :: [Int] Int [Expr] solutions' ns n = [e | ns' choices ns , (e,m) results ns' , m == n] 17

  19. How Fast Is It Now? Example: solutions' [1,3,7,10,25,50] 765 One solution: 0.014 seconds Around 10 times faster in both cases. All solutions: 1.312 seconds 18

  20. Can We Do Better? z Many expressions will be essentially the same using simple arithmetic properties, such as: = x y y x = x 1 x z Exploiting such properties would considerably reduce the search and solution spaces. 19

  21. Exploiting Properties Strengthening the valid predicate to take account of commutativity and identity properties: valid :: Op Int Int Bool x y valid Add x y = True valid Sub x y = x > y x y x y && x 1 x y && x 1 && y 1 valid Mul x y = True && y 1 valid Div x y = x `mod` y == 0 20

  22. How Fast Is It Now? Example: solutions'' [1,3,7,10,25,50] 765 Around 20 times less. Valid: 250,000 expressions Around 16 times less. Solutions: 49 expressions 21

  23. Around 2 times faster. One solution: 0.007 seconds Around 11 times faster. All solutions: 0.119 seconds More generally, our program usually returns all solutions in a fraction of a second, and is around 100 times faster that the original version. 22

More Related Content

giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#giItT1WQy@!-/#