Difference between revisions of "FP Homework 1"

From Marek Běhálek Wiki
Jump to navigation Jump to search
(Created page with "== 1 - Šachová pozice == Napište funkci sachy, která má 2 argumenty typu seznam řetězců. Řetězce v seznamech obsahují 3 znaky: - první určuje šachovou figuru ('...")
 
 
(49 intermediate revisions by the same user not shown)
Line 1: Line 1:
== 1 - Šachová pozice ==
+
<translate>
 +
== Basic notes == <!--T:1-->
  
Napište funkci sachy, která má 2 argumenty typu seznam řetězců. Řetězce v seznamech obsahují 3 znaky:
+
<!--T:2-->
- první určuje šachovou figuru ('K' - král, 'D' - dáma, 'V' - věž, 'S' - střelec, 'J' - jezdec, 'P' - pěšec)
+
In all exercises you are required to write something to standard output. You can use the same strategy as in  [[FP_Laboratory_7 | Laboratory 7]].  
- druhý znak určuje sloupec ('a'-'h')
 
- třetí je číslo řádku ('1'-'8')
 
První seznam reprezentuje aktuální rozmístění bílých figur a druhý černých. Vypište aktuální pozici tak, že volná políčka budou reprezentována znakem '.', bílé figury svým písmenem velkým a černé figury svým písmenem malým. Řádky i sloupce budou označeny čísly resp. písmeny.
 
  
sachy ["Ke1","Va1","Vh1","Pa2","Se5"] ["Ke8","Va8","Vh8","Pa7","Dd8","Sc8","Jb8"]
+
<!--T:3-->
 +
Lets define a type for the result:
 +
</translate>
 +
<syntaxhighlight lang="Haskell">type Result = [String]</syntaxhighlight>
 +
<translate>
 +
<!--T:4-->
 +
Now, if you want to print this result nicely on the screen, you can use:
 +
</translate>
 +
<syntaxhighlight lang="Haskell">
 +
pp :: Result -> IO ()
 +
pp x = putStr (concat (map (++"\n") x))
 +
</syntaxhighlight>
  
8vjsdk..v
+
<translate>
 +
== Example - Ships == <!--T:12-->
 +
 
 +
<!--T:13-->
 +
Implement the function <code>ships</code> which has 2 arguments. First argument is a list of strings representing play field of one player row by row from top to bottom ('o' - square containing a ship, ' ' - empty square). Second list contains coordinates of squares attacked by second player. Print actual state of a play in the way where every row and column will be labelled by its number or letter, 'o' will be square with ship not attacked yet, 'x' square with ship already attacked, '.' already attacked empty square, ' ' empty square not attacked yet. You can consider that the size of play-field is 10x10. 
 +
</translate>
 +
 
 +
<div style="float: right"> [[File:Video logo.png|80px|link=https://youtu.be/NC6pb3R7A0g]]</div>
 +
<div style="clear:both"></div>
 +
 
 +
<syntaxhighlight lang="Haskell">
 +
ships :: Result -> [(Char, Int)] -> Result
 +
sampleInput = ["  o    o  ",
 +
              "      ooo ",
 +
              "  oo    ",
 +
              "          ",
 +
              "    o    ",
 +
              "    o    ",
 +
              "    o    ",
 +
              "          ",
 +
              "          ",
 +
              "  oooo    "]
 +
</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark" >
 +
Prelude>pp(ships sampleInput [('a',1),('d',1),('d',2),('c',1),('b',1),('e',1),('f',1),('g',1),('c',7),('c',10)])
 +
10  x    o
 +
  9      ooo
 +
  8  oo
 +
  7  .
 +
  6    o
 +
  5    o
 +
  4    o
 +
  3
 +
  2  .
 +
  1..xxxx.
 +
  abcdefghij
 +
</syntaxhighlight>
 +
<div class="mw-collapsible mw-collapsed" data-collapsetext="Hide solution" data-expandtext="Show solution">
 +
<syntaxhighlight lang="Haskell">
 +
import Data.Char ( ord )
 +
type Result = [String]
 +
 
 +
pp :: Result -> IO ()
 +
pp x = putStr (concat (map (++"\n") x))
 +
 
 +
sampleInput :: Result
 +
sampleInput = ["  o    o  ",
 +
              "      ooo ",
 +
              "  oo    ",
 +
              "          ",
 +
              "    o    ",
 +
              "    o    ",
 +
              "    o    ",
 +
              "          ",
 +
              "          ",
 +
              "  oooo    "]
 +
 
 +
ships :: Result -> [(Char, Int)] -> Result
 +
ships input coordinates = let
 +
    coordinates' = [(ord ch - ord 'a' +1 ,ri) |(ch, ri)<-coordinates]
 +
    get x ch | elem x coordinates' = if ch == 'o' then 'x' else '.'
 +
            | otherwise = ch
 +
    niceShow x = let
 +
        number' = show x
 +
        in if length number' == 1 then "  "++number' else " "++number'       
 +
    nicePrint result = reverse [niceShow number ++ row|(number,row)<-zip [1..] result] ++ ["  abcdefghij"]
 +
    in nicePrint ([[get (ci,ri) ch |(ci,ch)<- zip [1..] row ]| (ri,row)<-zip [1..] (reverse input)])
 +
</syntaxhighlight>
 +
</div>
 +
<div style="clear:both"></div>
 +
 
 +
<translate>
 +
 
 +
== 1 - Magic 15 Puzzle == <!--T:16-->
 +
 
 +
<!--T:17-->
 +
Implement the function <code>puzzle</code>, it will simulate the game similar to [https://en.wikipedia.org/wiki/15_puzzle 15 Puzzle]. In our case, we have 25 squares, where 24 squares are ocupied by tiles with big case letters from <code>'A'</code> to <code>'X'</code>. One tile is free, it is denotated by <code>' '</code>. In one move, you can move a tile (denotated by its letter) into the free one. The function gets the original configuration and a sequence of '''valid''' moves. It will output the resulting configuration.
 +
</translate>
 +
<syntaxhighlight lang="Haskell">
 +
puzzle2 = ["AC DE",
 +
          "FBHIJ",
 +
          "KGLNO",
 +
          "PQMRS",
 +
          "UVWXT"]
 +
 
 +
puzzle :: Result -> [Char] -> Result
 +
</syntaxhighlight>
 +
 
 +
<syntaxhighlight lang="Haskell" class="myDark" >
 +
*Main> pp(puzzle puzzle2 "CBGLMRST")                   
 +
ABCDE
 +
FGHIJ
 +
KLMNO
 +
PQRST
 +
UVWX
 +
</syntaxhighlight>
 +
 
 +
<translate>
 +
== 2 - Crossword Answers == <!--T:18-->
 +
 
 +
<!--T:19-->
 +
Implement the function <code>answers</code> that takes as an input a crosword puzzle's solution and outputs all words from this solution. Words will be divided into two lists, first for lines (from left to right) and second for columns (from top to bottom).  A word is written only if it is longer than just one character.
 +
 
 +
<!--T:20-->
 +
*TIP: ''Use the function'' <code>words :: String -> [String]</code> ''to split lines into sequence of words.''
 +
</translate>
 +
 
 +
<syntaxhighlight lang="Haskell" class="myDark" >
 +
*Main> words "ABC cdef ghijkl"
 +
["ABC","cdef","ghijkl"]
 +
</syntaxhighlight>
 +
 
 +
<syntaxhighlight lang="Haskell">
 +
solution1 = ["DAD  SEND",
 +
            "O EAST  A",
 +
            "W A  ITSY",
 +
            "NERF N T ",
 +
            " A ARK U ",
 +
            " S T SYNC",
 +
            "MESH  A A",
 +
            "A  EVER R",
 +
            "NEAR  D D"]
 +
 
 +
answers :: Result -> ([String],[String])
 +
</syntaxhighlight>
 +
 
 +
<syntaxhighlight lang="Haskell" class="myDark" >
 +
*Main> answers solution1
 +
(["DAD","SEND","EAST","ITSY","NERF","ARK","SYNC","MESH","EVER","NEAR"],["DOWN","MAN","EASE","DEAR","FATHER","STINKS","YARD","STUN","DAY","CARD"])
 +
</syntaxhighlight>
 +
 
 +
<translate>
 +
== 3 - Creating Crossword Puzzles== <!--T:21-->
 +
 
 +
<!--T:22-->
 +
In this task, you will implement a function, that helps when creating the crossword puzzle. The function <code>positions</code> takes an input, an ''outline'' for the future puzzle, and prints all positions, where we need to put some words. The outline compose from empty spaces (<code>'.'</code>), where we can put some character, and from black boxes (<code>'#'</code>), where there are no characters. In our crossword puzzles, words need to be placed in all sequences of empty spaces, that are at least two spaces long. The functions output is all starting positions where we need to put some words. Positions are pairs <code>(row, column)</code>. They are indexed from topmost leftmost corner with coordinates <code>(0,0)</code>. Consider only words in '''lines''' (for rows, we can rotate and flip the puzzle outline and use the same function).
 +
</translate>
 +
 
 +
<syntaxhighlight lang="Haskell">
 +
--An example of a crossword puzzle with the same outline is in the previous task.
 +
crossword = ["...##....",
 +
            ".#....##.",
 +
            ".#.##....",
 +
            "....#.#.#",
 +
            "#.#...#.#",
 +
            "#.#.#....",
 +
            "....##.#.",
 +
            ".##....#.",
 +
            "....##.#."]
 +
 
 +
positions :: Result -> [(Int,Int)]
 +
</syntaxhighlight>
 +
 
 +
<syntaxhighlight lang="Haskell" class="myDark" >
 +
*Main> positions crossword
 +
[(0,0),(0,5),(1,2),(2,5),(3,0),(4,3),(5,5),(6,0),(7,3),(8,0)]
 +
</syntaxhighlight>
 +
 
 +
<translate>
 +
== 4 - Decoder == <!--T:23-->
 +
 
 +
<!--T:24-->
 +
On possibility how to encode text is to replace frequent pairs of characters by a new (until that time, not used) character.
 +
In this task, you should implement a function that decodes such encoded text. The function <code>decode</code> takes an encoded text and a vocabulary. Vocabulary is a sequence of pairs, where the first element is an encoded character (<code>Char</code>) and the second element is the original pair (as <code>String</code> of the length 2). The result is an original text. In fact, it is the text from the parameter, where all encoded characters were replaced by its original pairs of characters.
 +
</translate>
 +
 
 +
<syntaxhighlight lang="Haskell">
 +
decode :: String -> [(Char,String)] -> String
 +
</syntaxhighlight>
 +
 
 +
<syntaxhighlight lang="Haskell" class="myDark" >
 +
*Main> decode "HAHA" [('E',"AB"),('F',"CD"),('G',"EF"),('H',"GG")]
 +
"ABCDABCDAABCDABCDA"
 +
</syntaxhighlight>
 +
 
 +
<translate>
 +
== 5 - Prefix Decoder == <!--T:25-->
 +
 
 +
<!--T:26-->
 +
One possibility, how to code characters into the binary code is to use prefix coding (an example can be  [https://en.wikipedia.org/wiki/Huffman_coding Huffman coding] ). In this coding, a given code is not ''a prefix'' of any other code. If for example, one letter is coded as <code>101</code>, then no other letter's code starts with the same sequence <code>101</code>. In this task, write a function <code>toText</code>, that takes an encoded binary sequence (in our case <code>String</code> composed from <code>1</code> and <code>0</code>) along with a dictionary, and produces the original text like a result. Dictionary compose of pairs, where each pair contains the encrypted character (<code>Char</code>) and a sequence (<code>String</code>) of <code>1</code> and <code>0</code> - assigned prefix code. Safely assume, that all inputs are '''valid'''.
 +
</translate>
 +
 
 +
<syntaxhighlight lang="Haskell">
 +
dictionary = [('a',"0"),('b',"101"),('c',"100"),('d',"111"),('e',"1101"),('f',"1100")]
 +
 
 +
toText :: String->[(Char, String)]->String
 +
</syntaxhighlight>
 +
 
 +
<syntaxhighlight lang="Haskell" class="myDark" >
 +
*Main> toText "01011001111101" dictionary
 +
"abcde"
 +
</syntaxhighlight>
 +
 
 +
<translate>
 +
== 6 - Chess position == <!--T:5-->
 +
 
 +
<!--T:6-->
 +
Implement the function <code>chess</code> which has 2 arguments of the type <code>[String]</code>. Each of these strings in both lists contain 3 characters:
 +
* first stands for chess piece ('K' - king, 'Q' - queen, 'R' - rook, 'B' - bishop, 'N' - knight, 'P' - pawn)
 +
* second stands for column ('a'-'h')
 +
* third is row ('1'-'8')
 +
First list contains actual positions of white pieces and second list positions of black pieces. Print actual state of a chessboard in the way where '.' stands for empty square, capital letters mean white pieces and small letters mean black pieces. Each row and column should be labeled by its number or letter.
 +
</translate>
 +
<syntaxhighlight lang="Haskell">
 +
chess :: [String] -> [String] -> Result
 +
</syntaxhighlight>
 +
 
 +
<syntaxhighlight lang="Haskell" class="myDark" >
 +
Prelude> pp( chess["Ke1","Ra1","Rh1","Pa2","Be5"] ["Ke8","Ra8","Rh8","Pa7","Qd8","Bc8","Nb8"])
 +
8rnbqk..r
 
7p.......
 
7p.......
 
6........
 
6........
5....S...
+
5....B...
 
4........
 
4........
 
3........
 
3........
 
2P.......
 
2P.......
1V...K..V
+
1R...K..R
 
  abcdefgh
 
  abcdefgh
 
+
</syntaxhighlight>
== 2 - Piškvorky ==
+
<translate>
 +
== 7 - Ticktacktoe == <!--T:7-->
 
   
 
   
Napište funkci sachPozice, která má 2 argumenty. První je dvojice přirozených čísel určující počet řádků a sloupců hrací plochy. Druhý seznam reprezentuje průběh hry piškvorky, kde jsou souřadnice políček, na které střídavě hrál hráč 'x' a hráč 'o'. Vypište aktuální stav hry tak, že hrací pole bude ohraničeno znaky '-' a '|', volné pozice ' ' a znaky 'x' a 'o' budou na pozicích, kam zahráli příslušní hráči.
+
Implement the function <code>ticktack</code> which has 2 arguments. First argument is a tuple of natural numbers and defines the number of columns and rows  of a play field. Coordinates are counted from bottom left corner. Second list contains a record of a match of ticktacktoe game given by coordinates on which played in turns player 'x' and player 'o'. Print actual state of the game in the way where play-field will be bordered by characters '-' and '|', empty squares ' ' and characters 'x' and 'o' will be on squares where the players have played.
 
+
</translate>
piskvorky (8,8) [(1,1),(8,8),(2,2,)(3,3)(4,2)(3,2)]
+
<syntaxhighlight lang="Haskell">
 
+
ticktack::(Int,Int) -> [(Int,Int)] -> Result
 +
</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark" >
 +
Prelude>pp(ticktack (8,8) [(1,1),(8,8),(2,2),(3,3),(4,2),(3,2)])
 
----------
 
----------
 
|      o|
 
|      o|
Line 35: Line 257:
 
|x      |
 
|x      |
 
----------
 
----------
 +
</syntaxhighlight>
  
== 3 - Bludiště ==
+
<translate>
 +
== 8 - Maze == <!--T:8-->
  
Napište funkci bludiste, která má 2 argumenty. Prvním argumentem je seznam řetězců, které reprezentují bludiště po řádcích postupně shora dolů ('*' - stěna, ' ' - průchozí pole, 's' - startovní pozice, 'c' - cílová pozice). Na začátku se nacházíme na pozici 's'. Druhým argumentem je seznam směrů pohybu ('d' - down, 'u' - up, 'l' - left, 'r' - right). Každé písmeno znamená, že se posuneme o 1 buňku daným směrem a na novou pozici umístíme znak '.' Vypište aktuální situaci po provedení všech kroků z druhého seznamu.
+
<!--T:9-->
 
+
Implement the function <code>maze</code> which has 2 arguments. First argument is a list of strings representing a maze row by row from top to bottom ('*' - wall, ' ' - empty square, 's' - starting position). At the beginning we are at position 's'. Second argument is list of directions ('d' - down, 'u' - up, 'l' - left, 'r' - right). Each letter means move by one square in the given direction and on this new square character '.' is placed. Print actual state of a maze.
ukazkovyVstup = ["*********",
+
</translate>
                "*s*  * *",
+
<syntaxhighlight lang="Haskell">
                "* * * * *",
+
maze :: Result -> String -> Result
                "* * * * *",
 
                "*  *  *",
 
                "******* *",
 
                "c      *",
 
                "*********"]
 
               
 
bludiste ukazkovy
 
Vstup "dddrruuurrdddrrddllllll"
 
  
 +
sampleInput = ["*********",
 +
              "*s*  * *",
 +
              "* * * * *",
 +
              "* * * * *",
 +
              "*  *  *",
 +
              "******* *",
 +
              "        *",
 +
              "*********"]
 +
</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark" >
 +
Prelude>pp(maze sampleInput "dddrruuurrdddrrddllllll")
 
*********
 
*********
 
*s*...* *
 
*s*...* *
Line 58: Line 285:
 
*...*...*
 
*...*...*
 
*******.*
 
*******.*
c.......*
+
.......*
 
*********
 
*********
 +
</syntaxhighlight>
  
== 4 - Miny ==
+
<translate>
 
+
== 9 - Minesweeper == <!--T:10-->
Napište funkci miny, která má argument typu seznam řetězců. Řetězce reprezentují hrací plochu po řádcích postupně shora dolů ('*' - mina, ' ' - prázdné pole). Vypište hrací pole tak, že miny budou stále reprezentovány '*', ale na každém políčku bez miny bude číslo znamenající celkový počet min, se kterými toto prázdné pole přímo sousedí (sousedit může vodorovně, svisle i šikmo).
 
 
 
ukazkovyVstup = ["      ",
 
                " *    ",
 
                "    *  ",
 
                "  *  ",
 
                "      *",
 
                "***    ",
 
                "* *    ",
 
                "***    "]
 
 
 
miny ukazkovyVstup
 
  
 +
<!--T:11-->
 +
Implement the function <code>minesweeper</code> which has 1 argument of the type list of strings. The strings represent play field row by row from top to bottom ('*' - mine, ' ' - empty square). Print play field in a way where mines will be represented by '*' and on each square not containing a mine will be a number - count of all mines directly adjacent to this square (it can be adjacent vertically, horizontally or diagonally).
 +
</translate>
 +
<syntaxhighlight lang="Haskell">
 +
minesweeper :: Result -> Result
 +
sampleInput = ["      ",
 +
              " *    ",
 +
              "    *  ",
 +
              "  *  ",
 +
              "      *",
 +
              "***    ",
 +
              "* *    ",
 +
              "***    "]
 +
</syntaxhighlight>
 +
<syntaxhighlight lang="Haskell" class="myDark" >
 +
Prelude>pp(minesweeper sampleInput)
 
1110000
 
1110000
 
1*11110
 
1*11110
Line 84: Line 316:
 
*8*3000
 
*8*3000
 
***2000
 
***2000
 +
</syntaxhighlight>
  
== 5 - Lode ==
+
<translate>
 
+
== 10 - Turtle == <!--T:14-->
Napište funkci lode, která má dva argumenty. První je seznam řetězců, které reprezentují hrací plochu jednoho hráče po řádcích postupně shora dolů ('o' - políčko obsazené lodí, ' ' - prázdné pole). Druhým argumentem je seznam dvojic souřadnic políček, na které druhý hráč zkoušel střílet. Vykreslete aktuální stav hry tak, že řádky a sloupce budou označeny svým číslem resp. písmenem, 'o' bude dosud nezasažené políčko s lodí, 'x' zasažené políčko s lodí, '.' místo, kam se střílelo, ale nic nezasáhlo, ' ' prázdná a dosud nezasažená políčka. Můžete předpokládat hrací plochu velikosti 10x10.
+
Implement a function that will draw the movement of a turtle in a rectangular grid. It will be named <code>draw</code> and it will have one parameter - a list movements. Our turtle can move only horizontally or vertically. Each movement will be described by a pair (its type will be <code>(Char, Int)</code>), where the first character denotates a direction of this movement and the second its length. Possible directions are: <b>l</b>eft, <b>r</b>ight, <b>u</b>p, and <b>d</b>own. As the result, function <code>draw</code> returns a smallest possible rectangle with all turtle's movements. Each block from the grid will be represented with one character. If it was visited by our turtle, then it will be <code>'X'</code>, if it was not, then it will be <code>' '</code>.
 
+
</translate>
ukazkovyVstup = ["  o    o  ",
 
                "      ooo ",
 
                "  oo    ",
 
                "          ",
 
                "          ",
 
                "    o    ",
 
                "    o    ",
 
                "    o    ",
 
                "          ",
 
                "          ",
 
                "  oooo    "]
 
  
lode ukazkovyVstup [('a',1),('d',1),('d',2),('c',1),('b',1),('e',1),('f',1),('g',1),('c',7),('c',10)]
+
<syntaxhighlight lang="Haskell">
    
+
draw :: [(Char, Int)] -> Result
10  x  
+
</syntaxhighlight>
9     ooo
+
<syntaxhighlight lang="Haskell" class="myDark" >
8  oo   
+
*Main> pp (draw [('u',5),('r',5),('d',5),('l',10),('d',5),('r',5),('u',5)])    
7  .     
+
    XXXXXX
6         
+
    X   X
5    o    
+
    X   X
4    o    
+
     X    X
4    o    
+
    X    X
3         
+
XXXXXXXXXXX
2  .     
+
X    X
1..xxxx. 
+
X   X
  abcdefghij
+
X   X
 +
X   X
 +
XXXXXX
 +
</syntaxhighlight>

Latest revision as of 08:53, 7 October 2022

Basic notes

In all exercises you are required to write something to standard output. You can use the same strategy as in Laboratory 7.

Lets define a type for the result:

type Result = [String]

Now, if you want to print this result nicely on the screen, you can use:

pp :: Result -> IO ()
pp x = putStr (concat (map (++"\n") x))

Example - Ships

Implement the function ships which has 2 arguments. First argument is a list of strings representing play field of one player row by row from top to bottom ('o' - square containing a ship, ' ' - empty square). Second list contains coordinates of squares attacked by second player. Print actual state of a play in the way where every row and column will be labelled by its number or letter, 'o' will be square with ship not attacked yet, 'x' square with ship already attacked, '.' already attacked empty square, ' ' empty square not attacked yet. You can consider that the size of play-field is 10x10.

Video logo.png
ships :: Result -> [(Char, Int)] -> Result
sampleInput = ["  o    o  ",
               "      ooo ",
               "   oo     ",
               "          ",
               "     o    ",
               "     o    ",
               "     o    ",
               "          ",
               "          ",
               "  oooo    "]
Prelude>pp(ships sampleInput [('a',1),('d',1),('d',2),('c',1),('b',1),('e',1),('f',1),('g',1),('c',7),('c',10)])
 10  x    o
  9      ooo
  8   oo
  7  .
  6     o
  5     o
  4     o
  3
  2   .
  1..xxxx.
   abcdefghij
import Data.Char ( ord ) 
type Result = [String]

pp :: Result -> IO ()
pp x = putStr (concat (map (++"\n") x))

sampleInput :: Result
sampleInput = ["  o    o  ",
               "      ooo ",
               "   oo     ",
               "          ",
               "     o    ",
               "     o    ",
               "     o    ",
               "          ",
               "          ",
               "  oooo    "]

ships :: Result -> [(Char, Int)] -> Result
ships input coordinates = let
    coordinates' = [(ord ch - ord 'a' +1 ,ri) |(ch, ri)<-coordinates]
    get x ch | elem x coordinates' = if ch == 'o' then 'x' else '.'
             | otherwise = ch
    niceShow x = let 
        number' = show x
        in if length number' == 1 then "  "++number' else " "++number'         
    nicePrint result = reverse [niceShow number ++ row|(number,row)<-zip [1..] result] ++ ["   abcdefghij"]
    in nicePrint ([[get (ci,ri) ch |(ci,ch)<- zip [1..] row ]| (ri,row)<-zip [1..] (reverse input)])


1 - Magic 15 Puzzle

Implement the function puzzle, it will simulate the game similar to 15 Puzzle. In our case, we have 25 squares, where 24 squares are ocupied by tiles with big case letters from 'A' to 'X'. One tile is free, it is denotated by ' '. In one move, you can move a tile (denotated by its letter) into the free one. The function gets the original configuration and a sequence of valid moves. It will output the resulting configuration.

puzzle2 = ["AC DE",
           "FBHIJ",
           "KGLNO",
           "PQMRS",
           "UVWXT"]

puzzle :: Result -> [Char] -> Result
*Main> pp(puzzle puzzle2 "CBGLMRST")                    
ABCDE
FGHIJ
KLMNO
PQRST
UVWX

2 - Crossword Answers

Implement the function answers that takes as an input a crosword puzzle's solution and outputs all words from this solution. Words will be divided into two lists, first for lines (from left to right) and second for columns (from top to bottom). A word is written only if it is longer than just one character.

  • TIP: Use the function words :: String -> [String] to split lines into sequence of words.
*Main> words "ABC cdef ghijkl"
["ABC","cdef","ghijkl"]
solution1 = ["DAD  SEND",
             "O EAST  A",
             "W A  ITSY",
             "NERF N T ",
             " A ARK U ",
             " S T SYNC",
             "MESH  A A",
             "A  EVER R",
             "NEAR  D D"]

answers :: Result -> ([String],[String])
*Main> answers solution1 
(["DAD","SEND","EAST","ITSY","NERF","ARK","SYNC","MESH","EVER","NEAR"],["DOWN","MAN","EASE","DEAR","FATHER","STINKS","YARD","STUN","DAY","CARD"])

3 - Creating Crossword Puzzles

In this task, you will implement a function, that helps when creating the crossword puzzle. The function positions takes an input, an outline for the future puzzle, and prints all positions, where we need to put some words. The outline compose from empty spaces ('.'), where we can put some character, and from black boxes ('#'), where there are no characters. In our crossword puzzles, words need to be placed in all sequences of empty spaces, that are at least two spaces long. The functions output is all starting positions where we need to put some words. Positions are pairs (row, column). They are indexed from topmost leftmost corner with coordinates (0,0). Consider only words in lines (for rows, we can rotate and flip the puzzle outline and use the same function).

--An example of a crossword puzzle with the same outline is in the previous task.
crossword = ["...##....",
             ".#....##.",
             ".#.##....",
             "....#.#.#",
             "#.#...#.#",
             "#.#.#....",
             "....##.#.",
             ".##....#.",
             "....##.#."]

positions :: Result -> [(Int,Int)]
*Main> positions crossword
[(0,0),(0,5),(1,2),(2,5),(3,0),(4,3),(5,5),(6,0),(7,3),(8,0)]

4 - Decoder

On possibility how to encode text is to replace frequent pairs of characters by a new (until that time, not used) character. In this task, you should implement a function that decodes such encoded text. The function decode takes an encoded text and a vocabulary. Vocabulary is a sequence of pairs, where the first element is an encoded character (Char) and the second element is the original pair (as String of the length 2). The result is an original text. In fact, it is the text from the parameter, where all encoded characters were replaced by its original pairs of characters.

decode :: String -> [(Char,String)] -> String
*Main> decode "HAHA" [('E',"AB"),('F',"CD"),('G',"EF"),('H',"GG")]
"ABCDABCDAABCDABCDA"

5 - Prefix Decoder

One possibility, how to code characters into the binary code is to use prefix coding (an example can be Huffman coding ). In this coding, a given code is not a prefix of any other code. If for example, one letter is coded as 101, then no other letter's code starts with the same sequence 101. In this task, write a function toText, that takes an encoded binary sequence (in our case String composed from 1 and 0) along with a dictionary, and produces the original text like a result. Dictionary compose of pairs, where each pair contains the encrypted character (Char) and a sequence (String) of 1 and 0 - assigned prefix code. Safely assume, that all inputs are valid.

dictionary = [('a',"0"),('b',"101"),('c',"100"),('d',"111"),('e',"1101"),('f',"1100")]

toText :: String->[(Char, String)]->String
*Main> toText "01011001111101" dictionary
"abcde"

6 - Chess position

Implement the function chess which has 2 arguments of the type [String]. Each of these strings in both lists contain 3 characters:

  • first stands for chess piece ('K' - king, 'Q' - queen, 'R' - rook, 'B' - bishop, 'N' - knight, 'P' - pawn)
  • second stands for column ('a'-'h')
  • third is row ('1'-'8')

First list contains actual positions of white pieces and second list positions of black pieces. Print actual state of a chessboard in the way where '.' stands for empty square, capital letters mean white pieces and small letters mean black pieces. Each row and column should be labeled by its number or letter.

chess :: [String] -> [String] -> Result
Prelude> pp( chess["Ke1","Ra1","Rh1","Pa2","Be5"] ["Ke8","Ra8","Rh8","Pa7","Qd8","Bc8","Nb8"])
8rnbqk..r
7p.......
6........
5....B...
4........
3........
2P.......
1R...K..R
 abcdefgh

7 - Ticktacktoe

Implement the function ticktack which has 2 arguments. First argument is a tuple of natural numbers and defines the number of columns and rows of a play field. Coordinates are counted from bottom left corner. Second list contains a record of a match of ticktacktoe game given by coordinates on which played in turns player 'x' and player 'o'. Print actual state of the game in the way where play-field will be bordered by characters '-' and '|', empty squares ' ' and characters 'x' and 'o' will be on squares where the players have played.

ticktack::(Int,Int) -> [(Int,Int)] -> Result
Prelude>pp(ticktack (8,8) [(1,1),(8,8),(2,2),(3,3),(4,2),(3,2)])
----------
|       o|
|        |
|        |
|        |
|        |
|  o     |
| xox    |
|x       |
----------

8 - Maze

Implement the function maze which has 2 arguments. First argument is a list of strings representing a maze row by row from top to bottom ('*' - wall, ' ' - empty square, 's' - starting position). At the beginning we are at position 's'. Second argument is list of directions ('d' - down, 'u' - up, 'l' - left, 'r' - right). Each letter means move by one square in the given direction and on this new square character '.' is placed. Print actual state of a maze.

maze :: Result -> String -> Result 

sampleInput = ["*********",
               "*s*   * *",
               "* * * * *",
               "* * * * *",
               "*   *   *",
               "******* *",
               "        *",
               "*********"]
Prelude>pp(maze sampleInput "dddrruuurrdddrrddllllll")
*********
*s*...* *
*.*.*.* *
*.*.*.* *
*...*...*
*******.*
 .......*
*********

9 - Minesweeper

Implement the function minesweeper which has 1 argument of the type list of strings. The strings represent play field row by row from top to bottom ('*' - mine, ' ' - empty square). Print play field in a way where mines will be represented by '*' and on each square not containing a mine will be a number - count of all mines directly adjacent to this square (it can be adjacent vertically, horizontally or diagonally).

minesweeper :: Result -> Result
sampleInput = ["       ",
               " *     ",
               "    *  ",
               "   *   ",
               "      *",
               "***    ",
               "* *    ",
               "***    "]
Prelude>pp(minesweeper sampleInput)
1110000
1*11110
1122*10
001*221
233211*
***2011
*8*3000
***2000

10 - Turtle

Implement a function that will draw the movement of a turtle in a rectangular grid. It will be named draw and it will have one parameter - a list movements. Our turtle can move only horizontally or vertically. Each movement will be described by a pair (its type will be (Char, Int)), where the first character denotates a direction of this movement and the second its length. Possible directions are: left, right, up, and down. As the result, function draw returns a smallest possible rectangle with all turtle's movements. Each block from the grid will be represented with one character. If it was visited by our turtle, then it will be 'X', if it was not, then it will be ' '.

draw :: [(Char, Int)] -> Result
*Main> pp (draw [('u',5),('r',5),('d',5),('l',10),('d',5),('r',5),('u',5)])      
     XXXXXX
     X    X
     X    X
     X    X
     X    X
XXXXXXXXXXX
X    X
X    X
X    X
X    X
XXXXXX