Selection sort algorithm. Swift. - swift

There is a great resource for swift algorithms by Ray Wenderlich:
https://github.com/raywenderlich/swift-algorithm-club
One of the basic ones is "Selection Sort":
func selectionSort(_ array: [Int]) -> [Int] {
guard array.count > 1 else { return array }
var a = array
for x in 0 ..< a.count - 1 {
var lowest = x
for y in x + 1 ..< a.count {
if a[y] < a[lowest] {
lowest = y
}
}
if x != lowest {
swap(&a[x], &a[lowest])
}
}
return a
}
I was trying to understand whats happening in here and was confused with var lowest = x step.
I decided to write my own solution for the problem and didn't use that step :
func selectSortArray1(_ array: [Int]) -> [Int] {
guard array.count > 1 else {return array}
var subArray = array
for x in 0..<subArray.count - 1 {
for y in x+1..<subArray.count {
if subArray[y] < subArray[x] {
swap(&subArray[x], &subArray[y])
}
}
}
return subArray
}
Seems to work as intended.
However, I doubt myself.
Is var lowest = x required for some edge cases?

Related

Finding indices of array elements that add up to a target number. What would be a way to optimize my solution?

I'm practicing this problem
Given an array of integers nums and an integer target, return indices
of the two numbers such that they add up to target.
You may assume that each input would have exactly one solution, and
you may not use the same element twice.
You can return the answer in any order.
and came up with
class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
var indices = [Int]()
for (firstIndex, firstNum) in nums.enumerated() {
for (secondIndex, secondNum) in nums.enumerated() {
if firstNum + secondNum == target && firstIndex != secondIndex {
indices = [firstIndex, secondIndex]
}
}
}
return indices
}
}
However, it has quadratic time complexity because of the nested for-in loops. What would be a good way to optimize this to run in linear time?
Here's an idea that results in a O(n) time ans space solution.
Have a hashtable that maps elements to their indices.
As you iterate through the input array check whether target - element is in the hashtable already. If so, return the indices of the current element and target - element in the hashtable.
If not, add current element as key and its index as value to the hashtable.
Using #user1984 comment your solution should look like this:
class Solution {
func twoSum(_ nums: [Int], _ target: Int) -> [Int] {
var indices = [Int]()
var dictionary: [Int: Int] = [:]
for (index, num) in nums.enumerated()
{
let diff = target - num
if let index2 = dictionary[diff] {
return [index2, index]
}
else {
dictionary[num] = index
}
}
return []
}
}
There are several approaches (depending on your requirements and time/space constraints)
final class Solution {
// Time Complexity: O(n * (n - 1) / 2) = O(n^2)
// Auxiliary Space: O(1)
func twoSum1(_ nums: [Int], _ target: Int) -> [Int] {
for firstIndex in nums.indices {
for secondIndex in (firstIndex + 1)..<nums.count {
if nums[firstIndex] + nums[secondIndex] == target {
return [firstIndex, secondIndex]
}
}
}
return []
}
// Time Complexity: O(n log n).
// Auxiliary Space: O(n). Can be O(1) if do in-place sort
func twoSum2(_ nums: [Int], _ target: Int) -> [Int] {
let sorted = nums.sorted()
var left = 0
var right = nums.count - 1
while left < right {
if sorted[left] + sorted[right] == target {
return [left, right]
} else if sorted[left] + sorted[right] < target {
left += 1
} else {
right -= 1
}
}
return []
}
// Time Complexity: O(n). (Amortized)
// Auxiliary Space: O(n).
func twoSum3(_ nums: [Int], _ target: Int) -> [Int] {
var differences = [Int: Int]()
for (index, element) in nums.enumerated() {
let difference = target - element
if let dIndex = differences[difference] {
return [index, dIndex]
}
differences[element] = index
}
return []
}
static func test() {
// Given
let nums = [1, 5, 4, 3, 7, 9, -3]
let target = 7
let solution = Solution()
let expectedResult = [2, 3]
// When
let result1 = solution.twoSum1(nums, target)
let result2 = solution.twoSum2(nums, target)
let result3 = solution.twoSum3(nums, target)
// Then
assert(Set(result1) == Set(expectedResult))
assert(Set(result2) == Set(expectedResult))
assert(Set(result3) == Set(expectedResult))
}
}

Prime factorization with return being a string

I am trying to solve the following coding challenge:
Given a positive number n > 1 find the prime factor decomposition of n. The result will be a string with the following form:
"(p1xxn1)(p2xxn2)...(pkxxnk)"
with the p(i) in increasing order and n(i) empty if n(i) is 1.
Example: n = 86240 should return "(2xx5)(5)(7xx2)(11)"
I believe I have figured out how to find the prime factors of a number... my problem is that I have no idea how to convert them into the form required by the question (i.e., a string where p(i) is in increasing order). I tried to convert an integer array containing the prime factors into some sort of array of tuples containing factors p and n, but I have been struggling fruitlessly for several hours.
Here is what I have so far:
func factors(_ number: Int) -> String {
var changedNumber = number
var numberArr = [Int]()
while changedNumber >= 2 {
for i in 2...changedNumber {
if changedNumber % i == 0 {
numberArr.append(i)
changedNumber /= i
break
}
}
}
}
Any insight or resources would be greatly appreciated.
func factors(_ number: Int) -> String
I think it’s a mistake to make this return the String directly. It violates the separation of responsibilities, and makes this hard to reuse.
Imagine elsewhere in a codebase that uses this function, there might be a function which tries to parse the string result of this back into an array to use it in some other way. It may sound ridiculous, but a large number of the questions we get on here are about people trying to build systems to accept silly input from other systems that they should just change instead!
Here's what I would suggest:
func primeFactorization(of value: Int) -> (factor: Int, exponent: Int) {
...
}
func format(_ primeFactors: [(factor: Int, exponent: Int)]) -> String {
return primeFactors
.map { $0.exponent == 1 ? "(\($0.factor))" : "(\($0.factor)xx\($0.exponent))" }
.joined()
}
So you can then do:
let factorization = primeFactorization(of: 86240)
// Which results in: [
// (factor: 2, exponent: 5),
// (factor: 2, exponent: 1),
// (factor: 7, exponent: 2),
// (factor: 11, exponent: 1),
// ]
// Which you can then format as this one question wants:
format(factorization) // => "(2xx5)(5)(7xx2)(11)"
For extra points, you could generify the first function into an extension on BinaryInteger, which would let you be able to write something like 86240.primeFactorization().
Just make your function group the numbers and then use each sub collection count when creating your string:
func factors(_ number: Int) -> String {
var changedNumber = number
var numberArr: [[Int]] = []
while changedNumber >= 2 {
for i in 2...changedNumber {
if changedNumber.isMultiple(of: i) {
if numberArr.last?.last == i {
numberArr[numberArr.count-1].append(i)
} else {
numberArr.append([i])
}
changedNumber /= i
break
}
}
}
return numberArr.reduce(into: "") {
if let last = $1.last {
if $1.count == 1 {
$0 += "(" + String(last) + ")"
} else {
$0 += "(" + String(last) + "xx\($1.count))"
}
}
}
}
print(factors(86240)) // (2xx5)(5)(7xx2)(11)
There's lots of ways to handle this. Here's one, off the top of my head:
Write an extension to Int that has the following functions
func isPrime() -> Bool
func nextPrime() -> Int.
First check to see if the input number n is prime. If it is, return the result as "(nxxx1)" and you're done.
Define a struct primeFactor:
struct PrimeFactor {
let value: Int
var count: Int
}
Create an array of PrimeFactors.
func primeFactorsString(of value: String) -> String {
var primeFactors = [PrimeFactor]()
var currentPrime = 1
var remainder = value
guard !value.isPrime() else { return "(\(value)xx1)" }
while remainder > 1 {
currentPrime = currentPrime.nextPrime()
if remainder % currentPrime == 0 {
let newPrimeFactor = PrimeFactor(value: currentPrime, count: 1)
remainder /= currentPrime
while remainder % currentPrime == 0 {
newPrimeFactor.count = newPrimeFactor.count + 1
remainder /= currentPrime
}
primeFactors.append(newPrimeFactor)
}
}
// Now loop through your array of primeFactors and build your output string.
return primeFactors.map { "(\($0.value)xx\($0.count))".joined()

matrix Sort&Transpose swift4

I'm given a two dimensional array of integers as parameter and I should take it and sort. But sorting should be done manually. After sorting need should make a transpose of the sorted array and return the transposed one.
Input:[[3, 7, 9],[8, 6, 2],[1, 5, 4]]
Return value:[[1, 4, 7],[2, 5, 8],[3, 6, 9]]
func sortAndTranspose(matrix: [[Int]]) -> [[Int]] {
var isSwapped = true
while isSwapped == true {
isSwapped = false
for index in 1..<matrix.count {
if matrix[index] < matrix[index - 1] {
}
}
}
}
Here is my solution. I used flatMap to convert the matrix into an array, then I sorted the array using code I found in this answer. Once this was done I divided the array into a matrix
Updated version Make us of swapAt and support more than square formats. Thanks to #Rob for helping out.
func sortAndTranspose(matrix: [[Int]]) -> [[Int]] {
var array = matrix.flatMap({ $0 }) //create single row array
//manual sorting
for i in stride(from: array.count-1, to: 0, by: -1) {
for j in 1...i {
if array[j-1] > array[j] {
array.swapAt(j, j - 1)
}
}
}
//transpose sorted array back into 2D array
var result = [[Int]]()
let count = matrix[0].count
for i in 0..<array.count {
if (i < count) {
result.append([array[i]])
} else {
result[i % count].append(array[i])
}
}
Original answer
func sortAndTranspose(matrix: [[Int]]) -> [[Int]] {
var array = matrix.flatMap({ $0 }) //create single row array
//manual sorting
for i in stride(from: array.count-1, to: 0, by: -1) {
for j in 1...i {
if array[j-1] > array[j] {
let tmp = array[j-1]
array[j-1] = array[j]
array[j] = tmp
}
}
}
//transpose sorted array back into 2D array
var result = [[Int]]()
let count = matrix.count
for i in 0..<array.count {
if (i < count) {
result.append([array[i]])
} else {
result[i % count].append(array[i])
}
}

Swift return bool in method

I've made this method:
func checkScore(player: Int) -> Bool {
var checkedFields: [Int] = []
var won: Bool = false
for var i = 0; i <= 9; i += 1 {
if(winningCombinations[i] == player) {
checkedFields.append(i)
}
}
for value in winningCombinations {
var hits = 0
for n in checkedFields {
if value.contains(n){
hits += 1
}
}
if hits == 3 {
won = true
}
}
return won
}
But when I try to build it everything becomes white and the build crashes. Am I doing something wrong here? I pass the value like this:
if self.checkScore(player) {
print("Won!")
}
(I see no error message!)
Your func checkScore(player: Int) accepts player, which is of type Int.
In your code you also say : if(winningCombinations[i] == player), meaning that you expect the elements in array winningCombinations to also be of type Int
But then you say
for value in winningCombinations {
var hits = 0
for n in checkedFields {
if value.contains(n){
If value is an element in winningCombination, it means that value is an int.. how can you say value.contains(n). Int cannot perform contains operation. Arrays can.

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
}