Swift Permutation Algorithm Backtracking - swift

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()

Related

Union-find: largest component size by common factor algorithm gives different results on every run

I was practicing data structure algorithm and made a Union - Find solution for the question.
The problem is, I think the code seems ok, but when I run it on Xcode playground, it shows different answers for the same input.
For example, I put an array [4, 6, 15, 35] in the function largestComponentSize, then it shows 2, 3, or 4 as the answer. I don't understand what's happening behind.
class Solution {
var uf = UnionFind()
func largestComponentSize(_ nums: [Int]) -> Int {
var maxNum:Int = 0
var numFactorMap = [Int:Int]()
var factorAdded = Set<Int>()
for num in nums {
var pFactors = getPrimeFactors(num)
numFactorMap[num] = pFactors[0]
for (i, val) in pFactors.enumerated() {
if !factorAdded.contains(val) {
uf.addSet(val)
factorAdded.insert(val)
}
if i > 0 {
uf.union(pFactors[i-1], val)
}
}
}
var groupCountMap = [Int:Int]()
for num in nums {
var groupId = uf.find(numFactorMap[num]!)!
if groupCountMap.keys.contains(groupId) {
groupCountMap[groupId]! += 1
} else {
groupCountMap[groupId] = 1
}
maxNum = max(maxNum, groupCountMap[groupId]!)
}
return maxNum
}
func getPrimeFactors(_ num: Int) -> [Int] {
var ans:Set<Int> = []
if num == 1 {
return []
}
var crrNum = num
var deno = 2
while crrNum >= deno {
if crrNum % deno == 0 {
ans.insert(deno)
crrNum = crrNum / deno
} else {
deno = deno + 1
}
}
return Array(ans)
}
class UnionFind {
var index = [Int: Int]()
var parent: [Int]
var size: [Int]
init() {
parent = []
size = []
}
func addSet(_ ele: Int) {
index[ele] = parent.count
parent.append(parent.count)
size.append(1)
}
func getSetSize(_ ele: Int) -> Int {
if let found = find(ele) {
return size[found]
}
return 0
}
func find(_ ele: Int) -> Int? {
if let indexOfEle = index[ele] {
if parent[indexOfEle] == indexOfEle {
return indexOfEle
} else {
if let found = find(parent[indexOfEle]) {
parent[indexOfEle] = found
}
return parent[indexOfEle]
}
} else {
return nil //never come here
}
}
func union(_ first: Int, _ second: Int) {
guard let indexOfFirst = index[first], let indexOfSecond = index[second] else {
return
}
if parent[indexOfFirst] == parent[indexOfSecond] {
return
}
var indexOfLarger = indexOfFirst
var indexOfSmaller = indexOfSecond
if size[indexOfFirst] < size[indexOfSecond] {
indexOfLarger = indexOfSecond
indexOfSmaller = indexOfFirst
}
parent[indexOfSmaller] = indexOfLarger
size[indexOfLarger] += size[indexOfSmaller]
return
}
}
}
var sol = Solution()
var nums = [4, 6, 15, 35]
var ans = sol.largestComponentSize(nums)
Thank you for your help in advance!
I just tried it on Xcode playground.

Is it possible in Swift to return an Int and a list of int at the same time?

I have to write a function in Swift where I need create a list of int if the counter is different to 0.
Here is my code in Swift :
func compteurZeros(cellule:[[Int]]) -> (compteur:Int, liste:(Int))
{
var compteur = 0;
for i in 0...2
{
for j in 0...2
{
if(cellule[i][j] == 0)
{
compteur = compteur+1
}
}
}
print(compteur)
if (compteur != 0)
{
for i in 0..<(compteur) {
var liste:(Int)
}
}
return (compteur, liste!)
}
But, in the return, I've got this error :
error: use of unresolved identifier 'liste'
return (compteur, liste!)
Thank you for your answer.
You need to change your function somewhat so that it returns an [[Int]] as the second element in the tuple
func compteurZeros(cellule:[[Int]]) -> (compteur:Int, liste:[[Int]]) {
var compteur = 0;
for i in 0...2
{
for j in 0...2
{
if(cellule[i][j] == 0)
{
compteur = compteur+1
}
}
}
var liste = [[Int]]()
if (compteur != 0)
{
for i in 0..<(compteur) {
liste.append([])
}
}
return (compteur, liste)
}
Now this code is not the best so it can be improved by skipping the loops
func compteurZeros(cellule:[[Int]]) -> (compteur:Int, liste:[[Int]]) {
let compteur = cellule.flatMap {$0}.filter {$0 == 0}.count
let liste:[[Int]] = Array(repeating: [], count: compteur)
return (compteur, liste)
}
Since the value compteur is redundant this can be further simplified to
func compteurZeros(cellule:[[Int]]) -> [[Int]] {
return Array(repeating: [], count: cellule.flatMap {$0}.filter {$0 == 0}.count)
}

Practical number algorithm too slow

I am trying to write a program to find the practical numbers, from an input from 1 to n.
Practical numbers : https://en.wikipedia.org/wiki/Practical_number
My code is running correctly but it is extremely slow - takes over 20 minutes when it should take 10 seconds. This happens when calculating numbers around 50 - it gets stuck at 44.
It is written in Swift
import Foundation
func getInteger() -> Int {
var firstNum:Int = 0
while true {
// get value from user. Using optional input since readLine returns an optional string.
let input = readLine()
// ensure string is not nil
if let unwrappedInput = input {
if let unwrappedInt = Int(unwrappedInput) {
firstNum = unwrappedInt
break
}
else { // the input doesn't convert into an int
print("`\(unwrappedInput)` is not an integer. Please enter an integer")
}
}
else { // did not enter anything
print("Please enter an integer")
}
}
return firstNum
}
func addOne(signArray: [Int]) -> [Int] { // finds the combinations
var signArray2 = [Int]()
for i in 0...signArray.count-1 {
signArray2.append (signArray[i])
}
for i in 0...signArray2.count-1 {
if signArray2[i] == 1 {
signArray2[i] = 0
}
else {
signArray2[i] = 1
break
}
}
return signArray2
}
func signEval (signArray: [Int], divArray: [Int], inNum: Int) -> Bool {// changes 2nd
var counts = 0
for i in 0...divArray.count-1 {
if signArray[i] == 0 {
counts = divArray[i] + counts }
if counts == inNum {
return true
}
}
return false
}
print("Please enter a number to find the summable numbers up to that number:")
var input2 = getInteger()// if num = 1 print 1 if num = 2 print 1 and 2 else print >2 1, 2
var inNum = 0
var numHalf = 0.0
var numRound = 0.0
var numCheck = false
var numCheck2 = false
var numQuarter = 0.0
var numSixth = 0.0
var divArray:[Int] = []
var theirArray = [Int]()
var signArray = [Int]()// array of 0s and 1s
var summableArray:[Int] = [1,2] // need to check if num is bigger than 2!
for input in 1...input2 {
numHalf = Double (input) / 2.0
numRound = round(numHalf)
if numRound == numHalf {
numCheck = true }
if input > 2 && numCheck == false { // odd numbers greater than one are not summable
}
else { // these are possible summable nums
numQuarter = Double (input) / 4.0
numRound = round(numQuarter)
if numRound == numQuarter {
numCheck = true
}
else {
numCheck = false
}
numSixth = Double(input) / 6.0
numRound = round(numSixth)
if numRound == numSixth {
numCheck2 = true }
else { numCheck2 = false}
if numCheck == true || numCheck2 == true {
theirArray = []
divArray = []
signArray = []
summableArray = []
for i in 1...input {
theirArray.append (i)
}
for i in 1...input { // creates an array of all the diviors of inputted number
if input%i == 0 {
divArray.append (i)
}
}
for j in 1...divArray.count {//
signArray.append(0)
}
for i in 1...input{
let x: Int = Int(pow(Double(2),Double(input-1)))// int 2 to the power of input -1
var Boolcheck = false
for q in 1...x-1 { // i to 2^n -1 (sequence to check)
Boolcheck = (signEval(signArray: signArray, divArray: divArray, inNum: i))// checks
signArray = addOne(signArray: signArray)// adding the ones to the array
if Boolcheck == true {
summableArray.append(i)// creates array of mini summable numbers
break
}
}
if summableArray.count == input {
print ("\(input)")
}
}
}
}
}

Check prime number in array

Trying to write a check for Prime numbers in the array. The array is populated randomly. But when processing the array code does not work... What am I doing wrong? Thank you!
update 2
Filling the array correctly. But with the test simple number, something is wrong. Specifically what is wrong can not say, but the point is that the rules of a simple number sorting is not working.
import Foundation
func randomArray(var i:Int,var k:Int, var array: [Int]=[], var newArray: [Int]=[]) ->Int {
for i=0;i<10;i++ {
array.append(Int(arc4random_uniform(10)))
}
for i=0;i<=array.count; i++ {
for k=2; k<array[i]; k++ {
if array[i] != 0 && array[i] != 1 && array[i]%k != 0 {
newArray.append(array[i])
} else {
return 0
}
}
}
return newArray[i]
}
randomArray(0, k: 0)
It's not clear to me what you want to do.
a) If you want to generate an array of length k at random and filter for prime numbers, use the code below. Note that this can give give you an array of length between 0 to k, because they may be no prime in the randomly generated array, or every number generated was a prime:
func isPrime(num: Int) -> Bool {
if num < 2 {
return false
}
for i in 2..<num {
if num % i == 0 {
return false
}
}
return true
}
func randomArray(len: Int) -> [Int] {
var results = [Int]()
for _ in 0..<len {
results.append(Int(arc4random_uniform(10)))
}
return results.filter(isPrime)
}
b) If you want an array of k primes, use this instead:
func randomPrimeArray(len: Int) -> [Int] {
var results = [Int]()
while results.count < len {
let x = Int(arc4random_uniform(10))
if isPrime(x) {
results.append(x)
}
}
return results
}
if you want to filter prime numbers from an array use this code:
let primeNumbers = myArray.filter { number in
if number == 0 {
return false
}
return number % 2 == 0
}

How to check for palindrome in Swift using recursive definition

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
}
}
}