For loops being skipped without cause in VBA - algorithm

My code, as written, works for all the ways I've tested it. I have two questions though. First, Why in the blue blazes do I HAVE to use Do While loops instead of For loops in my code? I've searched Everywhere I can to help me on this issue. I can't reinstall excel, but I've reset as many of the settings as I can, but, invariably, the compiler skips over every for loop I have that isn't a for each loop... Except the first for loop in my programming... It is the weirdest and most bizarre behavior I have ever seen. I have used step through (F8) 10000 times to try and figure out why it keeps skipping. But every single time i make a for loop, it doesn't even run the first line of it.
To be clear, every place I have a Do While ... Loop, it SHOULD be a For Next. But making this change breaks the code every time because every spot the do while is changed to for, the code is skipped entirely. Even if I reset the i value to 0. The issue happens even if I have a different iterator for each loop.
Running w8 on an Intel i5 with Office 2010.
For i=1 To i = 100
If (i >= startRow And i <= stopRow And Not rowDone(i) And Not i = colFocus) Then
colCurPayAmounts(i) = S_Debt.Cells(i, 5)
Else
colCurPayAmounts(i) = 0
End If i = i + 1
Next i

The problem is it should be For i = 1 To 100 and not For i = 1 To i = 100 #Rory

Related

Looking for a more efficient way to pull data from multiple datasets in SAS

I'm trying to find a more efficient and speedier way (if possible) to pull subsets of observations that meet certain criteria from multiple hospital claims datasets in SAS. A simplified but common type of data pull would look like this:
data out.qualifying_patients;
set in.state1_2017
in.state1_2018
in.state1_2019
in.state1_2020
in.state2_2017
in.state2_2018
in.state2_2019
in.state2_2020;
array prcode{*} I10_PR1-I10_PR25;
do i=1 to 25;
if prcode{i} in ("0DTJ0ZZ","0DTJ4ZZ") then cohort=1;
end;
if cohort=1 then output;
run;
Now imagine that instead of 2 states and 4 years we have 18 states and 9 years -- each about 1GB in size. The code above works fine but it takes FOREVER to run on our non-optimized server setup. So I'm looking for alternate methods to perform the same task but hopefully at a faster clip.
I've tried including (KEEP=) or (DROP=) statements for each dataset included the SET statement to limit the variables being scanned, but this really didn't have much of an impact on speed -- and, for non-coding-related reasons, we pretty much need to pull all the variables.
I've also experimented a bit with hash tables but it's too much to store in memory so that didn't seem to solve the issue. This also isn't a MERGE issue which seems to be what hash tables excel at.
Any thoughts on other approaches that might help? Every data pull we do contains customized criteria for a given project, but we do these pulls a lot and it seems really inefficient to constantly be processing thru the same datasets over and over but not benefitting from that. Thanks for any help!
I happend to have a 1GB dataset on my compute, I tried several times, it takes SAS no more than 25 seconds to set the dataset 8 times. I think the set statement is too simple and basic to improve its efficient.
I think the issue may located at the do loop. Your program runs do loop 25 times for each record, may assigns to cohort more than once, which is not necessary. You can change it like:
do i=1 to 25 until(cohort=1);
if prcode{i} in ("0DTJ0ZZ","0DTJ4ZZ") then cohort=1;
end;
This can save a lot of do loops.
First, parallelization will help immensely here. Instead of running 1 job, 1 dataset after the next; run one job per state, or one job per year, or whatever makes sense for your dataset size and CPU count. (You don't want more than 1 job per CPU.). If your server has 32 cores, then you can easily run all the jobs you need here - 1 per state, say - and then after that's done, combine the results together.
Look up SAS MP Connect for one way to do multiprocessing, which basically uses rsubmits to submit code to your own machine. You can also do this by using xcmd to literally launch SAS sessions - add a parameter to the SAS program of state, then run 18 of them, have them output their results to a known location with state name or number, and then have your program collect them.
Second, you can optimize the DO loop more - in addition to the suggestions above, you may be able to optimize using pointers. SAS stores character array variables in memory in adjacent spots (assuming they all come from the same place) - see From Obscurity to Utility:
ADDR, PEEK, POKE as DATA Step Programming Tools from Paul Dorfman for more details here. On page 10, he shows the method I describe here; you PEEKC to get the concatenated values and then use INDEXW to find the thing you want.
data want;
set have;
array prcode{*} $8 I10_PR1-I10_PR25;
found = (^^ indexw (peekc (addr(prcode[1]), 200 ), '0DTJ0ZZ')) or
(^^ indexw (peekc (addr(prcode[1]), 200 ), '0DTJ4ZZ'))
;
run;
Something like that should work. It avoids the loop.
You also could, if you want to keep the loop, exit the loop once you run into an empty procedure code. Usually these things don't go all 25, at least in my experience - they're left-filled, so I10_PR1 is always filled, and then some of them - say, 5 or 10 of them - are filled, then I10_PR11 and on are empty; and if you hit an empty one, you're all done for that round. So not just leaving when you hit what you are looking for, but also leaving when you hit an empty, saves you a lot of processing time.
You probably should consider a hardware upgrade or find someone who can tune your server. This paper suggests tips to improve the processing of large datasets.
Your code is pretty straightforward. The only suggestion is to kill the loop as soon as the criteria is met to avoid wasting unnecessary resources.
do i=1 to 25;
if prcode{i} in ("0DTJ0ZZ","0DTJ4ZZ") then do;
output; * cohort criteria met so output the row;
leave; * exit the loop immediately;
end;
end;

Windows batch card game not working properly, don't know how to fix

So for our computer science class, we had to write a program that randomly generates cards, i decided to do mine in batch, because im a massive noob XD
I was confident that i could do it as im quite experienced with it. Even though batch isn't by any means a good 'language' if your going to call it that. I was able to fix most of the problems by myself with some hard work. I am however, still having some issues i don't know how to resolve.
My biggest issues i don't know how to fix are...
Text not being displayed properly.
Numbers (i use for the base of the AI and card generation) sometimes not being defined properly in variables.
The point system just refuses to work not matter what i do.
It sometimes randomly just flat out decides to crash on me if i skip a 'TIMEOUT' or a 'PAUSE'.
Some 'IF' statements not being executed properly even though there exactly the same as the other ones.
I'm sorry if this question is too broad, but i really didn't know quite how to summarize it.
Here is a link to my card game: http://pastebin.com/t2S3yWk5
Here is our question:
1) Create a program that will generate two random numbers - one that maps to a suit (hearts,diamonds, clubs or spades) and one that maps to a card (Ace, 2, 3, ..... Jack, Queen, King)
*Mine is slightly different, it generates two different suits based on two random numbers.*
2) Create a program that will generate a random card and then ask the user to go Higher,Lower or Quit. If the player chooses Higher the next card must be of a higher value or theplayer is out. Likewise for Lower.
3)Extending the previous program, the user will select a trump suit at the start of the game. If the card is a trump suit card then the game continues regardless of the card’s value. The program will keep score and will save the score to a highscore file. The user will also be able to display the current highscore file.
I would like to try and do this stuff (listed above) myself. I just need help trying to fix my existing program.
I hope that if your reading this you could give me some advise or provide solutions to some of my problems. Thanks in advance! :3
Good news; nothing is super wrong with your code, it's just a bunch of little things that seem like a lot. Some off-by-one errors and a missing variable that I can only assume got replicated from copying and pasting.
Text not being displayed properly
I assume this is the "Access denied" errors that your code produces instead of the AI's comments. This is due to the fact that > and < are used for output redirection, so the emoticons you are adding are trying to create a file in a place you don't have access to. Either get rid of them (recommended) or use ^ to escape them (^>:)).
Numbers (I use for the base of the AI and card generation) sometimes not being defined properly in variables
%random% %% 5 results in one of the numbers in the set 0, 1, 2, 3, 4. You currently do not have an if statement for what should happen if 0 is randomly selected. Add an if statement or have the code go back to the top of the section if a 0 is selected.
The point system just refuses to work no matter what I do
You're going to kick yourself...
Your set statements are missing the assignment portion. SET /A %p1p% + 2 should be SET /A p1p=%p1p% + 2 and so forth (or set /a p1p+=2 if you think that looks better).
If sometimes randomly just flat out decides to crash on me if I skip a 'TIMEOUT' or 'PAUSE'
I couldn't replicate that, but the code seemed to work fine when I removed those statements.
Some 'IF' statements not being executed properly even though they're exactly the same as the other ones
Your comment indicated lines 119-132, which include the if statements that assign points. See above for why those aren't working.
Some other recommendations for your code
Your variable names should be more descriptive. For example, ctog doesn't tell me anything about what that variable should be; I can look at the code to see what it does, but without any context, that could be doing anything.
You should add the /i flag to the if statements that check which card you put down so that C1 and c1 get treated the same. On a related note, you should add a check for when the player enters something other than C1 or C2. You can even use a choice command like you did earlier.
:pvic is missing an exit command, so you automatically play again if you win. Combined with the fact that you only check if lt is equal to 2, not greater than or equal to 2, there's no way to stop playing if you win. Also on the subject of end game conditions, there's no if statement for if you tie the computer.
cp1 and num1 are effectively the same variable, there's no reason to have both (same with cp2/num2, ap1/num3, and ap2/num4).
You need some kind of goto at the end of :pc1 so that :pc2 doesn't automatically run after :pc1 finishes.

Lua for loop reduce i? Weird behavior [duplicate]

This question already has answers here:
Decrementing a loop counter as loop is executing
(3 answers)
Closed 7 years ago.
Can someone explain me this?
for i = 1, 5 do
print(i)
i = i - 1
print(i)
end
Output is:
1
0
2
1
3
2
and so forth
I exspected i to alter between 1 and 0. But obviously it keeps increasing as if I did not change it at all. What's going on?
I have to delete an i'th table element every now and then. So the next element to process would be i again. In C I would just write --i at the end of my loop content. Any official way in lua? :)
The loop index (i in your case) is a variable local to the body of the loop, so any modifications you do to it have no effect on the loop conditions or the next element being processed (for the for loop).
If you need to have better control over the index to delete elements and keep processing, you should use the while loop form. See For Statement section for details.
What about using a while(true) loop instead? Then you'll have to break manually, but that might work.
local i = 5
while(true) do
print(i)
i = i - 1
if (i == 0) then break; end
end
Attempting to set the loop control variable causes a failsafe behavior.
I can't find it in the Language Incompatibility section of recent versions of the manual but I recall it being listed somewhere as a change. It was more of a formalization of previous undefined behavior.
If you are really curious, see the listing of your program from luac. The loop control variable is given an internal name so it can't be changed. If the same name is used in an assignment, a local variable is synthesized as a stand-in. It prevents unintentionally causing the for to become infinite.
You need another kind of loop.

Loop generating geometry hangs, memory seems fine

if I generate Tubes in a loop like here
http://jsfiddle.net/crizzis/RYQty/1/
for (var y = 0; y < 800; y++){...}
The loop is starting to hang and will not finish, despite the main memory seems ok (Task Manager) and the GPU Memory seems to be fine as well.
It hangs in the loop where the tube geometry is generated. It is not even rendered.
Does anyone know how this can happen?
Strange thing is 700 loops are Performing within 5 seconds, 800 loops not at all or really, really slow.
Well, i just looked at your fiddle and i am not sure about your whole loop.
You are creating WAY too much stuff inside your loop. See for example the material. Just create it once outside the loop.
Then move the vector[0] and [1] definitions outside of the loop and inside the loop do vector[0].y = . So you don't create 2 Three.Vector3()-objects for every run. Also, move all variable declarations outside your loop. Just something like var line; and inside, you do line = SPline...
Next, why don't you just create the whole Spline inside the loop and then AFTER the loop, create ONE TubeGeometry afterwards instead of creating hundreds of meshes? Well, I don't know your usecase anyway.

How do I make a function happen 50% of the time in vb6

Making a small app, and I want a function to execute 50% of the time. So if I were to dbl click the exe half the time the function would execute, and the other half it wouldn't. I can't seem to find anyway to easily do this, the one solution I tried seemed to determine the chance on compile rather than on run. Thanks in advance!
Generate a random decimal number between 0 and 1. If it is greater than 0.5 run, if it is less than or equal to 0.5 do not run.
Don't forget to seed the randomizer! Otherwise it will always give you the same value every time. You seed it using "Randomize Timer", e.g.:
Private Sub Main()
Randomize Timer
If Rnd > 0.5 Then
ExecuteFunction ()
End If
End Sub
For example:
Private Sub Main()
If Rnd > 0.5 Then
ExecuteFunction ()
End If
End Sub
If you want it to randomly run, others have already provided that solution. If you want a more deterministic behavior (it must run exactly every second time), you will need to store state between executions.
You can save the state in either the registry or on the file system by (for example) attempting to read an integer from a file (set it to zero if the file's not there), add 1 and write it back to the same file.
If the number written back was even, run your function otherwise exit.
That way, you'll alternate between execute and don't-execute.

Resources