Dart Regular Expression Validating the length - dart

I am beginner to dart. I have tried using regular expression to validate the length of string. But its not working as expected. The {} curly braces indicate a length range in regex. Using {12} means a length of exactly 12, {12,15} means a length of 12 to 15 characters, and {12,} means a length of at least 12 with no upper limit. Because {12,} follows the . character, allowing 12 or more of any character. I have done based on this.
const password = r"dsjRK##RDsk34$SwedfQWDF";
if (!password.contains(RegExp(r'[a-z]'))) {
print('password should contain atleast lower case character');
} else if (!RegExp(r'[A-Z]').hasMatch(password)) {
print('password should contain atleast lower case character');
} else if (!RegExp(r'[0-9]').hasMatch(password)) {
print('password should contain atleast one digits');
} else if (!RegExp(r'[$##%&*^!]').hasMatch(password)) {
print('password should contain atleast one special charatcer');
} else if (!RegExp(r'.{12,15}').hasMatch(password)) {
print('password atleast 12 max 15 digits');
} else {
print("Perfect Password");
}
OutPUT:
Perfect Password
We can use some other solutions also . But my doubt is min length validation is working , why maximum validation is not working ?Please help me to understand the issue.

Change the regex with this one r'^.{12,15}$'.
It literally means that the substring generated from 12th to 15th character should be at the end of the original string
else if (!RegExp(r'^.{12,15}$').hasMatch(password){
print('password atleast 12 max 15 digits');
}

Based on the text of this matcher: {12, 15} it seems like you'd want to have maximum of 15 characters allowed. So change to this, if you want to have separate print-outs for the different cases:
const password = r"dsjRK##RDsk34$SwedfQWDF";
if (!RegExp(r'[a-z]').hasMatch(password)) {
print('password should contain at least one lower case character');
} else if (!RegExp(r'[A-Z]').hasMatch(password)) {
print('password should contain at least lower case character');
} else if (!RegExp(r'[0-9]').hasMatch(password)) {
print('password should contain at least one digits');
} else if (!RegExp(r'[$##%&*^!]').hasMatch(password)) {
print('password should contain at least one special charatcer');
} else if (password.length < 12) {
print('password at least 12 characters');
} else if (password.length > 15) {
print('password should have max 15 characters');
} else {
print("Perfect Password");
}
I also changed the first if statement to be consistent with the rest...

Related

How Can I Construct an Efficient CoreData Search, Including Allowing For Preceding and Trailing Characters Here?

Based on straight SQL searches in a previous app, I am adding CoreData searching to a new app. These searches are in a custom dictionary db that the app contains; this function does the work:
public func wordMatcher (pad: Int, word: Array<String>, substitutes : Set<String> ) {
let context = CoreDataManager.shared.persistentContainer.viewContext
var query: Array<String>
var foundPositions : Set<Int> = []
var searchTerms : Array<String> = []
if word.count >= 4 {
for i in 0..<word.count {
for letter in substitutes {
query = word
query[i] = letter
searchTerms.append(query.joined())
let rq: NSFetchRequest<Word> = Word.fetchRequest()
rq.predicate = NSPredicate(format: "name LIKE %#", query.joined())
rq.fetchLimit = 1
do {
if try context.fetch(rq).count != 0 {
foundPositions.insert(i)
break
}
} catch {
}
}
// do aggregated searchTerms search here instead of individual searches?
}
}
}
The NSFetchRequest focuses on one permutation at a time. But I'm accumulating the search string fragments in the array searchTerms because I don't know if it would be more efficient to construct a single query connected with ORs, and I also don't know how to do that in CoreData.
The focus is on the positions in the original term word: I need to indicate if any given location has at least one of the substitutes as a valid fit. So to implement the aggregate searchTerms approach, a FetchRequest would have to happen for each location in the base term.
A second complication is the one referred to in the title of the question. I am using LIKE because the search term in the FetchRequest could be a substring in a longer word. However, the maximum number of letters is 11, and pad is the starting point of the original term in that field of 11 spaces.
So if pad is 3, then I would need to allow for 0..<pad preceding characters. And because there may be trailing characters, I would also want results with 0..<(11 - (pad + word.count)) alphabetic characters after the last letter in the search term.
Regex seems like one way to do this, but I haven't found a clear example of how to do this in this case, and especially with the multiple search terms (if that's the way to go). The limits of SQLite in the previous version forced constructing multiple queries with increasing numbers of "_" underscores to indicate the padding characters; that tended to really explode the number of queries.
BTW, substitutes is limited to an absolute maximum of 9 values, and in practice is usually below 5, so things are a little more manageable.
I would like to get a grip on this, and so if anyone can provide direction or examples that can make this a reasonably efficient function, the help is appreciated greatly.
EDIT:
I've realized that I need a result for each position in the target string, with cases where the leading and trailing spaces also may need to contain a substitute as well.
So I'm moving to this:
public func wordMatcher (pad: Int, word: Array<String>, substitutes : Set<String> ) {
let context = CoreDataManager.shared.persistentContainer.viewContext
var pad_ = pad
var query: Array<String>
var foundPositions : Set<Int> = []
let rq: NSFetchRequest<Word> = Word.fetchRequest()
rq.fetchLimit = 1
let subs = "[\(substitutes.joined())]"
// if word.count >= 4 { // because those locations will be blocked off anyway otherwise
let start = pad > 0 ? -1 : 0
let finish = 11 - (pad + word.count) > 0 ? word.count + 1 : word.count
for i in start..<finish {
query = word
var _pad = 11 - (pad + word.count)
if i == -1 {
query = Array(arrayLiteral: subs) + query
pad_ -= 1
} else if i > word.count {
query.append(subs)
_pad -= 1
} else {
pad_ = pad
query[i] = subs
}
let endPad = _pad > 0 ? "{0,\(_pad)}" : ""
let predMatch = ".\(query.joined())\(endPad)"
print(predMatch)
rq.predicate = NSPredicate(format:"position <= %# AND word MATCHES %#", pad_, predMatch)
do {
if try context.fetch(rq).count != 0 {
foundPositions.insert(i)
}
} catch {
}
// }
}
lFreq = foundPositions
}
This relies on a regex substitution, inserted into the original target string. What I'll have to find out is if this is fast enough at the edge cases, but it may not be critical even in the worst case.
predMatch will end up looking something like "ab[xyx]d{0,3}", and I think I can get rid of the position section by changing it to be "{0,2}ab[xyx]d{0,3}". But I guess I'm going to have to try to find out.

Extremely slow parsing text with Swift

I'm trying to parse a 46k characters text document and it takes forever to do so. Here's what I do :
for i in 0..<html.length() - SEARCH_START.length() {
if html.substring(i, end: i+SEARCH_START.length()) == SEARCH_START {
start = i + SEARCH_START.length();
break;
}
if i % 1000 == 0 {
NSLog("i = \(i)")
}
}
extension String {
public func length () -> Int {
return self.characters.count
}
public func substring(_ start : Int, end : Int) -> String {
if self.characters.count <= 0 {
return ""
}
let realEnd = end>0 ? end : 0
return self.substring(with: self.index(self.startIndex, offsetBy: start)..<self.index(self.startIndex, offsetBy: realEnd))
}
}
Sorry, had to extend String class to do less rewriting from Android.
So, Log is being triggered each 6.5 seconds for a next thousand means almost 5 minutes to get to the end. The wole process should take milliseconds. What's the deal? Any way to speed it up?
You Int indexing extension is the problem. To get a substring at position n, it needs to go through all the characters 0..n. Therefore your algorithm has O(n^2) (quadratic) complexity instead of the expected O(n) (linear) complexity.
Don't use that extension.
To search for a substring, there is a native method
if let range = html.range(of: SEARCH_START) {
let integerIndex = html.distance(from: html.startIndex, to: range.upperBound)
print(integerIndex)
}
If you really want to work with integers, you should convert your string to an array of characters first:
let chars = Array(html.characters)
and work with subarrays instead of substrings.
Edit:
To better understand what happens in your extension:
self.substring(with: self.index(self.startIndex, offsetBy: start)..<self.index(self.startIndex, offsetBy: realEnd))
In Java, where String is an array and supports random indexing this would be a constant (fast) operation. However, in Swift this is composed from 3 steps:
self.index(self.startIndex, offsetBy: start) iterates from the first character until it finds the character at index start.
self.index(self.startIndex, offsetBy: realEnd)) iterates from the first character until it finds the character at index realEnd.
Gets the substring (fast)
In short, for every substring at start position n, the algorithm has to iterate over 2n characters. To get a single substring at index 20000, you need 40000 operations!

How to take a Roman Numeral String and convert it to base10 digit? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
So I am building a sample project which takes roman numerals and converts it to a base10 digit. I tried getting this to work but have not accomplished my goal. Is there anyone who knows how to accomplish this? I am adding the roman numerals up to 10 below for reference. Thanks!
1 - I
2 - II
3 - III
4 - IV
5 - V
6 - VI
7 - VII
8 - VIII
9 - IX
10 - X
All you need is to iterate through your roman string characters in a reverse way and map those characters values. Start with maxValue equal to zero, switch the letters value, save it as the maxValue and if the value is equal to maxValue add it otherwise subtract the actual value. You can also use regex (strict or not) to validate and throw an error in case it fails. Try like this:
Xcode 9.x • Swift 4.x
Note: for Swift 3 version or earlier check the edit history.
extension String {
enum RomanParsingError: Error {
case invalidNumber
}
func romanNumeralValue() throws -> Int {
guard range(of: "^(?=[MDCLXVI])M*(C[MD]|D?C{0,3})(X[CL]|L?X{0,3})(I[XV]|V?I{0,3})$", options: .regularExpression) != nil else {
throw RomanParsingError.invalidNumber
}
var result = 0
var maxValue = 0
uppercased().reversed().forEach {
let value: Int
switch $0 {
case "M":
value = 1000
case "D":
value = 500
case "C":
value = 100
case "L":
value = 50
case "X":
value = 10
case "V":
value = 5
case "I":
value = 1
default:
value = 0
}
maxValue = max(value, maxValue)
result += value == maxValue ? value : -value
}
return result
}
}
usage:
do {
let decimal = try "MCMLXXVIII".romanNumeralValue()
print(decimal) // 1978
} catch {
print(error)
}
do {
let decimal = try "IIIV".romanNumeralValue()
print(decimal)
} catch {
print(error) // "invalidNumber\n"
}
Roman numerals do not have a one-to-one mapping to decimal digits. You mapped out the sequences of roman numerals from 1 to 9 (single decimal digits.) There are also roman numerals for 10, 50, 100, 500, and 1000.
If you want to convert a large number in roman numerals to decimal, you need to parse it. You'll need to handle those larger units first.
Map out on paper how you do the conversion yourself, in small steps. Then write those steps out in pseudocode. (Don't worry about syntax, just map out the steps.)
Finally, use your pseudocode as a guide to writing your Swift program.

NSRange in Strings having dialects

I was working on an app, which takes input in a language called "Tamil". So in order to find the range of any particular charater in the string i have used the below code.
var range = originalWord.rangeOfString("\(character)")
println("\(range.location)")
So this works fine except for some cases.
there are some characters like this -> í , ó . // am just saying an example.
So like this combination, in other languages there are several vowel diacritcs are there.
If i have this word "alv`in"
// which is alvin , but i used "v" with a dialect.
If i print the unicde value of these characters in xcode, i will get each unicode. But for "v`" there will be two unicode values but its considered as a single character.
So if i check this character in the above mentioned code. i get the folowing result. Which gives errors in my program.
range.location // 2147483647 , its not a single digit.? why.?
But for other characters its just prints the correct Int Value. // Single digit like "3"
Anybody have any idea of how to get this done.? How can i achieve this if i use characters with dialets
.?
code given below
// userInput = "இல்லம்"
var originalWord : NSString = ("இல்லம்")
var originalArray = Array("இல்லம்")
var userInputWord = Array(String(userInput))
// -------------------------------------------
for character in String(userInput)
{
switch character
{
case originalArray[0] :
// here matches first character of the userinput to the original word first character
// the character exists at the 0th index
var range = originalWord.rangeOfString("\(character)")
if range.location == 0
{
// same character in the same index
// correctValue increase by one (cow Value)
cowValue += 1
}
else
{
// same character but in the different index
// Wrong value increase by one (bull Value)
bullValue += 1
}
case originalArray[1] :
// here matches first character of the userinput to the original word first character
// the character exists at the 1th index
var range = originalWord.rangeOfString("\(character)")
println("\(range.location)") // here i get he long Int Value instead of single digit
if range.location == 1
{
// same character in the same index
// correctValue increase by one (cow Value)
cowValue += 1
}
else
{
// same character but in the different index
// Wrong value increase by one (bull Value)
bullValue += 1
}
You should use Swift strings instead of NSString, because Swift strings have
full Unicode support including composed character sequences, (extended) grapheme clusters etc.
For Swift strings, rangeOfString() returns an optional Range<String.Index>
which is a bit more complicated to handle. You can also use find() instead to
find the position of a character. This might help as a starting point:
var cowValue = 0
var bullValue = 0
let userInput = "இல்லம்"
let originalWord = "இல்லம்"
let originalArray = Array("இல்லம்")
for character in userInput {
switch character {
case originalArray[0] :
if let pos = find(originalWord, character) {
// Character found in string
println(pos)
if pos == originalWord.startIndex {
// At position 0
cowValue += 1
} else {
// At a different position
bullValue += 1
}
} else {
// Character not found in string
}
case originalArray[1] :
if let pos = find(originalWord, character) {
// Character found in string
println(pos)
if pos == advance(originalWord.startIndex, 1) {
// At position 1
cowValue += 1
} else {
// At a different position
bullValue += 1
}
} else {
// Character not found in string
}
default:
println("What ?")
}
}
Check out the documentation for NSString's rangeOfComposedCharacterSequenceAtIndex: and rangeOfComposedCharacterSequencesForRange:
You want to look for Composed Character Sequences, not individual characters.

What is an optional variable?

I have the following code to work out if a number is prime;
#IBAction func isPrimeBtn(sender: AnyObject) {
if(isPrimeTxt.text.isEmpty){
isPrimeResultLbl.text = "Please Enter A Value";
}else{
var value = isPrimeTxt.text.toInt();
println(value);
if(value == 0){
println("value was 0");
isPrimeResultLbl.text = "Its Not";
}else{
for(var i = 3; i * i < value; i += 2){
println("value was 0");
if(value! % i == 0){
isPrimeResultLbl.text = "Its Not";
}
}
isPrimeResultLbl.text = "Its Prime!!";
}
}
}
When i print the value using println(value) I get Optional 22, if I check the variable is 0 it is true.
What am I doing incorrectly?
Thanks
There's a few problems here. Firstly, you correctly use value! in your modulus test, but in the first test and in the for loop you use value. I suggest you use an if let block instead, so value is not an optional ever:
if let value = isPrimeTxt.text.toInt() {
// now you know it's an integer
// ... do your test
} else {
// some error message
}
However, even if you do this, your logic is wrong on three counts:
1) isPrimeResultLbl.text = "Its Prime!!" is always executed after your for loop
2) it's incorrect for everything less than 10 because your for (var i = 3; i * i < value; i += 2) { will never execute if 3 * 3 >= value.
3) you need to start checking divisors at 2, not 3. 16 will appear prime using your algorithm (though 4 & 8 won't, as they're under 9!)
What happens if prime.text is "abc"? What happens is that the conversion toInt() will fail. Because it can fail, toInt() doesn't return an integer, it returns an optional integer. The result is either an integer or nothing. When you call println, you don't print an integer, you print an optional integer. And that's what println prints - it says "optional 22". It might have said something like "empty".
If you print value! instead of value, you tell Swift that you are 100% sure that the optional integer value is actually there. If it isn't, the expression value! will crash. If it is there, println will print 22. So the exclamation mark turns an optional either into a proper value, or into a crash.

Resources