Selected Programming Challenges
Advanced Exercises for Haskell and Other Programming Languages
These exercises are optional and unassessed and you should only spend time on them if you feel you need a new challenge that takes you beyond the unassessed problems and weekly lab exercises. The exercises are taken from the text book: Steven S. Skiena and Miguel A. Rivella, “Programming Challenges – the Programming Contest Training Manual”, Springer 2003 and reproduced with permission from the authors. The text of each problem has been copied largely without modiﬁcation, although the input and output speciﬁcations have been modiﬁed so that you don’t have to do any explicit Haskell I/O. The exercises, without any supporting text or hints, can also be dowloaded from http://www.programming-challenges.com The purpose of setting you these exercises is twofold. Firstly, they provide an opportunity for you to practice your Haskell programming skills; in particular, you should ﬁnd that many of the problems have extremely succinct and elegant solutions when you make full use of Haskell’s higher-order functions and list comprehensions. Most importantly, however, they exercise your problem-solving skills. Inventing a smart way to solve a problem is an valuable skill in its own right. Some people are naturally better at problem solving than others, but everyone can hone their skills with practice. These exercises give you a chance to do that. If you get really good at it, you might consider entering one of the national or international programming competitions, for example: http://icpc.baylor.edu/icpc/ http://www.bcs.org/BCS/Awards/Events/ProgrammingCompetition/ You don’t have to solve the problems in Haskell, of course, but are encouraged to do so, even if you also produce solutions in other languages. In many cases a good Haskell solution is a fraction of the size of a good solution in a language like C++ or Java. If you’re not convinced, try it, although you’ll need to modify the speciﬁcation of the programs’ inputs and outputs, or learn how to do I/O in Haskell. If you enjoy these exercises, you are encouraged to look at the other problems in the book over the coming year, and beyond. You might even like to invent problems of your own. If you think you have invented an interesting and challenging new problem, please mail it to me (but don’t show me the solution!). There are thirteen problems in total. I have chosen ﬁve problems which I consider to be relatively easy, ﬁve that I’ve classed as being of intermediate diﬃculty and two that have a bit of a sting in their tail! At the end I’ve added an additional problem that’s not in the book, inspired by a popular day-time TV show.
210. and the maximum cycle length for integers between and including i and j. the cycle-length of n is the number of numbers generated up to and including the 1. If n is even. Int ) that given two integers i and j. some multiple of n is a number which in decimal notation is a sequence of 1’s. including both endpoints. In the example above. Main> solve 1 10 (1. and b is an integer greater than zero.3
A sequence of n > 0 integers is called a jolly jumper if the absolute values of the diﬀerences between successive elements take on all possible values 1 through n − 1. If n is odd.000.125) Main> solve 201 210 (201. divide by 2. the cycle length of 22 is 16. the following sequence of numbers will be generated for n = 22: 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1 It is conjectured (but not yet proven) that this algorithm will terminate at 1 for every starting integer n. the conjecture holds for all integers up to at least 1. Given any two numbers i and j. j in the same order in which they appeared in the input.2
These problems can be solved in just a few lines of Haskell code (of the order of 1–10 lines of neatly formatted code). Int. Still.
2. p = a × b. will return i. Start with an integer n. terminating when you reach 1. For example.20) Main> solve 100 200 (100.2
The 3n + 1 Problem
Consider the following algorithm to generate a sequence of numbers.1
Given any integer 0 ≤ n ≤ 10. For example. given an integer a. multiply by 3 and add 1. Deﬁne a function solve :: Int -> Int -> ( Int.10. 1423 2
. For instance.174)
2. For an input n.1000.89) Main> solve 900 1000 (900. How many digits are in the smallest such multiple of n? Deﬁne a function digits :: Integer -> Integer that. you are to determine the maximum cycle length over all numbers between i and j. 000 not divisible by 2 or 5. returns the smallx−1 est integer x > 0 such that p = i=0 1 × 10i .200.000. For example. Repeat this process. Main> 12 Main> 3 Main> 6 Main> 12 digits 9901 digits 3 digits 7 digits 9901
Note: Using Integer types is cheating somewhat. but it makes the (smart) solution extremely simple!
hotels. and h3 = 8. in dollars and cents. given a list of the amount spent by each student. Assume h1 = 3. given a list of integers returns True iﬀ the numbers constitute a jolly jumper. The group agrees in advance to share expenses equally. but it is not practical to share every expense as it occurs.3] True Main> isJumper [1. each party may be characterized by a positive integer h called the hartal parameter that denotes the average number of days between two successive strikes called by the given party. We can simulate the behavior of these three parties for N = 14 days. which cause considerable economic damage. that must be exchanged to 3
. Main> isJumper [1. This spring they are planning a trip to Eindhoven.is a jolly jumper. to within one cent.2. 9. Hence we lose ﬁve working days in two weeks.4. and Atlanta. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Days Su Mo Tu We Th Fr Sa Su Mo Tu We Th Fr Sa -------------------------------------------------------------Party 1 x x x x Party 2 x x x Party 3 x -------------------------------------------------------------Hartals 1 2 3 4 5 There will be exactly ﬁve hartals (on days 3. Consider three political parties.25.4
Political parties in Bangladesh show their muscle by calling for regular hartals (strikes). where hi is the hartal parameter for party i. respectively.5
A group of students are members of a club that travels annually to diﬀerent locations. There are no hartals on either Fridays or Saturdays.8] 5 Main> hartals 100 [12. taxi rides. and plane tickets.4. 4. For example. Deﬁne a function trip :: [ Float ] -> Float that. Deﬁne a function hartals :: Int -> [ Int ] -> Int that. this money exchange has been tedious and time consuming. There is no hartal on day 6 since it falls on Friday. given the value of N and the hartal parameters for several political parties.2.15. In the past.4. and 1. returns the number of working days lost in those N days. from a list of expenses. Thus individuals in the group pay for particular things. Main> hartals 14 [3. because the absolute diﬀerences are 3. Deﬁne a function isJumper :: [ Int ] -> Bool that. returns the total amount of money.6] False
2. San Jose. the minimum amount of money that must change hands in order to equalize (within one cent) all the students’ costs. Their destinations in the past have included Indianapolis. For example. After the trip. The deﬁnition implies that any sequence of a single integer is a jolly jumper. and 12) over the 14 days. Write a program to determine whether each of a number of sequences is a jolly jumper. For our purposes.40] 15
2. Philadelphia. 8.-1. h2 = 4. Your job is to compute. Phoenix. 2. such as meals. Nashville. We always start the simulation on a Sunday. each student’s expenses are tallied and money is exchanged so that the net cost to each is the same.
and thus we cannot possibly get the same fraction in two diﬀerent places. in some cases. We can.01] 11. 1 and then repeat 1 0 ′ the following operation as many times as desired: Insert m+m between two adjacent fractions m n+n′ n ′ 1 0 and m′ . Deﬁne a function play :: Int -> String that. . Well.15. . because each positive. . . then left to 5 . . reduced fraction occurs exactly once. does his multiplication.01. . Before a game starts. . the ﬁrst step gives us one new entry between 1 and 0 . they draw an integer 1 < n < 4294967295 and the winner is whoever reaches p ≥ n ﬁrst.30] 10.0 Main> trip [15. and so on. The 4
These require a little more thinking and. For example. The idea is to start with two fractions 0 . n 0 1 1 . then Ollie multiplies the number. then right to 2 . Stan always starts with p = 1. We can consider LRRL to be a representation of 7 . then Stan.3. then a string of L’s and R’s uniquely identiﬁes a place in the tree.2
Stern-Brocot Number System
The Stern-Brocot tree is a beautiful way for constructing the set of all i non-negative fractions m n where m and n are relatively prime. .000. . Every positive fraction 7 gets represented in this way as a unique string of L’s and R’s.
3. Let us use the letters “L” and “R” to stand for going down the left or right branch as we proceed from the root of the tree to a particular fraction.00. Main> trip [10. then right 1 2 3 5 3 to 4 . There are no more than 1000 students and no student spent more than $10. For example. regard the Stern-Brocot tree as a number system for representing rational numbers. 1 3 2 3 1 2 1 1 0 The entire array can be regarded as an inﬁnite binary tree structure whose top levels are shown in Figure 3. This construction preserves order. 1 1 0 and the next gives two more: 0 1 1 2 1 . in fact. almost every fraction. For example.equalize the students’ costs. 1 2 1 1 0
The next gives four more:
0 1 1 2 1 3 2 3 1 . .1
A Multiplication Game
Stan and Ollie play the game of multiplication by multiplying an integer p by one of the numbers 2 to 9. a little more code.20.2.3. . given n will return either the string “Stan wins” or “Ollie wins” assuming that both of them play perfectly. LRRL means that we go left from 1 down to 1 . Main> play 162 "Stan wins" Main> play 17 "Ollie wins" Main> play 34012226 "Stan wins"
3. For example.
He calculated the value of k which minimized the number of movements and found that 18. Calculate the k that minimizes the number of transfers under this strategy. Deﬁne a function rep :: ( Int. given a positive rational fraction. and 13 seconds with this scheme versus over 500. since that looks something like 1 1 and stands for “identity.0 1 1 1
Figure 1: The ﬁrst few levels of the Stern-Brocot tree fraction 1 corresponds to the empty string. returns the number of movements required to transfer the 5
.433 transfers would suﬃce. given a pair of integers m and n that are relatively prime returns the representation of the given fraction m in the Stern-Brocot n number system.000 million years without the additional needle! Try to follow the clever priest’s strategy and calculate the number of transfers using four needles. Thus they could spend just 5 hours.323) "RRLRRLRLLLLRLRRR"
The Priest Mathematician
The ancient folklore behind the “Towers of Hanoi” puzzle is quite well known. Deﬁne two functions. • Finally. Int ) -> String that. One of the priests at the temple informed his colleagues that they could achieve the transfer in single afternoon at a one disc-per-second rhythm by using an additional needle. given the number of disks.7) "LRRL" Main> rep (878. Firstly a function nMoves :: Int -> Integer that. • Then use the standard three needles strategy to move the remaining n−k discs (for a general case with n discs) to their destination. 7 minutes.Brocot number system. move the top k discs into their ﬁnal destination using the four needles. they decided to ﬁnd a faster strategy and be done with it.” In this problem. where the priest can move only one disc at a time and must place each disc on a needle such that there is no smaller disc below it. He proposed the following strategy: • First move the topmost discs (say the top k discs) to one of the spare needles. A more recent legend tells us that once the Brahmin monks discovered how long it would take to ﬁnish transferring the 64 discs from the needle which they were on to one of the other needles. represent it in the Stern. Main> rep (5. to be transferred. For example. We will denote it by I. 0 ≤ n ≤ 100.
3).3).(1.f. no two letters are replaced by the same letter. 1.2). given a dictionary of words and an encrypted string. To ensure that the encryption is reversible.(2.(3.(1.1). Secondly. computing Fibonnaci numbers the naive way. each letter of the alphabet is consistently replaced in the text by some other letter. If there is no solution.3). assuming that each line uses a diﬀerent set of replacements..1)."spot".(1..4).4). 2."puff". and that all words in the decrypted text are from a dictionary of known words. to be transferred.(2. optimum k) for each value of n from 0..(3.(1.3).(4.4)] Hint: The key to an eﬃcient solution here is a technique called memoisation which turns out to be very closely related to the general problem-solving technique of dynamic programming. deﬁne a function moves :: Int -> [ ( Int.(2.(4.1). c.(3.(1. the “table” might be implemented as a list where each element is deﬁned in terms of previously computed elements.4).(1. (2.(3.(4.4). (1.2). replace every letter of the alphabet by an asterisk. Main> nMoves 1 1 Main> nMoves 28 769 Main> nMoves 64 18433 Main> moves 3 [(1.3).(3.4
A common but insecure method of encrypting text is to permute the letters of the alphabet. Note: the use of Integer arithmetic will avoid problems of arithmetic overﬂow. Assume the needles are numbered 1.(1.(3.4)] Main> moves 8 [(1.4). 3 and 4 and that the disks are to be moved from needle 1 to needle 4 using needles 2 and 3 as ‘spares’. If there are multiple solutions.1)."dick"."yertle"] "bjvg xsb hxsn xsb qymm xsb rqat xsb pnetfn" "dick and jane and puff and spot and yertle" Main> decrypt ["and"."jane". (1. it is a look-up table mapping a given n to a corresponding pair.2). i.(1.(1.2). In Haskell."dick".(1."yertle"] "xxxx yyy zzzz www yyyy aaa bbbb ccc dddddd" "**** *** **** *** **** *** **** *** ******"
.(2.(1. Main> decrypt ["and". Int ) ] that.(4. If you write a recursive function to solve the problem of ﬁnding the number of movements and optimum k for a pile of n disks you’ll ﬁnd that you end up recomputing that function repeatedly with the same value of n.(4.(1.4). To get round this try building a “table” of pairs of the form (numbers of moves."spot".
3. The purpose of the table is to “remember” values previously computed by the function."puff".2). returns the string decrypted using the dictionary."jane". upwards. returns the sequence of movements required to move the n disks from one needle to another.4).4). n = 0.4). In other words. For example.1).2). For example.3).2). given the number of disks. 1.3).4).(2. 2.4).4).4). any one will do.1). 0 ≤ n ≤ 100.e.(2.(1. Your task is to decrypt several encoded lines of text.n disks from one needle to another using the strategy described. Deﬁne a function decrypt :: [ String ] -> String -> String that.(3.4).(2.4). A really neat way to do this is to build an inﬁnite list where the nth element delivers the numbers of moves and optimum k for n disks.2).(4.
has a higher rank.(8. 8.0).14) where 14 denotes an ace.3). "White wins" or "Tie" depending on the relative value of the two hands.2).3. Four of a Kind Four cards with the same value. the hands are ranked by the next highest. king.1).2). If the highest cards have the same value.(3. the hands are ranked by the values of the cards not forming the pair.2). which is a number from 0 to 3 (clubs.0). Hands which both contain two pairs are ranked by the value of their highest pair. 3. Each card has a suit of either clubs.2)] "White wins" Main> score [(2.5
A poker deck contains 52 cards.. Hands which both contain three of a kind are ranked by the value of the three cards.1).2)] "Tie"
. queen. and so on. given the ten cards deﬁning the two hands.(2.2).(13.(5.(4.(13.2).0). Each card also has a value of either 2 through 10. Poker hands are ranked by the following partial order from lowest to highest. 1.(3.(2.3).2). 2.2). or spades.(9. Hands which are both ﬂushes are ranked using the rules for High Card.(13. Ranked by the highest card in the hand.(14.3)] "Black wins" Main> score [(2. Each card has a value (2. Ranked by the value of the four cards..0). The suit has no impact on value.(12.2).0). with 2 having the lowest and ace the highest value.2)] "Black wins" Main> score [(2.. Two Pairs The hand contains two diﬀerent pairs.(9.3).(3.(8.3). 9. A pair of hands is a designation of ten cards: the ﬁrst ﬁve cards are the hand for the player named “Black” and the next ﬁve cards are the hand for the player named “White”. Full House Three cards of the same value.(13.3).0). jack.0). 5. in decreasing order. or ace.1). If these values are the same the hands are ranked by the value of the remaining card.(14. Hands which both contain a pair are ranked by the value of the cards forming the pair. if either. hearts.(5.(4. For scoring purposes card values are ordered as above. 6.(3. Ranked by the value of the three cards. Three of a Kind Three of the cards in the hand have the same value. For example.(4.(13.(2.1).1). Flush The hand contains ﬁve cards of the same suit.3).(3. diamonds.(2. Straight Flush Five cards of the same suit with consecutive values. Pair Two of the ﬁve cards in the hand have the same value. with the remaining two cards forming a pair.
Main> score [(2. If these values are the same. 7. Int) ] Deﬁne a function score :: Hand -> String that.(9. diamonds.3). Hands with the same highest pair are ranked by the value of their other pair. Your job is to compare several pairs of poker hands and to indicate which.(3. hearts and spades respectively)..(2. returns a string which is either "Black wins".3. High Card Hands which do not ﬁt any higher category are ranked by the value of their highest card. and a suit.(5. A poker hand consists of ﬁve cards dealt from the deck.1).1).1). Thus: type Hands = [ (Int.3).1).(8.(4.(9. Hands which both contain a straight are ranked by their highest card.3).(5.0). Straight The hand contains ﬁve cards with consecutive values.(4.3).(3.3). 4.
223. and a strategy for achieving this time.229.214.220. At most two people may cross at any time.115] Main> solve[ 216.113] Main> solve [-1. returns the total number of seconds required for all n people to cross the bridge. For example.224. this ambiguity is of no consequence.0.1.2
Any set of n integers form n(n − 1)/2 sums by adding every possible pair.204.210] [101.886] Main> solve [1. [ [ Int ] ] ) that.225. Your testing strategy is crucial to success.0. For example Main> solve [1.107. Note that the crossings alternate directions. Each person has a diﬀerent crossing speed. Your job is to determine a strategy that gets all n people across the bridge in the minimum time.-1. Deﬁne a function solve :: [ Int ] -> ( Int.Note that these correspond to the four deals: 2H 2H 2H 2H 3D 4S 3D 3D 5S 4C 5S 5S 9C 2D 9C 9C KD 4H KD KD 2C 2S 2C 2D 3H 8S 3H 3H 4S AS 4S 5C 8C QS 8C 9S AH 3S KH KH
These are particularly ﬁddly problems requiring rather more thought. returns n integers in non-descending order such that the input numbers are pairwise sums of the n numbers.109.777. the speed of a group is determined by the speed of the slower member.208.-1. Deﬁne a function solve :: [ Int ] -> [ [ Int ] ] that. Each person is indicated by the crossing time speciﬁed in the input. You may ﬁnd that you think you’ve solved the problem. If there is no solution.0.-1] [-1.-1. so some sort of shuttle arrangement must be arranged in order to return the ﬂashlight so that more people may cross. If there is more than one solution. and each group must have a ﬂashlight.184.108.40.206. given n(n−1)/2 integers.[10.1]
. Main> solve [1269.225.2].1160. Each entry in the strategy is a list containing either one or two integers. Only one ﬂashlight is available among the n people.-220.127.116.11.113.226.1663] [383. any one will do.114. any one will do. Although many people may have the same crossing time.112.[[1.216.
4.227] [111. given the crossing times for each of the people.212...[1.10] (17. If more than one strategy yields the minimal time. return the empty list.5.5].222. Your task is to ﬁnd the n integers given the set of sums.1]  Main> solve [226.1
A group of n people wish to cross a bridge at night.2]])
4. as it is necessary to return the ﬂashlight so that more may cross.103.0. only to discover that a deep subtlety lies within. indicating which person or people form the next group to cross.
Each number can be used at most once (or not at all) and only integer arithmetic is permitted. and each card. will deliver the required target value. face down.8] 26 "" Main> solve [9.1. * and /. In other words. -. For example. and target. In this variation of the game there will be at least one card and at most six. If there is more than one solution any one will do. Carol Vorderman is the brainy assistant on the show who can invariably ﬁnd a solution when the contestants can’t.4.4. The game involves combining the numbers on the cards using the operators +. Thus / can only be used provided the ﬁrst operand is an integer multiple of the second. Main> [2.5. Contestants select six cards. The solution should be a string comprising the text of a valid Haskell expression that.
. If there is no solution return "". A random number generator then picks a random target total. each of which has a number printed on it. one component of which is a “numbers game”. you’re task is to build a virtual “Carol Vorderman”1! Deﬁne a function solve :: [ Int ] -> Int -> String that takes the card numbers and the target total and computes a solution to the game. may assume any integer value. Contestants have 30 seconds to solve the problem.9. when computed.5
Bonus Problem – Countdown
Countdown is a popular day-time TV quiz show. to equal the total.75] 658 "(2*(9+(4*(5+75))))" Main> solve [9. Your job is is to show the contestants how to they could have solved the problem.8] (-17) "(1-((9*8)/4))"
1 In case you don’t know.4. should they fail to solve it themselves in the time available.1. if one exists.