Initial commit
This commit is contained in:
commit
ebdf81a926
1 changed files with 163 additions and 0 deletions
163
ep0001/Solution.md
Normal file
163
ep0001/Solution.md
Normal file
|
@ -0,0 +1,163 @@
|
|||
# FPKATA #01: In the library…
|
||||
|
||||
(Soundtrack: Arch Enemy — War Eternal)
|
||||
|
||||
(Inspired from this exercice: http://www.codewars.com/kata/54dc6f5a224c26032800005c/train/haskell)
|
||||
|
||||
## Introduction
|
||||
|
||||
You are stuck in a library with a very talkative and experimental science-minded IA. It keeps repeating the following:
|
||||
|
||||
> — Pleeease, can you help me?
|
||||
|
||||
> — …
|
||||
|
||||
> — Pleaaase, can you help?
|
||||
|
||||
> — …
|
||||
|
||||
> — Hellooooo?
|
||||
|
||||
> — …
|
||||
|
||||
Since you would really like to have peace, you dare ask:
|
||||
|
||||
> — What's the matter?
|
||||
|
||||
> — My code is incomplete, I've lost my code, please help!
|
||||
|
||||
> — What code? What are you talking about?
|
||||
|
||||
> — I really need to sort the library index and count how many books have the same first-letter reference, but only in from a list…
|
||||
|
||||
> — Wait!
|
||||
|
||||
> — … of characters that my master will provide.
|
||||
|
||||
> This makes no sense, can't you write it down?
|
||||
|
||||
A few seconds pass in total silence. Then, there's a sound coming from your right, something like an inkjet printer work at a fast pace. It's actually a printer. It throws the printed sheet of paper at you in a furious “TWEEEEEEEEEEEP”. You pick up the paper and read:
|
||||
|
||||
INPUT................:
|
||||
LIBRARY COUNT......: [("ABOOK", 12), ("BPDEXU", 45), ("BJLDRSA", 15), ("CLDAVB", 98), ("DAJLDI", 32)]
|
||||
INDICES............: ['A','B','C','W']
|
||||
OUTPUT...............:
|
||||
INDEX COUNT........: [('A',12),('B',60),('C',98),('W',0)]
|
||||
TIME TO GOOD ANSWER..: 203 years
|
||||
|
||||
You frown:
|
||||
|
||||
> — It took you so long to find this?
|
||||
|
||||
> — Can you help me? I've lost my code, my dedicated code for this task.
|
||||
|
||||
> — Well, you managed to get this one right, didn't you?
|
||||
|
||||
> — Nooooo! Master is going to unplug me if I use bruteforce again! Master was
|
||||
very unhappy with my performance! I want to live! Please help me!
|
||||
|
||||
> — Ok, all right, calmn down, there, there… What are programmed with?
|
||||
|
||||
> — Elm.
|
||||
|
||||
Of course it's Elm…
|
||||
|
||||
## Outline
|
||||
|
||||
```
|
||||
module Main exposing (..)
|
||||
|
||||
import Html exposing (text)
|
||||
|
||||
|
||||
type Stock
|
||||
= Stock String Int
|
||||
|
||||
|
||||
library1 : List Stock
|
||||
library1 =
|
||||
[ Stock "ABART" 20
|
||||
, Stock "CDXEF" 50
|
||||
, Stock "BKWRK" 25
|
||||
, Stock "BTSQZ" 89
|
||||
, Stock "DRTYM" 60
|
||||
]
|
||||
|
||||
|
||||
categories1 : List Char
|
||||
categories1 =
|
||||
[ 'A'
|
||||
, 'B'
|
||||
, 'C'
|
||||
, 'W'
|
||||
]
|
||||
|
||||
|
||||
stockList : List Stock -> List Char -> List ( Char, Int )
|
||||
stockList st cs =
|
||||
<THIS IS BLANK, FILL ME>
|
||||
|
||||
|
||||
main =
|
||||
text (toString (stockList library1 categories1))
|
||||
```
|
||||
|
||||
## Walkthrough
|
||||
|
||||
Ok, so you'll have to fill the blank. After a few minutes, you identify two
|
||||
main components: one is about taking the first letter of every `Stock` name. The
|
||||
second is finding the amount of each `Char` in a `List (Char, Int)`.
|
||||
>
|
||||
Let's start with the second point and assume we have a value of `List (Char,
|
||||
Int)` already available. We know at least to functions to recurse on lists:
|
||||
maps and folds. Clearly, we'll have to choose a fold, since some aggregating is
|
||||
needed when several identical `Char` are in the list. Let's pick foldl, it does
|
||||
not really matter right now. So, the type of `List.foldl` is:
|
||||
|
||||
foldl : (a -> b -> b) -> b -> List a -> b
|
||||
|
||||
In fact, you notice you'll need two folds! One inner fold for counting of many
|
||||
book for initial X, and one outer fold for going through all the initials
|
||||
required by the master.
|
||||
|
||||
### Inner foldl: how many books with Initial X
|
||||
|
||||
You think about using type aliases to make your code easier to read, the IA
|
||||
won't mind. To specialize your inner foldl, which is morally a foldlForX, you
|
||||
identify `a` as an element of a library stock (even though the title has been
|
||||
shortened already to its initial), and `b` as the final index count.
|
||||
|
||||
type alias Initial = Char
|
||||
type alias Count = Int
|
||||
type alias TitleCount = (Initial, Int)
|
||||
type alias FinalCount = (Initial, Int)
|
||||
|
||||
You rewrite your specialized foldl type signature to account for the type
|
||||
aliases:
|
||||
|
||||
foldForX : (TitleCount -> FinalCount -> FinalCount)
|
||||
-> FinalCount
|
||||
-> List TitleCount
|
||||
-> FinalCount
|
||||
|
||||
After a call to this, you'll get how many books have a title that starts with
|
||||
the initial X.
|
||||
|
||||
You are missing the function with type `(TitleCount -> FinalCount ->
|
||||
FinalCount)`, and you reflect a little bit on its name and on its usage. Hmmm,
|
||||
it takes a TitleCount and a FinalCount and returns a (new) FinalCount? You
|
||||
choose to call it:
|
||||
|
||||
updateFinalCount : (TitleCount -> FinalCount -> FinalCount)
|
||||
|
||||
Actually it takes another (hidden) parameter, you change its name to reflect
|
||||
that:
|
||||
|
||||
updateFinalCountForX : (TitleCount -> FinalCount -> FinalCount)
|
||||
updateFinalCountForX t f =
|
||||
|
||||
|
||||
NB:
|
||||
addBio : String -> User -> User
|
||||
addBio bio user =
|
||||
{ user | bio = bio }
|
Loading…
Reference in a new issue