iOS Development Made Simple!
  • Home
  • Blog
  • Contact
  • Enroll Now
  • Enroll Now

Reverse The Vowels – iOS Engineering Interview Question

  • Yasser Farahi
  • May 2, 2022May 2, 2022
  • Algorithms, General, Interview Challenges

Reverse The Vowels – iOS Engineering Interview Question

We’ve been asked to write an algorithm that reverses vowels in any given message. Assuming we are not allowed to use any native Swift String functions, How do we write such an algorithm🤔?

Here are some examples
Hello World = Hollo Werld
Welcome To RISING GALAXY = WAlcAmI TI RoSeNG GoLeXY
iOS Engineering = ieS enginEOring
Apple iPhone = epplo iPhenA
Reverse The Vowels = Revorse The Vewels

During some technical interviews, it’s not that uncommon to face challenges on String manipulation, such as being able to reverse character sequences.

This article is presenting a twist by reversing specific characters.

First, let’s break this challenge into pieces, and find out the correct approach. By rereading the challenge description and studying the provided examples. You’ll notice that we are facing two major challenges.

First, how do we reverse the series of vowels without using native Swift functions?. Second, how do we track the position of each vowels during loop iteration. 

Let’s see whether we are up for this challenge.

STEP ONE – Create a class and name it ReverseVowel

1
2
class ReverseVowel {
}

STEP TWO – Inside the ReverseVowel class we should write a method that can tell us whether a given character is a vowel by returning a Boolean value. This method should have a single input parameter, which accepts a Character as a value.

1
2
3
4
5
6
    private func isVowel( _ c: Character) -> Bool {
        switch c.lowercased() {
        case "a", "e", "i", "o","u" : return true
        default: return false
        }
    }

STEP THREE – It’s time to write the magical code. Our method should have a single input parameter of type String and a returning value of type String as well.

Since the explanation can become a little confusing from this point. I’ll be commenting on each part of the code individually inside the syntax highlighter. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
func reverseVowel(_ s: String) -> String {
        //Check whether the input value is not empty
        guard !s.isEmpty else { return s }
        
        //Converting the input value into an Array of Characters
        //We are going to be manipulating the order of this Array
        //That is why it should be a var/ variable and not a let/ constant
        var res: [Character] = Array(s)
        
        //Create a lookup array and remove any whitespaces
        let chars = Array(s.trimmingCharacters(in: .whitespacesAndNewlines))
        
        //Create a reference, which tells us the number of input Characters
        let m = s.count
        
        //The pointer that tracks characters from the left side
        var i = 0
        
        //The pointer that tracks characters from the right side
        var j = m - 1
        
        //We will continue looping as long as i is less than j
        while i < j {
            
            //MARK: FIRST CHECK
            //It's time to call our isVowel(_:Character) method,
            //and check whether the current character
            //on the left side is a vowel
            //and the one on the right side is not a vowel
            if isVowel(chars[i]) && !isVowel(chars[j]) {
                //We should grab the character
                //from our lookup array on the 'j(th)' index
                //and insert it to the res array at the 'j(th)' index
                res.insert(chars[j], at: j)
                
                //Now, because we have injected a
                //new character into our 'res' array
                //the number of the 'res' characters has grown by 1
                //that's why we should remove
                //the extra character on the (j + 1) index
                res.remove(at: j + 1)
                
                //Now, we should decrement 'j' by 1
                //this will move this pointer 1 step to the left
                //as you can see, we are not touching the 'i'
                //because were able to found a vowel there,
                //so it should remain were it is
                //until we find a vowel on the left side
                j -= 1
                
                //MARK: SECOND CHECK
                //if we didn't find a vowel on the left side
                //but we managed to find a vowel on the right side
            } else if !isVowel(chars[i]) && isVowel(chars[j]) {
                
                //We should grab the character
                //from our lookup array on the 'i'(th) index
                //and insert it to the 'res' array at the 'i'(th) index
                res.insert(chars[i], at: i)
                
                //Because we have injected a new character into our 'res' array
                //the number of the 'res' characters has grown by 1
                //that's why we should remove
                //the character on the (i + 1) index
                res.remove(at: i + 1)
                
                //Next, we should increment 'i' by 1
                //this will move this pointer 1 step to the right
                //as you can see, we are not touching 'j' this time.
                //Because found a vowel there,
                //we should let it stay where it is,
                //until we find a vowel on the right side
                i += 1
                
                //MARK: THIRD CHECK
                //If we were able to find a vowel on both sides
                //Now, we should handle our character swapping
            } else if isVowel(chars[i]) && isVowel(chars[j]) {
                
                //We should grab the vowel from
                //our lookup on the 'i'(th) index
                //and insert it to the 'res' array at the 'j'(th) position
                res.insert(chars[i], at: j)
                
                //Again because we have injected a new
                //character into our 'res' array
                //the number of the 'res' characters has grown by 1
                res.remove(at: j + 1)
                
                //We should grab the vowel from
                //our lookup on the 'j'(th) postion
                //and insert it to the 'res' array at the 'i'(th) position
                res.insert(chars[j], at: i)
                
                //Again, because we have injected
                //a new character into our 'res' array
                //the number of the 'res' characters has grown by 1
                res.remove(at: i + 1)
                
                //Decrementing 'j' by 1 and moving it to the left
                j -= 1
                
                //Incrementing 'i' by 1 and moving it to the right
                i += 1
                
                //MARK: FINAL CHECK
                //If we didn't find vowels on both side
            } else {
                //We should grab the 'i'(th) character from the lookup array
                //and insert it at the 'i'(th) position of the 'res' array
                res.insert(chars[i], at: i)
                
                //Remove character on (i + 1)
                res.remove(at: i + 1)
                
                //Then, grab the 'j'(th) character from the lookup array
                //and insert it at the 'j'(th) index of the 'res' array
                res.insert(chars[j], at: j)
                
                //Remove character on (j + 1)
                res.remove(at: j + 1)
                
                //Decrement 'j' by 1 and move it to the right
                j -= 1
                
                //Increment 'i' by 1 and move it to the left
                i += 1
            }
        }
        //Everything is handled properly,
        //it's time to return the final result
        //by converting the 'res' array to a String
        return String(res)
    }

FINAL SOLUTION – Clean Code + Unite Tests

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import Foundation
import XCTest
 
class ReverseVowel {
    
    func reverseVowel(_ s: String) -> String {
        guard !s.isEmpty else { return s }
        var res: [Character] = Array(s)
        let chars = Array(s.trimmingCharacters(in: .whitespacesAndNewlines))
        let m = s.count
        var i = 0
        var j = m - 1
        while i < j {
            if isVowel(chars[i]) && !isVowel(chars[j]) {
                res.insert(chars[j], at: j)
                res.remove(at: j + 1)
                j -= 1
            } else if !isVowel(chars[i]) && isVowel(chars[j]) {
                res.insert(chars[i], at: i)
                res.remove(at: i + 1)
                i += 1
            } else if isVowel(chars[i]) && isVowel(chars[j]) {
                res.insert(chars[i], at: j)
                res.remove(at: j + 1)
                res.insert(chars[j], at: i)
                res.remove(at: i + 1)
                j -= 1
                i += 1
            } else {
                res.insert(chars[i], at: i)
                res.remove(at: i + 1)
                res.insert(chars[j], at: j)
                res.remove(at: j + 1)
                j -= 1
                i += 1
            }
        }
        return String(res)
    }
    
    private func isVowel( _ c: Character) -> Bool {
        switch c.lowercased() {
        case "a", "e", "i", "o","u" : return true
        default: return false
        }
    }
}
 
class TestReverseVowels: XCTestCase {
    
    var sut: ReverseVowel!
    
    override func setUp() {
        super.setUp()
        sut = ReverseVowel()
    }
    
    override func tearDown() {
        sut = nil
        super.tearDown()
    }
    
    func testShort() {
        let input = "Hello"
        let testData = "Holle"
        let result = sut.reverseVowel(input)
        XCTAssertEqual(result, testData)
    }
    
    func testMedium() {
        let input = "Binary Search"
        let testData = "Banery Sairch"
        let result = sut.reverseVowel(input)
        XCTAssertEqual(result, testData)
    }
    
    func testLong() {
        let input = "United States Of America"
        let testData = "anited StAtOs ef americU"
        let result = sut.reverseVowel(input)
        XCTAssertEqual(result, testData)
    }
 
}
 
class TestObservation: NSObject, XCTestObservation {
    func testCase(_ testCase: XCTestCase, didRecord issue: XCTIssue) {
        assertionFailure(issue.description)
    }
}
 
let testObservation = TestObservation()
XCTestObservationCenter.shared.addTestObserver(testObservation)
XCTestSuite.default.run()
Tags: algoritmes Data Structure Interview Questions Reverse Values String Manipulation Value Swapping

Post navigation

Previous Post
Next Post

Categories

  • Algorithms
  • Beginner
  • Courses
  • Dart
  • General
  • Interview Challenges
  • OOP
  • Programming
  • Swift

New Posts

  • iOS Development Xcode Layout And Auto Layout Tools
    August 2, 2022
  • Composition – Relations Between Objects And Classes
    June 13, 2022
  • Aggregation – Relations Between Objects And Classes
    June 8, 2022

Tags

Aggregation algoritmes Association Basics Caesar Cipher Classes Composition Data Structure Dependency Implementation Inheritance Interfaces Interview Questions O(1) Runtime O(2n) Runtime Object Relations OOP Power Of N Reverse Values Shifting Characters Shifting Values Software Engineering String Manipulation Swift Value Swapping Xcode
© Copyright RISING GALAXY. All Rights Reserved | Read Our Privacy Policy  - Terms Of Use - Cookies Policy
Cookies Policy
We use cookies on our website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept”, you consent to the use of ALL the cookies.
Do not sell my personal information.
Cookie SettingsAccept
Manage consent

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. These cookies ensure basic functionalities and security features of the website, anonymously.
CookieDurationDescription
cookielawinfo-checkbox-analytics11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Analytics".
cookielawinfo-checkbox-functional11 monthsThe cookie is set by GDPR cookie consent to record the user consent for the cookies in the category "Functional".
cookielawinfo-checkbox-necessary11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookies is used to store the user consent for the cookies in the category "Necessary".
cookielawinfo-checkbox-others11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Other.
cookielawinfo-checkbox-performance11 monthsThis cookie is set by GDPR Cookie Consent plugin. The cookie is used to store the user consent for the cookies in the category "Performance".
viewed_cookie_policy11 monthsThe cookie is set by the GDPR Cookie Consent plugin and is used to store whether or not user has consented to the use of cookies. It does not store any personal data.
Functional
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Performance
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytics
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
Others
Other uncategorized cookies are those that are being analyzed and have not been classified into a category as yet.
SAVE & ACCEPT