Get median of array - arrays

I have an array that looks like this:
let arr = [1,2,3,4,5,6,7,8,9]
I know you can get min and max by:
let min = arr.min()
let max = arr.max()
But how do you get the median?

To get the median you can use the following:
let median = arr.sorted(by: <)[arr.count / 2]
In your case it will return 5.
As #Nirav pointed out [1,2,3,4,5,6,7,8] will return 5 but should return 4.5.
Use this instead:
func calculateMedian(array: [Int]) -> Float {
let sorted = array.sorted()
if sorted.count % 2 == 0 {
return Float((sorted[(sorted.count / 2)] + sorted[(sorted.count / 2) - 1])) / 2
} else {
return Float(sorted[(sorted.count - 1) / 2])
}
}
Usage:
let array = [1,2,3,4,5,6,7,8]
let m2 = calculateMedian(array: array) // 4.5

The median is defined as the number in the middle of the sequence. If there is not one middle number, then it's the average of the two middle numbers.
extension Array where Element == Int {
func median() -> Double {
let sortedArray = sorted()
if count % 2 != 0 {
return Double(sortedArray[count / 2])
} else {
return Double(sortedArray[count / 2] + sortedArray[count / 2 - 1]) / 2.0
}
}
}

Note that if the array is empty, the median is undefined. So a safe median function returns an optional, just like the min() and max() built-in methods do.
extension Array where Element == Int {
func median() -> Double? {
guard count > 0 else { return nil }
let sortedArray = self.sorted()
if count % 2 != 0 {
return Double(sortedArray[count/2])
} else {
return Double(sortedArray[count/2] + sortedArray[count/2 - 1]) / 2.0
}
}
}
With that defined, you can write:
if let median = arr.median() {
// do something
}

If someone (like me) likes two*-liners:
let sorted = arr.sorted(by: <)
let median = Double(sorted[arr.count/2] + sorted.reversed()[arr.count/2])/2.0

Algorithms that use sorted take O(n log n) time. That's typically not a problem for 9 numbers, but if your array is large, use an algorithm that completes in O(n) time. An example is this k-th largest element algorithm. It recursively partitions the array, but doesn’t have to go through all the work to sort it, so it’s much faster.

Related

Optimizing travel double for loop using swift

I used minimum edit distance algorithm to find the bundle of the most similar strings in an array.
So, I have to travel double for loop to compare all element.
If the data is large enough, this algorithm is Inefficient.
Is there a way to optimize?
let data = [
"10000", // count
"asdfqwerty", "asdfzxcvgh", "asdfpoiuyt",
...
]
for i in 1..<data.count {
let string = data[i]
for j in (i + 1)..<data.count {
let newMin = string.minimumEditDistance(other: data[j])
if min >= newMin {
// some logic
}
}
}
extension String {
public func minimumEditDistance(other: String, `default`: Int = 10) -> Int {
let m = self.count
let n = other.count
if m == 0 || n == 0 {
return `default`
}
var matrix = [[Int]](repeating: [Int](repeating: 0, count: n + 1), count: m + 1)
// initialize matrix
for index in 1...m {
// the distance of any first string to an empty second string
matrix[index][0] = index
}
for index in 1...n {
// the distance of any second string to an empty first string
matrix[0][index] = index
}
// compute Levenshtein distance
for (i, selfChar) in self.enumerated() {
for (j, otherChar) in other.enumerated() {
if otherChar == selfChar {
// substitution of equal symbols with cost 0
matrix[i + 1][j + 1] = matrix[i][j]
} else {
// minimum of the cost of insertion, deletion, or substitution
// added to the already computed costs in the corresponding cells
matrix[i + 1][j + 1] = Swift.min(matrix[i][j] + 1, matrix[i + 1][j] + 1, matrix[i][j + 1] + 1)
}
}
}
return matrix[m][n]
}
}
You can achieve desired behaviour by sorting your array using your minimumEditDistance as a sorting function and then taking first or last element (depends on how you define sorting) and what you need - min or max. It will likely run in O(N*log(N)) time. Which is already better than exponential.
As #Sultan mentioned, it will work not for all distances, as transitivity is applicable only to Metrics (functions that define a distance between each element of the set). You're using Levenstain distance as an editing distance algorithm, which is indeed a metric. The solution I mentioned should help to optimise in some circumstances.

Performance of moving zeros to the end of an array programming exercise

I wonder why my solution to this LeetCode "Move Zeros" problem is slower than the majority of other submissions. Is there a better way to approach this problem to make it faster?
The question is as follows:
Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements. You must do this in-place without making a copy of the array.
Example:
Input: [0,1,0,3,12]
Output: [1,3,12,0,0]
This is my solution:
func moveZeroes(_ nums: inout [Int]) {
var index = 0
for (i,n) in nums.enumerated()
{
if n != 0
{
nums[index] = n
index += 1
}
}
while index < nums.count
{
nums[index] = 0
index += 1
}
}
LeetCode gives me these statistics:
Runtime: 52 ms, faster than 40.50% of Swift online submissions for Move Zeroes.
Memory Usage: 19.4 MB, less than 13.33% of Swift online submissions for Move Zeroes.
EDIT 1:
If I approach the problem as follows, it does not move the zeros at the end,
EDIT 2:
Here is 36ms in-place solution for you :
class Solution {
func moveZeroes(_ nums: inout [Int]) {
if nums.count < 2 {
return
}
var j = 0
while j < nums.count, nums[j] != 0 {
j += 1
}
if j < nums.count - 1 {
for i in j+1..<nums.count {
if nums[i] != 0 {
nums.swapAt(i, j)
j += 1
}
}
}
}
}
From what I can see, it's likely other submissions are doing this
Check and count 0's in string
Remove 0's
Replace number of 0's at the end of the string
A logical method no doubt, but I'd say yours just picks the basic needs of the challenge and goes for it.
I would personally use:
input = input.filter { $0 != 0 } + input.filter { $0 == 0 }
which can be simplified to one pass:
let nonZeros = input.filter { $0 != 0 }
input = nonZeros + Array(repeating: 0, count: input.count - nonZeros.count)
EDIT: The simplest version without creating a new array would be some primitive version of bubble sort, e.g.:
var numZeros = 0
// iterate array from start to end
for (offset, element) in input.enumerated() {
if element == 0 {
// count every zero
numZeros += 1
} else if numZeros > 0 {
// move every non-zero element left
input[offset - numZeros] = element
// replace with zero
input[offset] = 0
}
}
Another approach is the half-stable-partition algorithm. The benefit is the items are swapped rather than removed and inserted/appended.
Half-stable means the order of the left side of the split point is preserved.
extension Array {
mutating func halfStablePartition(indexes : IndexSet) { // code is O(n)
guard var i = indexes.first, i < count else { return }
var j = index(after: i)
var k = indexes.integerGreaterThan(i) ?? endIndex
while j != endIndex {
if k != j { swapAt(i, j); formIndex(after: &i) }
else { k = indexes.integerGreaterThan(k) ?? endIndex }
formIndex(after: &j)
}
}
}
var input = [0,1,0,3,12]
let indices = IndexSet(input.indices.filter{input[$0] == 0})
input.halfStablePartition(indexes: indices)
Swift 4.2 or later using removeAll mutating method:
Mutating the input:
class Solution {
func moveZeroes(_ nums: inout [Int]) {
var counter = 0
nums.removeAll {
if $0 == 0 {
counter += 1
return true
}
return false
}
nums += repeatElement(0, count: counter)
}
}
A similar approach for Swift 4.1 or earlier
func moveZeroes(_ nums: inout [Int]) {
var counter = 0
nums.indices.reversed().forEach {
if nums[$0] == 0 {
counter += 1
nums.remove(at: $0)
}
}
nums += repeatElement(0, count: counter)
}
var input = [0,1,0,3,12]
moveZeroes(&input)
input // [1, 3, 12, 0, 0]
Non mutating approach:
func moveZeroes(_ nums: [Int]) -> [Int] {
var counter = 0
return nums.filter {
if $0 == 0 { counter += 1 }
return $0 != 0
} + repeatElement(0, count: counter)
}
let input = [0,1,0,3,12]
let zerosMoved = moveZeroes(input)
zerosMoved // [1, 3, 12, 0, 0]
For modifying array in place, and keeping it:
O(n) for Time Complexity
O(1) for Space Complexity
Cracked my head way to long for this one. The cleanest way if you swap element that is NOT zero:
func moveZeroes(_ nums: inout [Int]) {
// amount of swaps, will be used a as reference for next swap index
var j = 0
for (i, e) in nums.enumerated() {
if e != 0 {
nums.swapAt(j, i)
j += 1
}
}
}
One fast solution is to shift non-zero elements to the left by the amount of zeros encountered until then:
func moveZeroes(_ nums: inout [Int]) {
var offset = 0
for i in 0..<nums.count {
if nums[i] == 0 { offset += 1 }
else { nums.swapAt(i, i-offset) }
}
}
This solution takes exactly N steps, and at each step we either perform an addition, or a swap, which are both quite fast.
Your solution, on the other hand required two iterations, resulting in 2*N steps, which is why it was slower than other solutions.

Swift: Merge Sort Algorithm with alternate keys

I have an object with properties: Name, Relevance, Timestamp.
I want the objects in the array to be sorted interlaced by Most Relevant("Relevance") and Most Recent("Timestamp").
Such as: Relevant, Recent, Relevant, Recent, etc...
Now, I have a solution to sort based on a single key with Time Complexity of O(n log n).
Here's my solution in Swift:
func mergeSort(array: [Entity]) -> [Entity] {
guard array.count > 1 else { return array } // 1
let middleIndex = array.count / 2 // 2
let leftArray = mergeSort(Array(array[0..<middleIndex])) // 3
let rightArray = mergeSort(Array(array[middleIndex..<array.count])) // 4
return merge(leftPile: leftArray, rightPile: rightArray) // 5
}
func merge(leftPile leftPile: [Entity], rightPile: [Entity]) -> [Entity] {
// 1
var leftIndex = 0
var rightIndex = 0
// 2
var orderedPile = [Entity]()
// 3
while leftIndex < leftPile.count && rightIndex < rightPile.count {
if leftPile[leftIndex].timestamp.isGreaterThanDate(rightPile[rightIndex].timestamp) {
orderedPile.append(leftPile[leftIndex])
leftIndex += 1
} else if leftPile[leftIndex].timestamp.isLessThanDate(rightPile[rightIndex].timestamp) {
orderedPile.append(rightPile[rightIndex])
rightIndex += 1
}
else{
orderedPile.append(leftPile[leftIndex])
leftIndex += 1
orderedPile.append(rightPile[rightIndex])
rightIndex += 1
}
}
// 4
while leftIndex < leftPile.count {
orderedPile.append(leftPile[leftIndex])
leftIndex += 1
}
while rightIndex < rightPile.count {
orderedPile.append(rightPile[rightIndex])
rightIndex += 1
}
return orderedPile
}
The code sorts the array for "Most Recent" perfectly and i can also change the key from "timestamp" to "relevance", to sort it for "Most Relevant".
But, i want interlaced sort as described above with shortest complexity. Does anyone have a good solution for this?
Sort by relevance.
Make a copy sorted by recentness.
Merge the copies in alternate order, keeping a dictionary of the ones in the merge and not adding them again.
The two sorts are O(n log(n)) and the merge is O(n) for O(n log(n)).

[Swift 2.2]: analog arc4random for range with negative numbers

I wrote a function that finds the greatest difference among all elements of the array. But I need the restriction on the input elements array [-5..20]. Unfortunately it does not support UInt32. What are similar to a solution to fill the array randomly from the range [-5..20]?Thank you!
func highDifferenceV ( n: Int) ->String{
var a = [Int]() //array
var dif = 0 // max difference
var k = 0
for _ in 0..<n {
a.append(Int(arc4random_uniform(UInt32(20)))) // fill array
}
while k < a.count { //search the greatest difference
for i in 0..<n {
if a[k] - a[i] > dif {
dif = a[k] - a[i]
}
}
k++
}
print(a)
return "Maximum difference =\(dif)"
}
highDifferenceV(75)
To fill an array with values from -5...20, generate an number in the range 0...25 and then subtract 5:
for _ in 0..<n {
a.append(Int(arc4random_uniform(UInt32(26)))-5) // fill array
}
In general, to generate a value in the range min...max, call arc4random_uniform with max - min + 1 and then add min.

Project Euler 7 Scala Problem

I was trying to solve Project Euler problem number 7 using scala 2.8
First solution implemented by me takes ~8 seconds
def problem_7:Int = {
var num = 17;
var primes = new ArrayBuffer[Int]();
primes += 2
primes += 3
primes += 5
primes += 7
primes += 11
primes += 13
while (primes.size < 10001){
if (isPrime(num, primes)) primes += num
if (isPrime(num+2, primes)) primes += num+2
num += 6
}
return primes.last;
}
def isPrime(num:Int, primes:ArrayBuffer[Int]):Boolean = {
// if n == 2 return false;
// if n == 3 return false;
var r = Math.sqrt(num)
for (i <- primes){
if(i <= r ){
if (num % i == 0) return false;
}
}
return true;
}
Later I tried the same problem without storing prime numbers in array buffer. This take .118 seconds.
def problem_7_alt:Int = {
var limit = 10001;
var count = 6;
var num:Int = 17;
while(count < limit){
if (isPrime2(num)) count += 1;
if (isPrime2(num+2)) count += 1;
num += 6;
}
return num;
}
def isPrime2(n:Int):Boolean = {
// if n == 2 return false;
// if n == 3 return false;
var r = Math.sqrt(n)
var f = 5;
while (f <= r){
if (n % f == 0) {
return false;
} else if (n % (f+2) == 0) {
return false;
}
f += 6;
}
return true;
}
I tried using various mutable array/list implementations in Scala but was not able to make solution one faster. I do not think that storing Int in a array of size 10001 can make program slow. Is there some better way to use lists/arrays in scala?
The problem here is that ArrayBuffer is parameterized, so what it really stores are references to Object. Any reference to an Int is automatically boxed and unboxed as needed, which makes it very slow. It is incredibly slow with Scala 2.7, which uses a Java primitive to do that, which does it very slowly. Scala 2.8 takes another approach, making it faster. But any boxing/unboxing will slow you down. Furthermore, you are first looking up the ArrayBuffer in the heap, and then looking up again for java.lang.Integer containing the Int -- two memory accesses, which makes it way slower than your other solution.
When Scala collections become specialized, it should be plenty faster. Whether it should be enough to beat your second version or not, I don't know.
Now, what you may do to get around that is to use Array instead. Because Java's Array are not erased, you avoid the boxing/unboxing.
Also, when you use for-comprehensions, your code is effectively stored in a method which is called for each element. So you are also making many method calls, which is another reason this is slower. Alas, someone wrote a plugin for Scala which optimizes at least one case of for-comprehensions to avoid that.
Using Array should make it work in about zero seconds with the right algorithm. This, for example, takes about 7 milliseconds on my system:
class Primes(bufsize: Int) {
var n = 1
val pbuf = new Array[Int](bufsize max 1)
pbuf(0) = 2
def isPrime(num: Int): Boolean = {
var i = 0
while (i < n && pbuf(i)*pbuf(i) <= num) {
if (num % pbuf(i) == 0) return false
i += 1
}
if (pbuf(i)*pbuf(i) < num) {
i = pbuf(i)
while (i*i <= num) {
if (num % i == 0) return false
i += 2
}
}
return true;
}
def fillBuf {
var i = 3
n = 1
while (n < bufsize) {
if (isPrime(i)) { pbuf(n) = i; n += 1 }
i += 2
}
}
def lastPrime = { if (n<bufsize) fillBuf ; pbuf(pbuf.length-1) }
}
object Primes {
def timedGet(num: Int) = {
val t0 = System.nanoTime
val p = (new Primes(num)).lastPrime
val t1 = System.nanoTime
(p , (t1-t0)*1e-9)
}
}
Result (on second call; first has some overhead):
scala> Primes.timedGet(10001)
res1: (Int, Double) = (104743,0.00683394)
I think you have to think out of the box :)
Because the problem is manageable, you can use Sieve of Eratosthenes to solve it very efficiently.
Here's a recursive solution (using the isPrime function from your first solution). It seems to be good Scala style to prefer immutability (i.e. to try not to use vars) so I've done that here (in fact there are no vars or vals!). I don't have a Scala installation here though so can't tell if this is actually any quicker!
def problem_7:Int = {
def isPrime_(n: Int) = (n % 6 == 1 || n % 6 == 5) && isPrime(n)
def process(n: Int, acc: List[Int]): Int = {
if (acc.size == 10001) acc.head
else process(n+1, if isPrime_(n) n :: acc else acc)
}
process(1, Nil)
}

Resources