Simple chess function in Haskell - haskell

My homework is to write simple functions related to chess. The rook function is working fine i guess it shows where can you step from the given start coordinate. And now I'm stuck with the knight function. My idea is to filter the coordinates list by the following condition: If the abs value of the coordinate differences is 3 and the rows are different then its a valid step. But I don't really know how should i implement this in Haskell. Any idea how should i do that?
My Code:
import Data.List
possibleMoves = [ (x, y) | x <- [0..7], y <- [7,6..0]]
rook :: (Int, Int) -> [(Int, Int)]
rook (x,y) = filter (/=(x,y)) (filter ((==y).snd) possibleMoves ++ filter ((==x).fst ) possibleMoves)
knight :: (Int, Int) -> [(Int, Int)]
knight (x,y) = filter ((==3)((abs(y - head(map snd(possibleMoves))))).snd) possibleMoves
Resulting the following error :
* Couldn't match expected type `Int -> Bool'
with actual type `Bool'
* Possible cause: `== 3' is applied to too many arguments
In the first argument of `(.)', namely
`(== 3) ((abs (y - head (map snd (possibleMoves)))))'
In the first argument of `filter', namely
`((== 3) ((abs (y - head (map snd (possibleMoves))))) . snd)'
In the expression:
filter
((== 3) ((abs (y - head (map snd (possibleMoves))))) . snd)
possibleMoves
|
9 | knight (x,y) = filter ((==3)((abs(y - head(map snd(possibleMoves))))).snd) possibleMoves
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

It seems like you're making it harder than it needs to be.
Given position K below, you could simply list each knight move:
1 2 3 4 5
+---+---+---+---+---+
1 | | H | | A | |
+---+---+---+---+---+
2 | G | | | | B |
+---+---+---+---+---+
3 | | | K | | |
+---+---+---+---+---+
4 | F | | | | C |
+---+---+---+---+---+
5 | | E | | D | |
+---+---+---+---+---+
And remove the ones that are outside the chessboard.
knight :: (Int, Int) -> [(Int, Int)]
knight (x, y) = filter validPosition
[ (x + 1, y + 2)
, (x + 2, y + 1)
, (x + 2, y - 1)
, (x + 1, y - 2)
, (x - 1, y - 2)
, (x - 2, y - 1)
, (x - 2, y + 1)
, (x - 1, y + 2)
]
Then if you think you're repeating yourself too much:
knight' :: (Int, Int) -> [(Int, Int)]
knight' (x, y) = filter validPosition
[ (x + dx, y + dy) | dx <- [-2,-1,1,2]
, dy <- [-2,-1,1,2]
, ... something about dx, dy and 3 ...
]
It seems that the (== y) . snd stuff obscures the solution a little.

Your idea of filtering the knight's positions is actually really succinct and easy to implement using a list comprehension.
knight (x, y) = [(x', y') | x'<-[x-2..x+2], y'<-[y-2..y+2], abs (x' - x) + abs (y' - y) == 3 ]
Restricting the possible displacement values to -2 and +2 will also prevent the column and row from being the same, so you can do away with that condition.
The only thing is, it will also return values that are past the board. You could check this using your preexisting possibleMoves function:
import Data.List (intersect)
safeKnight = intersect possibleMoves . knight

Related

Possibility of having parameterized definitions in haskell?

Is there a way to compactly write multiple definitions in haskell via case, without having to repeat, other than the input parameters, the exact same syntax? The only possible solution I can imagine so far is a macro.
Below is an example of defining binary max and min functions. Can we compress
max' x y
| x > y = x
| otherwise = y
min' x y
| x < y = x
| otherwise = y
into something like
(max',min') x y
| x (>,<) y = x
| otherwise = y
?
Edit:
I know this allows us to parametrize over the "grumpy face", but it seems like there still could be a more succinct form.
maxmin x y f
| f x y = x
| otherwise = y
max' x y = maxmin x y (>)
min' x y = maxmin x y (<)
Well, you can always do this:
select op x y
| x `op` y = x
| otherwise = y
max' = select (>)
min' = select (<)
I.e. extract the common parts into a function and turn the differences into parameters.

How can you quickly map the indices of a banded matrix to a 1-dimensional array?

This is closely related to a the question: How to map the indexes of a matrix to a 1-dimensional array (C++)?
I need to assign a reversible index to each non-zero element in a banded matrix.
In the normal, full matrix it is easy to do:
|-------- 5 ---------|
Row ______________________ _ _
0 |0 1 2 3 4 | |
1 |5 6 7 8 9 | 4
2 |10 11 12 13 14| |
3 |15 16 17 18 19| _|_
|______________________|
Column 0 1 2 3 4
To find the array index we just use the following bijective formula:
matrix[ i ][ j ] = array[ i*m + j ]
In my case, we have a symmetrically banded matrix with some constraint on distance from the diagonal. For example, the following uses an upper and lower bound of 1:
|-------- 5 ---------|
Row ______________________ _ _
0 |0 1 X X X | |
1 |2 3 4 X X | 4
2 |X 5 6 7 X | |
3 |X X 8 9 10| _|_
|______________________|
Column 0 1 2 3 4
In this case, I want to assign an index position to each element within the bandwidth, and ignore everything outside. There are a couple of ways to do this, one of which is to create a list of all the acceptable indices ix's, and then use map lookups to quickly go back and forth between a (row,col) pair and a singular index:
ix's :: [(Int,Int)] -- List of all valid indices
lkup :: Map (Int,Int) Int
lkup = M.fromList $ zip ix's [0..]
rlkup :: Map Int (Int, Int)
rlkup = M.fromList $ zip [0..] ix's
fromTup :: (Int, Int) -> Int
fromTup tup = fromMaybe 0 $ M.lookup tup lkup
toTup :: Int -> (Int, Int)
toTup i = fromMaybe (0,0) $ M.lookup i rlkup
For large matrices, this leads to a huge number of map lookups, which causes a bottleneck. Is there a more efficient formula to translate between the valid addresses, k, and (row,col) pairs?
You might find it more straightforward to "waste" a few indexes at the beginning and end of the matrix, and so assign:
Row ______________________ _ _
0 (0) |1 2 X X X | |
1 |3 4 5 X X | 4
2 |X 6 7 8 X | |
3 |X X 9 10 11 | _|_
|______________________|
Column 0 1 2 3 4
where (0) is an ignored index.
This is similar to the band matrix representation used by the highly respected LAPACK library.
You just need to take care that the unused elements are properly ignored when performing operations where they might affect used elements. (For example, a fast fill routine can be written without regard to which elements are used or unused; but a matrix multiplication would need to take a little more more care.)
If you take this approach, then the bijections are pretty simple:
import Data.Char
import Data.Maybe
type Index = Int
-- |(row,col) coordinate: (0,0) is top level
type Coord = (Int, Int)
-- |Matrix dimensions: (rows, cols, edges) where edges gives
-- the count of auxiliary diagonals to *each side* of the main
-- diagonal (i.e., what you call the maximum distance), so the
-- total band width is 1+2*edges
type Dims = (Int, Int, Int)
-- |Get index for (row,col)
idx :: Dims -> Coord -> Index
idx (m, n, e) (i, j) = let w = 1+2*e in w*i+(j-i+e)
-- |Get (row,col) for index
ij :: Dims -> Index -> Coord
ij (m, n, e) idx = let w = 1+2*e
(i, j') = idx `quotRem` w
in (i, j'+i-e)
--
-- test code
--
showCoords :: Dims -> [(Coord, Char)] -> String
showCoords (m, n, _) cs =
unlines $
for [0..m-1] $ \i ->
for [0..n-1] $ \j ->
fromMaybe '.' $ lookup (i,j) cs
where for = flip map
test :: Dims -> IO ()
test dm#(m,n,_) = do
putStrLn $ "Testing " ++ show dm
let idxs = [0..]
-- get valid index/coordinates for this matrix
let cs = takeWhile (\(_, (i,j)) -> i<m || j<n)
$ filter (\(_, (i,j)) -> i>=0 && j>=0)
$ map (\ix -> (ix, ij dm ix)) idxs
-- prove the coordinates are right
putStr $ showCoords dm (map (\(ix, (i,j)) -> ((i,j), chr (ord 'A' + ix))) cs)
-- prove getIndex inverts getCoord
print $ all (\(ix, (i,j)) -> idx dm (i,j) == ix) cs
putStrLn ""
main = do test (4, 5, 1) -- your example
test (3, 8, 2) -- another example

Haskell program that gives pretty prime numbers

I've made a haskell program that computes pretty prime numbers. Pretty primes are primes that are very close to a power of 2. You give 2 numbers for example: 10 and 20 then it returns 17 because 17 is the closest to a power of 2. 17 - 16 = 1 so it is the closest.
I've made this:
EDIT: I've rewrote the primefunction like this and e verw function but still getting -1.
-- Geeft priemgetallen terug tussen de 2 grenzen
-- English: Gives primenumbers between 2 numbers
priemgetallen :: Int->[Int]
priemgetallen b = take b (zeef [2..])
where zeef (p:xs) = p : zeef [x | x<-xs, (mod x p) /= 0]
-- Geeft machten terug tussen de 2 grenzen
-- English: Gives powers of 2 between 2 numbers
machten :: Int->Int->[Int]
machten a b
| a <= 2 = 2:[2^x| x<-[2..b], (2^x) `mod` 2 == 0, 2^x < b, 2^x > a]
| otherwise = [2^x| x<-[2..b], (2^x) `mod` 2 == 0, 2^x < b, 2^x > a]
-- English: the start of the function
prettyprime :: Int->Int->Int
prettyprime a b = vergelijk ( verw a (priemgetallen b)) (machten a b)
-- Filter the list
verw :: Int->[Int]->[Int]
verw _ [] = []
verw k (x:xs)
| x > k = [x] ++ verw k xs
| otherwise = verw k xs
-- Vergelijkt alle priemgetallen en geeft welke korste bij het ander ligt
-- English this function must see what primenumber is the closest to a power of 2 but I can't fix it
vergelijk :: [Int]->[Int]->Int
vergelijk [] _ = -1
vergelijk _ [] = -1
vergelijk (x:xs) (y:ys)
| x - y < vergelijk (x:xs) ys = x
| x - y > vergelijk (x:xs) ys = vergelijk xs (y:ys)
| x - y == vergelijk (x:xs) ys = x
main = do
print $ prettyprime 14 20
Can someone help me?
Kind regards,
The incomplete pattern is because you've omitted the case when x - y == vergelijk (x:xs) ys. The compiler is capable of warning you about this if you add -fwarn-incomplete-patterns and convert your guards into a real case:
vergelijk (x:xs) (y:ys) = case compare (x - y) (vergelijk (x:xs) ys) of
LT -> x
-- you will get a warning about having no case for EQ
GT -> vergelijk xs (y:ys)
As a bonus, this version is much less likely to recompute the recursive call, especially on low optimization levels.

FizzBuzz cleanup

I'm still learning Haskell, and I was wondering if there is a less verbose way to express the below statement using 1 line of code:
map (\x -> (x, (if mod x 3 == 0 then "fizz" else "") ++
if mod x 5 == 0 then "buzz" else "")) [1..100]
Produces:
[(1,""),(2,""),(3,"fizz"),(4,""),(5,"buzz"),(6,"fizz"),(7,""),(8,""),(9,"fizz"),(10,"buzz"),(11,""),(12,"fizz"),(13,""),(14,""),(15,"fizzbuzz"),(16,""),(17,""),(18,"fizz"),(19,""),(20,"buzz"),(21,"fizz"),(22,""),(23,""),(24,"fizz"),(25,"buzz"),(26,""),(27,"fizz"),(28,""),(29,""),(30,"fizzbuzz"), etc
It just feels like I'm fighting the syntax more than I should. I've seen other questions for this in Haskell, but I'm looking for the most optimal way to express this in a single statement (trying to understand how to work the syntax better).
We need no stinkin' mod...
zip [1..100] $ zipWith (++) (cycle ["","","fizz"]) (cycle ["","","","","buzz"])
or slightly shorter
import Data.Function(on)
zip [1..100] $ (zipWith (++) `on` cycle) ["","","fizz"] ["","","","","buzz"]
Or the brute force way:
zip [1..100] $ cycle ["","","fizz","","buzz","fizz","","","fizz","buzz","","fizz","","","fizzbuzz"]
If you insist on a one-liner:
[(x, concat $ ["fizz" | mod x 3 == 0] ++ ["buzz" | mod x 5 == 0]) | x <- [1..100]]
How's about...
fizzBuzz = [(x, fizz x ++ buzz x) | x <- [1..100]]
where fizz n | n `mod` 3 == 0 = "fizz"
| otherwise = ""
buzz n | n `mod` 5 == 0 = "buzz"
| otherwise = ""
Couldn't resist going in the other direction and making it more complicated. Look, no mod...
merge as#(a#(ia,sa):as') bs#(b#(ib,sb):bs') =
case compare ia ib of
LT -> a : merge as' bs
GT -> b : merge as bs'
EQ -> (ia, sa++sb) : merge as' bs'
merge as bs = as ++ bs
zz (n,s) = [(i, s) | i <- [n,2*n..]]
fizzBuzz = foldr merge [] $ map zz [(1,""), (3,"fizz"), (5,"buzz")]
Along the same lines as larsmans' answer:
fizzBuzz = [(x, f 3 "fizz" x ++ f 5 "buzz" x) | x <- [1..100]]
where f k s n | n `mod` k == 0 = s
| otherwise = ""
I think the reason why you feel like you are fighting the syntax is because you are mixing too many types.
Instead of trying to print:
[(1, ""), (2,""), (3,"Fizz")...]
Just think of printing strings:
["1","2","Fizz"...]
My attempt:
Prelude> let fizzBuzz x | x `mod` 15 == 0 = "FizzBuzz" | x `mod` 5 == 0 = "Buzz" | x `mod` 3 == 0 = "Fizz" | otherwise = show x
Prelude> [fizzBuzz x | x <-[1..100]]
["1","2","Fizz","4","Buzz","Fizz","7","8","Fizz","Buzz","11","Fizz","13","14","FizzBuzz"...]
In order to convert an Int to String you use the:
show x
Just for studying
zipWith (\a b -> b a) (map show [1..100]) $ cycle [id,id,const "fizz",id,const "buzz",const "fizz",id,id,const "fizz",const "buzz",id,const "fizz",id,id,const "fizzbuzz"]
produces
["1","2","fizz","4","buzz","fizz","7","8","fizz","buzz","11","fizz","13","14","fizzbuzz","16","17","fizz","19","buzz","fizz","22","23","fizz","buzz","26","fizz","28","29","fizzbuzz","31","32","fizz","34","buzz","fizz","37","38","fizz","buzz","41","fizz","43","44","fizzbuzz","46","47","fizz","49","buzz","fizz","52","53","fizz","buzz","56","fizz","58","59","fizzbuzz","61","62","fizz","64","buzz","fizz","67","68","fizz","buzz","71","fizz","73","74","fizzbuzz","76","77","fizz","79","buzz","fizz","82","83","fizz","buzz","86","fizz","88","89","fizzbuzz","91","92","fizz","94","buzz","fizz","97","98","fizz","buzz"]
Writer monad may look nice (if you don't like concat):
fizzBuzz = [(x, execWriter $ when (x `mod` 3 == 0) (tell "fizz") >> when (x `mod` 5 == 0) (tell "buzz")) | x <- [1..100]]
It's not particularly succinct though.

Comparing Bool Value in Matrix

t = True
f = False
anzNachbarn :: [[Bool]] -> (Integer,Integer) -> Integer
anzNachbarn a (x,y)
| x < 0 || y < 0=-1
| otherwise ... here comes the comparison
This is an example matrix:
[[True,False,False],
[True,False,False],
[False,True,False]]
here i need an algorithm, where it calculates (for given x and y position in matrix) its neighbours (only "true" neighboors) and increase it by 1 for each true neighboor.
For example: anzNachbarn [[True,False,False],[True,False,False],[False,True,False]] (0,1)
returns 2 back.
:Edit
I still have a question how can I now implement each component of the result matrix, the number of named elements with True neighboring fields indicates the corresponding component of the argument matrix Applies to
[[True, False, False],
[True, False, False],
[False, True , False]]
the function func returns the results matrix [[1,2,0], [2,3,1], [2,1,1]]
with signature func :: [[Bool]] -> [[Integer]]
have you got any idea about this ?
You almost certainly want to use an array (from Data.Array) in this situation, since looking up an item in a list by its index is very slow.
Here's a quick implementation using Array:
countNeighbors :: Array (Int, Int) Bool -> (Int, Int) -> Int
countNeighbors board (x, y) = length
[ (x', y')
| x' <- [x - 1, x, x + 1]
, y' <- [y - 1, y, y + 1]
, x' /= x || y' /= y
, inRange (bounds board) (x', y')
, board ! (x', y')
]
This is a list comprehension with two generators and three guards. The generators simply give us the indices of the nine positions in a three-by-three square centered at (x, y) (you'll need a minor change if you don't want neighbors at the corners to be considered).
The first guard (x' /= y') ignores (x, y) itself. The second throws out positions that aren't within the bounds of the array. The final guard throws out positions that are in the array but have a False value.
So we now have a list of indices for the neighbors with True values. The length of this list is the desired count.
This is ugly, but seems to work...
anzNachbarn :: [[Bool]] -> (Int,Int) → Integer
anzNachbarn a (x,y)
| x < 0 || y < 0 = -1
| otherwise = sum [v x' y' | x' <- [max 0 (x-1)..x+1],
y' <- [max 0 (y-1)..y+1],
x ≠ x' || y ≠ y' ]
where v i j = if j >= length a
|| i >= length (a !! 0)
|| not (a !! j !! i)
then 0 else 1
[Edit]
In order to convert the whole array, you can write the equally ugly
conv a = [line y | y <- [0 .. (length a) - 1]]
where line y = [anzNachbarn a (x,y) | x <- [0 .. ((length (a !! 0) - 1)]]
Note that the performance of this is terrible.

Resources