Conditionally change the direction of a "for loop"? - actionscript-3

Is it possible to conditionally change the direction of a for loop in ActionScript?
Example:
for(if(condition){var x = 0; x<number; x++}else{var x=number; x>0; x--}){
//do something
}

Interesting requirement. One way to keep the for is:
var start, loop_cond, inc;
if(condition)
{
start = 0;
inc = 1;
loop_cond = function(){return x < number};
}
else
{
start = number - 1;
inc = -1;
loop_cond = function(){return x >= 0};
}
for(var x = start; loop_cond(); x += inc)
{
// do something
}
We setup the start value, a function for the termination condition, and either a positive or negative increment. Then, we just call the function and use += to the do the increment or decrement.

ActionScript has the ternary operator, so you could do something like:
for (var x = cond ? 0 : number; cond ? x < number : x > 0; cond ? x++ : x--) {
}
But this is pretty ugly. :-)
You might also need/want to put some parens around pieces of that. I'm not sure about the operator precedence.
You might also consider using a higher order function. Imagine you have:
function forward (count, func) {
for (var x = 0; x < count; x++) {
func(x);
}
}
function backward (count, func) {
for (var x = count - 1; x >= 0; x--) {
func(x);
}
}
Then you could do:
(condition ? forward : backward) (number, function (x) {
// Your loop code goes here
})

You probably want a while loop instead:
var continueLooping, x;
if(condition)
{
x = 0
continueLooping = (x < number);
}
else
{
x = number;
continueLooping = (x > 0);
}
while (continueLooping)
{
// do something
if(condition)
{
x++;
continueLooping = (x < number);
}
else
{
x--;
continueLooping = (x > 0);
}
}
If you really want a for loop, you should use two of them:
function doSomething()
{
//doSomething
}
if(condition)
{
for(var x = 0; x<number; x++)
{
doSomething(x);
}
}
else
{
for(var x=number; x>0; x--})
{
doSomething(x);
}
}

Related

Moving objects on the stage

Let's say I have 5 objects in an array and I move all them along x-axis like this:
vx = 5;
for (i:int = 0; i < objects.length; i++)
{
objects[i].x += vx;
}
I would like to make this.
If any object from array 'objects' hit PointA, move all objects from that array to left side, for example set vx *= -1;
I can make only this:
for (i:int = 0; i < objects.length; i++)
{
// move right
objects[i].x += vx;
if (objects[i].hitTest(PointA))
{
// move left
vx *= -1;
}
}
This will change object's direction, but I need to wait all objets hit PointA.
How to change the direction of all objects in array, if any of them hit PointA?
I don't know action script but you should set a boolean outside the for loop, like bGoingRight
Check that this is true and move objects right, if its false move the objects left. When you pass the hitTest you should changed the boolean to false.
Rough Example
var bGoRight:Boolean = true;
for (i:int = 0; i < objects.length; i++)
{
if(bGoRight)
{
// move right
objects[i].x += vx;
}
else
{
// move left
vx *= -1;
}
if (objects[i].hitTest(PointA))
{
// if any object hit the point, set the flag to move left
bGoRight = false;
}
}
So you'll need to check the objects that have already hit PointA, store them, then check if the updated storage count is equivalent to your objects array. Then when that case is satisfied you can change the vx variable. This could look something like this:
//set a variable for storing collided object references
//note: if you are doing this in the IDE remove the 'private' attribute
private var _contactList:Array = [];
for (i:int = 0; i < objects.length; i++)
{
// move right
objects[i].x += vx;
if (objects[i].hitTest(PointA))
{
if( contactList.length == objects.length ) {
// move left
vx *= -1;
//clear our contact list
contactList.length = 0;
}
else if ( noContact( objects[i] ) ) {
contactList.push( objects[i] );
}
}
}
Then the function in the else if statement noContact(), again if you are doing this in the IDE you will need to remove the private attribute.
private function noContact( obj:* ):Boolean {
if ( contactList.indexOf( obj ) != -1 ) {
return false;
}
return true;
}
Another way you can do this is like this (a boolean way as stated in the other answer), but is reliant on your storage setup correct:
//set this variable for directionRight (boolean)
private var directionRight:Boolean = true;
for (i:int = 0; i < objects.length; i++)
{
// move right
objects[i].x += vx;
if (objects[i].hitTest(PointA))
{
//we are moving to the right, object[i] is the last object
if( i == objects.length-1 && directionRight ) {
// move left
directionRight = !directionRight;
vx *= -1;
}
else if ( i == 0 && !directionRight ) ) {
// move right
directionRight = !directionRight;
vx *= -1;
}
}
}

% operator seems not working in google apps script

I want to count the number of 3 consecutive wins of team A and B. It seems to be always getting into the final ifs. Not when consecutivas equals 3,6,9...
var consecutivasA = 0;
var consecutivasB = 0;
var plusA = 0;
var plusB = 0;
for (var i = 2; i <= 30; i++) {
var row = values[i];
if (row[3] > row[4]) {
consecutivasA++;
consecutivasB = 0;
}
else if (row[3] < row[4]) {
consecutivasB++;
consecutivasA = 0;
}
else {
consecutivasA = 0;
consecutivasB = 0;
}
if (consecutivasB % 3 == 0) { plusB++; }
if (consecutivasA % 3 == 0) { plusA++; }
The way you do it you also increment when consecutivas is 0, because 0 % 3 is also 0. This example writes the outcome of the example data to the log.
function consecutivasMod () {
var consecutivasA = 0;
var consecutivasB = 0;
var plusA = 0;
var plusB = 0;
values=[
[0,0,0,1,0], [0,0,0,1,0], [0,0,0,1,0], [0,0,0,0,1], [0,0,0,0,1],
[0,0,0,0,1], [0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,0], [0,0,0,0,2],
[0,0,0,0,3], [0,0,0,0,4], [0,0,0,0,5], [0,0,0,0,6], [0,0,0,0,7],
]
for (var i = 0; i < 15; i++) {
var row = values[i];
if (row[3] > row[4]) {
consecutivasA++;
consecutivasB = 0;
}
else if (row[3] < row[4]) {
consecutivasB++;
consecutivasA = 0;
}
else {
consecutivasA = 0;
consecutivasB = 0;
}
if (consecutivasB>0&&(consecutivasB % 3) == 0) { plusB++; }
if (consecutivasA>0&&(consecutivasA % 3) == 0) { plusA++; }
}
Logger.log ("consecutivasA "+plusA);
Logger.log ("consecutivasB "+plusB);
}
Log the values of consecutivasA and B right before the final ifs... I suspect strongly that your values are always zero due to an earlier logic error.
I would go about doing this another way--instead of using the logic you provide, which I think just checks if the total number of wins by Team A or Team B are divisible by 3 (which does not necessarily say anything about whether the wins are consecutive), I would try the following:
Run through your array and write an if statement checking if Team A won in a particular place. If yes, check if it won in n+1 and n+2 as well. If so, increment plusA.
Run through your array again and write an if statement checking if Team B won in a particular place. If yes, check if it won in n+1 and n+2 as well. If so, increment plusB.
NOTE: Check only until two entries before the final entry in your array, as going beyond that would return an array size error.

Returns and/or breaks in the middle of a loop. Is it ever acceptable?

Suppose we have an array of integers. We've written a function to fetch the index of the first specified value in the array, or -1 if the array does not contain the value..
So for example, if the array = { 4, 5, 4, 4, 7 }, then getFirstIndexOf(4) would return 0, getFirstIndexOf(7) would return 4, and getFirstIndexOf(8) would return -1.
Below, I have presented three different ways to write this function. It is a widely accepted coding standard that returns in the middle of functions, and breaks in the middle of loops are poor practice. It seems to me that this might be an acceptable use for them.
public int getFirstIndexOf(int specifiedNumber) {
for (int i = 0; i < array.length; i++) {
if (array[i] == specifiedNumber) {
return i;
}
}
return -1;
}
VS.
public int getFirstIndexOf(int specifiedNumber) {
int result = -1;
for (int i = 0; i < array.length; i++) {
if (array[i] == specifiedNumber) {
result = i;
break;
}
}
return result;
}
VS.
public int getFirstIndexOf(int specifiedNumber) {
int result = -1;
for (int i = 0; i < array.length; i++) {
if (array[i] == specifiedNumber && result == -1) {
result = i;
}
}
return result;
}
What do you think? Which is best? Why? Is there perhaps another way to do this?
I think it's poor practice to run a full loop when you have already found your result...
If you really want to avoid using return from the middle of the loop, I would sugest to use a "sentinel" to stop your loop.
public int getFirstIndexOf(int specifiedNumber, int[] array) {
boolean found = false;
boolean exit = false;
int i = 0;
int arraySize = array.length();
while(!found && !exit) {
if(array[i] == specifiedNumber) {
found = true;
} else {
if(i++ > arraySize) {
exit = true;
}
}
if(found ==true) {
return i;
} else {
return 99999;
}
}
edit: I hate to indent code using spaces in StackOverflow...
That's why do...while & while loop was invented.
As requested:
public int getFirstIndexOf(int specifiedNumber) {
int i = array.Length;
while(--i > -1 && array[i] != specifiedNumber);
return i;
}

How to reduce code duplication in this example

I need to loop through a number (xx). xx always starts at zero. My problem is that if the moveDirection variable is +1 then xx increases until it reaches the positive of range. If moveDirection is -1, then xx decreases until reaching the negative of range.
In the code below, I have done this by having an if statement test for moveDirection first, then I have duplicated the for loop, and edited the values for each case. My code happens to be in ActionScript3, but the language does not matter.
var p:Point;
var xx:int;
if (moveDirection > 0)
{
for (xx = 0; xx < range; xx++)
{
if (hitTestPoint(xx, yy))
{
return true;
}
}
}
else
{
for (xx = 0; xx > range; xx--)
{
if (hitTestPoint(xx, yy))
{
return true;
}
}
}
Is there a better way of doing this, maybe without duplicating the for loop? If there is any other advice, it would be greatly appreciated.
for (xx = 0; xx != range; xx += moveDirection)
{
if (hitTestPoint(xx, yy))
{
return true;
}
}
This assumes that moveDirection will be either 1 or -1 for going up or down, respectively. Also, you'll have to slightly change your range for the != to work properly. But, it does cut down on code.
From the looks of the code, it doesn't really matter which direction the loop runs -- you're just returning true if hitTestPoint returns true for some value in the range. If that's so, another possibility would be something like:
var start:int = min(0, range);
var stop:int = max(0, range);
for (xx = start; xx!=stop; xx++)
if (hitTestPoint(xx,yy)
return true;
Another possibility:
int i;
for (i = abs(range), xx = 0; --i >= 0; xx += moveDirection){
if (hitTestPoint(xx, yy) return true;
}
Here's an example in Java (see also on ideone.com):
static void go(final int range, final int direction) {
for (int i = 0; i != direction*range; i += direction) {
System.out.println(i);
}
}
Then you can do:
go(5, +1); // 0, 1, 2, 3, 4
go(5, -1); // 0, -1, -2, -3, -4
If you want to accommodate non-unit step, it's simplest to define a third parameter as follows:
static void go(final int range, final int step, final int direction) {
for (int i = 0; i < range; i += step) {
System.out.println(i * direction);
}
}
Then you can do:
go(10, 3, +1); // 0, 3, 6, 9
go(10, 3, -1); // 0, -3, -6, -9

How would you calculate all possible permutations of 0 through N iteratively?

I need to calculate permutations iteratively. The method signature looks like:
int[][] permute(int n)
For n = 3 for example, the return value would be:
[[0,1,2],
[0,2,1],
[1,0,2],
[1,2,0],
[2,0,1],
[2,1,0]]
How would you go about doing this iteratively in the most efficient way possible? I can do this recursively, but I'm interested in seeing lots of alternate ways to doing it iteratively.
see QuickPerm algorithm, it's iterative : http://www.quickperm.org/
Edit:
Rewritten in Ruby for clarity:
def permute_map(n)
results = []
a, p = (0...n).to_a, [0] * n
i, j = 0, 0
i = 1
results << yield(a)
while i < n
if p[i] < i
j = i % 2 * p[i] # If i is odd, then j = p[i], else j = 0
a[j], a[i] = a[i], a[j] # Swap
results << yield(a)
p[i] += 1
i = 1
else
p[i] = 0
i += 1
end
end
return results
end
The algorithm for stepping from one permutation to the next is very similar to elementary school addition - when an overflow occurs, "carry the one".
Here's an implementation I wrote in C:
#include <stdio.h>
//Convenience macro. Its function should be obvious.
#define swap(a,b) do { \
typeof(a) __tmp = (a); \
(a) = (b); \
(b) = __tmp; \
} while(0)
void perm_start(unsigned int n[], unsigned int count) {
unsigned int i;
for (i=0; i<count; i++)
n[i] = i;
}
//Returns 0 on wraparound
int perm_next(unsigned int n[], unsigned int count) {
unsigned int tail, i, j;
if (count <= 1)
return 0;
/* Find all terms at the end that are in reverse order.
Example: 0 3 (5 4 2 1) (i becomes 2) */
for (i=count-1; i>0 && n[i-1] >= n[i]; i--);
tail = i;
if (tail > 0) {
/* Find the last item from the tail set greater than
the last item from the head set, and swap them.
Example: 0 3* (5 4* 2 1)
Becomes: 0 4* (5 3* 2 1) */
for (j=count-1; j>tail && n[j] <= n[tail-1]; j--);
swap(n[tail-1], n[j]);
}
/* Reverse the tail set's order */
for (i=tail, j=count-1; i<j; i++, j--)
swap(n[i], n[j]);
/* If the entire list was in reverse order, tail will be zero. */
return (tail != 0);
}
int main(void)
{
#define N 3
unsigned int perm[N];
perm_start(perm, N);
do {
int i;
for (i = 0; i < N; i++)
printf("%d ", perm[i]);
printf("\n");
} while (perm_next(perm, N));
return 0;
}
Is using 1.9's Array#permutation an option?
>> a = [0,1,2].permutation(3).to_a
=> [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]
Below is my generics version of the next permutation algorithm in C# closely resembling the STL's next_permutation function (but it doesn't reverse the collection if it is the max possible permutation already, like the C++ version does)
In theory it should work with any IList<> of IComparables.
static bool NextPermutation<T>(IList<T> a) where T: IComparable
{
if (a.Count < 2) return false;
var k = a.Count-2;
while (k >= 0 && a[k].CompareTo( a[k+1]) >=0) k--;
if(k<0)return false;
var l = a.Count - 1;
while (l > k && a[l].CompareTo(a[k]) <= 0) l--;
var tmp = a[k];
a[k] = a[l];
a[l] = tmp;
var i = k + 1;
var j = a.Count - 1;
while(i<j)
{
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
i++;
j--;
}
return true;
}
And the demo/test code:
var src = "1234".ToCharArray();
do
{
Console.WriteLine(src);
}
while (NextPermutation(src));
I also came across the QuickPerm algorithm referenced in another answer. I wanted to share this answer in addition, because I saw some immediate changes one can make to write it shorter. For example, if the index array "p" is initialized slightly differently, it saves having to return the first permutation before the loop. Also, all those while-loops and if's took up a lot more room.
void permute(char* s, size_t l) {
int* p = new int[l];
for (int i = 0; i < l; i++) p[i] = i;
for (size_t i = 0; i < l; printf("%s\n", s)) {
std::swap(s[i], s[i % 2 * --p[i]]);
for (i = 1; p[i] == 0; i++) p[i] = i;
}
}
I found Joey Adams' version to be the most readable, but I couldn't port it directly to C# because of how C# handles the scoping of for-loop variables. Hence, this is a slightly tweaked version of his code:
/// <summary>
/// Performs an in-place permutation of <paramref name="values"/>, and returns if there
/// are any more permutations remaining.
/// </summary>
private static bool NextPermutation(int[] values)
{
if (values.Length == 0)
throw new ArgumentException("Cannot permutate an empty collection.");
//Find all terms at the end that are in reverse order.
// Example: 0 3 (5 4 2 1) (i becomes 2)
int tail = values.Length - 1;
while(tail > 0 && values[tail - 1] >= values[tail])
tail--;
if (tail > 0)
{
//Find the last item from the tail set greater than the last item from the head
//set, and swap them.
// Example: 0 3* (5 4* 2 1)
// Becomes: 0 4* (5 3* 2 1)
int index = values.Length - 1;
while (index > tail && values[index] <= values[tail - 1])
index--;
Swap(ref values[tail - 1], ref values[index]);
}
//Reverse the tail set's order.
int limit = (values.Length - tail) / 2;
for (int index = 0; index < limit; index++)
Swap(ref values[tail + index], ref values[values.Length - 1 - index]);
//If the entire list was in reverse order, tail will be zero.
return (tail != 0);
}
private static void Swap<T>(ref T left, ref T right)
{
T temp = left;
left = right;
right = temp;
}
Here's an implementation in C#, as an extension method:
public static IEnumerable<List<T>> Permute<T>(this IList<T> items)
{
var indexes = Enumerable.Range(0, items.Count).ToArray();
yield return indexes.Select(idx => items[idx]).ToList();
var weights = new int[items.Count];
var idxUpper = 1;
while (idxUpper < items.Count)
{
if (weights[idxUpper] < idxUpper)
{
var idxLower = idxUpper % 2 * weights[idxUpper];
var tmp = indexes[idxLower];
indexes[idxLower] = indexes[idxUpper];
indexes[idxUpper] = tmp;
yield return indexes.Select(idx => items[idx]).ToList();
weights[idxUpper]++;
idxUpper = 1;
}
else
{
weights[idxUpper] = 0;
idxUpper++;
}
}
}
And a unit test:
[TestMethod]
public void Permute()
{
var ints = new[] { 1, 2, 3 };
var orderings = ints.Permute().ToList();
Assert.AreEqual(6, orderings.Count);
AssertUtil.SequencesAreEqual(new[] { 1, 2, 3 }, orderings[0]);
AssertUtil.SequencesAreEqual(new[] { 2, 1, 3 }, orderings[1]);
AssertUtil.SequencesAreEqual(new[] { 3, 1, 2 }, orderings[2]);
AssertUtil.SequencesAreEqual(new[] { 1, 3, 2 }, orderings[3]);
AssertUtil.SequencesAreEqual(new[] { 2, 3, 1 }, orderings[4]);
AssertUtil.SequencesAreEqual(new[] { 3, 2, 1 }, orderings[5]);
}
The method AssertUtil.SequencesAreEqual is a custom test helper which can be recreated easily enough.
How about a recursive algorithm you can call iteratively? If you'd actually need that stuff as a list like that (you should clearly inline that rather than allocate a bunch of pointless memory). You could simply calculate the permutation on the fly, by its index.
Much like the permutation is carry-the-one addition re-reversing the tail (rather than reverting to 0), indexing the specific permutation value is finding the digits of a number in base n then n-1 then n-2... through each iteration.
public static <T> boolean permutation(List<T> values, int index) {
return permutation(values, values.size() - 1, index);
}
private static <T> boolean permutation(List<T> values, int n, int index) {
if ((index == 0) || (n == 0)) return (index == 0);
Collections.swap(values, n, n-(index % n));
return permutation(values,n-1,index/n);
}
The boolean returns whether your index value was out of bounds. Namely that it ran out of n values but still had remaining index left over.
And it can't get all the permutations for more than 12 objects.
12! < Integer.MAX_VALUE < 13!
-- But, it's so very very pretty. And if you do a lot of things wrong might be useful.
I have implemented the algorithm in Javascript.
var all = ["a", "b", "c"];
console.log(permute(all));
function permute(a){
var i=1,j, temp = "";
var p = [];
var n = a.length;
var output = [];
output.push(a.slice());
for(var b=0; b <= n; b++){
p[b] = b;
}
while (i < n){
p[i]--;
if(i%2 == 1){
j = p[i];
}
else{
j = 0;
}
temp = a[j];
a[j] = a[i];
a[i] = temp;
i=1;
while (p[i] === 0){
p[i] = i;
i++;
}
output.push(a.slice());
}
return output;
}
I've used the algorithms from here. The page contains a lot of useful information.
Edit: Sorry, those were recursive. uray posted the link to the iterative algorithm in his answer.
I've created a PHP example. Unless you really need to return all of the results, I would only create an iterative class like the following:
<?php
class Permutator implements Iterator
{
private $a, $n, $p, $i, $j, $k;
private $stop;
public function __construct(array $a)
{
$this->a = array_values($a);
$this->n = count($this->a);
}
public function current()
{
return $this->a;
}
public function next()
{
++$this->k;
while ($this->i < $this->n)
{
if ($this->p[$this->i] < $this->i)
{
$this->j = ($this->i % 2) * $this->p[$this->i];
$tmp = $this->a[$this->j];
$this->a[$this->j] = $this->a[$this->i];
$this->a[$this->i] = $tmp;
$this->p[$this->i]++;
$this->i = 1;
return;
}
$this->p[$this->i++] = 0;
}
$this->stop = true;
}
public function key()
{
return $this->k;
}
public function valid()
{
return !$this->stop;
}
public function rewind()
{
if ($this->n) $this->p = array_fill(0, $this->n, 0);
$this->stop = $this->n == 0;
$this->i = 1;
$this->j = 0;
$this->k = 0;
}
}
foreach (new Permutator(array(1,2,3,4,5)) as $permutation)
{
var_dump($permutation);
}
?>
Note that it treats every PHP array as an indexed array.