Haskell, make single string from integer set? - string

I'd greatly appreciate if you could tell me how to make a single string from a range between two ints. Like [5..10] i would need to get a "5678910". And then I'd have to calculate how many (zeroes, ones ... nines) there are in a string.
For example: if i have a range from [1..10] i'd need to print out
1 2 1 1 1 1 1 1 1 1
For now i only have a function to search for a element in string.
`countOfElem elem list = length $ filter (\x -> x == elem) list`
But the part how to construct such a string is bugging me out, or maybe there is an easier way? Thank you.
I tried something like this, but it wouldn't work.
let intList = map (read::Int->String) [15..22]

I tried something like this, but it wouldn't work. let intList = map (read::Int->String) [15..22]
Well... the purpose of read is to parse strings to read-able values. Hence it has a type signature String -> a, which obviously doesn't unify with Int -> String. What you want here is the inverse1 of read, it's called show.
Indeed map show [15..22] gives almost the result you asked for – the numbers as decimal-encoded strings – but still each number as a seperate list element, i.e. type [String] while you want only String. Well, how about asking Hoogle? It gives the function you need as the fifth hit: concat.
If you want to get fancy you can then combine the map and concat stages: both the concatMap function and the >>= operator do that. The most compact way to achieve the result: [15..22]>>=show.
1show is only the right inverse of read, to be precise.

Related

Need help storing the previous element of a list (Haskell)

I'm currently working on an assignment. I have a function called gamaTipo that converts the values of a tuple into a data type previously defined by my professor.
The problem is: in order for gamaTipo to work, it needs to receive some preceding element. gamaTipo is defined like this: gamaTipo :: Peca -> (Int,Int) -> Peca where Peca is the data type defined by my professor.
What I need to do is to create a funcion that takes a list of tuples and converts it into Peca data type. The part that im strugling with is taking the preceding element of the list. i.e : let's say we have a list [(1,2),(3,4)] where the first element of the list (1,2) always corresponds to Dirt Ramp (data type defined by professor). I have to create a function convert :: [(Int,Int)] -> [Peca] where in order to calculate the element (3,4) i need to first translate (1,2) into Peca, and use it as the previous element to translate (3,4)
Here's what I've tried so far:
updateTuple :: [(Int,Int)] -> [Peca]
updateTuple [] = []
updateTuple ((x,y):xs) = let previous = Dirt Ramp
in (gamaTipo previous (x,y)): updateTuple xs
Although I get no error messages with this code, the expected output isn't correct. I'm also sorry if it's not easy to understand what I'm asking, English isn't my native tongue and it's hard to express my self. Thank you in advance! :)
If I understand correctly, your program needs to have a basic structure something like this:
updateTuple :: [(Int, Int)] -> [Peca]
updateTuple = go initialValue
where
go prev (xy:xys) =
let next = getNextValue prev xy
in prev : (go next xys)
go prev [] = prev
Basically, what’s happening here is:
updateTuple is defined in terms of a helper function go. (Note that ‘helper function’ isn’t standard terminology, it’s just what I’ve decided to call it).
go has an extra argument, which is used to store the previous value.
The implementation of go can then make use of the previous value.
When go recurses, the recursive call can then pass the newly-calculated value as the new ‘previous value’.
This is a reasonably common pattern in Haskell: if a recursive function requires an extra argument, then a new function (often named go) can be defined which has that extra argument. Then the original function can be defined in terms of go.

Test for positions- function

positions :: Eq a => a -> [a] -> [Int]
positions x xs = [i | (x',i) <- zip xs [0..], x == x']
i need to create a Test function for the positions function, which passes the quickcheck.
Does someone has an idea?
A possible test could perform the following operations:
randomly generate xs, ys :: [Int] and y :: Int
define list = xs ++ y : ys
test length xs `elem` positions y list
You might also want to write tests for missing elements.
That being said, it's weird to craft tests from the code. One should design test using the specification used to write the code instead. Otherwise, if the code has some quirks, they end up in tests as well: instead of checking for what the code should do, we check for what the code does, which can be pointless.
Good question! I had a bit of trouble with this too when I started using QuickCheck, but as I used it more I started to get a feel for what sort of properties you should test. Often, a good place to start is to think about what sort of relationships should hold between the input(s) and output. Your function finds the indices of an element in a list; now what properties should hold in this case? Here's two which I can think of:
The list of indices should have the same number of elements as there are occurrences of the value in the list.
Each index should correspond to the correct value.
And here's an outline of how these properties could be tested:
Generate a random list, apply positions to it, then count the number of indices returned and check that it matches with the number of occurrences of the searched value.
Generate a random list, then apply positions to it and check that the element at each of the returned indices is the value which was searched for.
I also think that #chi's answer makes a good point in saying that you should design tests from the specification rather than the code; this ties in with what I was saying above, in that a specification can help you find relationships between input(s) and output which may not be immediately apparent from the code.

Finding list entry with the highest count

I have an Entry data type
data Entry = Entry {
count :: Integer,
name :: String }
Then I want to write a function, that takes the name and a list of Entrys as arguments an give me the Entrys with the highest count. What I have so far is
searchEntry :: String -> [Entry] -> Maybe Integer
searchEntry _ [] = Nothing
searchEntry name1 (x:xs) =
if name x == name1
then Just (count x)
else searchEntry name xs
That gives me the FIRST Entry that the function finds, but I want the Entry with the highest count. How can I implement that?
My suggestion would be to break the problem into two parts:
Find all entries matching a given name
Find the entry with the highest count
You could set it up as
entriesByName :: String -> [Entry] -> [Entry]
entriesByName name entries = undefined
-- Use Maybe since the list might be empty
entryWithHighestCount :: [Entry] -> Maybe Entry
entryWithHighestCount entries = undefined
entryByNameWithHighestCount :: String -> [Entry] -> Maybe Entry
entryByNameWithHighestCount name entires = entryWithHighestCount $ entriesByName name entries
All you have to do is implement the relatively simple functions that are used to implement getEntryByNameWithHighestCount.
You need to add an inner method that takes a current result as a parameter and returns that instead of Nothing when reaching the end of the method.
Also you would need to update your result found logic to compare a potentially existing function and the found value.
I would consider changing the signature of the function to String->Maybe Entry (or String->[Entry]) if you indeed want to return the "Entry" items with the highest count.
Otherwise, you can actually do what you want as a oneliner using some pretty common Haskell functions....
As Bheklilr mentioned, the name filter can be done first, and it is really easy to do this using the filter function....
filter (hasName theName) entries
Note that hasName can be written out fully as a separate function, but Haskell also offers you the following shortcut.
hasName = (== theName) . name
Now you just need the maximum value.... Haskell has a maximum function, but it only works on the Ord class. You can make Entry an instance of Ord, or you can just use the related maximumBy function, that takes an extra ordering function
maximumBy orderFunction entries2
Again, you can write orderFunction yourself (which you might want to do as an excercise), but haskell again offers a shortcut.
orderFunction = compare `on` count
You will need to import some libs to get this all to work (Data.Function, Data.List). You also will need to put in some extra code to account for the Nothing case.
It might be worth it to write out the functions longhand first, but I recommend that you use Hoogle to lookup and understand compare, on, and maximumBy.... Using tricks like this can really shorten your code.
Putting it all together, you can get the entry with the maximum count like this
maxEntry = maximumBy (compare `on` count) $ filter ((theName ==) . name) $ entries
You will need to modify this to account for the Nothing case, or if you want to return all max Entries (this just chooses one), or if you really wanted to return count, and not the entry.

Haskell string to list

["6","","[[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18],[19,20,21,22,23,24],[25,26,27,28,29,30],[31,32,33,34,35,36]]"]
I must get from this 6 and [[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18],[19,20,21,22,23,24],[25,26,27,28,29,30],[31,32,33,34,35,36]]
I read from file in file it look
6.
[[1,2,3,4,5,6],[7,8,9,10,11,12],[13,14,15,16,17,18],[19,20,21,22,23,24],[25,26,27,28,29,30],[31,32,33,34,35,36]].
I tried with map and read to convert string but it wasnt working.
sry for english
The problem with using map and read directly is, that your list elements don't all have the same types. The first element is (or better: should be converted to) an Int, the second an empty list and the third an `[[Int]].
To convert the first element of the list into an Int, you can say something like read $ head xs :: Int, where xs is your list of strings.
The second element cannot be directly converted by read, since an empty string will result in an exception (Prelude.read: no parse).
To convert the third element, which is a list of lists of integers, you can simply say something like read $ xs !! 2 :: [[Int]].
This is not safe or elegant, but if your input always has this structure it should work.

Conversion from decimal to binary in Ocaml

I am trying to convert a given decimal value its corresponding binary form. I am using Ocaml about which I don't know much and am quite confused. So far I have the following code
let dec_to_bin_helper function 1->'T' | 0->'F'
let dec_to_bin x =
List.fold_left(fun a z -> z mod 2 dec_to_bin_helper a) [] a ;;
I must include here that I want my output to be in the form of a list of T's and F's where T's represent the binary 1's and F's represent binary 0's
If I try to run the above code it gives me an error saying "Error: This expression is not a function; it cannot be applied"
I understand that the part where I am calling the helper function is wrong... Any help in the matter would be appreciated!
I don't really understand your second function at all. You are folding an empty list, and your function takes an argument x which it never uses. Am I correct in assuming that you want to take a number and return a list of 'T's and 'F's which represent the binary? If that is the case, this code should work:
let dec_to_bin x =
let rec d2b y lst = match y with 0 -> lst
| _ -> d2b (y/2) ((dec_to_bin_helper (y mod 2))::lst)
in
d2b x [];;
This function inserts (x mod 2) converted into a T/F into a list, then recursively calls the function on x/2 and the list. When x = 0 the list is returned. If call it on 0 an empty list will be returned (I'm not sure if that's what you want or not).
I think the problem that you had is that you are treating lists as if they are mutable and thinking that fold mutates the list. That is not the case, fold just goes through each element in a list and applies a function to it. Since your list is empty it didn't do anything.

Resources