Difference between revisions of "99 questions/90 to 94"

From HaskellWiki
Jump to navigation Jump to search
(slight change in 8 queens solutions)
m (added problem 95 and wiki link to solutions for problem 97 (sudoku))
Line 31: Line 31:
 
where isSafe try alreadySet = not (sameRow try alreadySet || sameDiagonal try alreadySet)
 
where isSafe try alreadySet = not (sameRow try alreadySet || sameDiagonal try alreadySet)
 
sameRow try alreadySet = try `elem` alreadySet
 
sameRow try alreadySet = try `elem` alreadySet
sameDiagonal try alreadySet = not . null . filter (\(col,q) -> abs(try - q) == col) $ zip [1..] alreadySet
+
sameDiagonal try alreadySet = any (\(col,q) -> abs(try - q) == col) $ zip [1..] alreadySet
 
</haskell>
 
</haskell>
   
Line 116: Line 116:
 
== Problem 95 ==
 
== Problem 95 ==
   
  +
English number words
<Problem description>
 
  +
  +
On financial documents, like cheques, numbers must sometimes be written in full words. Example: 175 must be written as one-seven-five. Write a predicate full-words/1 to print (non-negative) integer numbers in full words.
   
 
<pre>
 
<pre>
Example:
 
<example in lisp>
 
 
 
Example in Haskell:
 
Example in Haskell:
  +
> numbers 175
<example in Haskell>
 
  +
one-seven-five
 
</pre>
 
</pre>
   
 
Solution:
 
Solution:
 
<haskell>
 
<haskell>
  +
import Data.List
<solution in haskell>
 
  +
import Data.Maybe
  +
  +
numbers :: Integer -> String
  +
numbers n = concat . intersperse "-" . map (fromJust . (`lookup` table)) $ show n
  +
where table = [('0',"zero"), ('1',"one"), ('2',"two"), ('3',"three"), ('4',"four"),
  +
('5',"five"), ('6',"six"), ('7',"seven"), ('8',"eight"), ('9',"nine")]
 
</haskell>
 
</haskell>
   
  +
This solution does a simple table lookup after converting the positive integer into a string. Thus dividing into digits is much simplified.
<description of implementation>
 
  +
 
 
== Problem 96 ==
 
== Problem 96 ==
   
Line 154: Line 160:
 
== Problem 97 ==
 
== Problem 97 ==
   
  +
Sudoku
<Problem description>
 
  +
  +
Sudoku puzzles go like this:
   
 
<pre>
 
<pre>
  +
Problem statement Solution
Example:
 
<example in lisp>
 
   
  +
. . 4 | 8 . . | . 1 7 9 3 4 | 8 2 5 | 6 1 7
Example in Haskell:
 
  +
| | | |
<example in Haskell>
 
  +
6 7 . | 9 . . | . . . 6 7 2 | 9 1 4 | 8 5 3
</pre>
 
  +
| | | |
  +
5 . 8 | . 3 . | . . 4 5 1 8 | 6 3 7 | 9 2 4
  +
--------+---------+-------- --------+---------+--------
  +
3 . . | 7 4 . | 1 . . 3 2 5 | 7 4 8 | 1 6 9
  +
| | | |
  +
. 6 9 | . . . | 7 8 . 4 6 9 | 1 5 3 | 7 8 2
  +
| | | |
  +
. . 1 | . 6 9 | . . 5 7 8 1 | 2 6 9 | 4 3 5
  +
--------+---------+-------- --------+---------+--------
  +
1 . . | . 8 . | 3 . 6 1 9 7 | 5 8 2 | 3 4 6
  +
| | | |
  +
. . . | . . 6 | . 9 1 8 5 3 | 4 7 6 | 2 9 1
  +
| | | |
  +
2 4 . | . . 1 | 5 . . 2 4 6 | 3 9 1 | 5 7 8
 
</pre>
   
  +
Every spot in the puzzle belongs to a (horizontal) row and a (vertical) column, as well as to one single 3x3 square (which we call "square" for short). At the beginning, some of the spots carry a single-digit number between 1 and 9. The problem is to fill the missing spots with digits in such a way that every number between 1 and 9 appears exactly once in each row, in each column, and in each square.
Solution:
 
<haskell>
 
<solution in haskell>
 
</haskell>
 
   
  +
see [[Sudoku]]
<description of implementation>
 
 
 
 
== Problem 98 ==
 
== Problem 98 ==

Revision as of 05:01, 13 December 2006


These are Haskell translations of Ninety Nine Lisp Problems.

If you want to work on one of these, put your name in the block so we know someone's working on it. Then, change n in your block to the appropriate problem number, and fill in the <Problem description>,<example in lisp>,<example in Haskell>,<solution in haskell> and <description of implementation> fields.

Miscellaneous problems

Problem 90

Eight queens problem

This is a classical problem in computer science. The objective is to place eight queens on a chessboard so that no two queens are attacking each other; i.e., no two queens are in the same row, the same column, or on the same diagonal.

Hint: Represent the positions of the queens as a list of numbers 1..N. Example: [4,2,7,3,6,8,5,1] means that the queen in the first column is in row 4, the queen in the second column is in row 2, etc. Use the generate-and-test paradigm.

Example in Haskell:
> length queens
92
> take 1 queens
[[4,2,7,3,6,8,5,1]]

Solution:

queens = queens' 8

queens' 0     = [[]]
queens' (n+1) = [ try:alreadySet | alreadySet <- queens' n, try <- [1..8], isSafe try alreadySet]
    where isSafe try alreadySet       = not (sameRow try alreadySet || sameDiagonal try alreadySet)
          sameRow try alreadySet      = try `elem` alreadySet
          sameDiagonal try alreadySet = any (\(col,q) -> abs(try - q) == col) $ zip [1..] alreadySet

By definition/data representation no two queens can occupy the same column. "try `elem` alreadySet" checks for a queen in the same row, "abs(try - q) == col" checks for a queen in the same diagonal.

This is a modification of a function I wrote when I was just learning haskell, so there's certainly much to improve here! For one thing there is speedup potential in caching "blocked" rows, columns and diagonals.

Problem 91

<Problem description>

Example:
<example in lisp>

Example in Haskell:
<example in Haskell>

Solution:

<solution in haskell>

<description of implementation>

Problem 92

<Problem description>

Example:
<example in lisp>

Example in Haskell:
<example in Haskell>

Solution:

<solution in haskell>

<description of implementation>

Problem 93

<Problem description>

Example:
<example in lisp>

Example in Haskell:
<example in Haskell>

Solution:

<solution in haskell>

<description of implementation>

Problem 94

<Problem description>

Example:
<example in lisp>

Example in Haskell:
<example in Haskell>

Solution:

<solution in haskell>

<description of implementation>

Problem 95

English number words

On financial documents, like cheques, numbers must sometimes be written in full words. Example: 175 must be written as one-seven-five. Write a predicate full-words/1 to print (non-negative) integer numbers in full words.

Example in Haskell:
> numbers 175
one-seven-five

Solution:

import Data.List
import Data.Maybe

numbers :: Integer -> String
numbers n = concat . intersperse "-" . map (fromJust . (`lookup` table)) $ show n
    where table = [('0',"zero"), ('1',"one"), ('2',"two"),   ('3',"three"), ('4',"four"), 
                   ('5',"five"), ('6',"six"), ('7',"seven"), ('8',"eight"), ('9',"nine")]

This solution does a simple table lookup after converting the positive integer into a string. Thus dividing into digits is much simplified.

Problem 96

<Problem description>

Example:
<example in lisp>

Example in Haskell:
<example in Haskell>

Solution:

<solution in haskell>

<description of implementation>

Problem 97

Sudoku

Sudoku puzzles go like this:

       Problem statement                 Solution

        .  .  4 | 8  .  . | .  1  7	     9  3  4 | 8  2  5 | 6  1  7	     
                |         |                          |         |
        6  7  . | 9  .  . | .  .  .	     6  7  2 | 9  1  4 | 8  5  3
                |         |                          |         |
        5  .  8 | .  3  . | .  .  4          5  1  8 | 6  3  7 | 9  2  4
        --------+---------+--------          --------+---------+--------
        3  .  . | 7  4  . | 1  .  .          3  2  5 | 7  4  8 | 1  6  9
                |         |                          |         |
        .  6  9 | .  .  . | 7  8  .          4  6  9 | 1  5  3 | 7  8  2
                |         |                          |         |
        .  .  1 | .  6  9 | .  .  5          7  8  1 | 2  6  9 | 4  3  5
        --------+---------+--------          --------+---------+--------
        1  .  . | .  8  . | 3  .  6	     1  9  7 | 5  8  2 | 3  4  6
                |         |                          |         |
        .  .  . | .  .  6 | .  9  1	     8  5  3 | 4  7  6 | 2  9  1
                |         |                          |         |
        2  4  . | .  .  1 | 5  .  .          2  4  6 | 3  9  1 | 5  7  8

Every spot in the puzzle belongs to a (horizontal) row and a (vertical) column, as well as to one single 3x3 square (which we call "square" for short). At the beginning, some of the spots carry a single-digit number between 1 and 9. The problem is to fill the missing spots with digits in such a way that every number between 1 and 9 appears exactly once in each row, in each column, and in each square.

see Sudoku

Problem 98

<Problem description>

Example:
<example in lisp>

Example in Haskell:
<example in Haskell>

Solution:

<solution in haskell>

<description of implementation>

Problem 99

<Problem description>

Example:
<example in lisp>

Example in Haskell:
<example in Haskell>

Solution:

<solution in haskell>

<description of implementation>