That's the code:
import Foundation
func hasAnyMatches(list: [Int], condition: Int -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(numbers, condition: lessThanTen)
There is a return true within the if condition and a return false at the end of func hasAnyMatches(). Why is the return false needed?
Without explicitly "telling it" to return something, no function returns false "automatically". I am not writing in swift but I am sure if you take away the return false it'll throw a warning.
The lessThanTen simply returns a bool if the number is smaller than 10.
number < 10 is a statement checking if something is true or false. Hence the return type bool of lessThanTen
You can do like, for such condition.
let LESS_THAN_TEN = 1
let LESS_THAN_HUNDRED = 2
func hasAnyMatch (list: [Int], condition: Int)-> Bool{
var x = false;
switch condition {
case LESS_THAN_TEN :
for a in list {
if a < 10 {
x = true
break
}
}
break
case LESS_THAN_HUNDRED :
for a in list {
if a < 100 {
x = true
break
}
}
break
default:
x = false
}
return x
}
var isLessThanTen = hasAnyMatch([14, 45, 12, 65], condition: LESS_THAN_TEN)
print(isLessThanTen)
Related
This question already has answers here:
Extending Array to check if it is sorted in Swift?
(13 answers)
Closed 3 months ago.
Write a function isIncreasing that takes a list of Ints and returns true if numbers are in increasing (equals OK) order. An empty list should result in true.
func isIncreasing(_ l: [Int]) -> Bool {
var flagreturn=true
if l.count == 0 {
flagreturn=true
} else {
for i: Int in l {
if l[i] < l[i + 1] {
flagreturn=true
}
else{
flagreturn=false
}
}
}
return flagreturn
}
Not sure if I implemented the true and false correctly in the code.
You can zip the sequence with itself dropping the first element and check if it all satisfy a condition like $0 <= $1:
func isIncreasing(_ l: [Int]) -> Bool {
zip(l, l.dropFirst()).allSatisfy { $0 <= $1 }
}
isIncreasing([1,2]) // true
isIncreasing([0,1,1,2]) // true
isIncreasing([0,1,1,2,1]) // false
Expanding on that you can extend sequence constraining its elements to Comparable an d create a generic property like areInIncreasingOrder:
extension Sequence where Element: Comparable {
var areInIncreasingOrder: Bool {
zip(self, dropFirst()).allSatisfy { $0 <= $1 }
}
}
Usage:
[1,2].areInIncreasingOrder // true
[1,2].dropFirst(2).areInIncreasingOrder // true
[0,1,1,2].areInIncreasingOrder // true
[0,1,1,2,1].areInIncreasingOrder // false
This question already has answers here:
Sorting array alphabetically with number
(8 answers)
Closed 9 months ago.
I'll try to define the problem in words, but this is easier explained with the use of the example test cases.
"b" > "a"
"3" > "1"
"ac" > "ab"
"32" > "25"
"abcd1" > "abc2"
"abc123a" > "abc2a"
"abc123a" < "abc1234a"
"abc123" < "abc123a"
"abc12a49" > "abc12a39"
"123ab3" = "123ab3"
"ab12" > "12ab"
"ab12" > "345"
I need to compare alphanumeric strings. It is trivial when there are only numbers or only characters in the string, but when they are combined, it becomes more complicated. Basically I need to compare the number groups as one whole number instead of individual numbers, if I make sense.
The following is what I tried. It is a brute force approach to split the string into groups of alphabets and numbers.
I think this works but it is not very performant nor elegant. Is there a better way to achieve this. I'm pretty much dumping all the dependent extensions and methods needed for this to run on the playground, so very sorry for the lack of formatting.
extension RangeReplaceableCollection {
mutating func removeFirstSafe() -> Element? {
guard !isEmpty else { return nil }
return removeFirst()
}
}
extension String {
func split(grouping charSets: [[Character]]) -> [(CharacterType, String)] {
var subStrings = [(CharacterType, String)]()
var copy = self
copy.__split(grouping: charSets, groupedSubstrings: &subStrings)
return subStrings
}
mutating func __split(grouping charSets: [[Character]], groupedSubstrings: inout [(CharacterType, String)]) {
guard let previousCharacter: Character = removeFirstSafe() else {
return
}
var groupedSubString = String(previousCharacter)
let prevCharSetGroup: CharacterType = charSets.indexOfCharSetGroupContainingCharacter(previousCharacter)
while let currentCharacter = first, charSets.indexOfCharSetGroupContainingCharacter(currentCharacter) == prevCharSetGroup {
groupedSubString.append(currentCharacter)
removeFirst()
}
groupedSubstrings.append((prevCharSetGroup, groupedSubString))
__split(grouping: charSets, groupedSubstrings: &groupedSubstrings)
}
}
enum CharacterType: Int, Comparable {
case alphabet = 1
case number = 0
case unknown = -1
static func < (lhs: CharacterType, rhs: CharacterType) -> Bool {
lhs.rawValue < rhs.rawValue
}
}
extension Array where Element == [Character] {
func indexOfCharSetGroupContainingCharacter(_ char: Character) -> CharacterType {
for (index, group) in self.enumerated() {
if group.contains(char) { return CharacterType(rawValue: index) ?? .unknown }
}
return .unknown
}
}
extension Collection {
subscript (safe index: Index) -> Element? {
return indices.contains(index) ? self[index] : nil
}
}
struct AlphanumericString {
var string: String
}
func <(lhs: (CharacterType, String), rhs: (CharacterType, String)) -> Bool {
if lhs.0 > rhs.0 { return false }
else if lhs.0 < rhs.0 { return true }
else {
if lhs.0 == .alphabet || lhs.0 == .unknown { return lhs.1 < rhs.1 }
else { return (Int(lhs.1) ?? 0) < (Int(rhs.1) ?? 0) }
}
}
extension AlphanumericString: Comparable {
static func < (lhs: AlphanumericString, rhs: AlphanumericString) -> Bool {
if lhs.string == rhs.string { return false }
let lhsGrouped = lhs.string.split(grouping: [Array("12345"), Array("abcde")])
let rhsGrouped = rhs.string.split(grouping: [Array("12345"), Array("abcde")])
for idx in lhsGrouped.indices {
let lhsItem = lhsGrouped[idx]
guard let rhsItem = rhsGrouped[safe: idx] else { return false }
if lhsItem < rhsItem { return true }
else if rhsItem < lhsItem { return false }
}
return true
}
}
print(AlphanumericString(string: "abcd1") < AlphanumericString(string: "abc2"))
It is trivial
It is indeed, because there is an API: localizedStandardCompare(_:)
The description is Compares strings as sorted by the Finder.
func numericCompare(lhs: String, rhs: String, mode: ComparisonResult) -> Bool {
lhs.localizedStandardCompare(rhs) == mode
}
numericCompare(lhs: "b" ,rhs: "a", mode: .orderedDescending) // true
numericCompare(lhs: "3" ,rhs: "1", mode: .orderedDescending) // true
numericCompare(lhs: "ac" ,rhs: "ab", mode: .orderedDescending) // true
numericCompare(lhs: "32" ,rhs: "25", mode: .orderedDescending) // true
numericCompare(lhs: "abcd1" ,rhs: "abc2", mode: .orderedDescending) // true
numericCompare(lhs: "abc123a" ,rhs: "abc2a", mode: .orderedDescending) // true
numericCompare(lhs: "abc123a" ,rhs: "abc1234a", mode: .orderedAscending) // true
numericCompare(lhs: "abc123" ,rhs: "abc123a", mode: .orderedAscending) // true
numericCompare(lhs: "abc12a49" ,rhs: "abc12a39", mode: .orderedDescending) // true
numericCompare(lhs: "123ab3" ,rhs: "123ab3", mode: .orderedSame) // true
An alternative is lhs.compare(rhs, options: .numeric) which does the same
The algorithm below checks to see if an array has at least two or more duplicates. It uses a dictionary to store the occurrences; the time complexity is linear because it has to traverse the dictionary to see if a key occurs twice. In swift, how can I look up a value to see if it occurs more than twice in constant time ?
func containsDuplicate(_ nums: [Int]) -> Bool {
var frequencyTable = [Int:Int]()
for num in nums {
frequencyTable[num] = (frequencyTable[num] ?? 0 ) + 1
}
for value in frequencyTable.values{
if value >= 2 {
return true
}
}
return false
}
containsDuplicate([1,1,2,3,3,3,3,4])
The second loop is not necessary if the first loop checks if the current element has already been inserted before, and returns from the function in that case:
func containsDuplicate(_ nums: [Int]) -> Bool {
var frequencyTable = [Int:Int]()
for num in nums {
if frequencyTable[num] != nil {
return true
}
frequencyTable[num] = 1
}
return false
}
Then it becomes apparent that we don't need a dictionary, a set is sufficient:
func containsDuplicate(_ nums: [Int]) -> Bool {
var seen = Set<Int>()
for num in nums {
if seen.contains(num) {
return true
}
seen.insert(num)
}
return false
}
This can be further simplified: The “insert and check if element was already present” operation can be done in a single call:
func containsDuplicate(_ nums: [Int]) -> Bool {
var seen = Set<Int>()
for num in nums {
if !seen.insert(num).inserted {
return true
}
}
return false
}
This is similar to the solution from this answer
return nums.count != Set(nums).count
but possibly more efficient: The function returns immediately when a duplicate element has been detected.
Finally we can make the function generic, so that it works with all arrays of a hashable type:
func containsDuplicate<T: Hashable>(_ array: [T]) -> Bool {
var seen = Set<T>()
for element in array {
if !seen.insert(element).inserted {
return true
}
}
return false
}
Example:
print(containsDuplicate([1,1,2,3,3,3,3,4])) // true
print(containsDuplicate(["A", "X"])) // false
Or as an extension for arbitrary collections of a hashable type:
extension Collection where Element: Hashable {
func containsDuplicate() -> Bool {
var seen = Set<Element>()
for element in self {
if !seen.insert(element).inserted {
return true
}
}
return false
}
}
print([1,1,2,3,3,3,3,4].containsDuplicate())
print(["A", "X"].containsDuplicate())
You just want to know if it has duplicate, you can use use set and compare the length.
func containsDuplicate(_ nums: [Int]) -> Bool {
return Set(nums).count != nums.count
}
like this examples, because the set remove the duplicate values.
Can anyone explain me the backtracking algorithm? I'm trying to make a permutation program for example if n=2, program will print
1,2
2,1
Although I did this in high-school the teacher didn't really care about us hard enough for us to understand it and I didn't really understand it, neither the algorithms on the internet.
This is what I did so far in the playground but I find myself stuck. I get
1
0
1
0
import Foundation
let n = 2
var tempMatrix : [Int] = []
var resultString : String = ""
//1,2 || 2,1
//0,0
func initTempMatrix(){
for _ in 0..<n {
tempMatrix.append(0)
}
}
func resetMatrixValue(val: Int) {
tempMatrix[val] = 0
}
func isSolution() -> Bool {
for i in 0..<n-1 {
if tempMatrix[i] == 0 {
return false
}
}
return true
}
func isValid() -> Bool {
for i in 0..<n-1 {
if tempMatrix[n-1] == tempMatrix[i] {
return false
}
}
return true
}
func increaseMatrix(val: Int) -> Bool {
if tempMatrix[val] < n {
tempMatrix[val] += 1
return true
}
return false
}
func backtrack() {
initTempMatrix()
var k = 1
while k != 0 {
while !isSolution() {
if increaseMatrix(val: k-1) {
k+=1
}
}
if isValid() {
for i in 0..<tempMatrix.count {
resultString += "\(tempMatrix[i])"
print(resultString)
resultString = ""
}
}
resetMatrixValue(val: k-1)
k -= 1
}
}
backtrack()
I like many of the features in Swift, but using manipulating strings are still a big pain in the ass.
func checkPalindrome(word: String) -> Bool {
print(word)
if word == "" {
return true
} else {
if word.characters.first == word.characters.last {
return checkPalindrome(word.substringWithRange(word.startIndex.successor() ..< word.endIndex.predecessor()))
} else {
return false
}
}
}
This code fails miserably whenever the string's length is an odd number. Of course I could make it so the first line of the block would be if word.characters.count < 2, but is there a way in Swift to get substrings and check easily?
Update
I like many of the suggestions, but I guess the original question could be misleading a little, since it's a question about String more than getting the right results for the function.
For instance, in Python, checkPalindrome(word[1:-1]) would work fine for the recursive definition, whereas Swift code is much less graceful since it needs other bells and whistles.
return word == String(word.reversed())
func isPalindrome(myString:String) -> Bool {
let reverseString = String(myString.characters.reversed())
if(myString != "" && myString == reverseString) {
return true
} else {
return false
}
}
print(isPalindrome("madam"))
I have used the below extension to find whether the number is Palindrome or Not.
extension String {
var isPalindrome: Bool {
return self == String(self.reversed())
}
}
Sometimes having a front end for a recursion can simplify life. I sometimes do this when the arguments which are most convenient to use are not what I want in the user interface.
Would the following meet your needs?
func checkPalindrome(str: String) -> Bool {
func recursiveTest(var charSet: String.CharacterView) -> Bool {
if charSet.count < 2 {
return true
} else {
if charSet.popFirst() != charSet.popLast() {
return false
} else {
return recursiveTest(charSet)
}
}
}
return recursiveTest(str.characters)
}
just add on more condition in if
func checkPalindrome(word: String) -> Bool {
print(word)
if (word == "" || word.characters.count == 1){
return true
}
else {
if word.characters.first == word.characters.last {
return checkPalindrome(word.substringWithRange(word.startIndex.successor() ..< word.endIndex.predecessor()))
} else {
return false
}
}
}
extension StringProtocol where Self: RangeReplaceableCollection {
var letters: Self { filter(\.isLetter) }
var isPalindrome: Bool {
let letters = self.letters
return String(letters.reversed()).caseInsensitiveCompare(letters) == .orderedSame
}
}
"Dammit I'm Mad".isPalindrome // true
"Socorram-me subi no onibus em marrocos".isPalindrome // true
You can also break your string into an array of characters and iterate through them until its half comparing one by one with its counterpart:
func checkPalindrome(_ word: String) -> Bool {
let chars = Array(word.letters.lowercased())
for index in 0..<chars.count/2 {
if chars[index] != chars[chars.count - 1 - index] {
return false
}
}
return true
}
And the recursive version fixing the range issue where can't form a range with endIndex < startIndex:
func checkPalindrome<T: StringProtocol>(_ word: T) -> Bool {
let word = word.lowercased()
.components(separatedBy: .punctuationCharacters).joined()
.components(separatedBy: .whitespacesAndNewlines).joined()
if word == "" || word.count == 1 {
return true
} else {
if word.first == word.last {
let start = word.index(word.startIndex,offsetBy: 1, limitedBy: word.endIndex) ?? word.startIndex
let end = word.index(word.endIndex,offsetBy: -1, limitedBy: word.startIndex) ?? word.endIndex
return checkPalindrome(word[start..<end])
} else {
return false
}
}
}
checkPalindrome("Dammit I'm Mad")
I think if you make an extension to String like this one then it will make your life easier:
extension String {
var length: Int { return characters.count }
subscript(index: Int) -> Character {
return self[startIndex.advancedBy(index)]
}
subscript(range: Range<Int>) -> String {
return self[Range<Index>(start: startIndex.advancedBy(range.startIndex), end: startIndex.advancedBy(range.endIndex))]
}
}
With it in place, you can change your function to this:
func checkPalindrome(word: String) -> Bool {
if word.length < 2 {
return true
}
if word.characters.first != word.characters.last {
return false
}
return checkPalindrome(word[1..<word.length - 1])
}
Quick test:
print(checkPalindrome("aba")) // Prints "true"
print(checkPalindrome("abc")) // Prints "false"
extension String {
func trimmingFirstAndLastCharacters() -> String {
guard let startIndex = index(self.startIndex, offsetBy: 1, limitedBy: self.endIndex) else {
return self
}
guard let endIndex = index(self.endIndex, offsetBy: -1, limitedBy: self.startIndex) else {
return self
}
guard endIndex >= startIndex else {
return self
}
return String(self[startIndex..<endIndex])
}
var isPalindrome: Bool {
guard count > 1 else {
return true
}
return first == last && trimmingFirstAndLastCharacters().isPalindrome
}
}
We first declare a function that removes first and last characters from a string.
Next we declare a computer property which will contain the actual recursive code that checks if a string is palindrome.
If string's size is less than or equal 1 we immediately return true (strings composed by one character like "a" or the empty string "" are considered palindrome), otherwise we check if first and last characters of the string are the same and we recursively call isPalindrome on the current string deprived of the first and last characters.
Convert the string into an Array. When the loop is executed get the first index and compare with the last index.
func palindrome(string: String)-> Bool{
let char = Array(string)
for i in 0..<char.count / 2 {
if char[i] != char[char.count - 1 - i] {
return false
}
}
return true
}
This solution is not recursive, but it is a O(n) pure index based solution without filtering anything and without creating new objects. Non-letter characters are ignored as well.
It uses two indexes and walks outside in from both sides.
I admit that the extension type and property name is stolen from Leo, I apologize. 😉
extension StringProtocol where Self: RangeReplaceableCollection {
var isPalindrome : Bool {
if isEmpty { return false }
if index(after: startIndex) == endIndex { return true }
var forward = startIndex
var backward = endIndex
while forward < backward {
repeat { formIndex(before: &backward) } while !self[backward].isLetter
if self[forward].lowercased() != self[backward].lowercased() { return false }
repeat { formIndex(after: &forward) } while !self[forward].isLetter
}
return true
}
}
Wasn't really thinking of this, but I think I came up with a pretty cool extension, and thought I'd share.
extension String {
var subString: (Int?) -> (Int?) -> String {
return { (start) in
{ (end) in
let startIndex = start ?? 0 < 0 ? self.endIndex.advancedBy(start!) : self.startIndex.advancedBy(start ?? 0)
let endIndex = end ?? self.characters.count < 0 ? self.endIndex.advancedBy(end!) : self.startIndex.advancedBy(end ?? self.characters.count)
return startIndex > endIndex ? "" : self.substringWithRange(startIndex ..< endIndex)
}
}
}
}
let test = ["Eye", "Pop", "Noon", "Level", "Radar", "Kayak", "Rotator", "Redivider", "Detartrated", "Tattarrattat", "Aibohphobia", "Eve", "Bob", "Otto", "Anna", "Hannah", "Evil olive", "Mirror rim", "Stack cats", "Doom mood", "Rise to vote sir", "Step on no pets", "Never odd or even", "A nut for a jar of tuna", "No lemon, no melon", "Some men interpret nine memos", "Gateman sees name, garageman sees nametag"]
func checkPalindrome(word: String) -> Bool {
if word.isEmpty { return true }
else {
if word.subString(nil)(1) == word.subString(-1)(nil) {
return checkPalindrome(word.subString(1)(-1))
} else {
return false
}
}
}
for item in test.map({ $0.lowercaseString.stringByReplacingOccurrencesOfString(",", withString: "").stringByReplacingOccurrencesOfString(" ", withString: "") }) {
if !checkPalindrome(item) {
print(item)
}
}
A simple solution in Swift:
func isPalindrome(word: String) -> Bool {
// If no string found, return false
if word.count == 0 { return false }
var index = 0
var characters = Array(word) // make array of characters
while index < characters.count / 2 { // repeat loop only for half length of given string
if characters[index] != characters[(characters.count - 1) - index] {
return false
}
index += 1
}
return true
}
func checkPalindrome(_ inputString: String) -> Bool {
if inputString.count % 2 == 0 {
return false
} else if inputString.count == 1 {
return true
} else {
var stringCount = inputString.count
while stringCount != 1 {
if inputString.first == inputString.last {
stringCount -= 2
} else {
continue
}
}
if stringCount == 1 {
return true
} else {
return false
}
}
}