How do I solve 'No exact matches in call to initializer'? - swift

func hasUniqueDigits(number: String) -> Bool {
var numbers = [1, 2, 3, 4, 5, 6, 7]
for i in 1...6 {
var partOne = number.firstIndex(of: String.Element("\(i)"))
var partTwo = String(numbers.firstIndex(of: Int(partOne))!)
numbers.remove(at: partTwo)
}
if numbers.count == 1 {
return true
} else {
return false
This is a function for determining whether a six-digit number containing only the digits 1-7 contains all unique digits.
Examples: 145327 works, 114723 doesn't because it has two ones, and 183427 doesn't because it contains an 8.
I have typed in random !'s to see if it was an optional problem and that didn't work. Can you please let me know hot to fix this error?

Not a direct answer to your question but it would be much easier to use sets. To check if the string have duplicated digits all you need is to check if the string count is the same of the character set count. To check if the string has only the allowed digits you can simply check if the number character set is a subset of the numbers character set:
func hasUniqueDigits(number: String) -> Bool {
let set1 = Set(number)
if number.count != set1.count { return false }
return set1.isStrictSubset(of: Set("1234567"))
}
hasUniqueDigits(number: "145327") // true
hasUniqueDigits(number: "114723") // false
hasUniqueDigits(number: "183427") // false
Note that this would return true for an empty string as well. If you want to make sure this method returns false just add a check to return false if number is empty:
if number.count != set1.count || number.isEmpty { return false }

Related

How to check the string doesn’t contain any letters in swift?

i have trouble during making the letter checker, my code is like this: if !containLetters(“1234h”){print(“pass”)}
my function is
func containsOnlyNum(input: String) -> Bool {
var ok = false
for chr in input {
for check in "1234567890.-"{
if chr == check{
ok = true
}
}
if ok != true{
return false
}
}
return true
}
If I check for “h” then didn’t pass, but if i check for ”1h” then it still pass! Please help me to fix this problem. I will give a big thank for anyone who helped me
The simplest way to fix the algorithm is this way:
func containsOnlyNum(input: String) -> Bool {
// check every character
for chr in input {
var isNum = false
for check in "1234567890.-"{
if chr == check {
isNum = true
// if we have found a valid one, we can break the iteration
break
}
}
if !isNum {
return false
}
}
return true
}
print(containsOnlyNum(input: "1234")) // true
print(containsOnlyNum(input: "1234h")) // false
However, then you can directly simplify it to:
func containsOnlyNum(input: String) -> Bool {
return input.allSatisfy { chr in
"1234567890.-".contains(chr)
}
}
which does exatly the same but uses allSatisfy and contains functions, which represent the logical operators ALL and EXISTS.
However, programmers normally use regular expressions for similar tasks:
func containsOnlyNum(input: String) -> Bool {
return input.range(of: "^[0-9.\\-]+$", options: .regularExpression) != nil
}
You can check that a string contains only the characters you're interested in like this:
extension String {
var containsOnlyNum: Bool {
let wanted = CharacterSet.decimalDigits
.union(CharacterSet(charactersIn: "-."))
return unicodeScalars
.allSatisfy(wanted.contains)
}
}
"-12.34".containsOnlyNum // true
"A1234".containsOnlyNum // false
But if you are interested in numbers, then this is a problem:
"-12.-34.".containsOnlyNum // true
Instead, you can just try casting the string to a double and see if it is a number or not
Double("1234") != nil // true, a number
Double("-1.234") != nil // true, a number
Double("A1234") != nil // false, not a number
Double("-12.-34.") != nil // false, not a number
Which is almost right unless you don't want this case:
Double("1234e2") != nil // true, a number
But you can use both checks if you don't want to allow that, or else if you are able to parse a Double from the input you can just do the cast.

Get String from Substring at a particular range

I want to write a function where I check the last 3 characters of a string are a part of another string or not, if it does I simply return true, else false.
Example :-
let str1 = "abc"
let str2 = "HiaBC"
What I want to check here is if str1 exists in last characters of str2, irrespective of case sensitiveness.
I tried
str2.contains("HI") // returned true as abc existed, should have returned false as it was not in the last 3 characters of the string.
func checkSubstring(str1:String, str2:String) -> Bool {
if str2.contains(str1) {
return true
}
return false
}
What I wanted was to somehow apply some range and check if last 3 characters are present in a substring or not.
Anyone can suggest anything?
You can use range(of:) with the appropriate options:
.caseInsensitive for case insensitive search,
.backwards to start the search from the end of the string, and
.anchored to limit the search to the end of the source string.
func checkSubstring(str1:String, str2:String) -> Bool {
return str2.range(of: str1, options: [.caseInsensitive, .backwards, .anchored]) != nil
}
Example:
print(checkSubstring(str1: "abc", str2: "HiaBC")) // true
print(checkSubstring(str1: "ab", str2: "HiaBC")) // false
There is suffix(3) to consider only the last three characters and caseInsensitiveCompare which is self-explanatory.
func checkSubstring(str1: String, str2: String) -> Bool {
return str2.suffix(3).caseInsensitiveCompare(str1) == .orderedSame
}

Compare three enums in swift [duplicate]

Does anybody know of a shortcut to test whether three numbers are the same? I know this works:
if number1 == number2 && number2 == number3 {
}
But I would like something cleaner, such as;
if number1 == number2 == number3 {
}
It's quite important as I'm comparing a lot of different values.
You could use a set
if Set([number1, number2, number3]).count == 1 {
...
though I'd argue it isn't as transparent as multiple if clauses
You can use the power of tuples and the Transitive Property of Equality.
if (number1, number2) == (number2, number3) {
}
The clause of this IF is true only when number1 is equals to number2 AND number2 is equals to number3. It means that the 3 values must be equals.
You can add them in an array and use sets:
var someSet = NSSet(array: [2,2,2])
if someSet.count == 1 {
print("Same values")
}
Don't know of anything other than a Set, I'd suggest wrapping it in a function to make your intent clear. Something along these lines:
func allItemsEqual<T>(items:[T]) -> Bool {
guard items.count > 1 else { fatalError("Must have at least two objects to check for equality") }
return Set(items).count == 1
}
func allItemsEqual(items:T...) -> Bool {
return equal(items)
}
if allItemsEqual(2,3,2) {
// false
}
if allItemsEqual(2, 2, 2) {
// true
}
Beyond that, maybe you could get fancy with operator overloading?
Try this:
func areEqual<T: NumericType>(numbers: T...) -> Bool {
let num = numbers[0]
for number in numbers {
if number != num {
return false
}
}
return true
}
Where NumericType is defined in this post: What protocol should be adopted by a Type for a generic function to take any number type as an argument in Swift?
This will allow you to use the function for all number types
You just pass any number of numbers like:
//returns true
if areEqual(1, 1, 1) {
print("equal")
}

How to separate characters in String by whitespace with multiple strides?

I have a working function that separates every n character with whitespace, which works fine.
Here is the code (Swift 5):
extension String {
/// Creates a new string, separating characters specified by stride lenght.
/// - Parameters:
/// - stride: Desired stride lenght.
/// - separator: Character to be placed in between separations
func separate(every stride: Int, with separator: Character) -> String {
return String(self.enumerated().map { $0 > 0 && $0 % stride == 0 ? [separator, $1] : [$1] }.joined())
}
}
This prints an example string of 1234123412341234 like this
1234 1234 1234 1234
Now, how can i separate this string 1234123412341234 with multiple strides, for example white space to be set after 4th, then after 6th and then after 5th character, like this:
1234 123412 34123 4
Here's how I would do this:
// Prints sequences of bools using 1/0s for easy reading
func p<S: Sequence>(_ bools: S) where S.Element == Bool {
print(bools.map { $0 ? "1" : "0"}.joined())
}
// E.g. makeWindow(span: 3) returns 0001
func makeWindow(span: Int) -> UnfoldSequence<Bool, Int> {
return sequence(state: span) { state in
state -= 1
switch state {
case -1: return nil
case 0: return true
case _: return false
}
}
}
// E.g. calculateSpacePositions(spans: [4, 6, 5]) returns 000100000100001
func calculateSpacePositions<S: Sequence>(spans: S)
-> LazySequence<FlattenSequence<LazyMapSequence<S, UnfoldSequence<Bool, Int>>>>
where S.Element == Int {
return spans.lazy.flatMap(makeWindow(span:))
}
extension String {
func insertingSpaces(at spans: [Int]) -> String {
let spacePositions = calculateSpacePositions(spans: spans + [Int.max])
// p(spacePositions.prefix(self.count))
let characters = zip(inputString, spacePositions)
.flatMap { character, shouldHaveSpace -> [Character] in
return shouldHaveSpace ? [character, "_"] : [character]
}
return String(characters)
}
}
let inputString = "1234123412341234"
let result = inputString.insertingSpaces(at: [4, 6, 5])
print(result)
The main idea is that I want to zip(self, spacePositions), so that I obtain a sequence of the characters of self, along with a boolean that tells me if I should append a space after the current character.
To calculate spacePositions, I first started by making a function that when given an Int input span, would return span falses followed by a true. E.g. makeWindow(span: 3) returns a sequence that yields false, false, false, true.
From there, it's just a matter of making one of these windows per element of the input, and joining them all together using flatMap. I do this all lazily, so that we don't actually need to store all of these repeated booleans.
I hit one snag though. If you give the input [4, 6, 5], the output I would get used to be 4 characters, space, 6 characters, space, 5 characters, end. The rest of the string was lost, because zip yields a sequence whose length is equal to the length of the shorter of the two inputs.
To remedy this, I append Int.max on the spans input. That way, the space positions are 000010000001000001 ...now followed by Int.max falses.
func separate(text: String,every stride: [Int], with separator: Character)->String {
var separatorLastPosition = 0 // This is the last separator position in text
var myText = text
if text.count < stride.reduce(0,+){
return text //if your text length not enough for adding separator for all stride positions it will return the text without modifications.you can return error msg also
}else{
for (index, item) in stride.enumerated(){
myText.insert(separator, at:myText.index(myText.startIndex, offsetBy: index == 0 ? item : separatorLastPosition+item))
separatorLastPosition += item+1
}
return myText
}
}
print(separate(text: "12345678901234567890", every: [2,4,5,2], with: " "))
//Result -- 12 3456 78901 23 4567890
func separateCharcters(numbers: String, every: inout [Int], character: Character) ->String{
var counter = 0
var numbersWithSpaces = ""
for (_, number) in numbers.enumerated(){
numbersWithSpaces.append(number)
if !every.isEmpty{
counter += 1
if counter == every.first!{
numbersWithSpaces.append(character)
every.removeFirst()
counter = 0
}
}
}
return numbersWithSpaces
}
Test Case
var numberArray = [4, 6, 5]
separateCharcters(numbers: "1234123412341234", every: &numberArray, character: " ")
Return Result = "1234 123412 34123 4"

Xcode 9.4.1 Swift 4 - Comparing a non-primitive Set to a primitive set containing Int

I am stumped on how to approach this scenario as I cannot figure out how to check if a single value within each list of the listGroup Exists before returning true and if one value is missing from one of the 4 lists the func must return false.
The list pasted through will have a data structure containing id, name, group
Example of the object passed through within objList:
Object - id: Int, name: String, group: String
init(){
//contains value which will match objList id's
let list1 : Set<Int> = [1,2]
let list2 : Set<Int> = [3,4]
let list3 : Set<Int> = [5,6,7]
let list4 : Set<Int> = [8,9]
//Set of Sets
listGroups = [list1,list2,list3,list4]
}
func checklist(_ objList: [Details]) -> Bool {
//I want to check that each sub set(list1-list4) elements exist
//E.G. if objList contains 2, 3, 7, 8, 15, 21 it will return true
//and if objList contains 1, 4, 7, return false as it doesn't contain a
//number from each set
//How I thought to approach but became stuck
for obj in objList {
for set in listGroups {
if set.contains(i.id){
//return true if objList contains numbers from list1, list2, list3 and list4
}
}
}
//I require an id from each list to be present in the objList
//but how would i know which set had which id and count how many group of 4
//there would be
}
The "Details" passed through contain details about them, however what I want to do is check whether the Int within the listGroups exist within the objList passed through. However the func can only return true if a value from each of the sub-sets of listGroups exists.
A single value from all 4 subsets must be present before I can return true and if a single one or more is missing func must return false
Create a Set from the id values of itemList and use intersection to check if one set contains at least one item of another set.
func checklist(_ objList: [Details]) -> Bool {
let idSet = Set(objList.map{$0.id})
for set in listGroups {
if set.intersection(idSet).isEmpty { return false }
}
return true
}
For a very long list it might be more efficient to subtract the currently checked values from idSet
func checklist(_ objList: [Details]) -> Bool {
var idSet = Set(objList.map{$0.id})
for set in listGroups {
let commonSet = set.intersection(idSet)
if commonSet.isEmpty { return false }
idSet.subtract(set)
}
return true
}