Return/break out of infinite foreach in kotlin - foreach

For class I have to make a program that calculates the birthday problem
Now I'm having trying to learn kotlin at the same time and I'm having trouble with a little snippet of code:
val checkSet = mutableSetOf<Int>()
generateSequence{ Random.nextInt(n)}.forEach {
if(!checkSet.add(it)) {
return#outForeach
}
}
outForeach#
sum += checkSet.size
As you can see I'm trying to do this with an infinite sequence. Kotlin doesn't accept this as outForeach is an unresolved reference. But this doesn't work either:
val checkSet = mutableSetOf<Int>()
generateSequence{ Random.nextInt(n)}.forEach {
if(!checkSet.add(it)) {
return#forEach
}
}
sum += checkSet.size
This will just start the forEach loop again. Is there a way to implement something as a forEachUntil or so?
p.s. I'm aware that this looks a lot like this question: 'return' doesn't jump out of forEach in Kotlin It's just that I don't really get the answers and I don't know if its applicable here. Also a way to implement forEachUntil seems for me to be far more elegant

Alternatives you may want to consider instead of first:
using a simple while without body:
while (checkSet.add(Random.nextInt(n))); // <- that semicolon is required! otherwise you execute what is coming next within the while
using run with a label:
run outForeach#{
generateSequence{ Random.nextInt(n)}.forEach {
if(!checkSet.add(it)) {
return#outForeach
}
}
}
maybe also takeWhile might be helpful. In this specific case however it is surely not (as it would check against the checkSet and leave us with a sequence that isn't consumed... but if the condition would be different, it may make sense to consider something like take, takeWhile, takeLast, etc.):
generateSequence { Random.nextInt(n) }
.takeWhile(checkSet::add) // as said: for this specific condition it doesn't make sense...
.forEach { /* do nothing except consume the sequence */ } // the same values you added to the set would be available in this step of course

I think I found the solution myself:
val checkSet = mutableSetOf<Int>()
generateSequence{ Random.nextInt(n)}.first { !checkSet.add(it) }
sum += checkSet.size
Basically use the function first() and keep returning false until you want to get out of the loop. And just drop the return of the function first()

Related

What is a less verbose way to repeatedly pop() items from a vector?

When using a vector as a stack (storing states which are pushed and popped).
while stack.len() != 0 {
let state = stack.pop().unwrap();
// ... optionally push other states onto the stack.
}
Is there a less verbose way to do this in Rust?
You can use the fact that pop() returns an Option<T> and match on that using a while let loop:
while let Some(state) = stack.pop() {
// ... fine to call stack.push() here
}
The while let desugars to something like the following:
loop {
match stack.pop() {
Some(state) => {
// ... fine to call stack.push() here
}
_ => break
}
}
Just to offer an alternative approach, you can also use the drain method to remove elements and give them to you in an Iterator.
stack.drain(..).map(|element| ...and so on
or
for element in stack.drain(..) {
//do stuff
}
You can also provide a RangeArgument if you only want to remove a certain range of elements. This can be provided in the form of <start-inclusive>..<end-exclusive>. Both the start and end of the range argument are optional and just default to the start of end of the vector, so calling drain(..) just drains the entire vector, while drain(2..) would leave the first 2 elements in place and just drain the rest.

how do i declare variables, compare them and then use them inside a function

i am developing an ea that requires me to compare the high of previous 2 bars and whichever one is higher, use that as a stop loss value.
same for opposite side trades, i need to compare previous 2 lows and use the lower one as stop loss value.
what i am doing is this:-
void onTick()
{
static int ticket=0;
double ab=(//calculation for ab);
double de=(//calculation for de);
if(Low[1]<Low[2])
double sll=Low[1];
if(Low[1]>Low[2])
double sll=Low[2];
if(buy logic comes here)
{
double entryPrice=////////;
double stoploss=sll-xyz;
double takeprofit=entryPrice+((entryPrice-stoploss)*3);
ticket = OrderSend(Symbol(),...entryPrice,stoploss,takeprofit,.....);
}
if(ticket == false)
{
Alert("Order Sending Failed");
}
}
the problem is i am not able to reference the values of sll and get an error message saying "sll undeclared identifier"
i am fairly new to programming and would appreciate if someone can help me out with this.
I have added most of the code for you to understand the logic.
you would have to declare them outside the scope of the if statements if you want to use variables anywhere else so instead of doing that take a look at this
double sll; // declare sll outside the if statements
if(Low[1]<Low[2])
sll=Low[1];
if(Low[1]>Low[2])
sll=Low[2];
if(buy logic comes here)
{
bool res = OrderSend(..........);
}
Judging by what you wrote, it looks like you may be using res somewhere else too which then you need to define outside of the if statement because scoping.

run function depending on passed integer in swift

I want to run different functions depending on selected level Integer
so if selected level is 1 then runfunc1(), if 2 then runfunc2()...
I know this is possible using if else
if levelselected == 1 {
runfunc1()
} else if levelseletecd == 2 {
runfunc2()
// ... and so on
}
Is there any better way than this, perhaps something like this
runfunc%i(),levelselected // I know its not correct but something similar
I dont want to write new code for every level, so any better way?
You can use something like:
var levelSelected = 0 //
var selector = Selector("runFunc\(levelSelected)")
if self.respondsToSelector(selector) {
NSThread.detachNewThreadSelector(selector, toTarget: self, withObject: nil)
}
You could have an array or dictionary of functions. A dictionary might be nicer since the logic for checking if the level is valid is a lot simpler:
let funcs = [1: runfunc1, 2: runfunc2]
if let funcToRun = funcs[levelselected] {
funcToRun()
}
However, you won't be able to easily dynamically build a function name from strings and numbers without using #objc functionality.
(except in the sense that you could make the key to the dictionary a string of the function name, but you still have to build the dictionary using actual function names determined at compile time)
That said, you can add to the funcs variable from elsewhere in the code so it does mean to can "hook up" new levels without changing this dispatching logic.
Not the exact solution you are looking for but this can make it easier :
Declare an array of the desired functions:
var levelFunctions: [()->()] = [runfunc1, runfunc2, runfunc3]
This syntax declares an array of functions that have zero argument and return nothing. You initialize this array with the required function names and then execute the desired function using the levelselected variable:
levelFunctions[levelselected]() // Or levelselected-1 if the variable is not zero-based
EDIT:
As Airspeed Velocity mentioned in the comment and his answer you should make sure the level is in the array bounds.
I prefer to create a function, for example runFuncFromLevel::Int -> (() -> Void). runFuncFromLevel return a proper function that you need.
func runFuncFromLevel(level: Int) -> () -> Void
{
switch level
{
case 1: return runfunc1
case 2: return runfunc2
default: return {}
}
}

Swift: Random number arrays inside images and variables with a for loop

I am creating a game in which, depending on the number of 'swipes' chosen to do, (let's say 3), 3 different patterns show on the screen, one by one. I am working on developing the first pattern.
So I have this:
if (swipes.no_of_swipes) == 3 {
swipeArray = Array<UInt32>(count: 3, repeatedValue: 0)
for i in 0 ..< 3 {
swipeArray[i] = arc4random_uniform(84)}
}
As far as I am aware, this code creates an array with three UInts which can be accessed by doing swipeArray[0], swipeArray[1], and swipeArray[2]. My first question is how long will this swipeArray stay the same? Until the close the view? Should I have a 'refresh button' when the user loses - and if so, how would I make one?
Then I have a property observer. You will notice the for loop, which I am using to keep code concise. I understand that I could do something like x++ somewhere in here so that it will go through each one.
var playBegin: Bool = false{
didSet {
if playBegin == true {
println("\(playBegin)")
var swipes = Menu()
if (swipes.no_of_swipes) == 3 {
for i in 0 ..< 3 {
patternRoom.image = UIImage(named: "pattern\(swipeArray[x])")
//rest of code
}
}
}
The pattern image comes from a set of 84 images named like pattern7 and pattern56. My second question is, how could I code the for loop to go through each swipeArray[x].
Thank you in advance,
Will
how long will this swipeArray stay the same?
This is a bit too open ended. It’ll stay the same until you assign a new value to it, either from this same bit of code or a different part. Only you can know when that will be, by looking at your code.
Since you express an interest in keeping the code concise, here’s a couple of code tips.
You might think about writing your first snippet’s loop like this:
swipeArray = (0..<swipes.no_of_swipes).map { _ in
arc4random_uniform(84)
}
This combines creating a new array and populating the values. By the way, just in case you don’t realize, there’s no guarantee this array won’t contain the same value twice.
It’s also probably better to make swipeArray of type [Int] rather than [UInt32], and to convert the result of arc4random to an Int straight away:
Int(arc4random_uniform(84))
Otherwise the UInt32s will probably be a pain to work with.
For your second for loop, you can do this:
for i in swipeArray {
patternRoom.image = UIImage(named: "pattern\(i)")
// rest of code
}
When writing Swift, usually (but not always), when you find yourself using array[x] there’s a better more expressive way of doing it.

What is the recommended way to break out of a block or stop the enumeration?

So, I just realize that break is only for loop or switch.
Here's my question: Is there a recommended way to break out of a block? For example:
func getContentFrom(group: ALAssetsGroup, withAssetFilter: ALAssetsFilter) {
group.enumerateAssetsUsingBlock { (result, index , stop) -> Void in
//I want to get out when I find the value because result contains 800++ elements
}
}
Right now, I am using return but I am not sure if this is recommended. Is there other ways? Thanks folks.
return is fine, block concept is similar to function, so returning is okay.
If you want to stop the current iteration of the enumeration, simply return.
But you say:
I want to get out when I find the value because result contains 800++ elements
So, that means that you want to completely stop the enumeration when you find the one you want. In that case, set the boolean value that the pointer points to. Or, a better name for that third parameter would be stop, e.g.:
func getContentFrom(group: ALAssetsGroup, withAssetFilter: ALAssetsFilter) {
group.enumerateAssetsUsingBlock() { result, index, stop in
let found: Bool = ...
if found {
//I want to get out when I find the value because result contains 800++ elements
stop.memory = true
}
}
}

Resources