Greetings, I am new to Haskell and I've gotten stuck in defining a datatype for an assignment.
I need to create the "Strategy" type, it's basically a string with 1-6 characters each representing a numeric value, and I must represent values greater than 9 as a letter (up to 35 total different values), I tried defining an auxiliary type representing each possible value and using that to create my type, but my code isn't working and I have ran out of ideas. This is the definition I have been trying:
data Value = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' | 'A' | 'B' |
'C' | 'D' | 'E' | 'F' | 'G' | 'I' |'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' |
'Q' |'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'Y' | 'X' | 'Z'
data Strategy = Value | Value:Value | Value:Value:Value |
Value:Value:Value:Value | Value:Value:Value:Value:Value |
Value:Value:Value:Value:Value:Value
The Value type isn't accepting the numbers, and the Strategy type "sort of" works up to the second constructor after which it goes bust. Thanks for your help!
Just like your previous (deleted) question, this looks a lot like homework. It also helps if you pick a real name and not use this throw-away account.
This page tells you how to use haskell's data type declarations. What are you doing different/wrong?
You use characters instead of constructors for Value. The '1' '2', etc are all characters, you need a constructor along with zero or more fields like ValueCon1 Char and ValueCon2 String
You are using list constructors and what I assume is a field of Value instead of defining any new constructors for Strategy. Perhaps you want data Strategy = Strat [Value], which will accept a list of any size. While more painful you can define many many strategy constructors with a finite number of separate Value fields.
BTW - where is your course taught? It seems late in the term to be covering these basics.
type Strategy = [Char]
^^ how I'd actually do it.
Or, maybe
newtype Strategy = Strategy [Char]
This is less principled, as the obligation is on you to not fill it with nonsense. Using the newtype solution, you can use "smart constructors" and say, e.g.
mkStrategy :: [Char] -> Strategy
mkStrategy x
| {- list is valid -} = Strategy x
| otherwise = error "you gave me a bad strategy!"
in real code, you don't want to throw error, but return an option type, but that's another story...
Related
I have the challenge that I need to search in Excel for multiple terms and to get the result back for each cell which of the different terms has matched.
I know there is a formula combination to search for multiple terms but this will not give me the matched term back. The exampel below gives only a "0" or "1" back.
=IF(ISNUMBER(SEARCH({"TermA","TermB","TermC"},A1)),"1","0")
| | A | B |
| 1 | This is TermA | TermA |
| 2 | Some TermB Text | TermB |
| 3 | And TermA Text | TermA |
| 4 | another TermC | TermC |
Background I have to do some normalization of the values and look therefore for some forumla which can identify the values and list the match. The values which are used to search for should be later on another page so it can be easily extended.
Thank you for some hints and approaches which will put me into the right direction.
To return all matching terms:
=INDEX(FILTERXML("<t><s>"&SUBSTITUTE(A1," ","</s><s>")&"</s></t>","//s[.='TermA' or .='TermB' or .='TermC']"),COLUMN(A1))
Wrap in an IFERROR() if no match is found at all.
If one has ExcelO365 and you refer to a range, things got a lot easier:
Formula in E1:
=TRANSPOSE(FILTER(C$1:C$3,ISNUMBER(FIND(C$1:C$3,A1))))
=INDEX(FILTER(C:C,C:C<>""),MATCH(1, COUNTIF(A1, "*"&FILTER(C:C,C:C<>"")&"*"), 0))
For use in office 365 version. If previous version replace FILTER(C:C,C:C<>"") with C$1:C$4 for your example or whatever your range of search values may be. Table reference is also possible.
The formula searches for the first match in your list of values if the text including your term contains a matching value anywhere in that text. It returns the first match.
This is my very first question linking to my first Python project.
To put it simple, I have 2 columns of data in Excel like this (first 6 rows):
destination_area | destination_code
SG37.D0 | SG37.D
SG30.C0 | SG30.C
SG4.A3.P | SG4.A
SG15.C16 | SG15.C
SG35.D02 | SG35.D
SG8.A5.BC | SG8.A
So in Excel, I'm using a function to get destination code by finding first "." in the cell & return all characters from the left of it, plus 1 character:
=IfError(left(E2,search(".",E2)+1),"")
Now I want to execute it using str.extract
df1['destination_code'] = df1['destination_area'].str.extract(r"(?=(.*[0-9][.][A-Z]))", expand = False)
print(df1['destination_area'].head(6),df1['destination_code'].head(6))
I almost got what I need but the code still recognize those that have more than 1 "."
destination_area | destination_code
SG37.D0 | SG37.D
SG30.C0 | SG30.C
SG4.A3.P | SG4.A3.P
SG15.C16 | SG15.C
SG35.D02 | SG35.D
SG8.A5.BC | SG8.A5.BC
I recognize that my regex is understanding the pattern of {a number + "." + a letter}, which returns all characters for the cases of "SG4.A3.P" and "SG8.A5.BC".
So how to modify my code? Or any better way to perform the code like how Excel does? Thanks in advance
No need in lookahead. Use
df1['destination_code'] = df1['destination_area'].str.extract(r"^([^.]+\..)", expand=False)
See proof. Mind the capturing group, it is enough here to return the value you need.
Explanation:
--------------------------------------------------------------------------------
^ the beginning of the string
--------------------------------------------------------------------------------
( group and capture to \1:
--------------------------------------------------------------------------------
[^.]+ any character except: '.' (1 or more
times (matching the most amount
possible))
--------------------------------------------------------------------------------
\. '.'
--------------------------------------------------------------------------------
. any character except \n
--------------------------------------------------------------------------------
) end of \1
Given the following examples,
16A6
ECCB15
I would only like to extract the last number or numbers from the string value. So the end result that I'm looking for is:
6
15
I've been trying to find a way, but can't seem to find the correct one.
Use thisformula:
=MID(A1,AGGREGATE(14,7,ROW($Z$1:INDEX($ZZ:$ZZ,LEN(A1)))/(NOT(ISNUMBER(--MID(A1,ROW($Z$1:INDEX($ZZ:$ZZ,LEN(A1))),1)))),1)+1,LEN(A1))
Try this:
=--RIGHT(A2,SUMPRODUCT(--ISNUMBER(--RIGHT(SUBSTITUTE(A2,"E",";"),ROW(INDIRECT("1:"&LEN(A2)))))))
or this (avoid using INDIRECT):
=--RIGHT(A2,SUMPRODUCT(--ISNUMBER(--RIGHT(SUBSTITUTE(A2,"E",";"),ROW($A$1:INDEX($A:$A,LEN(A2)))))))
Replace A2 in the above formula to suit your case.
Here are the data for testing:
| String |
|-----------|
| 16A6 |
| ECCB15 |
| BATT5A6 |
| 16 |
| A1B2C3E0 |
| 16E |
| TEST00004 |
I have an even shorter version: --RIGHT(A2,SUMPRODUCT(--ISNUMBER(--RIGHT(SUBSTITUTE(A2,"E",";"),ROW(INDIRECT("1:"&LEN(A2)))))))
The difference is the use of SUBSTITUTE in my final formula. I used SUBSTITUTE to replace letter E with a symbol because in the fifth string in the above list, the RIGHT function in my formula will return the following: {"0";"E0";"3E0";"C3E0";"2C3E0";"B2C3E0";"1B2C3E0";"A1B2C3E0"} where the third string 3E0 will return TRUE by ISNUMBER function, and this will result in an incorrect answer. Therefore I need to get rid of letter E first.
Let me know if you have any questions. Cheers :)
i had problem with my homework, can someone explane me for the question below. thank you
Construct a CFG for RE below :
a* b* (a│c)*
(a│c)* ba
If you want to write CFG for regular expression, try to understand what regular expression is saying.
For e.g. in 1. ab(a|c)*, we are given with regular expression for any number of a's followed by any number b's followed by any number of a or c's.
To write CGF for this,
S--> ABC
A--> aA | ^
B--> bB | ^
C--> aC | cC | ^
Where variable A will take care of a*, variable B will take care of b*, C will take care of (a|c)*
Similarly, for 2. (a|c)*ba, we are given with regular expression for any number of a or c followed by substring ba. CGF for this will be,
S--> Aba
A--> aA | cA | ^
I'm trying to define a function that does A if there's an even number of dollar signs (in my buffer), and B if there's an odd number of dollar signs. However, I'm unsure how to count the number of dollar signs, and then report that number for defining the function. For instance, entering
:%s/\$//gn
will spit out this number on the status line. But how can one apply the result for defining a function?
Based on #DaveNewman's comment, you may write:
:%s/\$//gn | let i = split(v:statusmsg)[0] | if i % 2 | ... | else | ... | endif