cannot assign through subscript in swift - swift

I am trying to implement common alghorithm in Swift.
Even though I did not define numbers as a let variable, but I am getting following error:
cannot assign through subscript: 'numbers' is a 'let' constant
numbers[i] = maxNumber
My Implementation is as follows:
func InsertionSort (numbers : [Int]) -> [Int]
{
var maxNumber = 0
var j = 0
var size = numbers.count-1
for (i,number) in numbers.enumerated()
{
j = i + 1
for index in j...size
{
if numbers[index] > number
{
maxNumber = numbers[index]
numbers[index] = numbers[i]
// error is thrown in the following line
numbers[i] = maxNumber
}
}
}
return numbers
}

Parameters are immutable by default. To make a parameter mutable, you need to add an inout modifier.
However, seeing that your method returns an array, you probably don't want the parameter to be modified as well. You should instead make a copy of the parameter, modify that, and return the copy:
func InsertionSort (numbers : [Int]) -> [Int]
{
var maxNumber = 0
var j = 0
let size = numbers.count-1
var numbersCopy = numbers // <------ note this line
for (i,number) in numbers.enumerated()
{
j = i + 1
for index in j...size
{
if numbers[index] > number
{
maxNumber = numbers[index]
// note how I modified the copy here
numbersCopy[index] = numbers[i]
numbersCopy[i] = maxNumber
}
}
}
return numbersCopy
}

Related

How to safely pass an array as parameter in swift

Hi this is my first question posted here. I have a class which updates an array from a stream of audio samples which I periodically need to process within another class. This is the code that updates the array and removes the oldest element when it reaches a maximum size:
public func update(sample: Sample) {
lastPeak = abs(sample.val) > abs(lastPeak) ? sample.val : lastPeak
if let last = lastSample {
if last.val * sample.val < 0 && abs(lastPeak) > minPeakSize { // this is a zero crossing
let offset = Double(sample.index) + Double(round((sample.val/(last.val - sample.val)) * 100) / 100)
let crossing = ZeroCrossing(
index: sample.index,
previousPeak: lastPeak,
indexWithOffset: offset
)
self.crossings.array.append(crossing) \\ <-- ARRAY UPDATE
lastPeak = 0
while crossings.array.count > crossingsMaxSize {
crossings.array.remove(at: 0) \\ <--ARRAY RESIZE
}
}
}
lastSample = sample
I then pass the array to a method within a separate class and occasionally get an index out of range error.
mutating func run(crossings: Crossings, octave: Int = 2) -> CorrelationResult? {
var result: CorrelationResult? = nil
if crossings.array.count > 4 {
var lastIndex: UInt = 0
if let lastCrossing = crossings.array.last {
lastIndex = lastCrossing.index
}
var startPoint = 0
var completeSet = false
for (i, crossing) in crossings.array.reversed().enumerated() { \\ <-- INDEX OUT OF RANGE
if lastIndex > crossing.index {
if lastIndex - crossing.index > windowSizeForOctave[octave] && crossing.previousPeak < 0 {
startPoint = crossings.array.count - i
completeSet = true
break
}
}
}
The array is wrapped within a struct
struct Crossings {
var locked = false
var array = [ZeroCrossing]()
}
struct ZeroCrossing {
var index: UInt
let previousPeak: Float
let indexWithOffset: Double
}
When the error occurs the array contains 500 elements and i = 0. Is there a safe way to pass arrays between classes (and I assume threads) without blocking updates to the original array?

Leetcode Q. 1528. Shuffle String

Given a string s and an integer array indices of the same length.
The string s will be shuffled such that the character at the ith position moves to indices[i] in the shuffled string.
Return the shuffled string.
Input: s = "codeleet", indices = [4,5,6,7,0,2,1,3]
Output: "leetcode"
Explanation: As shown, "codeleet" becomes "leetcode" after shuffling.
class Solution {
func restoreString(_ s: String, _ indices: [Int]) -> String {
//convert the string into a hash map where all keys are Ints and the values are the Strings.
//Run a for loop through the dictionary and return the key of the value in indices.
//time complexity: O(n)
//Space complexity: O(n)
var newString = s.map{ String($0) }
var y = ""
var count = 0
var dict = [Int:String]()
var z = 0
while count < newString.count {
dict[count] = newString[count]
count += 1
}
while z < indices.count {
y.append(dict[indices[z]]!)
z += 1
}
print(dict)
return y
}
}
The first while loop creates a dictionary and the second while loop finds the values with matching keys and appends into a string. My issue is that my code is outputting two characters in the wrong location.
Input: "codeleet"
[4,5,6,7,0,2,1,3]
Output: "leetcdoe"
Can you please help me explain what I'm missing here.
Its a one to one hashing not a index based hashing which you were doing in above code below is the updated correct version of your code:-
class Solution {
func restoreString(_ s: String, _ indices: [Int]) -> String {
var newString = s.map{ String($0) }
var y = ""
var count = 0
var dict = [Int:String]()
var z = 0
while count < newString.count {
dict[indices[count]] = newString[count]
count += 1
}
while z < indices.count {
y.append(dict[z]!)
z += 1
}
print(dict)
return y
}
}
class Solution {
public String restoreString(String s, int[] indices) {
String s1="";
for(int i=0;i<s.length();i++){
for(int j=0;j<s.length();j++){
if(i==indices[j]){
s1=s1+s.charAt(j);
}
}
}return s1;
}
func restoreString(_ s: String, _ indices: [Int]) -> String {
var letters = [String]()
var result = ""
s.forEach{
letters.append(String($0))
}
for (index,value) in s.enumerated(){
letters[indices[index]] = value.description
}
result = letters.reduce("", +)
return result }

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.

unresolved identifier - for in loop logic

This is a sort from bottom to top. While looping the iteration is substituted with the lowest number in the array and this continues all the way to the end.
As you can see I'm refactoring to use stride. Unfortunately var lowest = firstIndex is giving me some troubles.
I should be able to complete this function using stride right? I believe I should be using stride: to instead of stride: through. Thanks to Tim for that tip.
func selOrganize(myList: Array<Int>) -> Array<Int> { 1
var extract = myList
for firstIndex in 0..<extract.count {
var lowest = firstIndex
for var secondIndex = firstIndex + 1; secondIndex < extract.count; secondIndex++ {
if extract[lowest] > extract[secondIndex] {
lowest = secondIndex
}
}
if firstIndex != lowest {
swap(&extract[firstIndex], &extract[lowest])
}
}
return extract
}
Updated syntax
func selOrganize(myList: Array<Int>) -> Array<Int> {
var extract = myList
// var lowest = firstIndex
// Do I need 'key'? Should I declare 'lowest' as a variable here?
// If I do use it here I get a "'lowest' is unmutable because it's a let" error
for (firstIndex, key) in extract.enumerate() {
// < > stride uses 'to' and <= >= stride uses through
for secondIndex in (firstIndex).stride(to: 0, by: +1) {
if extract[lowest] > extract[secondIndex] {
lowest = secondIndex
}
}
if firstIndex != lowest {
swap(&extract[firstIndex], &extract[lowest])
}
}
return extract
}
I got it to work like this:
func selOrganize(myList: Array<Int>) -> Array<Int> {
var extract = myList
// Accessing indices is simpler than calling enumerate, and
// the function only needs access to the indices, not the
// values of the enumeration:
for firstIndex in extract.indices {
// lowest needs to be defined inside this loop if you
// are going to initialize it using firstIndex
// because firstIndex isn't defined outside the loop.
var lowest = firstIndex
// You need to stride from the firstIndex to the end of the
// array, so the call to stride should look like this:
for secondIndex in firstIndex.stride(to: extract.count, by: 1) {
if extract[lowest] > extract[secondIndex] {
lowest = secondIndex
}
}
if firstIndex != lowest {
swap(&extract[firstIndex], &extract[lowest])
}
}
return extract
}
Stride is not needed, you can do that with standard for i in start..<end syntax
func selOrganize(myList: Array<Int>) -> Array<Int> {
var extract = myList
for firstIndex in 0..<extract.count {
var lowest = firstIndex
for secondIndex in (firstIndex + 1)..<extract.count {
if extract[lowest] > extract[secondIndex] {
lowest = secondIndex
}
}
if firstIndex != lowest {
swap(&extract[firstIndex], &extract[lowest])
}
}
return extract
}
But actually you can do the same in one line
let sortedList = myList.sort{$0 < $1}

Swift 2 Error: Solve "Type of expression is ambiguous without more context"

I would like store permutations of shuffled array in a Dictionary who takes my custom array list in key and the number of permutations in value and I have the error "Type of expression is ambiguous without more context"
How can I solve that ?
There's an example of my code
func countPermutation() {
var count: Int = 0
let arrayCopy: [T] = self.data
var shuffled: [T] = self.data
var array = Array(count: 100, repeatedValue: [T]())
var myMap: Dictionary<MyArray<T>, Int> = Dictionary()
for var i = 0; i < 100; i++ {
shuffled = shuffle(arrayCopy)
array[i] = shuffled
}
let anyArray: AnyObject = array as! AnyObject
let anyCopy: AnyObject = shuffled as! AnyObject
for var j = 0; j < array.count; j++ {
if anyArray[j].isEqual(anyCopy) {
count++
myMap = [anyCopy: count]
}
}
print(myMap)
}
You see such expression when Xcode does not understand what type do you want to have. I think now you have such problem because of non-obvious type of you shuffled variable. Try to be more explicit about types.