swift: Using or in a loop condition statement - swift

sorry for asking a simple question, but unfortunately after an hour debugging I am a bit lost. I want to use "or" in the condition of a repeat while loop. Unfortunately the code just leave the loop when the first condition is true, the second seams to be never checked.
Here is my code:
j=1
repeat {
if (Int(scores[1][j]) != 0) {
if (nrOfMoves < Int(scores[1][j])) {
positionToStore = j
positionFound = true
}
} else {
positionToStore = j
positionFound = true
}
j++
} while(positionFound == false || j > 5)
while is just leaving when positionFound is true when j reaches 6 it just repeats or bette terminates by an exception

From documentation:
Repeat-While
The other variation of the while loop, known as the repeat-while loop,
performs a single pass through the loop block first, before
considering the loop’s condition. It then continues to repeat the loop
until the condition is false.
It meens that your loop works only when condition positionFound == false || j > 5 is false. When positionFound set to true, condition becomes true and you leave the loop.
In your situation you need to use while loop
From documentation:
While
A while loop starts by evaluating a single condition. If the condition
is true, a set of statements is repeated until the condition becomes
false.
Here’s the general form of a while loop:
while positionFound == false || j > 5 {
if (Int(scores[1][j]) != 0) {
if (nrOfMoves < Int(scores[1][j])) {
positionToStore = j
positionFound = true
}
} else {
positionToStore = j
positionFound = true
}
j++
}

The condition in a repeat-while loop tells what needs to happen for the loop to continue. You want to loop while j <= 5 so that it drops out of that loop when j reaches 6. Also, you need to continue when both conditions hold, so in this case you should use && instead of ||. With this change, the code then reads "continue looping as long as I haven't found what I'm looking for AND my index is still good":
j=1
repeat {
if (Int(scores[1][j]) != 0) {
if (nrOfMoves < Int(scores[1][j])) {
positionToStore = j
positionFound = true
}
} else {
positionToStore = j
positionFound = true
}
j++
} while(positionFound == false && j <= 5)
A common shorthand way of writing positionFound == false is !positionFound and is pronounced "not positionFound".

Related

sorting dates if timestamp is greater than zero

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...]

swift: about ternary operator Question. Why my code is error code??? Please tell me why I'm wrong

swift: about ternary operator Question. Why my code is error code??? Please tell me why I'm wrong.
var arr = [0,1,2,3,4,5,6,7,8]
var result = 0;
for a in 0..<arr.count{
for b in 1..<arr.count - 1{
for c in 2..<arr.count - 2 {
arr[a] + arr[b] + arr[c] <= input[1] ? result = arr[a] + arr[b] +arr[c] : continue
}
}
}
[this is my error]
[1]: https://i.stack.imgur.com/UdiUB.png
In Swift, the ternary condition operator is an expression which takes the form
<condition> ? <expression if true> : <expression if false>
Expressions are part of larger statements, and the ternary specifically is one which evaluates to either the expression after the ?, or the one after the : depending on the truth of the condition.
continue, however, is not an expression but a statement on its own, which means that it cannot be on either side of the ternary.
Thinking about this another way: expressions evaluate to some value (e.g., can be put on the right-hand-side of an assignment, like x = <some expression>), while statements do not (e.g., it doesn't make sense to write x = continue).
You will need to express this in the form of a regular if-statement then:
if arr[a] + arr[b] + arr[c] <= input[1] {
result = arr[a] + arr[b] +arr[c]
} else {
continue
}
Note that the above code might be grammatically correct (in that it will compile), but it is unlikely to be what you mean: the loop will automatically continue at the end of execution even if arr[a] + arr[b] + arr[c] <= input[1] by default, which means that your result may get overwritten later in the loop. It seems likely that you mean something like
outer_loop: for a in 0 ..< arr.count {
for b in 1 ..< arr.count - 1 {
for c in 2 ..< arr.count - 2 {
if arr[a] + arr[b] + arr[c] <= input[1] {
result = arr[a] + arr[b] + arr[c]
// `break` would only exit the `c` loop, but with this label
// we can exit all loops at once.
break outer_loop
}
}
}
}

How to print ONCE if there are multiple correct answers? (MATLAB)

So I have arr = randi([0,20],20,1). I want to show: If there are numbers less than 5, fprintf('Yes\n') only once. Im using a for loop (for i = 1 : length(arr)) and indexing it.
As your description, maybe you need if statement within for loop like below
for i = 1:length(arr)
if arr(i) < 5
fprintf('Yes\n');
break
end
end
If you want to print Yes once, you can try
if any(arr < 5)
fprintf('Yes\n')
endif
If you don't want to use break, the code below might be an option
for i = 1:min(find(arr <5))
if (arr(i) < 5)
fprintf('Yes\n');
end
end
You can use a break statement upon finding the first value under 5 and printing the Yes statement.
Using a break Statement:
arr = randi([0,20],20,1);
for i = 1: length(arr)
if arr(i) < 5
fprintf("Yes\n");
break;
end
end
Extension:
By Using any() Function:
Alternatively, if you'd like to concise it down without the need for a for-loop the any() function can be used to determine if any values within the array meet a condition in this case arr < 5.
arr = randi([0,20],20,1);
if(any(arr < 5))
fprintf("Yes\n");
end
By Using a While Loop:
Check = 0;
arr = randi([0,20],20,1);
i = 1;
while (Check == 0 && i < length(arr))
if arr(i) < 5
fprintf("Yes\n");
Check = 1;
end
i = i + 1;
end

Skip to index in for-in loop

Let's say I have a for-in loop like this:
for index in 1...5 {
}
And let's say that I find that, at index 2, I want to skip to index 4 due to some condition. The following does not work:
for index in 1...5 {
if index == 2 {
index = 4
}
}
Because it gives me the following error:
Cannot assign to value: 'index' is a 'let' constant
How can I modify the position of the index to skip to index 4?
In a for loop, you cannot jump the index in real time - that is, if you discover once the loop has started that you need to skip an iteration, you can't. But you can duck out of an iteration with continue. So for example:
var skip = 0
for i in 1...5 {
if i < skip { continue }
print(i)
if i == 2 { skip = 4}
}
In a situation like this, however, you might be happier with a while loop.
var i = 1
while i <= 5 {
print(i)
i += 1
if i == 3 { i = 4 }
}
Another possibility is to unroll the original for loop into a while loop:
var r = (1...5).makeIterator()
while let i = r.next() {
print(i)
if i == 2 { r.next() }
}
All of those are ways of printing 1,2,4,5.

Identify prime number

For some reason, it always gave me the wrong result. It's always isItPrime = true no matter what number was assigned to the "number" variable.
This is my code:
let number = 6
var i = 1
var isItPrime: Bool?
while i < number {
if number % i == 0 {
isItPrime = false
} else {
isItPrime = true
}
i += 1
}
print(isItPrime)
Can somebody explain to me what's wrong with my code and why the isItPrime bool outputs always true ?
Problem 1
The last iteration of your while loop
while i < number {
if number % i == 0 {
isItPrime = false
} else {
isItPrime = true
}
i += 1
}
does overwrite the result.
So you always end up with the following result
if number % (number-1) == 0 {
isItPrime = false
} else {
isItPrime = true
}
Problem 2
Finally every number can be divided by 1, so you should start i from 2.
So
let number = 6
var i = 2
var isItPrime = true
while i < number {
if number % i == 0 {
isItPrime = false
break
}
}
print(isItPrime)
Refactoring
You can write a similar logic using Functional Programming
let number = 5
let upperLimit = Int(Double(number).squareRoot())
let isPrime = !(2...upperLimit).contains { number % $0 == 0 }
Because isItPrime is overwritten in subsequent iterations, the last number which is checked, which is number - 1 will always set isItPrime to true, because number and number - 1 are coprime.
Instead of saving the value to a boolean, just end the loop when you found out that the number is not a prime:
let number = 6
var isItPrime: Bool = true
for i in 2 ..< number {
if number % i == 0 {
isItPrime = false
break // end the loop, as we know that the number is not a prime.
}
}
print(isItPrime)
When dealing with problems like this, don't be afraid to take out a piece of paper and manually see what is going on in your loop.
Your loop will go from i = 1 to number = 5 (because of the < operator.
With that in mind, we perform each iteration manually.
for i = 1, number = 6
6 mod 1 = 0, isItPrime = false
for i = 2, number = 6
6 mod 2 = 0, isItPrime = false
for i = 3, number = 6
6 mod 3 = 0, isItPrime = false
for i = 4, number = 6
6 mod 4 = 2, isItPrime = true
Last iteration of the loop, for i = 5, number = 6
6 mod 5 = 1, isItPrime = true
There we can see that the problem is that the last iteration will always have a module of 1, therefore resulting in in your else clause getting executed.
It is always returning true because your while loop isn't working the way you want. Currently, it loops until i is 1 less than number. During that final run through the loop, number % i == 0 is false, so your code sets isItPrime to true.
To fix this problem, try this code:
let number = 6
var i = 2
var isItPrime: Bool?
while (i < number || isItPrime == false) {
if number % i == 0 {
isItPrime = false
} else {
isItPrime = true
}
i += 1
}
print(isItPrime)
You may have noticed I set i to 2, because any number modulo (%) 1 is 0
I think it's worth pointing out, however, that:
You should probably make this a method
If you initially set isItPrime to true, you can dispense with the else part of your if-else statement
Hope this helps!
// MARK: - Function
func primeNo(_ num:Int,_ divisor :Int = 2){
if divisor == num{
print("Num is prime")
}else{
if num%divisor != 0{
primeNo(num, divisor + 1)
}else{
print("num is not prime")
}
}
}
// MARK: - Use
primeNo(6)
out Put
num is not prime