I have been trying to run this loop to change the position of an element in an array based but I get the error below. Not really sure what could be wrong. Any thoughts or Ideas!! Thanks.
var population = [[98, 8, 45, 34, 56], [9, 13, 65, 4, 90], [24, 5, 4, 56, 88], [3, 55, 22, 19, 10]]
private func randomIntergerInRange(low:Int, high:Int) -> Int {
let randomGeneratedNumber = low + Int(arc4random()) % (high - low);
return Int(randomGeneratedNumber)
}
for individual in population {
var mutate = 0.01
if mutate > Double(Float(arc4random()) / Float(UINT32_MAX)) {
var positionToMutate = randomIntergerInRange(0, (individual.count - 1))
var valueToAssign = randomIntergerInRange(minElement(individual), maxElement(individual))
individual[positionToMutate] = valueToAssign
print(individual)
}
}
Array are passed by value, so when you use individual at each iteration it is assigned a copy of the subarray of population, and even if you use for var individual in population ... you mutate only a copy of the original array.
If you want to mutate the values of the original array you can do it by using indices, for instance:
for index in population.indices {
var mutate = 0.01
if mutate > Double(Float(arc4random()) / Float(UINT32_MAX)) {
var positionToMutate = randomIntergerInRange(0, (population[index].count - 1))
var valueToAssign = randomIntergerInRange(minElement(population[index]), maxElement(population[index]))
population[index][positionToMutate] = valueToAssign
print(population[index])
}
}
Reason for the error message: the individual object in your loop is immutable, it's a copy of the object, not a reference.
You could do something like this, using enumerate:
for (index, individual) in enumerate(population) {
var mutate = 0.01
if mutate > Double(Float(arc4random()) / Float(UINT32_MAX)) {
var positionToMutate = randomIntergerInRange(0, (individual.count - 1))
var valueToAssign = randomIntergerInRange(minElement(individual), maxElement(individual))
population[index][positionToMutate] = valueToAssign
print(population[index])
}
}
You shouldn't modify a collection while iterating it, btw, it could have side effects.
Update for Swift 2
private func randomIntegerInRange(low:Int, _ high:Int) -> Int {
let randomGeneratedNumber = low + Int(arc4random()) % (high - low)
return Int(randomGeneratedNumber)
}
var mutate = 0.01
for (index, individual) in population.enumerate() {
if mutate > Double(Float(arc4random()) / Float(UINT32_MAX)) {
var positionToMutate = randomIntegerInRange(0, (individual.count - 1))
if let min = individual.minElement(), max = individual.maxElement() {
var valueToAssign = randomIntegerInRange(min, max)
population[index][positionToMutate] = valueToAssign
print(population[index])
}
}
}
Related
I want to output an array of random values, and array of factorials.
abstract class AClass {
Numbers: Array<number>;
NumbersFact: Array<number>;
constructor(Numbers: Array<number>, NumbersFact: Array<number>) {
this.Numbers = Numbers;
this.NumbersFact = NumbersFact;
for (var i = 0; i < 10; ++i) Numbers[i] = i;
Numbers = this.fill(Numbers);
NumbersFact = this.factorial(Numbers);
console.log(Numbers);
console.log(NumbersFact);
}
Everything works.
console.log showed two arrays
fill(array: number[]): number[] {
// Add random numbers to [Numbers]
var tmp: number, current: number, top = array.length;
if (top) while (--top) {
current = Math.floor(Math.random() * (top + 1));
tmp = array[current];
array[current] = array[top];
array[top] = tmp;
}
return array;
}
First array with random values from 0 to 9
factorial(array: Array<number>): Array<number> {
// Create factorial's array from [Numbers].
var arrayFact = [];
for (var i = 0; i < array.length; ++i) {
const fact = (x: number) => {
return (x == 0) ? 1 : x * fact(x - 1);
}
arrayFact.push(fact(array[i]));
}
return arrayFact
}
Second array with with factorial values from first array
abstract sort(): void;
}
class Class1 extends AClass {
sort(): void { }
}
var test = new Class1([], []);
console.log(test);
console.log(test.Numbers);
console.log(test.NumbersFact);
Result
console.log in the constructor:
(10) [0, 8, 4, 6, 3, 7, 1, 9, 2, 5],
(10) [1, 40320, 24, 720, 6, 5040, 1, 362880, 2, 120].
consol.log at the end of the code:
Class1 {Numbers: Array(10), NumbersFact: Array(0)}
(10) [0, 8, 4, 6, 3, 7, 1, 9, 2, 5]
[]
Why is the second array empty?
Because
NumbersFact = this.factorial(Numbers);
assigns the result of the function call to the NumbersFact method parameter, not to this.NumbersFact.
The reason
Numbers = this.fill(Numbers);
seemed to do the right thing is because unlike the factorial method, fill modifies the empty array you passed in as an arg. You had earlier assigned that array to this.Numbers:
this.Numbers = Numbers; // assigned an empty array that gets updated later in the ctor
this.NumbersFact = NumbersFact; // assigned an empty array that stays empty
The return value of fill also got assigned to a method parameter, not to the this.Numbers.
In other words, the first array was not empty for the wrong reasons.
Lessons to take away:
Your array methods should either modify their inputs and return void, or they should return new arrays and leave their inputs untouched.
The only exception to this rule is if you are creating chainable methods/functions.
Understand that array variables are references, like object variables. They don't hold the actual array.
If I have an array [-23,0,43,7,5,2,4], how to do I split the array [odd][even].
I want 4 elements in the first array and 3 elements in the second array.
I tried to do something like this:
let leftArray = Array(mainArray[0..<mainArray.count/2])
let rightArray = Array(mainArray[mainArray.count/2..<mainArray.count])
I keep on getting [-23,0,43] and [7,5,2,4].
I'd create an extension implementing properties that yield the left and right halves of the array. In this implementation left includes the larger half of the array if the array has an odd number of elements.
extension Array {
var left: ArraySlice<Element> {
prefix(count / 2 + count % 2)
}
var right: ArraySlice<Element> {
suffix(count / 2)
}
}
And its usage would be:
let main = [-23, 0, 43, 7, 5, 2, 4]
let left = main.left
let right = main.right
The result of the above is an ArraySlice for efficiency, but if you want an Array you can just use map.
let main = [-23, 0, 43, 7, 5, 2, 4]
let left = main.left.map { $0 }
let right = main.right.map { $0 }
I think you want to split your array in the middle, and for odd counts, have the first part be the larger one. Use a function like this (intentionally spelled our very explicitly):
func splitArray(_ arr: [Int]) -> ([Int], [Int]) {
let count = arr.count
let half = count.isMultiple(of: 2) ? count / 2 : count / 2 + 1
let left = arr[0..<half]
let right = arr[half..<count]
return (Array(left), Array(right))
}
splitArray([-23,0,43,7,5,2,4]) // ([-23, 0, 43, 7], [5, 2, 4])
splitArray([-23,0,43,7,5,2,4,1]) // ([-23, 0, 43, 7], [5, 2, 4, 1])
This can be simplified and be made generic (i.e., work on all kinds of Collections) like so:
extension Collection {
func splitHalf() -> (SubSequence, SubSequence) {
let count = self.count
let left = self.prefix(count / 2 + count % 2)
let right = self.suffix(count / 2)
return (left, right)
}
}
[-23,0,43,7,5,2,4].splitHalf() // ([-23, 0, 43, 7], [5, 2, 4])
[-23,0,43,7,5,2,4,1].splitHalf() // ([-23, 0, 43, 7], [5, 2, 4, 1])
"12345".splitHalf() // (.0 "123", .1 "45")
"123456".splitHalf() // (.0 "123", .1 "456")
Function for split the array
func getSplitArr(arr:[Int])->Void{
let count = arr.count
let secArrCount = abs(count/2)
var firstArray = [Int]()
for i in 0..<secArrCount{
let value = arr[i]
firstArray.append(value)
}
var secondArray = [Int]()
for i in secArrCount..<count{
let value = arr[i]
secondArray.append(value)
}
print("\(firstArray)")
print("\(secondArray)")
}
Use of Functions
self.getSplitArr(arr: [-23,0,43,7,5,2,4])
Your first question wasn't clear. This should return two arrays one where the first array is even and the second is odd every time.
var array = [-23,0,43,7,5,2,4]
func splitArray(in array : [Int]) -> (firstArray :[Int], secondArray: [Int]) {
let firstArray = array.dropLast(array.count / 2).compactMap { item -> Int in
item
}
let secondArray = array.dropFirst((array.count / 2) + 1).compactMap { item -> Int in
item
}
return (firstArray,secondArray)
}
var newArray = splitArray(in: array)
print(newArray)
I need to change values of a Swift array.
My first try was to just iterate through but this does not work as I only get a copy of each element and the changes do not affect the origin array.
Goal is to have a unique "index" in each array element.
myArray = [["index": 0], ["index":0], ["index":0], ["index":0]]
counter = 0
for item in myArray {
item["index"] = counter
counter += 1
}
My next attempt was using map but I don't know how to set an increasing value. I could set the $0["index"] = 1 but I need an increasing value.
In which way would this be possible using map?
myArray.map( { $0["index"] = ...? } )
Thanks for any help!
The counter in a for loop is a constant. To make it mutable, you could use :
for var item in myArray { ... }
But that won't be helpful here since we'd be mutating item and not the elements in myArray.
You could mutate the elements in myArray this way :
var myArray = [["index": 0], ["index":0], ["index":0], ["index":0]]
var counter = 0
for i in myArray.indices {
myArray[i]["index"] = counter
counter += 1
}
print(myArray) //[["index": 0], ["index": 1], ["index": 2], ["index": 3]]
The counter variable is not needed here :
for i in myArray.indices {
myArray[i]["index"] = i
}
A functional way of writing the above would be :
myArray.indices.forEach { myArray[$0]["index"] = $0 }
I found a simple way and would like to share it.
The key is the definition of myArray. It would success if it's in this way:
let myArray : [NSMutableDictionary] = [["firstDict":1, "otherKey":1], ["secondDict":2, "otherKey":1], ["lastDict":2, "otherKey":1]]
myArray.enumerated().forEach{$0.element["index"] = $0.offset}
print(myArray)
[{
firstDict = 1;
index = 0;
otherKey = 1;
}, {
index = 1;
otherKey = 1;
secondDict = 2;
}, {
index = 2;
lastDict = 2;
otherKey = 1;
}]
How about a more functional approach by creating a brand new array to store the modified dictionaries:
let myArray = [["index": 0], ["index":0], ["index":0], ["index":0]]
let myNewArray = myArray.enumerated().map { index, _ in ["index": index] }
I have an Array of numbers and I want to know which number is most frequent in this array. The array sometimes has 5-6 integers, sometimes it has 10-12, sometimes even more - also the integers in the array can be different. So I need a function which can work with different lengths and values of an array.
One example:
myArray = [0, 0, 0, 1, 1]
Another example:
myArray = [4, 4, 4, 3, 3, 3, 4, 6, 6, 5, 5, 2]
Now I am searching for a function which gives out 0 (in the first example) as Integer, as it is 3 times in this array and the other integer in the array (1) is only 2 times in the array. Or for the second example it would be 4.
It seems pretty simple, but I cannot find a solution for this. Found some examples in the web, where the solution is to work with dictionaries or where the solution is simple - but I cannot use it with Swift 3 it seems...
However, I did not find a solution which works for me. Someone has an idea how to get the most frequent integer in an array of integers?
You can also use the NSCountedSet, here's the code
let nums = [4, 4, 4, 3, 3, 3, 4, 6, 6, 5, 5, 2]
let countedSet = NSCountedSet(array: nums)
let mostFrequent = countedSet.max { countedSet.count(for: $0) < countedSet.count(for: $1) }
Thanks to #Ben Morrow for the smart suggestions in the comments below.
let myArray = [4, 4, 4, 3, 3, 3, 4, 6, 6, 5, 5, 2]
// Create dictionary to map value to count
var counts = [Int: Int]()
// Count the values with using forEach
myArray.forEach { counts[$0] = (counts[$0] ?? 0) + 1 }
// Find the most frequent value and its count with max(by:)
if let (value, count) = counts.max(by: {$0.1 < $1.1}) {
print("\(value) occurs \(count) times")
}
Output:
4 occurs 4 times
Here it is as a function:
func mostFrequent(array: [Int]) -> (value: Int, count: Int)? {
var counts = [Int: Int]()
array.forEach { counts[$0] = (counts[$0] ?? 0) + 1 }
if let (value, count) = counts.max(by: {$0.1 < $1.1}) {
return (value, count)
}
// array was empty
return nil
}
if let result = mostFrequent(array: [1, 3, 2, 1, 1, 4, 5]) {
print("\(result.value) occurs \(result.count) times")
}
1 occurs 3 times
Update for Swift 4:
Swift 4 introduces reduce(into:_:) and default values for array look ups which enable you to generate the frequencies in one efficient line. And we might as well make it generic and have it work for any type that is Hashable:
func mostFrequent<T: Hashable>(array: [T]) -> (value: T, count: Int)? {
let counts = array.reduce(into: [:]) { $0[$1, default: 0] += 1 }
if let (value, count) = counts.max(by: { $0.1 < $1.1 }) {
return (value, count)
}
// array was empty
return nil
}
if let result = mostFrequent(array: ["a", "b", "a", "c", "a", "b"]) {
print("\(result.value) occurs \(result.count) times")
}
a occurs 3 times
The most frequent value is called the "mode". Here's a concise version:
let mode = myArray.reduce([Int: Int]()) {
var counts = $0
counts[$1] = ($0[$1] ?? 0) + 1
return counts
}.max { $0.1 < $1.1 }?.0
Whether that's considered "unreadable" or "elegant" depends on your feelings towards higher order functions. Nonetheless, here it is as a generic method in an extension on Array (so it'll work with any Hashable element type):
extension Array where Element: Hashable {
var mode: Element? {
return self.reduce([Element: Int]()) {
var counts = $0
counts[$1] = ($0[$1] ?? 0) + 1
return counts
}.max { $0.1 < $1.1 }?.0
}
}
Simply remove the .0 if you'd rather have a tuple that includes the count of the mode.
My take on it with Swift 5:
extension Collection {
/**
Returns the most frequent element in the collection.
*/
func mostFrequent() -> Self.Element?
where Self.Element: Hashable {
let counts = self.reduce(into: [:]) {
return $0[$1, default: 0] += 1
}
return counts.max(by: { $0.1 < $1.1 })?.key
}
}
I have tried the following code. It helps especially when the max count is applicable for 2 or more values.
var dictionary = arr.reduce(into: [:]) { counts, number in counts[number, default: 0] += 1}
var max = dictionary.values.max()!
dictionary = dictionary.filter{$0.1 == max}
mode = dictionary.keys.min()!
func mostR(num : [Int]) -> (number : Int , totalRepeated : Int)
{
var numberTofind : Int = 0
var total : Int = 0
var dic : [Int : Int] = [:]
for index in num
{
if let count = dic[index]
{
dic[index] = count + 1
}
else
{
dic[index] = 1
}
}
var high = dic.values.max()
for (index , count) in dic
{
if dic[index] == high
{
numberTofind = index
top.append(count)
total = count
}
}
return (numberTofind , total)
}
var array = [1,22,33,55,4,3,2,0,0,0,0]
var result = mostR(num : [1,22,3,2,43,2,11,0,0,0])
print("the number is (result.number) and its repeated by :(result.totalRepeated)" )
Here is an encapsulated/reusable method.
extension Array where Element: Hashable {
/// The mode will be nil when the array is empty.
var mode: Element? {
var counts: [Element: Int] = [:]
forEach { counts[$0] = (counts[$0] ?? 0) + 1 }
if let (value, count) = counts.max(by: {$0.1 < $1.1}) {
print("\(value) occurs \(count) times")
return value
} else {
return nil
}
}
}
usage:
print([3, 4, 5, 6, 6].mode) // 6
Keep track of each occurrence, counting the value of each key in a dictionary. This case is exclusive for integers. Will update this method using generics.
func mostCommon(of arr: [Int]) -> Int {
var dict = [Int:Int]()
arr.forEach {
if let count = dict[$0] {
dict[$0] = count + 1
} else {
dict[$0] = 1
}
}
let max = dict.values.max()
for (_ , value) in dict {
if value == max {
return value
}
}
return -1
}
I wrote a really simple bubble sort for a card game. It takes an array of "Card" objects, each of which has a an "order" attribute which indicates the value to be sorted against for the game in question.
The following code stopped compiling some time between Swift Beta 1 and Beta 6, and I'm not exactly sure why.
///Sort the cards array by order
func sortCards(cards: Array<Card>) -> Array<Card> {
var sorted = false
while sorted == false {
sorted = true
for i in 0...cards.count - 2 {
if cards[i].order > cards[i+1].order {
sorted = false
var first = cards[i]
var second = cards[i + 1]
cards[i] = second //ERROR
cards[i + 1] = first //ERROR
}
}
}
return cards
}
The lines where the swap occurs bombs out with a very cryptic message:
#!value $T5 is not identical to 'Card'
What changed, and what am I doing wrong here?
Bonus question: How am I supposed to understand the error message?
Function parameters are by default constant (as if declared with let).
If you want to modify the parameter inside your function, you have to declare it as a variable:
func sortCards(var cards: Array<Card>) -> Array<Card> { ...
Note that only the local parameter cards is modified, not the array passed as
an argument to the function (which seems to be your intention because the function
returns a new array).
I played with the following using swift 3. Hope it'll help some people who come here.
bubble sort:
func bubble(arr: inout [Int]) {
for i in (1..<arr.count).reversed() {
for j in 0..<i where arr[j] > arr[j + 1] {
swap(&arr[j], &arr[j + 1])
}
}
}
using stride:
func bubbleStride(arr: inout [Int]) {
for i in stride(from: arr.count - 1, to: 1, by: -1) {
for j in 0..<i where arr[j] > arr[j + 1] {
swap(&arr[j], &arr[j + 1])
}
}
}
using while:
func bubbleWhile(arr: inout [Int]) {
var i = arr.count - 1
while(i > 0) {
var j = 0
while(j < i) {
if arr[j] > arr[j + 1] {
swap(&arr[j], &arr[j + 1])
}
j += 1
}
i -= 1
}
}
This can be used to generate a random array of integers:
import Cocoa
func ints(cnt: Int, ceiling: Int) -> [Int] {
let arr = Array(repeating: 0, count: cnt)
return arr.map { _ in Int(arc4random_uniform(UInt32(ceiling))) }
}
E.g.:
let a = ints(cnt: 10, ceiling: 100)
print(a)
var b = a
bubble(arr: &b)
print(b)
output:
[13, 30, 68, 19, 1, 4, 28, 65, 96, 13]
[1, 4, 13, 13, 19, 28, 30, 65, 68, 96]
If you declare the function like this, then the array is inmutable. You need to use the keyword inoutlike this:
func sortCards(inout cards: Array<Card>) -> Array<Card> {
//code
}
Then you call it with &:
sortCards(&myArray)
Explanation
The whole model of Arrays and pass by value/reference has changed during the beta process.
In beta 1 arrays passed into subroutines were only kind of passed by value. Arrays passed by value (and let arrays) were still modifiable as long as you didn't change the length of the array, thus breaking the pass-by-value rules and allowing your original code to work.
In beta 4 I believe it was, they changed arrays to effectively always be passed by value and changed constant arrays (let) do be truly unmodifiable, which resulted in your code not working and breaking in the compile phase.
The inout keyword changes the array to be passed by reference instead of by value and changes it from being implicitly defined with let to defined with var, which means the array is now mutable, and changes to the array are seen by the caller.
Here is bubble sort implemented in swift 4.0.2
var array = [15,11,20,14,12,13,17,16,18,19]
var sortedArray = Array(array)
var sortedAboveIndex = array.count
for i in 0 ..< sortedAboveIndex-1 {
for j in 0 ..< sortedAboveIndex-i-1 {
if (sortedArray[j] > sortedArray[j+1]) {
sortedArray.swapAt(j, j+1)
}
}
}
print(sortedArray)
if any queries on above code please comment below
The function always runs O(n^2) time even if the array is sorted. It can be optimized by stopping the algorithm if inner loop didn’t cause any swap.
func main() {
var array: [Int] = [1, 3, 15, 6, 8, 12, 10, 33, 2, 88]
var swapped = false
for i in 0..<array.count {
for j in 0..<array.count - i - 1 {
if array[j] > array[j + 1] {
// let temp = array[j]
// array[j] = array[j+1]
// array[j+1] = temp
array.swapAt(j, j + 1)
swapped = true
}
}
if swapped == false {
break
}
}
print(array)
}
Swift 5: Generic bubble sort method,
func bubbleSort<T: Comparable>(with array: inout [T]) -> [T] {
for i in 1..<array.count {
for j in 0..<array.count-i where array[j] > array[j+1] {
array.swapAt(j, j+1)
}
}
return array
}
Input:-
var intArray = [8, 3, 5, 10, 4, -1, 17, 3, 18, 10]
var floatArray = [12.231, 12.23, 14.5, 3.4, 67.899, 0.0, -1.234]
var doubleArray = [123.43555, 123.1223332, -121.2212, 23.343434, 1.232434]
var stringArray = ["Ratheesh", "Srini", "Thangu", "Muthu", "Gopi"]
print(bubbleSort(with: &intArray))
print(bubbleSort(with: &floatArray))
print(bubbleSort(with: &doubleArray))
print(bubbleSort(with: &stringArray))
Output:-
[-1, 3, 3, 4, 5, 8, 10, 10, 17, 18]
[-1.234, 0.0, 3.4, 12.23, 12.231, 14.5, 67.899]
[-121.2212, 1.232434, 23.343434, 123.1223332, 123.43555]
["Gopi", "Muthu", "Ratheesh", "Srini", "Thangu"]
100% working tested code
func bubbleSort(arrValue:[Int])->[Int]{
var arr = arrValue
for i in 0..<arr.count-1{
for j in 0..<arr.count-i-1{
if arr[j] > arr[j+1]{
arr.swapAt(j, j+1)
}
}
}
print(arr)
return arr
}
Here is a way to sort in place anything Comparable.
extension Array where Element: Comparable {
mutating func bubble(by areInIncrreasingOrder: (Element, Element) -> Bool) {
for i in (0 ..< count) {
for j in (0 ..< count - i - 1) where !areInIncrreasingOrder(self[j], self[j + 1]) {
swapAt(j, j + 1)
}
}
}
}
Quick check:
var arr = (0...8).map{ _ in Int.random(in: 0...100)}
arr
arr.bubble(by: <)
arr.sorted(by: <)