Apply void function on array - swift

I am learning swift right now and wanted to write a quicksort algorithm for [Int]
func swap(array:[Int], x:Int, y:Int)->[Int] { //swap elements in array
var result:[Int] = array
result[y] = array[x]
result[x] = array[y]
return result
}
func split(array:[Int], u:Int, o:Int , p:Int)->Int { //where the sorting happens
let pivot:Int = array[p]
swap(array: array, x: p, y: o)
var pn:Int = u
for j in u...o {
if(array[j] <= pivot) {
swap(array: array, x: pn, y: j)
pn = pn+1
}
}
swap(array: array, x: pn, y: o);
return pn;
}
func quickSortR(array:[Int],u:Int ,o:Int) { //recursive call
if(u < o){
let p:Int = o
let pn:Int = split(array: array, u: u, o: o, p: p)
quickSortR(array: array,u: u,o: pn-1)
quickSortR(array: array,u: pn+1,o: o)
}
}
func quickSort(array:[Int]) { //initial call
quickSortR(array: array, u: 0, o: array.count-1)
}
My problem is that I don't know how to apply this implementation on an array.
For example if I got the array a:[Int] = [3,1,2].
I can't check if the implementation is working by print(quickSort(a)), because the return type of quickSort is void.
Of course I can't apply quickSort on that array like a.quickSort(a)
I really don't want to change my implementation of the algorithm by much if it isn't the cause of that problem (e.g. just the signature or return type)

Just improve your syntax:
func swap(array: inout [Int], x:Int, y:Int) { //swap elements in array
let temp = array[x]
array[x] = array[y]
array[y] = temp
}
func split(array: inout [Int], u:Int, o:Int , p:Int) -> Int { //where the sorting happens
print(ar, u , o , p)
let pivot:Int = array[p]
swap(array: &array, x: p, y: o)
var pn:Int = u
for j in u..<o {
if(array[j] <= pivot) {
swap(array: &array, x: pn, y: j)
pn = pn+1
}
}
swap(array: &array, x: pn, y: o);
return pn;
}
func quickSortR(array: inout [Int],u:Int ,o:Int) { //recursive call
if(u < o){
let p:Int = o
let pn:Int = split(array: &array, u: u, o: o, p: p)
quickSortR(array: &array,u: u,o: pn-1)
quickSortR(array: &array,u: pn+1,o: o)
}
}
func quickSort(array: inout [Int]) { //initial call
quickSortR(array: &array, u: 0, o: array.count-1)
}
If you use func swap(array: [Int]) array is immutable inside the method. It just copies. Using inout resolves this problem.
To check the code use somethink like this:
var ar = [1]
quickSort(array: &ar)
print(ar)

Related

How to write mutating function for enum in Swift

I want to write mutating function like the following. But this code cannot be compiled because x and y are immutable and copied value. I want to get the reference of x and y. How to get the reference of variables wrapped by enum?
enum Fruit {
case apple(Int)
case banana(Int, Int, Int)
mutating func increment() {
switch self {
case let .apple(x):
x += 1
case let .banana(x, y, z):
x += 1
}
}
}
var a = Fruit.banana(100, 200, 300)
a.increment()
I know the following code can do the same thing. But I think this solution is redundant because we have to write each variable twice.
enum Fruit {
case apple(Int)
case banana(Int, Int, Int)
mutating func increment() {
switch self {
case let .apple(x):
self = .apple(x + 1)
case let .banana(x, y, z):
self = .banana(x + 1, y, z)
}
}
}
var a = Fruit.banana(100, 200, 300)
a.increment()
Using self = .apple(x) will do the trick. It is customary, but you already knew this.
enum Fruit {
case apple(Int)
case banana(Int, Int, Int)
mutating func increment() {
switch self {
case let .apple(x):
self = .apple(x + 1)
case let .banana(x, y, z):
self = .banana(x + 1, y + 1, z + 1)
}
}
}
var a = Fruit.banana(100, 200, 300)
a.increment()
You could also add support for generic operators:
enum Fruit {
case apple(Int)
case banana(Int, Int, Int)
mutating func operate(_ op: (Int, Int) -> Int,_ num: Int) {
switch self {
case let .apple(x):
self = .apple(op(x, num))
case let .banana(x, y, z):
self = .banana(op(x, num), op(y, num), op(z, num))
}
}
}
var a = Fruit.banana(100, 200, 300)
a.operate(+, 1) // adds all by 1
a.operate(*, 500) // multiplies all by 500
You could also add support for an array of generic operators:
enum Fruit {
case apple(Int)
case banana(Int, Int, Int)
mutating func operate(_ nest: [((Int, Int) -> Int, Int)]) {
for i in nest {
switch self {
case let .apple(x):
self = .apple(i.0(x, i.1))
case let .banana(x, y, z):
self = .banana(i.0(x, i.1), i.0(y, i.1), i.0(z, i.1))
}
}
}
}
var a = Fruit.banana(100, 200, 300)
a.operate([(+, 500), (*, 2)]) // Adds all by 500, then multiply all by 2
Here's a nice simplification
If it were up to me, this is what I would do to get rid of repeating self =. You can simplify this further if you wish.
enum FruitList: String { case apple, banana }
struct Fruit {
static func apple(_ one: Int) -> Fruit {
return Fruit.init(.apple, [one])
}
static func banana(_ one: Int,_ two: Int,_ three: Int) -> Fruit {
return Fruit.init(.apple, [one, two, three])
}
var picked: (FruitList, [Int])
init(_ fruit: FruitList,_ list: [Int]) {
picked = (fruit, list)
}
mutating func operate(_ nest: [((Int, Int) -> Int, Int)]) {
for i in nest {
for j in 0..<picked.1.count {
picked.1[j] = i.0(picked.1[j], i.1)
}
}
}
}
var a = Fruit.apple(100)
a.operate([(+, 500), (*, 2)]) // Add all by 500, then multiply all by 2

Swift function that swaps two values

I need to write a function that swaps the contents of any two variables. This is what I have currently but I am getting the error "Cannot assign to value: 'a' is a 'let' constant".
func swap<T>(a: T, b: T) {
(a, b) = (b, a);
}
Can somebody please explain why this doesn't work and suggest how to fix it?
Thank you.
You need to make the parameters inout to be able to do that, like this:
func swap<T>(_ a: inout T,_ b: inout T) {
(a, b) = (b, a)
}
var a = 0, b = 1
swap(&a, &b)
The parameters inside your function is immutable so it cannot be swapped , like if you trying to swap two let value:
let x = 5
let y = 6
//if you try to swap these values Xcode will tell you to change their declaration to var
Here almost the same and to be able to change the values you have to pass inout declaration like below :
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
(a, b) = (b, a)
}
// call it like this
var x = 1
var y = 2
swapTwoValues(&x, &y)
// Note that you cannot call it like this: swapTwoValues(&1, &2)
That is because the arguments of functions are constants and are treated as local properties, unless you mark them inout and then they are treated as sort of "pass-through" properties that aren't confined to the scope of the function.
var kiwi = "kiwi"
var mango = "mango"
func swap<T>(a: inout T, b: inout T) {
(a, b) = (b, a)
}
swap(&kiwi, &mango)
If having to put & everywhere or the verbosity of the function annoy you, you could always use a descriptive operator like this:
infix operator <->: AssignmentPrecedence
func <-> <A>(lhs: inout A, rhs: inout A) {
(lhs, rhs) = (rhs, lhs)
}
var kenobi = "Hello there!"
var helloThere = "Kenobi..."
helloThere <-> kenobi
print(helloThere, kenobi, separator: "\n")
// Hello there!
// Kenobi...
Which I feel looks much nicer. You don't need to use & in operators with inout parameters – that's how the += and -= operators work:
public extension AdditiveArithmetic {
static func +=(lhs: inout Self, rhs: Self) {
lhs = lhs + rhs
}
static func -=(lhs: inout Self, rhs: Self) {
lhs = lhs - rhs
}
}

Swift convenience subscript

Can I define a convenience subscript setter in Swift?
For instance let's say I've:
extension Matrix {
subscript(_ i: Int, _ j: Int) -> Double {
get {
return value(atRow: i, column: j)
}
set {
setValue(newValue, row: i, column: j)
}
}
}
and I also want to define a setter that accepts Float since I'm tired of casting manually. I'd like to do:
extension Matrix {
subscript(_ i: Int, _ j: Int) -> Double {
get {
return value(atRow: i, column: j)
}
set {
setValue(newValue, row: i, column: j)
}
}
subscript(_ i: Int, _ j: Int) -> Float {
set {
setValue(Double(newValue), row: i, column: j)
}
}
}
But I can't do this since the second subscript has no getter.
Since Swift allows overloading on return value (unlike Java and C++), you could add a Float getter:
extension Matrix {
subscript(_ i: Int, _ j: Int) -> Double {
get { return value(atRow: i, column: j) }
set { setValue(newValue, row: i, column: j) }
}
subscript(_ i: Int, _ j: Int) -> Float {
get { return Float(value(atRow: i, column: j)) }
set { setValue(Double(newValue), row: i, column: j) }
}
}
However, you'll run into trouble when you try to use the subscript operator in a context that allows either Float or Double. Example:
20. let m = Matrix()
21. let x = m[0, 0]
error: repl.swift:21:10: error: ambiguous use of 'subscript'
let x = m[0, 0]
^
repl.swift:9:5: note: found this candidate
subscript(_ i: Int, _ j: Int) -> Double {
^
repl.swift:14:5: note: found this candidate
subscript(_ i: Int, _ j: Int) -> Float {
^
You can disambiguate by specifying the type:
let x: Float = m[0, 0]

How to find the index of an item in a multidimensional array swiftily?

Let's say I have this array:
let a = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Now I want something like this:
public func indicesOf(x: Int, array: [[Int]]) -> (Int, Int) {
...
}
so that I can call it like this:
indicesOf(7, array: a) // returns (2, 0)
Of course, I can use:
for i in 0..<array.count {
for j in 0..<array[i].count {
if array[i][j] == x {
return (i, j)
}
}
}
But that is not even close to swifty!
I want a way to do this which is swifty. I think maybe I can use reduce or map?
You can simplify your code slightly with enumerate() and indexOf().
Also the function should return an optional tuple because the element
might not be present in the "matrix". Finally, you can make it generic:
func indicesOf<T: Equatable>(x: T, array: [[T]]) -> (Int, Int)? {
for (i, row) in array.enumerate() {
if let j = row.indexOf(x) {
return (i, j)
}
}
return nil
}
You can also make it an extension for a nested Array of Equatable
elements:
extension Array where Element : CollectionType,
Element.Generator.Element : Equatable, Element.Index == Int {
func indicesOf(x: Element.Generator.Element) -> (Int, Int)? {
for (i, row) in self.enumerate() {
if let j = row.indexOf(x) {
return (i, j)
}
}
return nil
}
}
if let (i, j) = a.indicesOf(7) {
print(i, j)
}
Swift 3:
extension Array where Element : Collection,
Element.Iterator.Element : Equatable, Element.Index == Int {
func indices(of x: Element.Iterator.Element) -> (Int, Int)? {
for (i, row) in self.enumerated() {
if let j = row.index(of: x) {
return (i, j)
}
}
return nil
}
}
Swift 5+
extension Array where Element : Collection,
Element.Iterator.Element : Equatable, Element.Index == Int {
func indicesOf(x: Element.Iterator.Element) -> (Int, Int)? {
for (i, row) in self.enumerated() {
if let j = row.firstIndex(of: x) {
return (i, j)
}
}
return nil
}
}
Version accepting a closure, similar to index(where:), so there it is usable on the array of any elements, not only Equatable
extension Array where Element : Collection, Element.Index == Int {
func indices(where predicate: (Element.Iterator.Element) -> Bool) -> (Int, Int)? {
for (i, row) in self.enumerated() {
if let j = row.index(where: predicate) {
return (i, j)
}
}
return nil
}
}
Use like this:
let testArray = [[1,2,3], [4,5,6], [7,8]]
let testNumber = 6
print(testArray.indices(of: testNumber))
print(testArray.indices{$0 == testNumber})
Optional((1, 2))
Optional((1, 2))
Also, it can be used with IndexPath:
extension Array where Element : Collection, Element.Index == Int {
func indexPath(where predicate: (Element.Iterator.Element) -> Bool) -> IndexPath? {
for (i, row) in self.enumerated() {
if let j = row.index(where: predicate) {
return IndexPath(indexes: [i, j])
}
}
return nil
}
}

How to compare generic objects in Swift?

consider the following simplified snippet:
class Foo<T: Equatable> {
var x: T
init(_ x: T, _ y: T) {
self.x = x
if (x == y) {
// do something
}
}
}
I would like this class to work for all kinds of Ts that are somehow comparable. Ideally it would compare the identities if T is an object and directly compare everything else that conforms to Equatable.
The code above doesn't work for Array for example. If I change Equatable to AnyObject and == to === then it doesn't work for Ints. How do I solve this problem? I thought about creating my own protocol but then I couldn't figure out how to implement it for all types that conform to Equatable.
Edit:
I didn't know that it would work on the Mac because I am on Linux and when I try to compile
Foo<[Int]>([1, 2], [1, 2])
I get the following error:
error: type '[Int]' does not conform to protocol 'Equatable'
Foo<[Int]>([1, 2], [1, 2])
^
A simple solution would be to simply add another initializer for arrays of Equatable elements.
class Foo<T: Equatable> {
init(_ x: T, _ y: T) {
if (x == y) {
print("Initialization by equal equatable types.")
}
}
init(_ x: [T], _ y: [T]) {
if (x == y) {
print("Initialization by equal arrays of equatable types.")
}
}
}
let a = Foo<Int>(1, 1)
/* Initialization by equal equatable types. */
let b = Foo<Int>([1, 2, 3], [1, 2, 3])
/* Initialization by equal arrays of equatable types. */
Depending on what you intend to do with Foo, it may not be necessary to make it a generic class but rather just have generic initializers:
class Foo
{
init<T:Equatable>(_ x: T, _ y: T)
{
if (x == y)
{
// do something
}
}
init<T:AnyObject>(_ x: T, _ y: T)
{
if (x === y)
{
// do something
}
}
}
// in Playground ...
class Bar { }
let C = Foo(3,4) // no error
let O1 = Bar()
let O2 = Bar()
let D = Foo(O1,O2) // no error