Get evenly spaced X, Y cords from a given size and required amount - arrays

I'm working in Actionscript 3, but this is pretty general.
I'd like to make a simple function that I can call, e.g. GiveCords(Width, Height, Num) that will take a width and height, map that out and using the Num variable place the given amount evenly across the space.
Say I give it a value of 500, 500, 1. I'd expect it to return an X, Y position of 250, 250.
But I'd like it to return an array of given points with X, Y.
So If I gave it 10 points, it would find the best position for them all to be of even distance apart from each other.
I'm guessing there is a simple formula for working this out, but I've searched a plenty and found nothing.
Cheers

If I understood correctly this should do the job:
var object:Object = {width: 500, height:500, num:10};
var points:Array = getCoordinates(object);
function getCoordinates(object:Object):Array {
var array:Array = new Array();
var widthMultiplier:Number = object.width / (object.num + 1);
var heightMultiplier:Number = object.height / (object.num + 1);
for (a = 1; a <= object.num; a++) {
var coordinates:Point = new Point();
coordinates.x = widthMultiplier * a;
coordinates.y = heightMultipler * a;
array.push(coordinates);
}
return array;
}
It takes the number of items and the total space, divides the total space by the number of items + 1 (to account for the space at the end of the last element) increment the objects each time.
Edit: In response to comments here is a version where you can state the number of rows you want your objects to spread across. If the number of rows does not divide the number of objects and return an integer then the function will return null. If you do not give it a rows paramater it assumes you want it across one row. Enjoy.
var object:Object = {width:500,height:500,num:10};
var points:Array = getCoordinates(object,2);
function getCoordinates(object:Object, rows:int = 1):Array
{
if ((object.num / rows) % 1)
{
return null;
}
else
{
var columns:int = object.num / rows;
var array:Array = new Array();
var widthMultiplier:Number = object.width / (columns + 1);
var heightMultiplier:Number = object.height / (rows + 1);
for (var a = 1; a <= rows; a++)
{
for (var b = 1; b <= columns; b++)
{
var coordinates:Point = new Point();
coordinates.x = widthMultiplier * b;
coordinates.y = heightMultiplier * a;
array.push(coordinates);
}
}
return array;
}
}

Related

Concurrent access to elements of Array in Swift

I try to write and read from Arrays (from different arrays) in Swift in concurrent way, and have exception in the runtime on write operation.
I have concurrent blur code in Objective-C++:
- (cpp_blur::Bitmap)blur {
Bitmap result(_source);
auto indexes = [[NSIndexSet alloc] initWithIndexesInRange:NSMakeRange(0, _source.size())];
int minIndex = 0;
int maxIndex = static_cast<int>(result.size()) - 1;
[indexes enumerateIndexesWithOptions:NSEnumerationConcurrent
usingBlock:[&](NSUInteger idx, BOOL* _Nonnull stop){
double sum = 0.0;
for (int i = static_cast<int>(idx) - static_cast<int>(self.radius); i <= idx + self.radius; i++) {
int index = clamp(i, minIndex, maxIndex);
sum += self->_source.at(index);
}
sum /= static_cast<double>(self.radius * 2 + 1);
result.at(idx) = sum;
}];
return result;
}
I try to write same code in Swift:
#objc public func blur() -> [Double] {
var result = source
let indexSet = NSIndexSet(indexesIn: NSMakeRange(0, source.count))
let from = -Int(self.blurRadius)
let to = Int(self.blurRadius)
let lastIndex = self.source.count - 1
indexSet.enumerate(options: .concurrent) { (index:Int, _) in
let sum = ((from + index)...(to + index)).reduce(0.0) { (partial:Double, nonClamped:Int) -> Double in
let index = self.clamp(nonClamped, min: 0, max: lastIndex)
let result = partial + self.source[index]
return result
}
let avg = sum / Double(2 * self.blurRadius + 1);
result[index] = avg //here I have crash in runtime
}
return result
}
If I add a lock around result[index] = avg, this exception will move away, but I will have performance issue.
How I can change values of elements in Swift Array without lock (In same time I change only different elements)?
Github repo.

Infinite execution of the code in google apps script

I have this code wich runs infinitly. I checked step by step and the error is in the last part of it where there is a loop.
I have in cell(f,3) the value 400 and respectively in cell(f,4) cell(f-1,4) cell(f-2,4) cell(f-3,4) : 200, 50, 20, 100
The cell(f,12) should show the value 270.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Feuille 1");
var active = sheet.getActiveCell();
var f = active.getRowIndex();
var r = sheet.getRange(f,3).getValues();
var i = f
var cellule = sheet.getRange(i,4).getValues();
var C = 0
do {
C = C + cellule;
var destverif = sheet.getRange(f,12);
destverif.setValue(C);
i = i-1;
}while (C + cellule <= r);
}
You are using getValues() instead of getValue() which returns an array. Your while condition is essentially checking while(NaN + [["200"]] <= [["400"]]) which will not really work out, it seems as though it was returning true and you had a loop that was essentially while(true).
To correct this, use getValue() instead. This immediately corrects your infinite loop.
I chatted with you over gchat and determined your logic was also faulty for the output you expected. You are trying to take a set of data like this:
Get the value of the highlighted column starting at 200 and going up till your total is greater than or equal to 400. Once it hits this value, write into column 12 of that row 400 / AVERAGE(200,100,101)
I corrected your code, this code does the trick:
function getValues(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Feuille 1");
var active = sheet.getActiveCell();
var rowIndex = active.getRowIndex(); //Get the rowindex of the current active cell
var maxValue = sheet.getRange(rowIndex,3).getValue(); //Your max value is the active cells value
var currentValue = 0;
var activeRowIndex = rowIndex
var loopIndex = 0;
do{
var cellData = sheet.getRange(activeRowIndex, 4).getValue(); //Get the value of the cell next to the selectedCell
if(cellData !== ''){ //If the cell is not blank continue
currentValue += cellData; //Add up the total as we go
activeRowIndex --; //Subtract the row index so we can keep movign up
loopIndex++; //Iterate the loopIndex so we know how many numbers we have added up to calculate the average
} else {
break; //If the cell is blank, break out of the loop
}
} while (currentValue <= maxValue);
sheet.getRange(rowIndex, 12).setValue(maxValue/(currentValue/loopIndex)); //set the ranges value and do the math in line for the average.
}

Each array to come up with a number, calculate out the location of the array

var a = [1,2,3]
var b = [1,2,3]
var c = [1,2,3,4]
Each array inside take out a number of a three digits.
A total of 36 kinds of combination of the above.
I want to compute the position of the each combination.
[1,1,1] position is 1
[1,1,2] position is 2
[2,2,4] position is?
I want to ask how much the position of a combination of them, is there a specific formula?
Write three nested for loops. First one is for array a,second for b and third for c. That way you will first change the c for a new permutation than b, than a. Before going to for loop declare a variable called count which is 1. At the third loop increase that variable by one. Example:
int first,second,third,count=1;
for(int i=0;i<a.size();i++)
{
first=a[i];
for(int k=0;k<b.size();k++)
{
second=b[k];
for(int g=0;g<c.size();g++)
{
third=c[g];
count=count+1; //count++
}
}
}
This is written in C++. But you get the idea.You can put if statements inbetween to find the number of the permutation that you are looking for.
var a = [1,2,3];
var b = [1,2,3];
var c = [1,2,3,4];
var all = [a,b,c];
var allCount = [b.length * c.length, c.length, 0];
function getIndex(combo) {
var count = 0;
for (var i = 0; i < combo.length; i++) {
var pos = all[i].indexOf(combo[i]);
if (pos < 0) {
throw new Error(combo[i] + "Not effective elements");
}
count += allCount[i] * pos;
}
count += combo[combo.length - 1];
return count;
}
console.log("index of [2,2,4] is " + getIndex([2,2,4]));
console.log("index of [1,1,1] is " + getIndex([1,1,1]));
console.log("index of [3,3,4] is " + getIndex([3,3,4]));
console.log("index of [1,2,3] is " + getIndex([1,2,3]));
console.log("index of [3,2,1] is " + getIndex([3,2,1]));
The output:
index of [2,2,4] is 20
index of [1,1,1] is 1
index of [3,3,4] is 36
index of [1,2,3] is 7
index of [3,2,1] is 29

generating random numbers without repeating with an exception AS3

I have seen this question for other languages but not for AS3... and I'm having a hard time understanding it...
I need to generate 3 numbers, randomly, from 0 to 2, but they cannot repeat (as in 000, 001, 222, 212 etc) and they cannot be in the correct order (0,1,2)...
Im using
for (var u: int = 0; u < 3; u++)
{
mcCor = new CorDaCarta();
mcCor.x = larguraTrio + (mcCor.width + 5) * (u % 3);
mcCor.y = alturaTrio + (mcCor.height + 5) * (Math.floor(u / 3));
mcCor.gotoAndStop((Math.random() * (2 - u + 1) + u) | 0); // random w/ repeats
//mcCor.gotoAndStop(Math.floor(Math.random() * (2 - u + 1) + u)); // random w/ repeats
//mcCor.gotoAndStop((Math.random() * 3) | 0); // crap....
//mcCor.gotoAndStop(Math.round(Math.random()*u)); // 1,1,1
//mcCor.gotoAndStop(u + 1); // 1,2,3
mcCor.buttonMode = true;
mcCor.addEventListener(MouseEvent.CLICK, cliquetrio);
mcExplic.addChild(mcCor);
trio.push(mcCor);
}
those are the codes i've been trying.... best one so far is the active one (without the //), but it still gives me duplicates (as 1,1,1) and still has a small chance to come 0,1,2....
BTW, what I want is to mcCor to gotoAndStop on frames 1, 2 or 3....without repeating, so THE USER can put it on the right order (1,2,3 or (u= 0,1,2), thats why I add + 1 sometimes there)
any thoughts?? =)
I've found that one way to ensure random, unique numbers is to store the possible numbers in an array, and then sort them using a "random" sort:
// store the numbers 0, 1, 2 in an array
var sortedNumbers:Array = [];
for(var i:int = 0; i < 3; i++)
{
sortedNumbers.push(i);
}
var unsortedNumbers:Array = sortedNumbers.slice(); // make a copy of the sorted numbers
trace(sortedNumbers); // 0,1,2
trace(unsortedNumbers); // 0,1,2
// randomly sort array until it no longer matches the sorted array
while(sortedNumbers.join() == unsortedNumbers.join())
{
unsortedNumbers.sort(function (a:int, b:int):int { return Math.random() > .5 ? -1 : 1; });
}
trace(unsortedNumbers); // [1,0,2], [2,1,0], [0,1,2], etc
for (var u: int = 0; u < 3; u++)
{
mcCor = new CorDaCarta();
mcCor.x = larguraTrio + (mcCor.width + 5) * (u % 3);
mcCor.y = alturaTrio + (mcCor.height + 5) * (Math.floor(u / 3));
// grab the corresponding value from the unsorted array
mcCor.gotoAndStop(unsortedNumbers[u] + 1);
mcCor.buttonMode = true;
mcCor.addEventListener(MouseEvent.CLICK, cliquetrio);
mcExplic.addChild(mcCor);
trio.push(mcCor);
}
Marcela is right. Approach with an Array is widely used for such task. Of course, you will need to check 0, 1, 2 sequence and this will be ugly, but in common code to get the random sequence of integers can look like this:
function getRandomSequence(min:int, max:int):Array
{
if (min > max) throw new Error("Max value should be greater than Min value!");
if (min == max) return [min];
var values:Array = [];
for (var i:int = min; i <= max; i++) values.push(i);
var result:Array = [];
while (values.length > 0) result = result.concat(values.splice(Math.floor(Math.random() * values.length), 1));
return result;
}
for (var i:uint = 0; i < 10; i++)
{
trace(getRandomSequence(1, 10));
}
You will get something like that:
2,9,3,8,10,6,5,1,4,7
6,1,2,4,8,9,5,10,7,3
3,9,10,6,8,2,5,4,1,7
7,6,1,4,3,8,9,2,10,5
4,6,7,1,3,2,9,10,8,5
3,10,5,9,1,7,2,4,8,6
1,7,9,6,10,3,4,5,2,8
4,10,8,9,3,2,6,1,7,5
1,7,8,9,10,6,4,3,2,5
7,5,4,2,8,6,10,3,9,1
I created this for you. It is working but it can be optimized...
Hope is good for you.
var arr : Array = [];
var r : int;
for (var i: int = 0; i < 3; i++){
r=rand(0,2);
if(i == 1){
if(arr[0] == r){
i--;
continue;
}
if(arr[0] == 0){
if(r==1){
i--;
continue;
}
}
}else if(i==2){
if(arr[0] == r || arr[1] == r){
i--;
continue;
}
}
arr[i] = r;
}
trace(arr);
for(var i=0;i<3;i++){
mcCor = new CorDaCarta();
mcCor.x = larguraTrio + (mcCor.width + 5) * (i % 3);
mcCor.y = alturaTrio + (mcCor.height + 5) * (Math.floor(i / 3));
mcCor.gotoAndStop(arr[i]);
mcCor.buttonMode = true;
mcCor.addEventListener(MouseEvent.CLICK, cliquetrio);
mcExplic.addChild(mcCor);
trio.push(mcCor);
}
function rand(min:int, max:int):int {
return Math.round(Math.random() * (max - min) + min);
}
try this...

Action Script 3. Randomly moving items UP and DOWN from array

So I'm creating game similar like this: example
I have an array of items already added to 4 holes. I need to make that these items randomly moved up (+100px) and down(-100px).
I have added to all holes for 6 items:
for(var i:uint = 0; i < 6; i++)
{
holeArr[0].inside.addChild(itemsArr[4][i]);
holeArr[1].inside.addChild(itemsArr[5][i]);
holeArr[2].inside.addChild(itemsArr[6][i]);
holeArr[3].inside.addChild(itemsArr[7][i]);
}
How can I make them randomly move up (+100px) and down(-100px)? I started, but I don't know what to do next... Could you help me, please?
function randomSpawn() {
for(var i:uint = 0; i < 6; i++)
{
itemsArr[4][i].x += 100;
itemsArr[5][i].x += 100;
itemsArr[6][i].x += 100;
itemsArr[7][i].x += 100;
}
}
To move an item randomly up/down +-100 pixels:
var distance = Math.round(Math.random() * 2 - 1) * 100;
mySprite.y += distance;
To animate it with Tweenlite
var newPosY = mySprite.y;
newPosY += Math.round(Math.random() * 2 - 1) * 100;
TweenLite.to(mySprite,1,{y:newPosY});
The simplest way to select a random item from an array
var index = Math.round(Math.random * (myArray.length - 1));
var myRandomItem = myArray[index];

Resources