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;
Related
I have a small txt file that I would like to write to BPF here. Here is what my python code looks like for BPF but I am unable to print out anything as of now. I keep ending up with a Failed to load program: Invalid argument with a bunch of register errors. As of now my string basically says hello, world, hi
BPF_ARRAY(lookupTable, char, 512);
int helloworld2(void *ctx)
{
//print the values in the lookup table
#pragma clang loop unroll(full)
for (int i = 0; i < 512; i++) {
char *key = lookupTable.lookup(&i);
if (key) {
bpf_trace_printk("%s\n", key);
}
}
return 0;
}
Here is the Python code:
b = BPF(src_file="hello.c")
lookupTable = b["lookupTable"]
#add hello.csv to the lookupTable array
f = open("hello.csv","r")
file_contents = f.read()
#append file contents to the lookupTable array
b_string1 = file_contents.encode('utf-8')
b_string1 = ctypes.create_string_buffer(b_string1)
lookupTable[0] = b_string1
f.close()
b.attach_kprobe(event=b.get_syscall_fnname("clone"), fn_name="helloworld2")
b.trace_print()
I have the error linked in this pastebin since it's so long:
BPF Error
One notable error is the mention of infinite loop detected which is something I would need to check out.
The issue is that i is passed by pointer in bpf_map_lookup_elem, so the compiler can't actually unroll the loop (from its point of view, i may not linearly increase).
Using an intermediate variable is enough to fix this:
BPF_ARRAY(lookupTable, char, 512);
#define MAX_LENGTH 1
int helloworld2(void *ctx)
{
//print the values in the lookup table
#pragma clang loop unroll(full)
for (int i = 0; i < 1; i++) {
int k = i;
char *key = lookupTable.lookup(&k);
if (key) {
bpf_trace_printk("%s\n", key);
}
}
return 0;
}
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));
For the following code:
inc = -> value = (value ? 0) + 1
dec = -> value = (value ? 0) - 1
print = -> console.log value ? 0
How can you make this work properly, so inc and dec close upon value instead of creating separate function-local variables, in the way other than explicitly assigning something to value?
In plain Javascript, you would just declare var value at outer scope:
var value;
function inc() { value = (value || 0) + 1; };
function dec() { value = (value || 0) - 1; };
function print() { console.log(value || 0); };
What is CoffeeScript way for exactly the same thing?
In CoffeeScript, the way to introduce a local variable is to assign to the variable in the appropriate scope.
This is simply the way that CoffeeScript was defined and as such is similar to Python or Ruby, which do not require a "variable declaration", except CoffeeScript also allows forward access. A side-effect is that one cannot shadow a lexical variable.
Just as with the placement of var in JavaScript, where this assignment is done (as long as it is in the correct scope) does not affect the scope of the variable.
Given
x = undefined
f = -> x
// JS
var f, x;
x = void 0;
f = function() {
return x;
};
Given
f = -> x
x = undefined
// JS
var f, x;
f = function() {
return x;
};
x = void 0;
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);
}
I have a WCF RESTful service that returns a complex object with the following format:
{"GetMatterSearchRESTResult":{"BreakDownBypracticeGroups":[],"BreakDownByCountry":[],"TotalMatterCount":0}}.
When I have this value return, I try to access it using the following code below:
if (executor.get_responseAvailable) {
var serviceResults = executor.get_responseData();
var prasevalues = eval('(' + serviceResults + ')');
var mattersResults = prasevalues.GetMatterSearchRESTResult;
for (var a = 0; a < mattersResults.length; a++) {
alert(mattersResults[a].TotalMatterCount);
var pgBreakDown = mattersResults[a].BreakDownBypracticeGroups;
for (var b = 0; b < pgBreakDown.length; b++) {
alert(pgBreakDown[b].DepartmentName + " " + pgBreakDown[b].Count);
}
}
}
return false;
After the eval function called, i get an undefined value. Please help.
GetMatterSearchRESTResult isn't an array, it's an object, so matterResults won't have a length method. Make GetMatterSearchRESTResult an array of objects:
{"GetMatterSearchRESTResult":[{"BreakDownBypracticeGroups":[],"BreakDownByCountry":[],"TotalMatterCount":0}]}
Edit: Or, if that's not possible, you don't need to loop through the object