Swift Subscript for getting columns and/or rows of matrix - swift

I created a custom Matrix struct but am having problems with subscript definitions. I want to have 2 subscripts, one for getting a row, and one for getting a column. Currently, I have this:
subscript(row: Int, column: Int? = nil) -> [Double] {
get {
return Array(self.matrix[row*self.column..<(row*self.column)+3])
}
set(rowValues) {
for i in 0..<self.column{
self.matrix[row*self.column + i] = rowValues[i]
}
}
}
subscript(row: Int? = nil, column: Int) -> [Double] {
get {
var col = [Double]()
for columnIndex in 0..<self.row{
col.append(self.matrix[columnIndex*self.column + column])
}
return col
}
}
But if I call matrix[i] it returns the ith row (and if I write matrix[column: i] it says it's extra and doesn't accept) and there is no way to specify its the column if I don't call it like matrix[nil, i]. Which is fine but I was wondering if it could be possible to not have to write anything for the row and directly get the column (like matrix[, i]).

Related

Units and Measurements in Swift

I am trying to make a measurement entry keyboard class that has a text field for the value, and a picker for the unit.
I am having trouble using the Measurement type because of its generic behaviour.
I would like my class to return a new Measurement instance based on the initial value, but allowing the user to change the unit without necessarily converting it. I get the error "Cannot convert value of type 'Unit' to expected argument type 'T'" on the line where I am initialising meas with a value, and a unit of a different type.
Also, is there an way to iterate through the built-in sub units of a Dimension Type? i.e get all the sub units of UnitPressure for example.
If someone could just point me to an answer about similar generic behaviour, that would be much appreciated.
class MeasurementPicker<T : Dimension> {
init(initialUnit: Measurement<T>) {
self.initUnit = initialUnit
}
var initUnit: Measurement<T>
func getUnitList() -> [Unit]? {
switch initUnit.unit.self {
case is UnitPressure:
let retUnits: [Unit]? = [
UnitPressure.bars,
UnitPressure.gigapascals,
UnitPressure.hectopascals,
UnitPressure.inchesOfMercury,
UnitPressure.kilopascals,
UnitPressure.megapascals,
UnitPressure.millibars,
UnitPressure.millimetersOfMercury,
UnitPressure.newtonsPerMetersSquared,
UnitPressure.poundsForcePerSquareInch
]
return retUnits
default:
return nil
}
}
func getNewType(index: Int) -> Measurement<T> {
let myNewUnit : Unit = getUnitList()![index]
var meas = Measurement<T>.init(value: 6, unit: myNewUnit)
}
}
let x = Measurement(value: 5.5, unit: UnitPressure.kilopascals)
let y = MeasurementPicker<UnitPressure>(initialUnit: x)
let z = y.getNewType(index: 0)
print(z.unit.symbol)
There is no need to create a generic class. Just create a unit or dimension property. And in your method getNewType return Measurement<Unit> or just the unit or the dimension. You can also just use a subscript to get the dimension from your list:
class MeasurementPicker {
init(dimension: Dimension) { self.dimension = dimension }
var dimension: Dimension
var list: [Dimension] {
switch dimension.self {
case is UnitPressure:
return [UnitPressure.bars,
UnitPressure.gigapascals,
UnitPressure.hectopascals,
UnitPressure.inchesOfMercury,
UnitPressure.kilopascals,
UnitPressure.megapascals,
UnitPressure.millibars,
UnitPressure.millimetersOfMercury,
UnitPressure.newtonsPerMetersSquared,
UnitPressure.poundsForcePerSquareInch]
default: return []
}
}
}
Usage:
let y = MeasurementPicker(dimension: UnitPressure.kilopascals)
let z = y.list[0]
print(z.symbol) // "bar\n"

How to sort an array by one of the elements?

I created an alias - typealias frequenciesSymbol = (String, Double).
I created an array using an alias as the data type frequenciesSymbol. Then I filled this array with elements, and now I need to sort this array by Double elements. How should I do it?
typealias frequenciesSymbol = (String, Double)
// WE THINK THE FREQUENCY OF MEETING EACH SYMBOL
var frequencies2 = [Double](repeating: 0, count: 33)
for c in outputText.unicodeScalars {
switch c {
case "а"..."я":
frequencies2[Int(c.value - UnicodeScalar("а").value)] += 1
default:
break
}
}
// TRANSFER FREQUENCY IN %
for i in 0..<(frequencies2.count) {
frequencies2[i] = (frequencies2[i] * 100) / Double(outputText.count)
}
// CREATE AN ARRAY IN WHICH WE FORM THE FREQUENCY IN ACCORDANCE WITH THE SYMBOLS WITH THE SYMBOLS
var frequenciesOutputText = [frequenciesSymbol]()
// WRITE THE ARRAY OF VALUES OF FREQUENCY ACCORDING TO THE SYMBOL
for i in 0..<(frequencies2.count-1) {
frequenciesOutputText.append((rus[i], Double(frequencies2[i])))
print("\(rus[i]) - \(frequencies2[i])%")
}
//SORT ARRAY BY FREQUENCY VALUES
I want to get something like this
("о", 10.97)%
("е", 8.45)%
("а", 8.01)%
("и", 7.35)%
("н", 6.7)%
("т", 6.26)%
("с", 5.47)%
("р", 4.73)%
("в", 4.54)%
("л", 4.4)%
("к", 3.49)%
("м", 3.21)%
("д", 2.98)%
("п", 2.81)%
("у", 2.62)%
("я", 2.01)%
("ы", 1.9)%
("ь", 1.74)%
("г", 1.7)%
("з", 1.65)%
("б", 1.59)%
("ч", 1.44)%
("й", 1.21)%
("х", 0.97)%
("ж", 0.94)%
("ш", 0.73)%
("ю", 0.64)%
("ц", 0.48)%
("щ", 0.36)%
("э", 0.32)%
("ф", 0.26)%
("ъ", 0.04)%
This should work
consider
frequenciesSymbol = (name: String, value: Double)
frequenciesSymbol.sorted(by: { $0. value > $1. value })

Swift create object matrix

I'm new to Swift and I am trying to create a array of arrays of a custom object. I did some research and what mostly came up online is:
Array(repeating: Array(repeating: [Object](), count: y), count: x)
or similar but I haven't been able to get them working for me. ( Deprecated because different swift versions,etc.. ) Right now I have
class ChessPiece {
// class definition...
}
class ChessBoard {
var board: [[ChessPiece]] = []
init() {
board = [[ChessPiece(),ChessPiece(),ChessPiece()],
[ChessPiece(),ChessPiece(),ChessPiece()],
[ChessPiece(),ChessPiece(),ChessPiece()]]
}
}
But what if I had 100 rows or columns? Isn't there a more efficient and direct way to create a matrix with x rows and y columns?
I just do with normal for-in loop
class ChessPiece {
// class definition...
}
class ChessBoard {
var board: [[ChessPiece]] = []
init(row: Int, column: Int) {
for _ in 1...row {
var innerArray: [ChessPiece] = []
for _ in 1...column {
innerArray.append(ChessPiece())
}
board.append(innerArray)
}
}
}
let chessBoard = ChessBoard(row: 8, column: 8)
The function you mentioned is fine Array(repeating:count:).
This works on my playground:
struct ChessPiece {}
func makeChessPlate(dimension: Int) -> [[ChessPiece]] {
return Array(repeating: Array(repeating: ChessPiece(), count: dimension), count: dimension)
}
print(makeChessPlate(dimension: 2)) // Result: [[ChessPiece, ChessPiece],[ChessPiece, ChessPiece]]
EDIT: Notice that my example works only because I used a struct instead of a class. On the contrary to classes, structs are copied by values, then this results in an array of unique objects.
You can use this loop to create a multidimensional array.
class ChessPiece{
}
var numColumns = 27
var numRows = 52
var array = [[ChessPiece]]()
for column in 0...numColumns {
array.append(Array(repeating: ChessPiece(), count:numRows))
}
This would create an array of array of ChessPieces.

How to split or iterate over an Int without converting to String in Swift [duplicate]

This question already has answers here:
Break A Number Up To An Array of Individual Digits
(6 answers)
Closed 5 years ago.
I was wondering if there was a way in Swift to split an Int up into it's individual digits without converting it to a String. For example:
let x: Int = 12345
//Some way to loop/iterate over x's digits
//Then map each digit in x to it's String value
//Return "12345"
For a bit of background, I'm attempting to create my own method of converting an Int to a String without using the String description property or using String Interpolation.
I've found various articles on this site but all the ones I've been able to find either start with a String or end up using the String description property to convert the Int to a String.
Thanks.
Just keep dividing by 10 and take the remainder:
extension Int {
func digits() -> [Int] {
var digits: [Int] = []
var num = self
repeat {
digits.append(num % 10)
num /= 10
} while num != 0
return digits.reversed()
}
}
x.digits() // [1,2,3,4,5]
Note that this will return all negative digits if the value is negative. You could add a special case if you want to handle that differently. This return [0] for 0, which is probably what you want.
And because everyone like pure functional programming, you can do it that way too:
func digits() -> [Int] {
let partials = sequence(first: self) {
let p = $0 / 10
guard p != 0 else { return nil }
return p
}
return partials.reversed().map { $0 % 10 }
}
(But I'd probably just use the loop here. I find sequence too tricky to reason about in most cases.)
A recursive way...
extension Int {
func createDigitArray() -> [Int] {
if self < 10 {
return [self]
} else {
return (self / 10).createDigitArray() + [self % 10]
}
}
}
12345.createDigitArray() //->[1, 2, 3, 4, 5]
A very easy approach would be using this function:
func getDigits(of number: Int) -> [Int] {
var digits = [Int]()
var x = number
repeat{
digits.insert(abs(x % 10), at: 0)
x/=10
} while x != 0
return digits
}
And using it like this:
getDigits(of: 97531) // [9,7,5,3,1]
getDigits(of: -97531) // [9,7,5,3,1]
As you can see, for a negative number you will receive the array of its digits, but at their absolute value (e.g.: -9 => 9 and -99982 => 99982)
Hope it helps!

Index and Iterate over CollectionType in swift

I have code which is basically like this:
func arrayHalvesEqual(data:[UInt8]) -> Bool {
let midPoint = data.count / 2
for i in 0..<midPoint {
let b = data[i]
let b2 = data[i + midPoint]
if b != b2 {
return false
}
}
return true
}
This works fine, but sometimes I want to pass in Arrays, and other times ArraySlice. I thought I'd change it to use generics and the CollectionType protocol, which converts as follows:
func arrayHalvesEqual<ByteArray : CollectionType where ByteArray.Generator.Element == UInt8>(data:ByteArray) -> Bool {
let midPoint = data.count / 2
for i in 0..<midPoint {
let b = data[i]
let b2 = data[i + midPoint]
if b != b2 {
return false
}
}
return true
}
However, I get the following compiler error:
error: binary operator '..<' cannot be applied to operands of type 'Int' and 'ByteArray.Index.Distance'
for i in 0..<midPoint {
I can switch the for loop to for i in data.indices which makes that compile, but then I can no longer divide it by 2 to get the midPoint, as data.indices returns the abstract CollectionType.Index whereas / 2 is an Int.
Is it possible to do something like this in Swift? Can I bridge between an abstract protocol Index type and some real type I can do maths on?
P.S: I've seen and found other examples for iterating over the whole collection by using indices and enumerate, but I explicitly only want to iterate over half the collection which requires some sort of division by 2
Thanks
You can restrict the method to collections which are indexed
by Int:
func arrayHalvesEqual<ByteArray : CollectionType where ByteArray.Index == Int, ByteArray.Generator.Element == UInt8>
(data:ByteArray) -> Bool { ... }
This covers both Array and ArraySlice.
And if you use indices.startIndex instead of 0 as initial index
then it suffices to restrict the index type to IntegerType.
Also the data type UInt8 can be replaced by a generic Equatable,
and the entire method shortened to
func arrayHalvesEqual<ByteArray : CollectionType where ByteArray.Index : IntegerType, ByteArray.SubSequence.Generator.Element : Equatable>
(data:ByteArray) -> Bool {
let midPoint = (data.indices.endIndex - data.indices.startIndex)/2
let firstHalf = data[data.indices.startIndex ..< midPoint]
let secondHalf = data[midPoint ..< data.indices.endIndex]
return !zip(firstHalf, secondHalf).contains { $0 != $1 }
}