Loop in coffee script? - coffeescript

I'm translating a piece of code from javascript to coffeescript.
for (var i = 0, len = keys.length; i < len; i++) {
k = keys[i];
if (!mailOptions.hasOwnProperty(k))
mailOptions[k] = app.set('mailOptions')[k]
}
I have no idea how to approach to it and on the doc website is not clear, can someone give me a clear explanation? thank you very much!

for key in keys
if not mailOptions.hasOwnProperty key
mailOptions[key] = (app.set 'mailOptions')[key]
Or guard-style:
for key in keys when not mailOptions.hasOwnProperty key
mailOptions[key] = (app.set 'mailOptions')[key]
Compiles to:
var key, _i, _len;
for (_i = 0, _len = keys.length; _i < _len; _i++) {
key = keys[_i];
if (!mailOptions.hasOwnProperty(key)) {
mailOptions[key] = (app.set('mailOptions'))[key];
}
}

Here's one way (from here: http://js2coffee.org/):
i = 0
len = keys.length
while i < len
k = keys[i]
mailOptions[k] = app.set("mailOptions")[k] unless mailOptions.hasOwnProperty(k)
i++
But I wouldn't do it this way. I would just do:
for k in keys
mailOptions[k] = app.set("mailOptions")[k] unless mailOptions.hasOwnProperty k
This outputs the following (excluding var, which it also outputs):
for (_i = 0, _len = keys.length; _i < _len; _i++) {
k = keys[_i];
if (!mailOptions.hasOwnProperty(k)) {
mailOptions[k] = app.set("mailOptions")[k];
}
}
Or, if you wanted to be fancier, which I don't advise in this situation, since it sacrifices some readability:
(mailOptions[k] = app.set("mailOptions")[k] unless mailOptions.hasOwnProperty k) for k in keys

Related

Unable to Get Bitwise XOR to work in GameMaker 2

I'm trying to implement Zobrist hashing for a chess game and thought I was doing things correctly. However, when I try to apply XOR to a Hash value, it simply changes between 0 (the starting value for the hash) and -2147483648, in spite of conducting a bitwise XOR against a random number between 0 and 18446744073709551616.
Here's some code. I thought it was relatively simple with a struct for each entry in the Grid, a constructor function to make an entry, a function to create the Hash Table, and finally one for the Hash itself.
//Hash Table struct. This can be expanded for each new piece type
HashTableEntry = {
QueenHash:-1,
BishopHash:-1,
KnightHash:-1,
RookHash:-1,
PawnHash:-1,
KingHash:-1
};
//A function for creating a Hash Table Entry
function toHashTableEntryStruct() constructor {
var HashUpperBound = 18446744073709551616;
QueenHash = random(HashUpperBound);
BishopHash = random(HashUpperBound);
KnightHash = random(HashUpperBound);
RookHash = random(HashUpperBound);
PawnHash = random(HashUpperBound);
KingHash = random(HashUpperBound);
}
//A function to create a ds_grid Hash Table of the size passed to it, which it then returns
function CreateHashTable(_width, _height){
//Copy the local variables
var width = _width;
var height = _height;
//Create the grid for the Hash Table
var NewHashTable = ds_grid_create(width, height);
//Copy the original seed and set the game's seed to create the same table each time
var OriginalSeed = random_get_seed;
random_set_seed(280804);
//Loop through the Grid and fill each value with a HashTableEntry struct
for(var i = 0; i < width; i++;){
for(var j = 0; j < height; j++;){
var NewHash = new toHashTableEntryStruct();
ds_grid_set(NewHashTable, i, j, NewHash);
}
}
//Reset the seed
random_set_seed(OriginalSeed);
//Return the shiny new Hash Table
return NewHashTable;
}
//A function for creating the original Hash of a board. This should only be called on
initialising a Board as it sets the Original Hash
function CreateBoardHash(_board){
var Board = _board;
var width = ds_grid_width(Board);
var height = ds_grid_height(Board);
HashTable = CreateHashTable(width, height);
var FinalHash = 0;
for(var i = 0; i < width; i++;){
for(var j = 0; j < height; j++;){
var PieceToCheck = ds_grid_get(Board, i, j);
if(PieceToCheck == Pieces.BLANK){ continue; }
var HashEntry = ds_grid_get(HashTable, i, j);
var XorValue = MatchPieceToHashTableEntry(PieceToCheck, HashEntry);
FinalHash ^= XorValue;
}
}
if(FinalHash == 0){
//Error here
return;
}
//Set the instance variable for this original Hash
OriginalHash = FinalHash;
//Add it to the Current Hash stack
CurrentHash = FinalHash;
//Return said hash for the calling function
return FinalHash;
}
The problem comes in the FinalHash ^= XorValue; line, where XorValue each time is a random number, but FinalHash only ever comes out as 0 or -2147483648.
Can someone help with why this is the case and what I may be doing wrong with my XOR function?
Thanks to Reddit, I have fixed this. GameMaker must be doing something weird with the ^= operator, as the solution was as follows:
FinalHash = FinalHash ^ XorValue;

array - efficiency & general approach towards the question

Edit
**After quite a bit of playing around with my code I have written few versions, one of them is what I sought for.
I'd do the following:
Create a helper Set with all the numbers from 1 to 100 - O(n) in time and space
Create an (initially) empty Set to record the indexes with 0s - O(1)
Go over the array - O(n):
If the value is 0, add the index to the index set
If the value isn't 0, remove it from the helper Set
Go over the helper set, and assign the remaining values to the indexes saved to the index set - O(m), where m<=n
All in all - an O(n) solution in time and space.
In java:
int[] numbers = /* the array with missing numbers */
Set<Integer> allNumbers = IntStream.rangeClosed(1, 100).boxed().Collect(Collectors.toSet());
Set<Ineteger> missingIndexes = new HashSet<>();
for (int i = 0; i < numbers.length; ++i) {
if (numbers[i] == 0) {
missingIndexes.add(i);
} else {
allNumbers.remove(i);
}
}
Iterator<Integer> numberIter = allNumbers.iterator();
Iterator<Integer> indexIter = missingIndexes.iterator();
while (numberIter.hasNext() && indexIter.hasNext()) {
numbers[indexIter.next()] = numberIter.next();
}
If you can sacrifice a little more space to optimize for time.
Basically just create another missing array and fill it with what's missing by traversing your helper array.
Modified your original solution.
int input [] = {5,6,0,3,0,2,1};
int output [] = new int[input.length];
boolean [] helper = new boolean[input.length];
for(int i = 0; i <input.length; i++)
{
if(input[i] != 0)
helper[i] = true;
}
int missing [] = new int[input.length];
int missingCount = 0;
for(int j = 0; j < helper.length; j++)
{
if(!helper[j]){
missing[missingCount++] = j;
}
}
missingCount = 0;
for(int j = 0; j < input.length; j++){
if(input[j]==0){
input[j]=missing[missingCount++];
}
}
Below code can find the missing element and add them back in O(n) complexity:
notFound - Will store index or location of input array having number
with zero
numberDetails - Contains details of numbers whether its present in
input array or not(true or false)
Example: input[3] = false means 4 (3+1) is not present in input array
, input[4] = true means 5 (4+1) is present in input array
int input[] = { 5, 6, 0, 3, 0, 2, 1 };
int notFound[] = new int[input.length];
boolean[] numberDetails = new boolean[input.length];
int notFoundIndex=0;
for(int i=0;i<input.length;i++) {
if(input[i]==0) {
notFound[notFoundIndex++]=i;
}
else {
numberDetails[input[i]-1]=true;
}
}
notFoundIndex=0;
for(int j=0;j<numberDetails.length;j++) {
if(!numberDetails[j]) {
input[notFound[notFoundIndex++]] = j+1;
}
}
System.out.println(Arrays.toString(input));

Why CoffeeScript create a unexpected array for my loops

My CoffeeScript code:
myloop = () ->
size = parseInt $('#size').val
$('#result').css 'text-align', 'center'
for i in [1..size] by 1
for j in [1..i] by 1
$('#result').append "<img src='alpha.jpg' />"
$('#result').append "<br />"
Compile into Javascript:
// Generated by CoffeeScript 1.6.3
(function() {
var myloop;
myloop = function() {
var i, j, size, _i, _j, _results;
size = parseInt($('#size').val);
$('#result').css('text-align', 'center')
_results = [];
for (i = _i = 1; _i <= size; i = _i += 1) {
for (j = _j = 1; _j <= i; j = _j += 1) {
$('#result').append("<img src='alpha.jpg' />");
}
_results.push($('#result').append("<br />"));
}
return _results;
};
}).call(this);
As my expect that _result should not be generated.
It should be $('#result').append("<br />") instead.
How can I fixed this? Thx.
Look at the docs:
Sometimes functions end with loops that are intended to run only for their side-effects. Be careful that you're not accidentally returning the results of the comprehension in these cases, by adding a meaningful return value — like true — or null, to the bottom of your function.
To "fix" your code, just add a return statement at the end of your function.

EXC_ARM_DA_ALIGN crash

I'm having a EXC_ARM_DA_ALIGN crash in my application. Here's the code that Xcode flag as "malignant". On the simulator I don't have this crash, only on device, so I think it is a memory alignment problem.
Is there anyone who knows how to fix this code?
Thank you so much.
-(int) Save:(void*) pBuf {
int nNeedSize = sizeof(fType) + sizeof(sizeBrush) + sizeof(nBrushType) + sizeof(rcImage) + sizeof(count) + sizeof(data[0]) * count;
if (pBuf == nil)
return nNeedSize;
*(NSInteger*)pBuf = count; pBuf += sizeof(count);
*(BOOL*)pBuf = fType; pBuf += sizeof(fType);
(*(CGSize*)pBuf).width = sizeBrush.width;
(*(CGSize*)pBuf).height = sizeBrush.height;
pBuf += sizeof(sizeBrush);
*(NSInteger*)pBuf = nBrushType; pBuf += sizeof(nBrushType);
(*(CGRect*)pBuf).size.width = rcImage.size.width;
(*(CGRect*)pBuf).size.height = rcImage.size.height;
(*(CGRect*)pBuf).origin.x = rcImage.origin.x;
(*(CGRect*)pBuf).origin.y = rcImage.origin.y;
pBuf += sizeof(rcImage);
for (int i = 0; i < count; i++)
{
(*(CGPoint*)pBuf).x = data[i].x;
(*(CGPoint*)pBuf).y = data[i].y;
pBuf += sizeof(data[0]);
}
return nNeedSize;}
And here's another part flagged as malignant:
int i;
int nTotalSize = 0;
for (i = 0; i < m_Data.count; i++)
{
maskStroke* one = [m_Data objectAtIndex:i];
nTotalSize += [one Save:NULL];
}
unsigned char* buf = (unsigned char*)malloc(nTotalSize+100);
unsigned char* cur_ptr = buf;
for (i = 0; i < m_Data.count; i++)
{
maskStroke* one = [m_Data objectAtIndex:i];
cur_ptr += [one Save:cur_ptr];
}
You should use a struct or something sensible to serialize... if you can't do that, at least make sure your 32 bit and 16bit pointers are aligned to 16 or 32bit memory addresses.
*(int *foo)0x800002 (or 1) is probably going to end badly. Some processors have functions to un-screw unaligned memory addresses, but it is a waste of cycles and others (rightly) crash when you try to do this. If it doesn't crash, it is doing multiple memory accesses then combining them to create your unaligned address.
You have to make sure your pBuf pointers are aligned to sizeof(CGPoint), meaning pointers%sizeof(CGPoint) == 0

coffeescript - array initialisation

I have the following code that obviously works but I am fairly sure there is a more terse way of expressing this in coffeescript:
todos = []
for i in [1..10]
todos.push App.store.find App.Todo, i
todos = (App.store.find(App.Todo, i) for i in [1..10])
The enclosing parentheses indicate a list comprehension, which collects the return values into an array and returns it.
Consider the two following examples. The enclosing parentheses change how Coffeescript interprets the loop.
# With parentheses (list comprehension)
todos = (App.store.find(App.Todo, i) for i in [1..10])
# Without parentheses (plain old loop)
todos = App.store.find(App.Todo, i) for i in [1..10]
And the output:
// With parentheses
todos = (function() {
var _i, _results;
_results = [];
for (i = _i = 1; _i <= 10; i = ++_i) {
_results.push(App.store.find(App.Todo, i));
}
return _results;
})();
// Without parentheses
for (i = _i = 1; _i <= 10; i = ++_i) {
todos = App.store.find(App.Todo, i);
}