Solutions to Basic Algorithms with SwiftUI
UFuk ?atalca
Senior Mobile Engineering Manager | MBA+PhD | PSM | PMP? | UI&UX | Digital Banking | Fintech | Enterprise Architecture | Digital Media | HR | Aviation | E-Commerce | Telecommunication | Insurance | Event Speaker | WWDC?
In this article, we will explore the solutions to popular algorithms in Swift and how they can be visualized with SwiftUI.
1. Reverse a String
Algorithm
To reverse a string, we can convert the string into an array of characters and then reverse that array.
Code:
func reverseString(_ str: String) -> String {
return String(str.reversed())
}
Example Scenario:
let input = "Hello, World!"
let reversed = reverseString(input) // "!dlroW ,olleH"
SwiftUI Implementation:
struct ReverseStringView: View {
@State private var inputString: String = ""
@State private var reversedString: String = ""
var body: some View {
VStack {
TextField("Enter a string", text: $inputString)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: {
self.reversedString = reverseString(self.inputString)
}) {
Text("Reverse String")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
Text(reversedString)
.padding()
}
.padding()
}
}
func reverseString(_ str: String) -> String {
return String(str.reversed())
}
2. Check if a String is a Palindrome
Algorithm
A palindrome is a word, phrase, number, or other sequence of characters that reads the same forward and backward. We can check if a string is a palindrome by comparing it to its reverse.
Code:
func isPalindrome(_ str: String) -> Bool {
return str == String(str.reversed())
}
Example Scenario:
let word = "madam"
let result = isPalindrome(word) // true
SwiftUI Implementation:
struct PalindromeView: View {
@State private var inputString: String = ""
@State private var result: String = ""
var body: some View {
VStack {
TextField("Enter a string", text: $inputString)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: {
self.result = isPalindrome(self.inputString) ? "Palindrome" : "Not a Palindrome"
}) {
Text("Check Palindrome")
.padding()
.background(Color.green)
.foregroundColor(.white)
.cornerRadius(8)
}
Text(result)
.padding()
}
.padding()
}
}
func isPalindrome(_ str: String) -> Bool {
return str == String(str.reversed())
}
3. Remove Duplicates from a String
Algorithm
To remove duplicates from a string, we can use a set to track the characters we’ve seen.
Code:
func removeDuplicates(_ str: String) -> String {
var seen = Set<Character>()
var result = ""
for char in str {
if !seen.contains(char) {
seen.insert(char)
result.append(char)
}
}
return result
}
Example Scenario:
let input = "aabbcc"
let result = removeDuplicates(input) // "abc"
SwiftUI Implementation:
struct RemoveDuplicatesView: View {
@State private var inputString: String = ""
@State private var resultString: String = ""
var body: some View {
VStack {
TextField("Enter a string", text: $inputString)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: {
self.resultString = removeDuplicates(self.inputString)
}) {
Text("Remove Duplicates")
.padding()
.background(Color.orange)
.foregroundColor(.white)
.cornerRadius(8)
}
Text("Result: \(resultString)")
.padding()
}
.padding()
}
}
func removeDuplicates(_ str: String) -> String {
var seen = Set<Character>()
var result = ""
for char in str {
if !seen.contains(char) {
seen.insert(char)
result.append(char)
}
}
return result
}
4. Find the First Non-Repeating Character
Algorithm
To find the first non-repeating character, we can keep track of character counts in a dictionary.
Code:
func firstNonRepeatingCharacter(_ str: String) -> Character? {
var counts = [Character: Int]()
for char in str {
counts[char, default: 0] += 1
}
for char in str {
if counts[char] == 1 {
return char
}
}
return nil
}
Example Scenario:
let input = "swiss"
let result = firstNonRepeatingCharacter(input) // "w"
SwiftUI Implementation:
struct FirstNonRepeatingCharacterView: View {
@State private var inputString: String = ""
@State private var resultCharacter: String = ""
var body: some View {
VStack {
TextField("Enter a string", text: $inputString)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: {
if let character = firstNonRepeatingCharacter(self.inputString) {
self.resultCharacter = "First Non-Repeating Character: \(character)"
} else {
self.resultCharacter = "No non-repeating character."
}
}) {
Text("Find First Non-Repeating Character")
.padding()
.background(Color.red)
.foregroundColor(.white)
.cornerRadius(8)
}
Text(resultCharacter)
.padding()
}
.padding()
}
}
func firstNonRepeatingCharacter(_ str: String) -> Character? {
var counts = [Character: Int]()
for char in str {
counts[char, default: 0] += 1
}
for char in str {
if counts[char] == 1 {
return char
}
}
return nil
}
5. Check if Two Strings are Anagrams
Algorithm
To check if two strings are anagrams, we can sort the characters of both strings and compare them.
Code:
func areAnagrams(_ str1: String, _ str2: String) -> Bool {
return str1.sorted() == str2.sorted()
}
Example Scenario:
let str1 = "listen"
let str2 = "silent"
let result = areAnagrams(str1, str2) // true
SwiftUI Implementation:
struct AnagramCheckView: View {
@State private var string1: String = ""
@State private var string2: String = ""
@State private var result: String = ""
var body: some View {
VStack {
TextField("Enter first string", text: $string1)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
TextField("Enter second string", text: $string2)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: {
self.result = areAnagrams(self.string1, self.string2) ? "Anagrams" : "Not Anagrams"
}) {
Text("Check Anagram")
.padding()
.background(Color.purple)
.foregroundColor(.white)
.cornerRadius(8)
}
Text(result)
.padding()
}
.padding()
}
}
func areAnagrams(_ str1: String, _ str2: String) -> Bool {
return str1.sorted() == str2.sorted()
}
6. Find the Longest Substring Without Repeating Characters
Algorithm
To find the longest substring without repeating characters, we can use a sliding window technique.
Code:
func longestSubstringWithoutRepeating(_ str: String) -> String {
var seen = Set<Character>()
var start = 0
var maxLength = 0
var longestSubstring = ""
for (end, char) in str.enumerated() {
while seen.contains(char) {
seen.remove(str[start])
start += 1
}
seen.insert(char)
let length = end - start + 1
if length > maxLength {
maxLength = length
longestSubstring = String(str[start...end])
}
}
return longestSubstring
}
Example Scenario:
let input = "abcabcbb"
let result = longestSubstringWithoutRepeating(input) // "abc"
SwiftUI Implementation:
struct LongestSubstringView: View {
@State private var inputString: String = ""
@State private var longestSubstring: String = ""
var body: some View {
VStack {
TextField("Enter a string", text: $inputString)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: {
self.longestSubstring = longestSubstringWithoutRepeating(self.inputString)
}) {
Text("Find Longest Substring")
.padding()
.background(Color.cyan)
.foregroundColor(.white)
.cornerRadius(8)
}
Text("Longest Substring: \(longestSubstring)")
.padding()
}
.padding()
}
}
func longestSubstringWithoutRepeating(_ str: String) -> String {
var seen = Set<Character>()
var start = 0
var maxLength = 0
var longestSubstring = ""
for (end, char) in str.enumerated() {
while seen.contains(char) {
seen.remove(str[start])
start += 1
}
seen.insert(char)
let length = end - start + 1
if length > maxLength {
maxLength = length
longestSubstring = String(str[start...end])
}
}
return longestSubstring
}
7. Reverse Integer
Algorithm
We can reverse an integer by converting it to a string, reversing the string, and then converting it back to an integer.
Code:
func reverseInteger(_ num: Int) -> Int? {
let isNegative = num < 0
var num = abs(num)
var reversed = 0
while num != 0 {
let digit = num % 10
reversed = reversed * 10 + digit
num /= 10
}
return isNegative ? -reversed : reversed
}
Example Scenario:
let number = 12345
let reversed = reverseInteger(number) // 54321
SwiftUI Implementation:
struct ReverseIntegerView: View {
@State private var inputNumber: String = ""
@State private var reversedNumber: String = ""
var body: some View {
VStack {
TextField("Enter an integer", text: $inputNumber)
.keyboardType(.numberPad)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: {
if let num = Int(self.inputNumber), let reversed = reverseInteger(num) {
self.reversedNumber = "Reversed: \(reversed)"
} else {
self.reversedNumber = "Invalid input"
}
}) {
Text("Reverse Integer")
.padding()
.background(Color.yellow)
.foregroundColor(.white)
.cornerRadius(8)
}
Text(reversedNumber)
.padding()
}
.padding()
}
}
func reverseInteger(_ num: Int) -> Int? {
let isNegative = num < 0
var num = abs(num)
var reversed = 0
while num != 0 {
let digit = num % 10
reversed = reversed * 10 + digit
num /= 10
}
return isNegative ? -reversed : reversed
}
8. Find the Most Frequent Character in the String
Algorithm
We can track the frequency of characters using a dictionary and then find the character with the highest frequency.
Code:
func mostFrequentCharacter(_ str: String) -> Character? {
var counts = [Character: Int]()
for char in str {
counts[char, default: 0] += 1
}
return counts.max(by: { $0.value < $1.value })?.key
}
Example Scenario:
let str = "abacabad"
let mostFrequentChar = mostFrequentCharacter(str) // "a"
SwiftUI Implementation:
struct MostFrequentCharacterView: View {
@State private var inputString: String = ""
@State private var frequentCharacter: String = ""
var body: some View {
VStack {
TextField("Enter a string", text: $inputString)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: {
if let character = mostFrequentCharacter(self.inputString) {
self.frequentCharacter = "Most frequent character: \(character)"
} else {
self.frequentCharacter = "No characters found."
}
}) {
Text("Find Most Frequent Character")
.padding()
.background(Color.teal)
.foregroundColor(.white)
.cornerRadius(8)
}
Text(frequentCharacter)
.padding()
}
.padding()
}
}
func mostFrequentCharacter(_ str: String) -> Character? {
var counts = [Character: Int]()
for char in str {
counts[char, default: 0] += 1
}
return counts.max(by: { $0.value < $1.value })?.key
}
9. Generic Optional
Algorithm
In Swift, Optionals are used to represent values that may or may not be present. Using Generic types with Optionalmakes parameters nullable.
Code:
func unwrap<T>(_ value: T?) -> String {
guard let value = value else {
return "Value is nil"
}
return "Value is \(value)"
}
Example Scenario:
let str: String? = "Hello"
let result = unwrap(str) // "Value is Hello"
let num: Int? = nil
let result2 = unwrap(num) // "Value is nil"
SwiftUI Implementation:
struct GenericOptionalView: View {
@State private var inputString: String? = nil
@State private var result: String = ""
var body: some View {
VStack {
TextField("Enter a string (optional)", text: Binding(
get: { self.inputString ?? "" },
set: { self.inputString = $0.isEmpty ? nil : $0 }
))
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: {
self.result = unwrap(self.inputString)
}) {
Text("Unwrap Optional")
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(8)
}
Text(result)
.padding()
}
.padding()
}
}
func unwrap<T>(_ value: T?) -> String {
guard let value = value else {
return "Value is nil"
}
return "Value is \(value)"
}
10. Longest Common Prefix
Algorithm
To find the longest common prefix, we can compare the characters of the first word with the other words character by character.
Code:
func longestCommonPrefix(_ strs: [String]) -> String {
guard !strs.isEmpty else { return "" }
var prefix = strs[0]
for str in strs.dropFirst() {
while !str.hasPrefix(prefix) {
prefix = String(prefix.dropLast())
if prefix.isEmpty {
return ""
}
}
}
return prefix
}
Example Scenario:
let words = ["flower", "flow", "flight"]
let commonPrefix = longestCommonPrefix(words) // "fl"
SwiftUI Implementation:
struct LongestCommonPrefixView: View {
@State private var inputStrings: String = ""
@State private var commonPrefix: String = ""
var body: some View {
VStack {
TextField("Enter words separated by commas", text: $inputStrings)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
Button(action: {
let words = inputStrings.split(separator: ",").map { String($0).trimmingCharacters(in: .whitespaces) }
self.commonPrefix = longestCommonPrefix(words)
}) {
Text("Find Common Prefix")
.padding()
.background(Color.green)
.foregroundColor(.white)
.cornerRadius(8)
}
Text("Common Prefix: \(commonPrefix)")
.padding()
}
.padding()
}
}
func longestCommonPrefix(_ strs: [String]) -> String {
guard !strs.isEmpty else { return "" }
var prefix = strs[0]
for str in strs.dropFirst() {
while !str.hasPrefix(prefix) {
prefix = String(prefix.dropLast())
if prefix.isEmpty {
return ""
}
}
}
return prefix
}
Conclusion
In this article, we covered basic algorithms and how to implement them in Swift. For each algorithm, we also integrated a SwiftUI interface to make the solution interactive. These algorithms can be beneficial both for improving your programming skills and for building interactive applications in Swift.