sorting dates if timestamp is greater than zero - swift

I'm trying to sort dates from oldest to most recent but I want timestamps that are zero to be at the bottom of the sorted list. Only dates that are greater than zero should be sorted and at the top of the list.
The issue I have is that timestamps that are zero show up at the top... how do I ignore zero timestamps and put them at the bottom and give the timestamps that are greater > 0 priority on the list ?
Here's what I have:
//DATE SORT
self.tasklist.sort { $0.onsiteThreshold < $1.onsiteThreshold }
self.tasklist.sort { $0.resolutionThreshold < $1.resolutionThreshold }
self.tasklist.sort { $0.scheduleDateTime < $1.scheduleDateTime }
self.tasklist.sort { (o1, o2) -> Bool in
if o1.onsiteThreshold == 0 || o2.onsiteThreshold == 0 || o1.resolutionThreshold == 0 || o2.resolutionThreshold == 0 || o1.scheduleDateTime == 0 || o2.scheduleDateTime == 0 {
return false
}
return true
}

Sorting an array four(!) times is pretty expensive.
A more efficient way is first to move all items which contain zero properties to the end of the list with partition(by:). This API is part of Standard Library but doesn't preserve the order of the left side, therefore the partition must take place first.
let partitionIndex = tasklist.partition(by: {$0.onsiteThreshold == 0 || $0.resolutionThreshold == 0 || $0.scheduleDateTime == 0})
Then sort the left side tasklist[0..<partitionIndex] by all three properties and append the right side.
let sorted = tasklist[0..<partitionIndex].sorted { (lhs, rhs) in
if lhs.scheduleDateTime == rhs.scheduleDateTime {
if lhs.resolutionThreshold == rhs.resolutionThreshold {
return lhs.onsiteThreshold < rhs.onsiteThreshold
}
return lhs.resolutionThreshold < rhs.resolutionThreshold
}
return lhs.scheduleDateTime < rhs.scheduleDateTime
}
taskList = sorted + tasklist[partitionIndex...]

Related

Speeding up Swift CodeFight Challenge

Per Codefighters:
Note: Write a solution with O(n) time complexity and O(1) additional space complexity, since this is what you would be asked to do during a real interview.
Given an array a that contains only numbers in the range from 1 to a.length, find the first duplicate number for which the second occurrence has the minimal index. In other words, if there are more than 1 duplicated numbers, return the number for which the second occurrence has a smaller index than the second occurrence of the other number does. If there are no such elements, return -1.
Example
For a = [2, 3, 3, 1, 5, 2], the output should be firstDuplicate(a) = 3.
There are 2 duplicates: numbers 2 and 3. The second occurrence of 3 has a smaller index than than second occurrence of 2 does, so the answer is 3.
For a = [2, 4, 3, 5, 1], the output should be firstDuplicate(a) = -1.
So here is what I came up with. It works but fails on the final test because it ran over 4000ms. I am stuck to what else I can do. Any Ideas to improve speed?
func firstDuplicate(a : [Int]) -> Int {
var duplicateIndexArray = [Int]()
for firstIndex in 0..<a.count {
for secondIndex in 0..<a.count {
if a[firstIndex] == a[secondIndex] && firstIndex != secondIndex {
print(firstIndex, secondIndex)
if !(duplicateIndexArray.contains(firstIndex)){
duplicateIndexArray.append(secondIndex)
break
}
}
}
}
// Check for duplicacy
if duplicateIndexArray.count > 0 {
print(duplicateIndexArray)
return a[duplicateIndexArray.min()!]
}
return -1
}
The O(n) time part is easy, but the O(1) additional space is a bit tricky. Usually, a hash set (or bit array in your case) can be used to check if a number occurred more than once, but that requires O(n) additional space. For O(1) additional space, we can use the source array itself as a bit array by making some of the numbers in it negative.
For example if the first number in the array is 3, then we make the number at position 3-1 negative. If one of the other numbers in the array is also 3, we can check if the number at position 3-1 is negative.
I don't have any experience with Swift, so I'll try to write a function in pseudocode:
function firstDuplicate(a)
result = -1
for i = 0 to a.count - 1
if a[abs(a[i])-1] < 0 then
result = a[i]
exit for loop
else
a[abs(a[i])-1] = -a[abs(a[i])-1]
// optional restore the negative numbers back to positive
for i = 0 to a.count - 1
if a[i] < 0 then
a[i] = -a[i]
return result
Replace this line
for secondIndex in 0..<a.count
with
for secondIndex in firstIndex..<a.count
There is no requirement of double checking
So Your Final code is
func firstDuplicate(a : [Int]) -> Int {
var duplicateIndexArray = [Int]()
for firstIndex in 0..<a.count {
for secondIndex in firstIndex..<a.count {
if a[firstIndex] == a[secondIndex] && firstIndex != secondIndex {
print(firstIndex, secondIndex)
if !(duplicateIndexArray.contains(firstIndex))
{
duplicateIndexArray.append(secondIndex)
break
}
}
}
}
// Check for duplicacy
if duplicateIndexArray.count > 0
{
print(duplicateIndexArray)
return a[duplicateIndexArray.min()!]
}
return -1
}
func firstDuplicate(input: [Int]) -> Int{
var map : [String : Int] = [:]
var result = -1
for i in 0 ..< input.count {
if map["\(input[i])"] != nil {
result = i
break
}
else {
map["\(input[i])"] = i
}
}
return result
}

speed up prime number generating

I have written a program that generates prime numbers . It works well but I want to speed it up as it takes quite a while for generating the all the prime numbers till 10000
var list = [2,3]
var limitation = 10000
var flag = true
var tmp = 0
for (var count = 4 ; count <= limitation ; count += 1 ){
while(flag && tmp <= list.count - 1){
if (count % list[tmp] == 0){
flag = false
}else if ( count % list[tmp] != 0 && tmp != list.count - 1 ){
tmp += 1
}else if ( count % list[tmp] != 0 && tmp == list.count - 1 ){
list.append(count)
}
}
flag = true
tmp = 0
}
print(list)
Two simple improvements that will make it fast up through 100,000 and maybe 1,000,000.
All primes except 2 are odd
Start the loop at 5 and increment by 2 each time. This isn't going to speed it up a lot because you are finding the counter example on the first try, but it's still a very typical improvement.
Only search through the square root of the value you are testing
The square root is the point at which a you half the factor space, i.e. any factor less than the square root is paired with a factor above the square root, so you only have to check above or below it. There are far fewer numbers below the square root, so you should check the only the values less than or equal to the square root.
Take 10,000 for example. The square root is 100. For this you only have to look at values less than the square root, which in terms of primes is roughly 25 values instead of over 1000 checks for all primes less than 10,000.
Doing it even faster
Try another method altogether, like a sieve. These methods are much faster but have a higher memory overhead.
In addition to what Nick already explained, you can also easily take advantage of the following property: all primes greater than 3 are congruent to 1 or -1 mod 6.
Because you've already included 2 and 3 in your initial list, you can therefore start with count = 6, test count - 1 and count + 1 and increment by 6 each time.
Below is my first attempt ever at Swift, so pardon the syntax which is probably far from optimal.
var list = [2,3]
var limitation = 10000
var flag = true
var tmp = 0
var max = 0
for(var count = 6 ; count <= limitation ; count += 6) {
for(var d = -1; d <= 1; d += 2) {
max = Int(floor(sqrt(Double(count + d))))
for(flag = true, tmp = 0; flag && list[tmp] <= max; tmp++) {
if((count + d) % list[tmp] == 0) {
flag = false
}
}
if(flag) {
list.append(count + d)
}
}
}
print(list)
I've tested the above code on iswift.org/playground with limitation = 10,000, 100,000 and 1,000,000.

for in loop with where clause in Swift

I have tried to update a little function to Swift 2.1. The original working code was:
import func Darwin.sqrt
func sqrt(x:Int) -> Int { return Int(sqrt(Double(x))) }
func sigma(n: Int) -> Int {
// adding up proper divisors from 1 to sqrt(n) by trial divison
if n == 1 { return 0 } // definition of aliquot sum
var result = 1
let root = sqrt(n)
for var div = 2; div <= root; ++div {
if n % div == 0 {
result += div + n/div
}
}
if root*root == n { result -= root }
return (result)
}
print(sigma(10))
print(sigma(3))
After updating the for loop I get a runtime error for the last line. Any idea why that happens?
import func Darwin.sqrt
func sqrt(x:Int) -> Int { return Int(sqrt(Double(x))) }
func sigma(n: Int) -> Int {
// adding up proper divisors from 1 to sqrt(n) by trial divison
if n == 1 { return 0 } // definition of aliquot sum
var result = 1
let root = sqrt(n)
for div in 2...root where n % div == 0 {
result += div + n/div
}
if root*root == n { result -= root }
return (result)
}
print(sigma(10))
print(sigma(3)) //<- run time error with for in loop
When you pass 3 to sigma, your range 2...root becomes invalid, because the left side, the root, is less than the right side, 2.
The closed range operator (a...b) defines a range that runs from a to b, and includes the values a and b. The value of a must not be greater than b.
root is assigned sqrt(n), which means that in order for the 2...root range to remain valid, n must be above 22.
You can fix by supplying a lower limit for the right side, i.e.
for div in 2...max(root,2) where n % div == 0 {
...
}
However, at this point your solution with the regular for loop is more readable.

finding the left substring is equal to right substring

Write a function which given a string S returns the index (counting from 0) of character such that the substring on its left is a reversed susbstring on its right (or -1 if such an index does not exist).
For example, given a string
racecar
Function should return 3, because the substring on the left of the character e at index 3 is rac, and the one on the right is car.
get the length/2 and verify lengths first and then if the lengths are same then reverse the first half and compare with the second.
Example function:
private int TestMethod1(string str)
{
if (str.Length > 0)
{
if (str.Length % 2 != 0)
{
string strFront = string.Empty;
for (int i = (str.Length / 2) - 1; i >= 0; i--)
{
strFront += str.Substring(i, 1);
}
if (strFront.Equals(str.Substring((str.Length / 2) + 1)))
{
return str.Length / 2;
}
}
}
return -1;
}

multiple instance if statement in xcode (iphone)

what is the proper way to do If statement with two variable in Xcode for Iphone
currently I have
if (minute >0) && (second == 0) {
minute = minute - 1;
second = 59;
}
The same was you would do it in any C/C++/Objective-C compiler, and most Algol derived languages, and extra set of parenthesis in order to turn to seperate boolean statements and an operator into a single compound statement:
if ((minute > 0) && (second == 0)) {
minute = minute - 1;
second = 59;
}
You'll need another set of parenthesis:
if ((minute >0) && (second == 0)) {
minute = minute - 1;
second = 59;
}
Or you could also write:
if (minute > 0 && second == 0)
Which is what you'll start doing eventually anyway, and I think (subjective) is easier to read. Operator precedence insures this works...