Check for dates consistency in MATLAB - validation

Is there any straight forward way to do that? I want to give an array of dates as an input (for example 1997-01-02 1997-01-03... using the format yyyy-mm-dd) and get 1 if all the elements of the given array are consistent and 0 otherwise.
Any idea?

Here is one idea:
d = {
'1997-01-02'
'1997-01-03'
'1111-99-99'
'not a date'
}
isDateValid = false(size(d));
for i=1:numel(d)
try
str = datestr(datenum(d{i},'yyyy-mm-dd'),'yyyy-mm-dd');
isDateValid(i) = isequal(str,d{i});
catch ME
end
end
The result:
>> isDateValid
isDateValid =
1
1
0
0
The reason I do the conversion back and forth is that MATLAB will carry values outside the normal range of fields to the next one -- third example will actually be parsed as: 1119-06-07. While the last one will throw an exception

Many ways to do this using regexp. A couple of simple ones:
str = '1917-01-23';
regexp(str,'\d\d\d\d-\d\d-\d\d')
ans =
1
If the string matches exactly that pattern, you will get 1, else empty.
Or do this:
regexp(str,'-','split')
ans =
'1917' '01' '23'
Now you can verify the first piece is a valid year, the second a valid month, etc.

Related

ruby regex string $

I have to cut the price from strings like that:
s1 = "somefing $ 100"
s2 = "$ 19081 words $"
s3 = "30$"
s4 = "hi $90"
s5 = "wow 150"
Output should be:
s1 = "100"
s2 = "19081"
s3 = "30"
s4 = "90"
s5 = nil
I use the following regex:
price = str[/\$\s*(\d+)|(\d+)\s*\$/, 1]
But it doesn't work for all types of strings.
Your code always returns the result of the first capture group group whereas in the failing case it is the second capture group that you are interested in. I don't think the [] method has a good way of dealing with this (when using numbered capture groups). You could write this like so
price = str =~ /\$\s*(\d+)|(\d+)\s*\$/ && ($1 || $2)
Although this isn't very legible. If instead you use a named capture group, then you can do
price = str[/\$\s*(?<amount>\d+)|(?<amount>\d+)\s*\$/, 'amount']
Duplicate named capture groups won't always do what you want but when they are in separate alternation branches (as they are here) then it should work.
The problem is that you're always getting value from the first regex group and you don't check the second. So, you're not looking the case after | - the one when digit is before $ sign.
If you look at the graphical representation of your regex, by typing 1 as a second parameter in square brackets, you are covering only the upper path (first case), and you never check lower one (second case).
Basically, try:
price = str[/\$\s*(\d+)|(\d+)\s*\$/, 1] or str[/\$\s*(\d+)|(\d+)\s*\$/, 2]
P.S. I'm not that experienced in Ruby, there might be some more optimal way to type this, but this should do the trick
try this, its much simpler but it may not be the most efficient.
p1 = s1.gsub(' ','')[/\$(\d+)|(\d+)\$/,1]

Classic ASP InStr() Evaluates True on Empty Comparison String

I ran into an issue with the Classic ASP VbScript InStr() function. As shown below, the second call to InStr() returns 1 when searching for an empty string in a non empty string. I'm curious why this is happening.
' InStr Test
Dim someText : someText = "So say we all"
Dim emptyString : emptyString = ""
'' I expect this to be true
If inStr(1,someText,"so",1) > 0 Then
Response.write ( "I found ""so""<br />" )
End If
'' I expect this to be false
If inStr(1, someText, emptyString, 1) > 0 Then
Response.Write( "I found an empty string<br />" )
End If
EDIT:
Some additional clarification: The reason for the question came up when debugging legacy code and running into a situation like this:
Function Go(value)
If InStr(1, "Option1|Option2|Option3", value, 1) > 0 Then
' Do some stuff
End If
End Function
In some cases function Go() can get called with an empty string. The original developer's intent was not to check whether value was empty, but rather, whether or not value was equal to one of the piped delimited values (Option1,Option2, etc.).
Thinking about this further it makes sense that every string is created from an empty string, and I can understand why a programming language would assume a string with all characters removed still contains the empty string.
What doesn't make sense to me is why programming languages are implementing this. Consider these 2 statements:
InStr("so say we all", "s") '' evaluates to 1
InStr("so say we all", "") '' evaluates to 1
The InStr() function will return the position of the first occurrence of one string within another. In both of the above cases, the result is 1. However, position 1 always contains the character "s", not an empty string. Furthermore, using another string function like Len() or LenB() on an empty string alone will result in 0, indicating a character length of 0.
It seems that there is some inconsistency here. The empty string contained in all strings is not actually a character, but the InStr() function is treating it as one when other string functions are not. I find this to be un-intuitive and un-necessary.
The Empty String is the Identity Element for Strings:
The identity element I (also denoted E, e, or 1) of a group or related
mathematical structure S is the unique element such that Ia=aI=a for
every element a in S. The symbol "E" derives from the German word for
unity, "Einheit." An identity element is also called a unit element.
If you add 0 to a number n the result is n; if you add/concatenate "" to a string s the result is s:
>> WScript.Echo CStr(1 = 1 + 0)
>> WScript.Echo CStr("a" = "a" & "")
>>
True
True
So every String and SubString contains at least one "":
>> s = "abc"
>> For p = 1 To Len(s)
>> WScript.Echo InStr(p, s, "")
>> Next
>>
1
2
3
and Instr() reports that faithfully. The docs even state:
InStr([start, ]string1, string2[, compare])
...
The InStr function returns the following values:
...
string2 is zero-length start
WRT your
However, position 1 always contains the character "s", not an empty
string.
==>
Position 1 always contains the character "s", and therefore an empty
string too.
I'm puzzled why you think this behavior is incorrect. To the extent that asking Does 'abc' contain ''? even makes sense, the answer has to be "yes": All strings contain the empty string as a trivial case. So the answer to your "why is this happening" question is because it's the only sane thing to do.
It is s correct imho. At least it is what I expect that empty string is part of any other string. But maybe this is a philosophical question. ASP does it so, so live with it. Practically speaking, if you need a different behavior write your own Method, InStrNotEmpty or something, which returns false on empty search string.

Can't convert String into Integer (TypeError)

I am learning Ruby
I am trying to create a simple script that will convert a given number to roman numerals (old style roman numerals)
I am unable to understand why I get the "can't convert String into Integer (TypeError)"
def convert_to_roman number
romans_array = [[1000,'M'],[500,'D'],[100,'C'],[50,'L'],[10,'X'],[5,'V'][1,'I']]
converted_array = []
romans_array.each do |rom_num|
num = rom_num[0]
letter = rom_num[1]
if number > num
times = number / num
roman_letter = letter*times
converted_array.push(roman_letter)
number = number % num
end
end
converted_array.join()
end
number = ''
puts 'please write a number and I will convert it to old style Roman numerals :)'
puts 'p.s. to exit this program simply hit enter on an empty line, or type 0 and enter :)'
while number != 0
number = gets.chomp.to_i
puts convert_to_roman number
end
My code is at:
https://github.com/stefanonyn/ruby-excercises/blob/master/roman_numerals.rb
You will see that at the end of the file commented out there is an old revision of the code, which actually does work but has a lot of repetition.
I would appreciate if someone could clarify why I get the error described above.
Please don't write the code for me, I am trying to learn Ruby, I would appreciate just some support in moving to the next step.
Thank you very much!
You are missing a comma in your array
romans_array = [[1000,'M'],[500,'D'],[100,'C'],[50,'L'],[10,'X'],[5,'V'][1,'I']]
^ here
This error is definitely not all that helpful, but the reason that it is appearing is that to the interpreter it looks like you are attempting to access a range of indexes in the [5,'V'] array for the last element. However the index's that are being provided go from 1 to 'I' which of course makes no sense. If it had been written [5,'V'][1,1] the last element of the array would be ['V'], which might have been even more confusing to debug!

Ruby Truncate Words + Long Text

I have the following function which accepts text and a word count and if the number of words in the text exceeded the word-count it gets truncated with an ellipsis.
#Truncate the passed text. Used for headlines and such
def snippet(thought, wordcount)
thought.split[0..(wordcount-1)].join(" ") + (thought.split.size > wordcount ? "..." : "")
end
However what this function doesn't take into account is extremely long words, for instance...
"Helloooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo
world!"
I was wondering if there's a better way to approach what I'm trying to do so it takes both word count and text size into consideration in an efficient way.
Is this a Rails project?
Why not use the following helper:
truncate("Once upon a time in a world far far away", :length => 17)
If not, just reuse the code.
This is probably a two step process:
Truncate the string to a max length (no need for regex for this)
Using regex, find a max words quantity from the truncated string.
Edit:
Another approach is to split the string into words, loop through the array adding up
the lengths. When you find the overrun, join 0 .. index just before the overrun.
Hint: regex ^(\s*.+?\b){5} will match first 5 "words"
The logic for checking both word and char limits becomes too convoluted to clearly express as one expression. I would suggest something like this:
def snippet str, max_words, max_chars, omission='...'
max_chars = 1+omision.size if max_chars <= omission.size # need at least one char plus ellipses
words = str.split
omit = words.size > max_words || str.length > max_chars ? omission : ''
snip = words[0...max_words].join ' '
snip = snip[0...(max_chars-3)] if snip.length > max_chars
snip + omit
end
As other have pointed out Rails String#truncate offers almost the functionality you want (truncate to fit in length at a natural boundary), but it doesn't let you independently state max char length and word count.
First 20 characters:
>> "hello world this is the world".gsub(/.+/) { |m| m[0..20] + (m.size > 20 ? '...' : '') }
=> "hello world this is t..."
First 5 words:
>> "hello world this is the world".gsub(/.+/) { |m| m.split[0..5].join(' ') + (m.split.size > 5 ? '...' : '') }
=> "hello world this is the world..."

Ruby String pad zero OPE ID

I'm working with OPE IDs. One file has them with two trailing zeros, eg, [998700, 1001900]. The other file has them with one or two leading zeros for a total length of six, eg, [009987, 010019]. I want to convert every OPE ID (in both files) to an eight-digit string with exactly two leading zeros and however many zeros at the end to get it to be eight digits long.
Try this:
a = [ "00123123", "077934", "93422", "1231234", "12333" ]
a.map { |n| n.gsub(/^0*/, '00').ljust(8, '0') }
=> ["00123123", "00779340", "00934220", "001231234", "00123330"]
If you have your data parsed and stored as strings, it could be done like this, for example.
n = ["998700", "1001900", "009987", "0010019"]
puts n.map { |i|
i =~ /^0*([0-9]+?)0*$/
"00" + $1 + "0" * [0, 6 - $1.length].max
}
Output:
00998700
00100190
00998700
00100190
This example on codepad.
I'm note very sure though, that I got the description exactly right. Please check the comments and I correct in case it's not exactly what you were looking for.
With the help of the answers given by #detunized & #nimblegorilla, I came up with:
"998700"[0..-3].rjust(6, '0').to_sym
to make the first format I described (always with two trailing zeros) equal to the second.

Resources