How get limited number of input in Haskell - list

I am a newbie in Haskell.
Let says my program want to calculate something from this pattern of input:
a1 b1 c1
a2 b2 c2
...
16 b6 c6
The input contains 6 lines and each line has 3 numbers
I want to get data as [(Integer, Integer, Integer)] but limit the length of the list to be only 6 before going to the calculation.
How could I do this? Also, how could I get a length from [(Integer, Integer, Integer)]
Thank you for your help

There are three steps to this:
Read 6 lines
Break each line into the (hopefully three) parts
Convert to the desired result
Some sample code is below:
input = do
lines <- sequence $ take 6 $ repeat readLn
let table = words <$> lines
return [(a, b, c) | [a,b,c] <- table]
This gives input :: IO [(String, String, String)] but I'm sure you could modify this to give you what you want.

Related

How to add user input values to an array in Ocaml

I am working in OCaml and have to do the following problem
7.1 Problem 1 – Number of values less than average
Input: An integer, listlen, followed by listlen number of integer values.
Output: The list of values, number of items on the list, and the number of input values that are less than the average of all the values
Sample input:
Enter the count and the corresponding integer values:
7 10 60 3 55 15 45 40
Corresponding output:
The list:
10 60 3 55 15 45 40
The average:
32.57
Number of values less than average:
3
The idea is to use user input, get a length of numbers to be averaged, get the numbers to be averaged, average them and then tell which numbers from the list are less than the average. My issue comes in trying to add the values given from the user into the array. I was able to create the array but can't figure out what code to use to add the values.
The code I have currently...
(* Prompts the user to enter the number of values they want to average
then gets that number and prints it *)
print_string "Enter The Number of Values You Want To Average:\n";;
let n_values = Scanf.scanf "%d" (fun n -> n);;
Printf.printf "%d\n" n_values;;
(* Prompts the user to enter the numbers they want averaged then
adds those values to an array and prints the numbers *)
print_string "Enter The Values To Be Averaged:\n";;
let a = Array.make n_values 0;;
for i = 0 to Array.length a - 1 do
(*let values = Scanf.scanf "%d" (fun n -> n)*)
a.(i) <- i
done;;
for i = 0 to Array.length a - 1 do
Printf.printf "%i" a.(i);
done;;
(* Adds each of the values of the array together, stores it in sum and then divides by the n_values initialized above and stores in average, then prints this value *)
print_string "\nThe Average:\n";;
let sum = Array.fold_left (+) 0 a;;
let average = sum / n_values;;
Printf.printf "%d\n" average;;
(* Checks which numbers in the array are less than the computed average and increments a counter if it is less*)
print_string "The Number of Values Less Than The Average:\n";;
let counter = ref 0;;
for i = 0 to Array.length a - 1 do
if a.(i) < average then incr counter;
done;;
Printf.printf "%d\n" !counter;;
The code in question is...
let a = Array.make n_values 0;;
for i = 0 to Array.length a - 1 do
(*let values = Scanf.scanf "%d" (fun n -> n)*)
a.(i) <- i
done;;
for i = 0 to Array.length a - 1 do
Printf.printf "%i" a.(i);
done;;
I have tried what is currently commented out w/ adding a.(i) <- values but that did not work and it gave me an error of
Fatal error: exception Scanf.Scan_failure("scanf: bad input at char number 1: character ' ' is not a decimal digit")
If you include the commented out code you have this:
let values = Scanf.scanf "%d" (fun n -> n)
a.(i) <- i
This isn't syntactically valid because it has a let with no in. Your description of the problem isn't specific enough to tell whether that was your problem. If so, you need add in after the right parenthesis in the first line.
If this wasn't your problem, you might note that the second line of code here doesn't use values even though that's pretty much what I would expect it to do. The code as it stands reads a value from stdin, then ignores the value that it read.
If neither of these is your problem, you need to describe your problem more carefully. It's difficult to help if all you say is "it did not work."

Minesweeper board labels (beginner level)

We were given a homework, where we get a sample minesweeper-like board, with blank spaces instead of numbers (board is in [String] form) and already placed mines. What we need is to create a function, that replaces all blank spaces with numbers, which are equal to number of adjecent mines.
I was unable of making any real progress, except for removing all spaces with zeroes, which is probably not even useful in any way. I also had a problem with zeroes being of Char type, which made me unable to add for example +1 to it. It would be great if this could be solved without advanced functions, so I can understand it, but any solution or at least idea of solution will do.
This is what the beginning of the code should look like.
import Data.Char
type Result = [String]
pp :: Result -> IO ()
pp x = putStr (concat (map (++"\n") x)) --prints strings in a column.
sampleInput = [" ",
" * ",
" * ",
" * ",
" *",
"*** ",
"* * ",
"*** "]
minesweeper :: Result -> Result
And result should be this
Prelude>pp(minesweeper sampleInput)
1110000
1*11110
1122*10
001*221
233211*
***2011
*8*3000
***2000
I'm incredibly glad for any guidance as I'm unable of any real progress.
Update: Did a bit different yet similar solution. You can check related question here
What you need here is called "stencil convolution". Look at this picture:
111
1x1
111
This is your stencil. Pick a tile on the playing board and place the stencil on top of that tile.
How many 1s overlay mines, that number we should display in this tile. For example:
..... .....
111 .*... .....
1x1 + ..x*. = ..3..
111 ...*. .....
..... .....
Once we apply this operation to the whole board, we are basically done.
There are advanced devices for this, such as comonads and arrays, but for the purpose of this post
I will keep things simple, so we are going to draft everything by hand, in the simplest types. I
am also going to leave some blanks in the code, so that it is less boring for the reader. If you
enable -fdefer-typed-holes, you can put things like _wut in place of ... and ghc
will tell you what it thinks the type of the hole should be.
I should like to deal with numbers, rather than characters: as you point out, characters
are ill-suited for algorithmic work. Conversion should be two way, so that we can display our
result as well.
charsToInts :: [[Char]] -> [[Int]]
charsToInts = (fmap . fmap) charToInt
where
charToInt '*' = ...
charToInt ... = ...
intsToChars :: [[Int]] -> [[Char]]
intsToChars = ...
A nested list is not a very comfortable type to work with. We will define some helper functions
to make it easier. The operation that we will surely need is "indexing", that is, accessing an
element by its index — if it is there in the first place.
lookup2DMaybe :: [[a]] -> (Int, Int) -> Maybe a
lookup2DMaybe u (i, j) = do
xs' <- lookupMaybe xs i
x <- ...
return x
where
lookupMaybe :: [a] -> Int -> Maybe a
lookupMaybe xs i
| 0 <= i && i < length xs = ...
| ... = ...
Now, to interesting stuff — stencil application.
applyStencil :: [[Int]] -> (Int, Int) -> Int
applyStencil u = sum . Data.Maybe.catMaybes . fmap (... u) . stencil
where
stencil :: (Int, Int) -> [(Int, Int)]
stencil (i, j) = [ (i + di, ...) | di <- ..., dj <- ..., (di, dj) /= ... ]
Does this work?
λ applyStencil (charsToInts sampleInput) (3, 5)
2
λ applyStencil (charsToInts sampleInput) (6, 1)
8
All that is left to do is to "map" the stencil all around the minefield. To this end, we are
going to generate a board where at every point its coordinates are written. I hope somewhere along
the way you will see why.
indices :: [[a]] -> [[(Int, Int)]]
indices u = [ [ ... | ... ] | ... ]
The idea here is that we give it a board of anything, and it creates a board of coordinates of
the same size.
Consider the type we have so far:
λ :type applyStencil (charsToInts sampleInput)
applyStencil (charsToInts sampleInput) :: (Int, Int) -> Int
So, this is a function that converts coordinates to the number of mines around these
coordinates. What happens if we map it over a board of coordinates?
fill :: [[Int]] -> [[Int]]
fill u = (fmap.fmap) (... u) (... u)
λ intsToChars (fill (charsToInts sampleInput))
["1110000","1011110","1122110","0011221","2332110","2422011","4843000","2422000"]
Looks about right, does it not?
Only small things left to do: given two boards of characters, overlay them. This is outlined in
an answer to another question about lists of lists. (We get a lot of of questions of this
kind of late. Say hi to your professor from the Stack Overflow Haskell Teacher's Assistants
Team!)
Final solution!
minesweeper x = overlay x (intsToChars . fill . charsToInts $ x)
Not hard at all!
There are some ways to improve this code:
Create a specialized type for the board, such that only correct boards can be constructed.
Define a comonad for that type.
Scratch the type altogether and generalize the code to the Store comonad.
Use efficient array processing.
But the ideas we explored are there to last.
Some further reading:
The basics of stencil convolution.
The use of standard comonad types.
Advanced optimization of stencil convolution.
Let me know how it goes!

Print elements of a list in the same line

I'm new at haskell and I'm trying to print the elements of a list in a same line . For example:
[1,2,3,4] = 1234
If elements are Strings I can print it with mapM_ putStr ["1","2","3","\n"]
but they aren't.. Someone knows a solution to make a function and print that?
I try dignum xs = [ mapM_ putStr x | x <- xs ] too buts don't work ..
You can use show :: Show a => a -> String to convert an element (here an integer), to its textual representation as a String.
Furthermore we can use concat :: [[a]] -> [a] to convert a list of lists of elements to a list of elements (by concatenating these lists together). In the context of a String, we can thus use concat :: [String] -> String to join the numbers together.
So we can then use:
printConcat :: Show a => [a] -> IO ()
printConcat = putStrLn . concat . map show
This then generates:
Prelude> printConcat [1,2,3,4]
1234
Note that the printConcat function is not limited to numbers (integers), it can take any type of objects that are a type instance of the Show class.

Haskell List of Int : [123] to [1,2,3]

Problem
i have list of int as [123,123] which i required to be as [1,2,3,1,2,3]
Current Code
i tried out the following code using recursion
fat::[Int]->[Int]
fat [] = []
fat (a,b,c:xs) = a : b : c : fat xs
Conclusions
i have no idea how to acess values as '1' , '2 , '3 in a list [123,123] separetly
I suggest to use the digs function given in this answer on each element of your list. It splits an Int into a list of digits ([Int]). Then you just need to concatenate the resulting lists. This 'map and concatenate results' requirement is a perfect job for concatMap
fat :: [Int] -> [Int]
fat = concatMap digs
This gives:
*Main> fat [123,123]
[1,2,3,1,2,3]
Which is what you want, if I understood correctly.
splitNum :: Int -> [Int]
splitNum n | n <= 9 = [n]
| otherwise = (splitNum (n `div` 10)) ++ [n `mod` 10]
fat :: [Int] -> [Int]
fat x = concatMap splitNum x
splitNum is used to convert an Int to a [Int] by splitting it into the division by ten reminders and appending the resulting Int to the splitted rest (recursion!)
Now, having a function that converts numbers into lists, go through input, apply splitNum to any Number in the inner list and concat all resulting lists (list comprehension!)
As a new Haskell programmer I will give you my thoughts of this problem. Just because I think it's good to have many alternatives, especially from different people with different experience.
Here's my take on the problem:
For each item in the list, convert that item to a char list using read.
Send that char list into a function which converts each item of that list into an int, then return an list of ints.
Concat that list of ints into the main list.
To clarify:
[123, 234]
123 turns into ['1', '2', '3']
['1', '2', '3'] turns into [1, 2, 3]
[1, 2, 3] gets concat in the main list
the cycle repeats for 234.
The util function would look something like this:
import Char
charsToInts :: [Char] -> [Int]
charsToInts [] = []
charsToInts (x:xs) = digitToInt x : charsToInts xs
Coming from a imperative background that's how I would have solved it. Probably slower than just splitting the number mathematically, but I thought it would be interesting to show a alternative.
To pinpoint the problem bluntly, you have no idea how to access the digits separately because you do not understand Haskell types and pattern matching. Let me try to help dispel some of your misconceptions.
Let's look at your list:
[123, 123]
What is its type? It is clearly a list of ints, or [Int]. With lists, you can pattern match on the constructor :, known to lispers as "cons", or "list constructor". You put a single element on the left side of the :, and another list on the right side. The list on the right side can be the empty list [], which basically indicates the end of the list. Haskell provides "syntactic sugar" to make lists easier to write, but [123,456] actually gets desugared into 123:(456:[]). So when you pattern match (x:y:z), you can now see that x will be assigned 123 and y will be assigned 456. z will be the rest of the list after x and y; in this case only [] is left.
Now then, pattern matching with : works for lists. Ints are not lists, so you can't use : to pattern match on the digits of an Int. However, Strings are lists, because String is the same as [Char]. So if you turn your Int into a String then you can pattern match on each character.
map show [123, 123]
map applies a function to all elements of a list. show can take an Int and turn it into a String. So we map show over the list of Ints to get a list of Strings.
["123", "123"]
Now let's turn those Strings into lists of Ints. Since String is simply [Char], we will again make use of map.
map digitToInt "123" -- this requires that you import Data.Char (digitToInt)
This will give us [1,2,3]; each Char in the list is turned into an Int. This is what we want to do to each String in our list ["123", "123"]. We want to map digitToInt to each String. But we have a list of Strings. So what do we do? We map it!
map (map digitToInt) ["123", "123"]
This will give us [[1,2,3], [1,2,3]]. Almost what we wanted. Now we just have to flatten the list of list of Ints ([[Int]]) into just a list of Int ([Int]). How can we do that? Stop...Hoogle time! Hoogling [[a]] -> [a] we find the very first hit, concat, is exactly what we wanted.
Let's put it all together. First we do map show to get from [Int] to [String]. Then we do map (map digitToInt) to get from [String] to [[Int]]. Then we do concat to get from [[Int]] to [Int]. Then we'll just print it out!
import Data.Char (digitToInt)
main = print $ concat $ map (map digitToInt) $ map show $ [123, 123]
Now let's pull most of that out into a function fat
import Data.Char (digitToInt)
main = print $ fat [123, 123]
fat :: [Int] -> [Int]
fat xs = concat $ map (map digitToInt) $ map show $ xs
From here you could make it prettier in a few different ways. concat $ map is the same as concatMap, and since we map both (map digitToInt) and show in sequence, we can merge those. Also making it pointfree, we can end up with quite a terse definition:
fat = concatMap (map digitToInt . show)
For the sake of completeness, I wrote it as suggested by #Ancide
Implementation
fat' :: [Int] -> [Int]
fat' l = map (read) [[z] | z <- [x | k <- (map (show) l), x <- k]]
Explanation:
{- last result -} stands for the result of the last code explained.
map (show) l
This takes every element inside l and converts it to [String].
[x | k <- {- last result -}, x <- k]
While k goes through all elements inside the last result, x enumerates all character in each k. All those are added to a list. Now you have a String, respectively a [Char] with all digits next to each others.
[[z] | z <- {- last result -}]
This part takes each Char from the String and puts it into an empty String. Notice the [z] part! This make a list around z, which is (see above) the same as String. Now you have a list of String with a String for each digit.
map (read) {- last result -}
This takes every item in the last result and converts it back to Int and joins them to [Int]. Now you have a list of type [Int] of the wanted result.
Resumé
Although this implementation is possible, it's neither fast, due to all the type conversions, nor readable.
Playing around with the list monad I came up with this. Pretty much the same #Ankur's solution, except using the list monad:
fat :: [Int] -> [Int]
fat is = is >>= show >>= return . digitToInt
If you had two numbers, a and b then you could turn them into a single number by doing 10*a + b. The same principles apply for three.
It sounds like one way of doing this would be to splitEvery into lumps of three and then map a function to turn a list of three into a single number.
Does that help?
You need a function to convert Integer to string... which is obviously Show function
Another function to convert a Char to Integer which is "digitToInt" in module Char
And here we go :
fat::[Int]->[Int]
fat [] = []
fat ls = concat $ map (map digitToInt) (map show ls)
Please let me know if it works :)

Convert list of Integers into one Int (like concat) in haskell

Pretty much what the title says. I have a list of Integers like so: [1,2,3]. I want to change this in to the Integer 123. My first thought was concat but that doesn't work because it's of the wrong type, I've tried various things but usually I just end up returning the same list. Any help greatly appreciated.
Also I have found a way to print the right thing (putStr) except I want the type to be Integer and putStr doesn't do that.
You can use foldl to combine all the elements of a list:
fromDigits = foldl addDigit 0
where addDigit num d = 10*num + d
The addDigit function is called by foldl to add the digits, one after another, starting from the leftmost one.
*Main> fromDigits [1,2,3]
123
Edit:
foldl walks through the list from left to right, adding the elements to accumulate some value.
The second argument of foldl, 0 in this case, is the starting value of the process. In the first step, that starting value is combined with 1, the first element of the list, by calling addDigit 0 1. This results in 10*0+1 = 1. In the next step this 1 is combined with the second element of the list, by addDigit 1 2, giving 10*1+2 = 12. Then this is combined with the third element of the list, by addDigit 12 3, resulting in 10*12+3 = 123.
So pointlessly multiplying by zero is just the first step, in the following steps the multiplication is actually needed to add the new digits "to the end" of the number getting accumulated.
You could concat the string representations of the numbers, and then read them back, like so:
joiner :: [Integer] -> Integer
joiner = read . concatMap show
This worked pretty well for me.
read (concat (map show (x:xs))) :: Int
How function reads:
Step 1 - convert each int in the list to a string
(map show (x:xs))
Step 2 - combine each of those strings together
(concat (step 1))
Step 3 - read the string as the type of int
read (step 2) :: Int
Use read and also intToDigit:
joinInt :: [Int] -> Int
joinInt l = read $ map intToDigit l
Has the advantage (or disadvantage) of puking on multi-digit numbers.
Another idea would be to say: the last digit counts for 1, the next-to last counts for 10, the digit before that counts for 100, etcetera. So to convert a list of digits to a number, you need to reverse it (in order to start at the back), multiply the digits together with the corresponding powers of ten, and add the result together.
To reverse a list, use reverse, to get the powers of ten you can use iterate (*10) 1 (try it in GHCi or Hugs!), to multiply corresponding digits of two lists use zipWith (*) and to add everything together, use sum - it really helps to know a few library functions! Putting the bits together, you get
fromDigits xs = sum (zipWith (*) (reverse xs) (iterate (*10) 1))
Example of evaluation:
fromDigits [1,2,3,4]
==> sum (zipWith (*) (reverse [1,2,3,4]) [1,10,100,1000, ....]
==> sum (zipWith (*) [4,3,2,1] [1,10,100,1000, ....])
==> sum [4 * 1, 3 * 10, 2 * 100, 1 * 1000]
==> 4 + 30 + 200 + 1000
==> 1234
However, this solution is slower than the ones with foldl, due to the call to reverse and since you're building up those powers of ten only to use them directly again. On the plus side, this way of building numbers is closer to the way people usually think (at least I do!), while the foldl-solutions in essence use Horner's rule.
join :: Integral a => [a] -> a
join [x] = x
join (x:xs) = (x * (10 ^ long)) + join(xs)
where long = length(x:xs)
We can define the function called join, that given a list of Integral numbers it can return another Integral number. We are using recursion to separate the head of the given list with the rest of the list and we use pattern matching to define an edge condition so that the recursion can end.
As for how to print the number, instead of
putStr n
just try
putStr (show n)
The reasoning is that putStr can only print strings. So you need to convert the number to a string before passing it in.
You may also want to try the print function from Prelude. This one can print anything that is "showable" (any instance of class Show), not only Strings. But be aware that print n corresponds (roughly) to putStrLn (show n), not putStr (show n).
I'm no expert in Haskell, but this is the easiest way I can think of for a solution to this problem that doesn't involve using any other external functions.
concatDigits :: [Int] -> Int
concatDigits [] = 0
concatDigits xs = concatReversed (reverseDigits xs) 1
reverseDigits :: [Int] -> [Int]
reverseDigits [] = []
reverseDigits (x:xs) = (reverseDigits xs) ++ [x]
concatReversed :: [Int] -> Int -> Int
concatReversed [] d = 0
concatReversed (x:xs) d = (x*d) + concatReversed xs (d*10)
As you can see, I've assumed you're trying to concat a list of digits. If by any chance this is not your case, I'm pretty sure this won't work. :(
In my solution, first of all I've defined a function called reverseDigits, which reverses the original list. For example [1,2,3] to [3,2,1]
After that, I use a concatReversed function which takes a list of digits and number d, which is the result of ten power the first digit on the list position. If the list is empty it returns 0, and if not, it returns the first digit on the list times d, plus the call to concatReversed passing the rest of the list and d times 10.
Hope the code speaks for itself, because I think my poor English explanation wasn't very helpful.
Edit
After a long time, I see my solution is very messy, as it requires reversing the list in order to be able to multiply each digit by 10 power the index of the digit in the list, from right to left. Now knowing tuples, I see that a much better approach is to have a function that receives both the accumulated converted part, and the remainder of the list, so in each invocation in multiplies the accumulated part by 10, and then adds the current digit.
concatDigits :: [Int] -> Int
concatDigits xs = aggregate (xs, 0)
where aggregate :: ([Int], Int) -> Int
aggregate ([], acc) = acc
aggregate (x:xs, acc) = aggregate (xs, (acc * 10 + x))