Skip to content

solved chapters 1 and 2 #562

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 49 additions & 29 deletions src/Chapter1.hs
Original file line number Diff line number Diff line change
@@ -209,31 +209,31 @@ So, the output in this example means that 'False' has type 'Bool'.
> Try to guess first and then compare your expectations with GHCi output

>>> :t True
<INSERT THE RESULT INSTEAD OF THE TEXT>
True :: Bool
>>> :t 'a'
<INSERT THE RESULT INSTEAD OF THE TEXT>
'a' :: Char
>>> :t 42
<INSERT THE RESULT INSTEAD OF THE TEXT>
42 :: Num a => a

A pair of boolean and char:
>>> :t (True, 'x')
<INSERT THE RESULT INSTEAD OF THE TEXT>
(True, 'x') :: (Bool, Char)

Boolean negation:
>>> :t not
<INSERT THE RESULT INSTEAD OF THE TEXT>
not :: Bool -> Bool

Boolean 'and' operator:
>>> :t (&&)
<INSERT THE RESULT INSTEAD OF THE TEXT>
(&&) :: Bool -> Bool -> Bool

Addition of two numbers:
>>> :t (+)
<INSERT THE RESULT INSTEAD OF THE TEXT>
(+) :: Num a => a -> a -> a

Maximum of two values:
>>> :t max
<INSERT THE RESULT INSTEAD OF THE TEXT>
max :: Ord a => a -> a -> a

You might not understand each type at this moment, but don't worry! You've only
started your Haskell journey. Types will become your friends soon.
@@ -301,43 +301,43 @@ expressions in GHCi
functions and operators first. Remember this from the previous task? ;)

>>> 1 + 2
<INSERT THE RESULT INSTEAD OF THE TEXT>
3

>>> 10 - 15
<INSERT THE RESULT INSTEAD OF THE TEXT>
-5

>>> 10 - (-5) -- negative constants require ()
<INSERT THE RESULT INSTEAD OF THE TEXT>
15

>>> (3 + 5) < 10
<INSERT THE RESULT INSTEAD OF THE TEXT>
True

>>> True && False
<INSERT THE RESULT INSTEAD OF THE TEXT>
False

>>> 10 < 20 || 20 < 5
<INSERT THE RESULT INSTEAD OF THE TEXT>
True

>>> 2 ^ 10 -- power
<INSERT THE RESULT INSTEAD OF THE TEXT>
1024

>>> not False
<INSERT THE RESULT INSTEAD OF THE TEXT>
True

>>> div 20 3 -- integral division
<INSERT THE RESULT INSTEAD OF THE TEXT>
6

>>> mod 20 3 -- integral division remainder
<INSERT THE RESULT INSTEAD OF THE TEXT>
2

>>> max 4 10
<INSERT THE RESULT INSTEAD OF THE TEXT>
10

>>> min 5 (max 1 2)
<INSERT THE RESULT INSTEAD OF THE TEXT>
2

>>> max (min 1 10) (min 5 7)
<INSERT THE RESULT INSTEAD OF THE TEXT>
5

Because Haskell is a __statically-typed__ language, you see an error each time
you try to mix values of different types in situations where you are not
@@ -428,7 +428,7 @@ task is to specify the type of this function.
>>> squareSum 3 4
49
-}

squareSum :: Integral a => a -> a -> a
squareSum x y = (x + y) * (x + y)


@@ -449,7 +449,7 @@ Implement the function that takes an integer value and returns the next 'Int'.
function body with the proper implementation.
-}
next :: Int -> Int
next x = error "next: not implemented!"
next x = x + 1

{- |
After you've implemented the function (or even during the implementation), you
@@ -490,7 +490,9 @@ Implement a function that returns the last digit of a given number.
whether it works for you!
-}
-- DON'T FORGET TO SPECIFY THE TYPE IN HERE
lastDigit n = error "lastDigit: Not implemented!"

lastDigit :: Integral a => a -> a
lastDigit n = mod (abs n) 10


{- |
@@ -520,7 +522,7 @@ branches because it is an expression and it must always return some value.
satisfying the check will be returned and, therefore, evaluated.
-}
closestToZero :: Int -> Int -> Int
closestToZero x y = error "closestToZero: not implemented!"
closestToZero x y = if abs x > abs y then y else x


{- |
@@ -554,7 +556,15 @@ value after "=" where the condition is true.
Casual reminder about adding top-level type signatures for all functions :)
-}

mid x y z = error "mid: not implemented!"
mid :: Int -> Int -> Int -> Int
mid x y z
| x == y = x
| y == z = y
| z == x = z
| x /= max (max x y) z && x /= min (min x y) z = x
| y /= max (max x y) z && y /= min (min x y) z = y
-- | z /= max (max x y) z && z /= min (min x y) z = z
| otherwise = z

{- |
=⚔️= Task 8
@@ -568,7 +578,10 @@ True
>>> isVowel 'x'
False
-}
isVowel c = error "isVowel: not implemented!"
isVowel :: Char -> Bool
isVowel c
| c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' = True
| otherwise = False


{- |
@@ -632,7 +645,10 @@ Try to introduce variables in this task (either with let-in or where) to avoid
specifying complex expressions.
-}

sumLast2 n = error "sumLast2: Not implemented!"
sumLast2 :: Integral a => a -> a
sumLast2 n = lastDigit n + slastDigit n
where
slastDigit x = mod (abs x) 100 `div` 10


{- |
@@ -653,7 +669,11 @@ You need to use recursion in this task. Feel free to return to it later, if you
aren't ready for this boss yet!
-}

firstDigit n = error "firstDigit: Not implemented!"
firstDigit :: Integral t => t -> t
firstDigit n
| an `mod` 10 == an = an
| otherwise = firstDigit (div an 10)
where an = abs n


{-
94 changes: 58 additions & 36 deletions src/Chapter2.hs
Original file line number Diff line number Diff line change
@@ -136,43 +136,43 @@ functions in GHCi and insert the corresponding resulting output below:
List of booleans:
>>> :t [True, False]
[True, False] :: [Bool]
String is a list of characters:
>>> :t "some string"
"some string" :: String
Empty list:
>>> :t []
[] :: [a]
Append two lists:
>>> :t (++)
(++) :: [a] -> [a] -> [a]
Prepend an element at the beginning of a list:
>>> :t (:)
(:) :: a -> [a] -> [a]
Reverse a list:
>>> :t reverse
reverse :: [a] -> [a]
Take first N elements of a list:
>>> :t take
take :: Int -> [a] -> [a]
Create a list from N same elements:
>>> :t replicate
replicate :: Int -> a -> [a]
Split a string by line breaks:
>>> :t lines
lines :: String -> [String]
Join a list of strings with line breaks:
>>> :t unlines
unlines :: [String] -> String
-}

@@ -186,31 +186,31 @@ Evaluate the following expressions in GHCi and insert the answers. Try
to guess first, what you will see.
>>> [10, 2] ++ [3, 1, 5]
[10,2,3,1,5]
>>> [] ++ [1, 4] -- [] is an empty list
[1,4]
>>> 3 : [1, 2]
[3,1,2]
>>> 4 : 2 : [5, 10] -- prepend multiple elements
[4,2,5,10]
>>> [1 .. 10] -- list ranges
[1,2,3,4,5,6,7,8,9,10]
>>> [10 .. 1]
[]
>>> [10, 9 .. 1] -- backwards list with explicit step
[10,9,8,7,6,5,4,3,2,1]
>>> length [4, 10, 5] -- list length
3
>>> replicate 5 True
[True,True,True,True,True]
>>> take 5 "Hello, World!"
"Hello"
>>> drop 5 "Hello, World!"
", World!"
>>> zip "abc" [1, 2, 3] -- convert two lists to a single list of pairs
[('a',1),('b',2),('c',3)]
>>> words "Hello Haskell World!" -- split the string into the list of words
["Hello","Haskell","World!"]
👩‍🔬 Haskell has a lot of syntax sugar. In the case with lists, any
@@ -336,7 +336,10 @@ from it!
ghci> :l src/Chapter2.hs
-}
subList :: Int -> Int -> [a] -> [a]
subList = error "subList: Not implemented!"
subList a b _
| a < 0 = []--subList 0 b c
| b < 0 = []--subList a 0 c
subList a b c = (b - a + 1) `take` drop a c

{- |
=⚔️= Task 4
@@ -349,7 +352,8 @@ Implement a function that returns only the first half of a given list.
"b"
-}
-- PUT THE FUNCTION TYPE IN HERE
firstHalf l = error "firstHalf: Not implemented!"
firstHalf :: [a] -> [a]
firstHalf l = take (div (length l) 2) l


{- |
@@ -501,7 +505,9 @@ True
>>> isThird42 [42, 42, 0, 42]
False
-}
isThird42 = error "isThird42: Not implemented!"
isThird42 :: Integral a => [a] -> Bool
isThird42 (_ : _ : 42 : _) = True
isThird42 _ = False


{- |
@@ -606,7 +612,8 @@ Implement a function that duplicates each element of the list
-}
duplicate :: [a] -> [a]
duplicate = error "duplicate: Not implemented!"
duplicate [] = []
duplicate (x:xs) = x : x : duplicate xs


{- |
@@ -621,7 +628,10 @@ Write a function that takes elements of a list only in even positions.
>>> takeEven [2, 1, 3, 5, 4]
[2,3,4]
-}
takeEven = error "takeEven: Not implemented!"
takeEven :: [a] -> [a]
takeEven (x : _ : xs) = x : takeEven xs
takeEven (x : _) = [x]
takeEven [] = []

{- |
=🛡= Higher-order functions
@@ -728,7 +738,7 @@ value of the element itself
🕯 HINT: Use combination of 'map' and 'replicate'
-}
smartReplicate :: [Int] -> [Int]
smartReplicate l = error "smartReplicate: Not implemented!"
smartReplicate l = concat (map (\x -> replicate x x) l)

{- |
=⚔️= Task 9
@@ -741,7 +751,10 @@ the list with only those lists that contain a passed element.
🕯 HINT: Use the 'elem' function to check whether an element belongs to a list
-}
contains = error "contains: Not implemented!"
contains :: Integral a => a -> [[a]] -> [[a]]
contains _ [] = []
contains a (b:bs) = if elem a b then b : cab else cab
where cab = contains a bs


{- |
@@ -781,13 +794,15 @@ Let's now try to eta-reduce some of the functions and ensure that we
mastered the skill of eta-reducing.
-}
divideTenBy :: Int -> Int
divideTenBy x = div 10 x
divideTenBy = div 10

-- TODO: type ;)
listElementsLessThan x l = filter (< x) l
listElementsLessThan :: Integral a => a -> [a] -> [a]
listElementsLessThan x = filter (< x)

-- Can you eta-reduce this one???
pairMul xs ys = zipWith (*) xs ys
pairMul :: Num a => [a] -> [a] -> [a]
pairMul = zipWith (*)

{- |
=🛡= Lazy evaluation
@@ -808,7 +823,7 @@ evaluation:
>>> take 5 (repeat 0)
[0,0,0,0,0]
Another useful construction is an infinite list of all numbers!
Another useful construction is an infinite list of all integers!
>>> take 4 [0 ..]
[0,1,2,3]
@@ -842,7 +857,12 @@ list.
🕯 HINT: Use the 'cycle' function
-}
rotate = error "rotate: Not implemented!"
rotate :: Int -> [a] -> [a]
rotate _ [] = []
rotate n _
| n < 0 = []
rotate n l = (drop mn l) ++ (take mn l )
where mn = mod n (length l)

{- |
=💣= Task 12*
@@ -858,7 +878,9 @@ and reverses it.
function, but in this task, you need to implement it manually. No
cheating!
-}
rewind = error "rewind: Not Implemented!"
rewind :: [a] -> [a]
rewind [] = []
rewind (n:ns) = (rewind ns) ++ [n]


{-
43 changes: 43 additions & 0 deletions src/Chapter3.hs
Original file line number Diff line number Diff line change
@@ -311,6 +311,7 @@ setKnightName newName (MkKnight _ victories) =
record. Like so:
@
data Knight = MkKnight
{ knightName :: String
, knightVictories :: Int
@@ -344,6 +345,13 @@ of a book, but you are not limited only by the book properties we described.
Create your own book type of your dreams!
-}

data Book = Book
{ bookTitle :: String
, bookAuthor :: String
, bookDate :: Int
, bookPages :: Int
}

{- |
=⚔️= Task 2
@@ -375,6 +383,24 @@ after the fight. The battle has the following possible outcomes:
♫ NOTE: In this task, you need to implement only a single round of the fight.
-}
data Knight = MkKnight
{ knightHealth :: Int
, knightAttack :: Int
, knightGold :: Int
}

data Monster = MkMonster
{ monsterHealth :: Int
, monsterAttack :: Int
, monsterGold :: Int
}

fight :: Monster -> Knight -> Int
fight m k
| monsterHealth m <= knightAttack k = knightGold k + monsterGold m
| knightHealth k <= monsterAttack m = -1
| otherwise = knightGold k


{- |
=🛡= Sum types
@@ -462,6 +488,13 @@ Create a simple enumeration for the meal types (e.g. breakfast). The one who
comes up with the most number of names wins the challenge. Use your creativity!
-}

data Food
= Breakfast String
| Lunch String
| Dinner String

fact n = product [1..n]

{- |
=⚔️= Task 4
@@ -482,6 +515,16 @@ After defining the city, implement the following functions:
and at least 10 living __people__ inside in all houses of the city in total.
-}

-- what am i to do ? THIS ‽
data MagicalCity
= Castle String


data House = House
{ houseName :: String
, houseNumber :: Int
}

{-
=🛡= Newtypes