Haskell Regular Expressions and Reading String as Integer - regex

Let's say I want to consider input of the form
[int_1, int_2, ..., int_n]
[int_1, int_2, ..., int_m]
...
where the input is read in from a text file. My goal is to obtain the maximum size of this list. Currently I have a regular expression that recognizes this pattern:
let input = "[1,2,3] [1,2,3,4,5]"
let p = input =~ "(\\[([0-9],)*[0-9]\\])" :: [[String]]
Output:
[["[1,2,3]","[1,2,3]","2,"],["[1,2,3,4,5]","[1,2,3,4,5]","4,"]]
So what I'm after is the max of the third index + 1. However, where I'm stuck is trying to consider this index as an int. For instance I can refer to the element just fine:
(p !! 0) !! 2
> "2,"
But I can't convert this to an int, I've tried
read( (p !! 0) !! 2)
However, this does not work despite the fact that
:t (p !! 0) !! 2
> (p !! 0) !! 2 :: String
Appears to be a string. Any advice as to why I can't read this as an int would be greatly appreciated.
Thanks again.

I'm not entirely sure that your approach is one I'd recommend, but I'm struggling to wrap my head around the goal, so I'll just answer the question.
The problem is that read "2," can't just produce an Int, because there's a leftover comma. You can use reads to get around this. reads produces a list of possible parses and the strings left over, so:
Prelude> (reads "2,") :: [(Int,String)]
[(2,",")]
In this case it's unambiguous, so you get one parse from which you can then pull out the int, although regard for your future self-respect suggests being defensive and not assuming that there will always be a valid parse (the Safe module is good for that sort of thing).
Alternatively, you could modify your regex to not include the comma in the matched group.

Related

Patterns not matched: Haskell

I wrote a function that takes a list as an input and outputs the sum of its elements, but I get the following error: "Pattern match(es) are non-exhaustive
In an equation for ‘addfunc’: Patterns not matched: []"
Here is my code:
addfunc :: [Int] -> Int
addfunc(x:xs) = x + addfunc xs
When pattern matching, you have to list out all possible cases, so that your program knows what to do for every possible input. Here, the possible input is all lists of integers, which also includes an empty list (a list of zero integers). Your function knows what to do when the input has a first element and other elements; but if it should receive an empty list (which cannot be decomposed into the first element and the other elements), it would not know what to do.
To correct it, simply provide the matching rules for the missing case(s), e.g.
addfunc [] = 0

Checking if a string contains a character in Scala

I have a collection of Strings and I'm checking if they're correctly masked or not.
They're in a map and so I'm iterating over it, pulling out the text value and then checking. I'm trying various different combinations but none of which are giving me the finished result that I need. I have gotten it working by iterating over each character but that feels very java-esque.
My collection is something like:
"text"-> "text"
"text"-> "**xt"
"text"-> "****"
in the first two cases I need to confirm that the value is not all starred out and then add them to another list that can be returned.
Edit
My question: I need to check if the value contains anything other an '*', how might I accomplish this in the most efficient scala-esque way?
My attempt at regex also failed giving many false positives and it seems like such a simple task. I'm not sure if regex is the way to go, I also wondered if there was a method I could apply to .contains or use pattern matching
!string.matches("\\*+") will tell you if the string contains characters other than *.
If I understand correctly, you want to find the keys in your map for which the value is not just stars. You can do this with a regex :
val reg = "\\*+".r
yourMap.filter{ case (k,v) => !reg.matches(v) }.keys
If you're not confortable with a regex, you can use a forall statement:
yourMap.filter{ case(k,v) => v.forall(_ == '*') }.keys
Perhaps I misunderstood your question, but if you started with a Map you could try something like:
val myStrings = Map("1"-> "text", "2"-> "**xt", "3"-> "****")
val newStrings = myStrings.filterNot( _._2.contains("*") )
This would give you a Map with just Map(1 -> "text").
Try:
val myStrings = Map("1"-> "text", "2"-> "**xt", "3"-> "****")
val goodStrings = myStrings.filter(_._2.exists(_ !='*'))
This finds all cases where the value in the map contains something other than an asterisk. It will remove all empty and asterisk-only strings. For something this simple, i.e. one check, a regex is overkill: you're just looking for strings that contain any non-asterisk character.
If you only need the values and not the whole map, use:
val goodStrings = myStrings.values.filter(_.exists(_ !='*'))

Find numbers in string using Golang regexp

I want to find all numbers in a string with the following code:
re:=regexp.MustCompile("[0-9]+")
fmt.Println(re.FindAllString("abc123def", 0))
I also tried adding delimiters to the regex, using a positive number as second parameter for FindAllString, using a numbers only string like "123" as first parameter...
But the output is always []
I seem to miss something about how regular expressions work in Go, but cannot wrap my head around it. Is [0-9]+ not a valid expression?
The problem is with your second integer argument. Quoting from the package doc of regex:
These routines take an extra integer argument, n; if n >= 0, the function returns at most n matches/submatches.
You pass 0 so at most 0 matches will be returned; that is: none (not really useful).
Try passing -1 to indicate you want all.
Example:
re := regexp.MustCompile("[0-9]+")
fmt.Println(re.FindAllString("abc123def987asdf", -1))
Output:
[123 987]
Try it on the Go Playground.
#icza answer is perfect for fetching positive numbers but, if you have a string which contains negative numbers also like below
"abc-123def987asdf"
and you are expecting output like below
[-123 987]
replace regex expression with below
re := regexp.MustCompile(`[-]?\d[\d,]*[\.]?[\d{2}]*`)

Get decimals from String

I got a function that takes a string and search it for decimals and output them.
What I got so far is:
getDecimal :: String -> [Int]
getDecimal[] = 0
getDecimal (x:y:xs) =
if
isDecimal x y
then
//output list
else
getDecimal xs
(for example: getDecimal "he12llo035" will output 12 , 035
But cant fill in the then because I simply cant find the solution, can you guys give me tips?
You try to tackle this in an imperative-like way: "look at this part of the list, is it what we want? Well then do that thing... oh, no it's not? Well then proceed there..."
It sure can't hurt to know how to implement it in such terms as well, but anyway better to learn more concise, explanative, declarative approaches right away. "The Haskell way".
That normally means roughly: split up your goal in subtasks. You'll first want to group all numbers down to one element, rather than a group of characters within the list. Well, you can hoogle for "group"!
Indeed there's a group comparison, but it simply puts together elements that are equal. That's a bit too strong, we sure want to allow different digits in each number! groupBy is the version that allows this. So, according to what do we want to group? Well, depending on whether it's a number. There's a nice helper from the Data.Function module that allows you to formulate this very much to the point:
groupBy ((==) `on` isDigit)
Meaning, we want to group such elements that have "the same status of digit-being".
After that, you'll have a lists of strings, and know each string is either a complete number, or something unrelated. The latter is to be thrown away...
filter (isDigit . head)
(I've just checked if the first character is a digit; the following are sure to be as well because that's what we've grouped by.
Now you've a list of numbers still in string form, all that's left to be done is parse (read!) each of them.
import Data.Char
import Data.List
import Data.Function
getDecimalNums :: String -> [Int]
getDecimalNums = map read . filter (isDigit . head) . groupBy ((==) `on` isDigit)

Pattern match failure on a list in Haskell

I just started working with Haskell and stumbled on a problem.
According to Haskell, I have a pattern match failure, but I fail to see how.
This is the code I try to execute:
statistics :: [Int] -> (Int, Int, Int)
statistics [gradelist] = ( amountParticipants, average, amountInsufficient)
where
amountParticipants= length [gradelist]
average= sum[gradelist] `div` amountParticipants
amountInsufficient= length [number| number<- [gradelist], number<6]
I call 'statistics' with:
statistics[4,6,4,6]
this causes a pattern match failure, while I expect to see : (4, 5, 2)
statistics[6]
gives the answer : ( 1, 6, 0 ) (which is correct).
Can someone tell me why my first call causes this pattern match? Because I'm pretty sure I give a list as an argument
If you write statistics [gradelist] = ... you are pattern matching against a singleton list containing a sole element referred to as gradelist. Hence, your function is only defined for lists of length exactly 1 (such as [6]); it is undefined for the empty list ([]) or lists with two or more elements (such as [4,6,4,6]).
A correct version of your function would read
statistics :: [Int] -> (Int, Int, Int)
statistics gradelist = (amountParticipants, average, amountInsufficient)
where
amountParticipants = length gradelist
average = sum gradelist `div` amountParticipants
amountInsufficient = length [number| number <- gradelist, number < 6]
As #thoferon remarked, you will also need to make special arrangements for the case in which gradelist is empty, in order to avoid dividing by zero when computing average.
Just replace your [gradelist]'s by gradelist as said before. Also, you might want to match against the empty list with [], in order to avoid dividing by zero in average, like :
statistics [] = (0,0,0)
The list syntax [ ] in a pattern deconstructs a list. The pattern [gradelist] matches a list holding exactly one value, and it names the value in the list gradelist. You get a pattern match failure if you try to call the function with a list holding four values.
To match a value without deconstructing it, use a variable as the pattern.