SpriteKit for loop - for-loop

Hi I'm trying to follow a tutorial on Ray Wenderlich site
[http://www.raywenderlich.com/76740/make-game-like-space-invaders-sprite-kit-and-swift-tutorial-part-1][1]
so I'm going thru the functions breaking it down so i can get an understanding of how it works I've commented out stuff which i think i understand but this bit has me stumped
thanks for looking
the for loop whats the var row = 1 at the beginning doing ?
I've only ever done for lops like
for Position in 0...9
{
// do something with Position ten times
}
then whats the % in if row %3 mean?
for var row = 1; row <= kInvaderRowCount; row++ // start of loop
{
var invaderType: InvaderType // varible of atype etc
if row % 3 == 0
{
invaderType = .AType
} else if row % 3 == 1
hers the rest of the code
func makeInvaderOfType(invaderType: InvaderType) -> (SKNode) // function passes in a enum of atype,btype,ctype and returns sknode
{
var invaderColor: SKColor// variable for the colour
switch(invaderType)// switch statment if we pass in atype we will get red
{
case .AType:
invaderColor = SKColor.redColor()
case .BType:
invaderColor = SKColor.greenColor()
case .CType:
invaderColor = SKColor.blueColor()
default:
invaderColor = SKColor.blueColor()
}
let invader = SKSpriteNode(color: invaderColor, size: kInvaderSize)//variable of a skspritenode with color from switch statement size from vairiabe kinvadersize
invader.name = kInvaderName // name is invader fron let kinvadername
return invader //return the spritenode with color size name
}
func setupInvaders()
{
let baseOrigin = CGPoint(x:size.width/3, y:180) // vairible to hold cgpoint screen size /3 width 180 height
for var row = 1; row <= kInvaderRowCount; row++ // start of loop
{
var invaderType: InvaderType // varible of atype etc
if row % 3 == 0
{
invaderType = .AType
} else if row % 3 == 1
{
invaderType = .BType
} else
{
invaderType = .CType
}
let invaderPositionY = CGFloat(row) * (kInvaderSize.height * 2) + baseOrigin.y// varible to hold cgfloat row ? think its the incriment of the for loop times 16 times 2 = 32 plus 180 first time is 212 then 244
/* so if ive got his rightthe sum goes row = 1 kinvadersize.hieght *2 = 32 + baseoringin.y = 180
1 * 32 +180 = 212
2 * 32 + 180 = 392 but its 244
*/
println(row)
var invaderPosition = CGPoint(x:baseOrigin.x, y:invaderPositionY) // varible to hold cgpoint
println(invaderPosition.y)
for var col = 1; col <= kInvaderColCount; col++
{
var invader = makeInvaderOfType(invaderType)// varible that runs function and return the spritenode with color size name????
invader.position = invaderPosition
addChild(invader)
invaderPosition = CGPoint(x: invaderPosition.x + kInvaderSize.width + kInvaderGridSpacing.width, y: invaderPositionY)
}
}
}

If I understand your question correctly, here's the answer. Based on this code:
for var row = 1; row <= kInvaderRowCount; row++ // start of loop
{
var invaderType: InvaderType // varible of atype etc
if row % 3 == 0
{
invaderType = .AType
} else if row % 3 == 1
The first line means:
var row = 1: given a new variable, row, with a value of 1
row <= kInvaderRowCount: as long as the variable row is less than or equal to kInvaderRowCount, keep running the for loop
row++: after each time the loop is run, increment (increase) the value of row by 1
As for the "%", that is the modulo operator. It returns the remainder after a division operation on integer values. So if 7 divided by 3 = 2, with a remainder of 1, then
7 / 3 = 2
7 % 3 = 1
The modulus operator results in an integer. While 1 / 3 = 0.33..., 1 % 3 = 1. Because the remainder of 1 divided by 3 is 1.
1 % 3 = 1
2 % 3 = 2
3 % 3 = 0
4 % 3 = 1
5 % 3 = 2
6 % 3 = 0
see also: How Does Modulus Divison Work.

Related

Optimised EmEditor macro to populate column based on another column for a large file

I’ve got a really large file, circa 10m rows, in which I’m trying to populate a column based on conditions on another column via a jsee macro. While it is quite quick for small files, it does take some time for the large file.
//pseudocode
//No sorting on Col1, which can have empty cells too
For all lines in file
IF (cell in Col2 IS empty) AND (cell in Col1 IS NOT empty) AND (cell in Col1 = previous cell in Col1)
THEN cell in Col2 = previous cell in Col2
//jsee code
document.CellMode = true; // Must be cell selection mode
totalLines = document.GetLines();
for( i = 1; i < totalLines; i++ ) {
nref = document.GetCell( i, 1, eeCellIncludeNone );
gsize = document.GetCell( i, 2, eeCellIncludeNone );
if (gsize == "" && nref != "" && nref == document.GetCell( i-1, 1, eeCellIncludeNone ) ) {
document.SetCell( i, 2, document.GetCell( i-1, 2, eeCellIncludeNone ) , eeAutoQuote);
}
}
Input File:
Reference
Group Size
14/12/01819
1
14/12/01820
1
15/01/00191
4
15/01/00191
15/01/00191
15/01/00198
15/01/00292
3
15/01/00292
15/01/00292
15/01/00401
5
15/01/00401
15/01/00402
1
15/01/00403
2
15/01/00403
15/01/00403
15/01/00403
15/01/00404
20/01/01400
1
Output File:
Reference
Group Size
14/12/01819
1
14/12/01820
1
15/01/00191
4
15/01/00191
4
15/01/00191
4
15/01/00198
15/01/00292
3
15/01/00292
3
15/01/00292
3
15/01/00401
5
15/01/00401
5
15/01/00402
1
15/01/00403
2
15/01/00403
2
15/01/00403
2
15/01/00403
2
15/01/00404
20/01/01400
1
Any ideas on how to optimise this and make it run even faster?
I wrote a JavaScript for EmEditor macro for you. You might need to set the correct numbers in the first 2 lines for iColReference and iColGroupSize.
iColReference = 1; // the column index of "Reference"
iColGroupSize = 2; // the column index of "Group Size"
document.CellMode = true; // Must be cell selection mode
sDelimiter = document.Csv.Delimiter; // retrieve the delimiter
nOldHeadingLines = document.HeadingLines; // retrieve old headings
document.HeadingLines = 0; // set No Headings
yBottom = document.GetLines(); // retrieve the number of lines
if( document.GetLine( yBottom ).length == 0 ) { // -1 if the last line is empty
--yBottom;
}
str = document.GetColumn( iColReference, sDelimiter, eeCellIncludeQuotes, 1, yBottom ); // get whole 1st column from top to bottom, separated by TAB
sCol1 = str.split( sDelimiter );
str = document.GetColumn( iColGroupSize, sDelimiter, eeCellIncludeQuotes, 1, yBottom ); // get whole 2nd column from top to bottom, separated by TAB
sCol2 = str.split( sDelimiter );
s1 = "";
s2 = "";
for( i = 0; i < yBottom; ++i ) { // loop through all lines
if( sCol2[i].length != 0 ) {
s1 = sCol1[i];
s2 = sCol2[i];
}
else {
if( s1.length != 0 && sCol1[i] == s1 ) { // same value as previous line, copy s2
if( s2.length != 0 ) {
sCol2[i] = s2;
}
}
else { // different value, empty s1 and s2
s1 = "";
s2 = "";
}
}
}
str = sCol2.join( sDelimiter );
document.SetColumn( iColGroupSize, str, sDelimiter, eeDontQuote ); // set whole 2nd column from top to bottom with the new values
document.HeadingLines = nOldHeadingLines; // restore the original number of headings
To run this, save this code as, for instance, Macro.jsee, and then select this file from Select... in the Macros menu. Finally, select Run Macro.jsee in the Macros menu.

Gold Mine Problem - Sequence of for loops

Gold mine problem. Following sequence for loop is giving correct result.
//see link for other code
static int getMaxGold(int gold[][], int m, int n) {
//see link for other code
for (int col = n-1; col >= 0; col--) {
for (int row = 0; row < m; row++) {
int right = (col == n-1) ? 0 : goldTable[row][col+1];
int right_up = (row == 0 || col == n-1) ? 0 : goldTable[row-1][col+1];
int right_down = (row == m-1 || col == n-1) ? 0 : goldTable[row+1][col+1];
goldTable[row][col] = gold[row][col] + Math.max(right, Math.max(right_up, right_down));
}
}
}
//see link for other code
While other way round does not give the expected result. For example
for (int col = 0; col < n; col ++) {
for (int row = 0; row < m; row++) {
//same code to calculate right, rightUp and rightDown
}
}
Any explanation for this behaviour?
You don't need to store a whole matrix.
When you build the table, you just need to keep the last layer you processed.
In your recursion, there is diagonally right, or right, so the layer is a column because to compute the value of some cell, you need to know three values (on its right)
You conclude (as spotted by Damien already) that you start from the rightmost column, then to compute the value of every cells of the n-1 column, you only need to know the nth column (which you luckily computed already)
In below example. m_ij refers to i-th line, j-th column. (e.g m_01 == 2, m_10 = 5)
1 2 3 4
5 6 7 8
9 1 2 3
4 5 6 3
The last column is {4,8,3,3}
To compute the max value for m_02 you need to choose between 4 and 8
3 - 4
\
8
m_02 = 3 + 8 = 11
To compute the max value of m_12 you need to choose between 4, 8 and 3
4
/
7 - 8
\
3
m_12 = 7 + 8 = 15
Skipping stuff
m_22 = 2 + 8 = 10
m_32 = 6 + 3 = 9
Now you know the max value for each square of the third column
1 2 11 .
5 6 15 .
9 1 10 .
4 5 9 .
You do the same for m_10, m_11, ...
idem
m_01 = 2 + max(11, 15) = 17
m_11 = 6 + 15
m_21 = 1 + 15
m_31 = 5 + 10
Left to process is thus
1 17
5 21
9 16
4 15
Then
1+21
5+21
9+21
4+16
And finally score = max(22, 26, 30, 20)
As you have noticed you only need to keep track of the last processed column. Not a whole table of computation. And the last processed column must start from the right and always be the rightmost one...
I don't think an implem is relevant to help you understand but in case
const s = `
1 2 3 4
5 6 7 8
9 1 2 3
4 5 6 3`
const m = s.trim().split('\n').map(x => x.trim().split(' ').map(y => parseInt(y)))
let layer = [0, 0, 0, 0]
for (let j = 3; j >= 0; --j) {
const nextLayer = []
for (let i = 0; i < 4; ++i) {
nextLayer[i] = m[i][j] + Math.max(
layer[i-1] || 0, // we default undefined value as 0 supposing s only holds positive coefficient
layer[i],
layer[i+1] || 0
)
}
layer = nextLayer
}
console.log(Math.max(...layer))

grouping duplicate rows while the original sort remains intact

Say I have Account Numbers, Sub-account Numbers and values in a google spreadsheet where there can be duplicate Account Numbers with different sub-acc numbers:
acc no / sub acc no / val
2 / 5 / 6
3 / 10 / 8
4 / 9 / 2
2 / 14 / 1
After I sort the whole sheet by the third column, values, it's gonna look like this:
acc no / sub acc no / val
3 / 10 / 8
2 / 5 / 6
4 / 9 / 2
2 / 14 / 1
So, what I want to do is to group all meters under the same accounts while having the original sort remain intact:
acc no / sub acc no / val
3 / 10 / 8
2 / 5 / 6
2 / 14 / 1
4 / 9 / 2
Seems like after sorting it by values, I need a script that loops through the account No column, for each cell it will check the remaining account numbers, and if there's a matching duplicate one, it's gonna get moved up.
This is what I could come up with so far:
function group(){
var sheet = SpreadsheetApp.getActiveSpreadsheet();
// find how many accounts we have
var Avals = sheet.getRange("A2:A").getValues();
var Alast = Avals.filter(String).length;
for (var i = 0; i < Alast-2; i++) {
if(Avals[i].toString() == Avals[i+1].toString()){
continue;
}
for (var j = i+2; j < Alast; j++){
if(Avals[i].toString() == Avals[j].toString()){
//move
break;
}
}
}
}
Thanks in advance!
This is a sample script. Untested. Assumes Sheet is already sorted by C column.
function group(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
// find how many accounts we have
//get A2:C range& values
var rng = sheet.getRange(2,1,sheet.getLastRow()-1,3);
var val = rng.getValues();
var data =[];//output array
var k=0; //data array new row count
//loop through existing rows
for(i=0;i<val.length;i++){
//if A is not empty, new k row data array = original row.
if (val[i][0]) { //value check
data[k] = val[i];
k++; //increment k to next row
//Loop through rows after current row to find next similar A value,if any
for(j=i+1;j<val.length;j++) {
if (val[i][0] == val[j][0]) { //if one of the folllowing row's A value is == current A value
data[k] =val[j].slice(0); //new k data array = j row
k++; //increment k
val[j][0] =''; //set the duplicate j row's A value to null to skip during value check
}
}
}
}
//Logger.log(data);
sheet.getRange(2,1,data.length,data[0].length).setValues(data);
}

Most Frequent Digit In a Specific Range

First of all: before you downgrade THIS IS NOT MY HOMEWORK, this question belongs to codingbat or eulerproject or another website. I am NOT asking you to give me a fully completed and coded answer I am asking you to give me some ideas to HELP me.
Later on, I am having a time limit trouble with this problem. I actually solved it but my solution is too slow. It needs to be done within at 0 to 1 second. In the worst case scenario my code consumes more than 8 seconds. If you could help me with some ideas or if you could show me a more accurate solution pseudo code etc. I would really appreciate it.
First input means how many times we are going to process. Later on, user enters two numbers [X, Y], (0 < X < Y < 100000) We need to compute the most frequent digit in the range of these two numbers X and Y. (including X and Y) Besides, If multiple digits have the same maximum frequency than we suppose to print the smallest of them.
To illustrate:
User first enters number of test cases: 7
User enters X and Y(first test case): 0 21
Now I did open all digits in my solution you may have another idea you are free to use it but to give you a hint: We need to treat numbers like this: 0 1 2 3 ... (here we should open 10 as 1 and 0 same for all of them) 1 0 1 1 1 2 1 3 ... 1 9 2 0 2 1 than we show the most frequent digit between 0 and 21 (In this case: 1)
More examples: (Test cases if you want to check your solution)
X: 7 Y: 956 Result: 1
X: 967 Y: 8000 Result: 7
X: 420 Y: 1000 Result: 5 etc.
Here's my code so far:
package most_frequent_digit;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
public class Main
{
public static int secondP = 0;
public static void getPopularElement(int[] list)
{
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Integer nextInt : list)
{
Integer count = map.get(nextInt);
if (count == null)
{
count = 1;
} else
{
count = count + 1;
}
map.put(nextInt, count);
}
Integer mostRepeatedNumber = null;
Integer mostRepeatedCount = null;
Set<Integer> keys = map.keySet();
for (Integer key : keys)
{
Integer count = map.get(key);
if (mostRepeatedNumber == null)
{
mostRepeatedNumber = key;
mostRepeatedCount = count;
} else if (count > mostRepeatedCount)
{
mostRepeatedNumber = key;
mostRepeatedCount = count;
} else if (count == mostRepeatedCount && key < mostRepeatedNumber)
{
mostRepeatedNumber = key;
mostRepeatedCount = count;
}
}
System.out.println(mostRepeatedNumber);
}
public static void main(String[] args)
{
#SuppressWarnings("resource")
Scanner read = new Scanner(System.in);
int len = read.nextInt();
for (int w = 0; w < len; w++)
{
int x = read.nextInt();
int y = read.nextInt();
String list = "";
for (int i = x; i <= y; i++)
{
list += i;
}
String newList = "";
newList += list.replaceAll("", " ").trim();
int[] listArr = new int[list.length()];
for (int j = 0; j < newList.length(); j += 2)
{
listArr[secondP] = Character.getNumericValue(newList.charAt(j));
secondP++;
}
getPopularElement(listArr);
secondP = 0;
}
}
}
As you can see it takes too long if user enters X: 0 Y: 1000000 like 8 - 9 seconds. But it supposed to return answer in 1 second. Thanks for checking...
Listing all digits and then count them is a very slow way to do this.
There are some simple cases:
X = 10n, X = 10n+1-1 (n > 0) :
The digits 1 to 9 are appearing 10n + n⋅(10n-10n-1) times, 0 appears n⋅(10n-10n-1) times.
E.g.
10, 99: the digits 1 to 9 are appearing 19 times, 0 appears 9 times.
100, 999: the digits 1 to 9 are appearing 280 times, 0 appears 180 times.
X = a⋅10ⁿ, Y = (a+1)⋅10ⁿ-1 (1 ≤ a ≤ 9):
All digits except for a appears n⋅10n-1, the digit a appears 10n + n⋅10n-1 times.
E.g.
10, 19: all digits except for 1 appear one time, 1 appears 11 times.
20, 299: all digits except for 2 appear 20 times, 2 appears 120 times.
With this cases you can split off the input into sub cases. E.g.
X = 0, Y = 21. Split it up into
X₁ = 0, Y₁ = 9 (special case, but very simple),
X₂ = 10, Y₂ = 19 (case 2),
X₃ = 20, Y₃ = 21 (case 3)
X = 0, Y = 3521. Split it up into
X₁ = 0, Y₁ = 9 (special case, but very simple),
X₂ = 10, Y₂ = 99 (case 1),
X₃ = 100, Y₃ = 999 (case 1),
X₄ = 1000, Y₄ = 1999 (case 2),
X₅ = 2000, Y₅ = 2999 (case 2),
X₆ = 3000, Y₆ = 3521 (case 3)
I left case 3 open. The case looks like X = a⋅10ⁿ, Y = a⋅10ⁿ + b (1 ≤ a ≤ 9, 0 ≤ b < 10ⁿ).
Here you know you get the digit a b-times plus the number of appearances in 0 to b. Since X and Y are n+1 digit numbers, b has n digits, with leading zeros.
The missing parts of case 3 have to be filled by the reader.

Formula needed: Sort array to array-"snaked"

After the you guys helped me out so gracefully last time, here is another tricky array sorter for you.
I have the following array:
a = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
I use it for some visual stuff and render it like this:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Now I want to sort the array to have a "snake" later:
// rearrange the array according to this schema
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
// the original array should look like this
a = [1,2,3,4,12,13,14,5,11,16,15,6,10,9,8,7]
Now I'm looking for a smart formula / smart loop to do that
ticker = 0;
rows = 4; // can be n
cols = 4; // can be n
originalArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
newArray = [];
while(ticker &#60 originalArray.length)
{
//do the magic here
ticker++;
}
Thanks again for the help.
I was bored, so I made a python version for you with 9 lines of code inside the loop.
ticker = 0
rows = 4
cols = 4
originalArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
newArray = [None] * (rows * cols)
row = 0
col = 0
dir_x = 1
dir_y = 0
taken = {}
while (ticker < len(originalArray)):
newArray[row * cols + col] = originalArray[ticker]
taken[row * cols + col] = True
if col + dir_x >= cols or row + dir_y >= rows or col + dir_x < 0:
dir_x, dir_y = -dir_y, dir_x
elif ((row + dir_y) * cols + col + dir_x) in taken:
dir_x, dir_y = -dir_y, dir_x
row += dir_y
col += dir_x
ticker += 1
print newArray
You can index into the snake coil directly if you recall that
1 + 2 + 3 + ... + n = n*(n+1)/2
m^2 + m - k = 0 => m - (-1+sqrt(1+4*k))/2
and look at the pattern of the coils. (I'll leave it as a hint for the time being--you could also use that n^2 = (n-1)^2 + (2*n+1) with reverse-indexing, or a variety of other things to solve the problem.)
When translating to code, it's not really any shorter than Tuomas' solution if all you want to do is fill the matrix, however.

Resources