Assignment in loop then breaking - javascript

I am coming from a C/Python background and the following JavaScript code is puzzling me.
Why is the value of c at the end of the program not 6? Because we are assigning and breaking afterwards. (I have run this on JSFiddle)
function funct() {
var bytes = new Uint8Array(6);
bytes[0] = 228;
bytes[1] = 191;
bytes[2] = 157;
bytes[3] = 233;
bytes[4] = 153;
bytes[5] = 186;
bytes[6] = 255;
bytes[7] = 17;
bytes[8] = 23;
bytes[9] = 223;
var c = 0;
for (var i = 0; i < bytes.length; i++) {
if (bytes[i] == 255) {
c = i;
break;
}
}
console.log(i);
console.log(c);
}
funct();
Output:
6
0

Your array is of size 6, but index 6 is the 7th entry. You need to allocate more space for your array:
function funct() {
var bytes = new Uint8Array(10);
bytes[0] = 228;
bytes[1] = 191;
bytes[2] = 157;
bytes[3] = 233;
bytes[4] = 153;
bytes[5] = 186;
bytes[6] = 255;
bytes[7] = 17;
bytes[8] = 23;
bytes[9] = 223;
var c = 0;
for (var i = 0; i < bytes.length; i++) {
if (bytes[i] == 255) {
c = i;
break;
}
}
console.log(i);
console.log(c);
}
funct();

bytes has 6 elements it breaks at 5 never reach the if statement; on
bytes = new Uint8Array(6); you should declare it like bytes = new Uint8Array(10)

You have defined var bytes = new Uint8Array(6) which means it can hold only 6 elements and rest are ignored from bytes[6]... bytes[9]. Which means that ifcondition is never true and loop exist naturally without break.
Hope this helps !!

you are asking for trouble by defining the size of your array:
var bytes = new Uint8Array(6);
instead do this;
var bytes = [];
bytes.push(228);
bytes.push(191);
bytes.push(157);
etc...
or:
var bytes = [228, 191, 157];

Related

Why aren't the bigInts adding?

I made a NodeJS program that takes pairs of integers (m, n) as input and prints the sum of their factorials (facm, factn) on the console. I used the BigInteger.js library so that I can calculate using big numbers.
But when I input 20 1, the program just outputs the value of 20! instead of 20! + 1!. It doesn't add. Why?
(For some reason, it works for when the two inputs are the same, for example, 20 20. It also works when the values are smaller.)
var input = require('fs').readFileSync('/dev/stdin', 'utf8');
var lines = input.split('\n');
var bigInt = require("big-integer");
for (var i = 0; lines[i] != ""; i++) {
var strings = lines[i].split(" ");
var m = parseInt(strings[0]);
var n = parseInt(strings[1]);
var factm = bigInt(1);
var factn = bigInt(1);
for (var a = m; a != 0; a--) {
factm = factm.multiply(a);
}
for (var b = n; b != 0; b--) {
factn = factn.multiply(b);
}
var sum = factm.add(factn);
console.log(sum.toString());
}
Replacing var sum = factm.add(factn) with var sum = factm.add(factn.toString()) solves the problem.

c pointers and javascript

I have been working on a conversion of a C code into javascript. But they just don't return the same data.
I have an idea on how to handle the pointers. In javascript I'll create an array.
Note: This are not the full code, only partials
Origin:
// file.h
unsigned char m_aucState0[256];
unsigned char m_aucState[256];
unsigned char m_ucI;
unsigned char m_ucJ;
unsigned char* m_pucState1;
unsigned char* m_pucState2;
// file.c
unsigned char *pucKeyData
for(i=0; i<256; i++)
{
m_pucState1 = m_aucState0 + i;
m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
m_pucState2 = m_aucState0 + m_ucJ;
//Swaping
m_ucTemp = *m_pucState1;
*m_pucState1 = *m_pucState2;
*m_pucState2 = m_ucTemp;
m_ucI = (m_ucI + 1) % iKeyLen;
}
memcpy(m_aucState, m_aucState0, 256);
Javascript:
// buffer or array???
this.m_aucState0 = new Buffer(256)
this.m_aucState = new Buffer(256)
this.m_ucI
this.m_ucJ
this.m_pucState1 = []
this.m_pucState2 = []
for (var i = 0; i < 256; i++)
{
this.m_pucState1 = this.m_aucState0 + i
this.m_ucJ += this.m_pucState1[0] + (pucKeyData[0] + this.m_ucI)
this.m_pucState2 = this.m_aucState0 + this.m_ucJ
//Swaping
this.m_ucTemp = this.m_pucState1[0]
this.m_pucState1[0] = this.m_pucState2[0]
this.m_pucState2[0] = this.m_ucTemp
this.m_ucI = (this.m_ucI + 1) % iKeyLen
}
this.m_aucState.copy(this.m_aucState0, 0, 0, 256)
So my idea is because a pointer returns an address, that address contains the first byte of the pointer data. So if in an array I could just also point to the first index of the array right?
Is what I did above right?
Just for context let me add 1 function:
Javascript:
Crypt.prototype.setup = function(pucKeyData, iKeyLen) {
if (iKeyLen < 1)
throw new Error("Key Length should be at least 1")
var i;
for (i = 0; i < 256; i++)
this.m_aucState0[i] = i
this.m_ucI = 0
this.m_ucJ = 0
for (var i = 0; i < 256; i++)
{
this.m_pucState1 = this.m_aucState0 + i
this.m_ucJ += this.m_pucState1[i] + (pucKeyData[i] + this.m_ucI)
this.m_pucState2 = this.m_aucState0 + this.m_ucJ
//Swaping
this.m_ucTemp = this.m_pucState1[i]
this.m_pucState1[i] = this.m_pucState2[i]
this.m_pucState2[i] = this.m_ucTemp
this.m_ucI = (this.m_ucI + 1) % iKeyLen
}
this.m_aucState.copy(this.m_aucState0, 0, 0, 256)
//Initialize Indexes
this.m_ucI = 0
this.m_ucJ = 0
//Initialization Finished
this.m_bInit = true
}
CPP:
void CArcfourPRNG::SetKey(unsigned char *pucKeyData, int iKeyLen)
{
if(iKeyLen < 1)
throw exception("Key Length should be at least 1");
int i;
for(i=0; i<256; i++)
m_aucState0[i] = i;
m_ucI = 0;
m_ucJ = 0;
for(i=0; i<256; i++)
{
m_pucState1 = m_aucState0 + i;
m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
m_pucState2 = m_aucState0 + m_ucJ;
//Swaping
m_ucTemp = *m_pucState1;
*m_pucState1 = *m_pucState2;
*m_pucState2 = m_ucTemp;
m_ucI = (m_ucI + 1) % iKeyLen;
}
memcpy(m_aucState, m_aucState0, 256);
//Initialize Indexes
m_ucI = 0;
m_ucJ = 0;
//Initialization Finished
m_bInit = true;
}
What is the difference of m_pucState1 and *m_pucState1 in this:
m_pucState1 = m_aucState + m_ucI;
m_ucJ += *m_pucState1;
In Javascript, there are typed buffer objects: http://www.javascripture.com/ArrayBuffer
You will also find something about the ctypes collection, but in my understanding they are used only for native OS library calls.
Also, I don't know a native JS Buffer object like you mention it. There is one in NodeJS, but I don't know its features.
If you insist of translating your code one-by-one, then these typed buffer objects may greatly support you. I think it's not a good way as while translating from C to Javascript, your terminology alters anyway. It alters from adding long pointer values to forming array indices.
Here is one problem example in your translation:
In C, you write:
m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
In Javascript, you write:
this.m_ucJ += this.m_pucState1[0] + (pucKeyData[0] + this.m_ucI);
The brackets in the C term make m_ucI altering the address. So in Javascript this should rather be in the square brackets, somehow like this:
this.m_ucJ += this.m_pucState1[0] + pucKeyData[0 + this.m_ucI];
and then you can skip the "0 +". This shows how one-by-one translation between such different languages is full of traps.
So let's assume that we will use the simplest Javascript object, which is the array []. Then this is my suggestion. It's a draft, but it should give you a thorough idea:
// Define arrays
var aState0 = []; // m_aucState0
var aState = []; // m_aucState
// Define helpers
var state1Index; // *m_pucState1
var state2Index; // *m_pucState2
var i; // m_uci. There is no such thing as "uc" in Javascript.
var j; // m_ucj
var iLoop; // i in loop.
// It's readable to have this constant.
var bufferLength = 255;
// Somewhere we need:
var keyData;
var temp;
var iKeyLen;
// Just for here, give the array a size. So it's done in Javascript.
// Alternatively, fill it with 256 values from anywhere.
aState0[bufferLength] = 0;
// console.log(state0.length) will now print 256
// ...
// init i, j, iKeyLen ...
// ...
for (iLoop = 0; iLoop <= bufferLength; iLoop++) {
// This:
// m_pucState1 = m_aucState0 + i;
// m_ucJ += *m_pucState1 + *(pucKeyData+m_ucI);
// becomes:
state1Index = iLoop;
j += aState0[state1Index] + keyData[i];
// This:
// m_pucState2 = m_aucState0 + m_ucJ;
// becomes:
state2Index = j;
// This:
// m_ucTemp = *m_pucState1;
// *m_pucState1 = *m_pucState2;
// *m_pucState2 = m_ucTemp;
// becomes:
temp = aState0[state1Index];
aState0[state1Index] = aState0[state2Index];
aState0[state2Index] = temp;
// This:
// m_ucI = (m_ucI + 1) % iKeyLen;
// becomes:
i = (i+1) % iKeyLen;
}
// this:
// memcpy(m_aucState, m_aucState0, 256);
// would be a clone. So you'd need jQuery or else. But you can simply write:
for (index in state0) {
state[index] = state0[index];
}
Finally, you can drop j as it is equal to state2Index, and state1Index equal to iLoop.
But this is a puzzle where you will probably have to use paper and pencil and to draw some boxes and arrows to get clear with.
Hth :-)

JavaScript syntax issue

I'm doing "fifteen puzzle" game. I'm only a beginner, so I chose this project to implement. My problem is shuffle algorithm :
function shuffle() {
$('td').empty();
var p = 0;
var f = 0;
do {
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
var rand = arr[Math.floor(Math.random() * arr.length)];
if ($('#' + rand).is(':empty')) {
p = p + 1;
document.getElementById(rand).textContent = p
var f = $('td').not(":empty").length;
} else {}
} while (f < 15)
That works cool, but I've heard that almost 50% of all random shuffle like mine is unsolvable. So I found math formula at wikipedia.org for this game, explaining how you can avoid that.
Here's modified algorithm that doesn't work either. The way I know it is alert stuff: it launches only 2 times instead of 31.
array = [];
function algorithm (){
// alert('works')
for (var c=16; c<17; c++){
document.getElementById(c).textContent = '100';
}
for (var i=1; i<16; i++){
var curId = document.getElementById(i).id;
var curIdNum = Math.floor(curId);
alert('works')
var curIn = document.getElementById(i).textContent;
var curInNum = Math.floor(curIn);
array.push(i);
array[i] = new Array();
for (var j=1; j<15; j++){
var nextId = curIdNum + j; //curIdNum NOT cerIdNum
var nextIn = document.getElementById(nextId).textContent;
//alert('works')
if (nextId < 16){
var nextInNum = Math.floor(nextIn);
if (curInNum > nextInNum){
array[i].push(j)
}
}
}
var sum = 0;
for (var a=0; a<15; a++){
var add = array[a].length;
sum = sum + add;
}
var end = sum + 4;
if (end % 2 == 0){
document.getElementById('16').textContent = "";
}
else {
shuffle();
}
}
}
The question is the same:
What's wrong? Two-dimensional array doesn't work.If you've got any questions - ask.
Just to make it clear: 2 for loops with i and j should make a 2-dimensional array like this [ this is " var i" -->[1,3,4,5,7], this is "var i" too-->[5,7,9,14,15]]. Inside each i there's j. The for loop with var a should count the number of js inside each i. if the number of js is even, the code is finished and shuffle's accomplished, otherwise shuffle should be made once again.
var nextId = cerIdNum + j;
in that fiddle, I don't see this cerIdNum declared & defined neither as local nor as global variable, I suppose that is curIdNum
Please use the below definition of algorithm and let us know if this works. Basically, the alert messages would come only twice, since there were usages of undefined variables. For the purpose of illustration, I have placed comments at where the problem points occured. Due to these problems, your script would stop executing abruptly thereby resulting in the behavior you described.
Oh and by the way - I did not have time to go through the Wiki link provided - hence you will have to verify your logic is correct. However, I have definitely resolved the errors causing the behavior you observed.
As an aside - consider using jQuery, your code will be a lot cleaner...
function algorithm (){
// alert('works')
for (var c=16; c<17; c++){
document.getElementById(c).textContent = '100';
}
for (var i=1; i<16; i++){
var curId = document.getElementById(i).id;
var curIdNum = Math.floor(curId);
alert('works')
var curIn = document.getElementById(i).textContent;
var curInNum = Math.floor(curIn);
array.push(i);
for (var j=1; j<15; j++){
var nextId = curIdNum + j; //curIdNum NOT cerIdNum
var nextIn = document.getElementById(nextId).textContent;
//alert('works')
if (nextId < 16){
var nextInNum = Math.floor(nextIn);
if (curInNum > nextInNum){
array.push(j) //array[i].push does not make sense
}
}
}
var sum = 0;
for (var a=0; a<15; a++){
var add = array.length; //array[1].length does not make sense
sum = sum + add;
}
var end = sum + 4;
if (end % 2 == 0){
document.getElementById('16').textContent = "";
}
else {
shuffle();
}
}
}
I found the solution by totally rewriting the code. Thank everyone for help!
Here's what do work:
function shuffle (){
press = 1;
$('td').empty().removeClass();
p=0;
var f;
do {
var arr=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
var rand=arr[Math.floor(Math.random()*arr.length)];
if ($('#'+ rand).is(':empty')){
p = p + 1;
document.getElementById(rand).textContent = p
var f = $('td').not(":empty").length;
}
else{}
}while(f < 15){
winChance();
}
}
function winChance (){
array = [];
for (i=1;i<16;i++){
array[i]= new Array();
var currentId = $('#' + i).attr('id');
var currentIn = $('#' + i).html()
var currentIdNum = parseInt(currentId, 10);
var currentInNum = parseInt(currentIn, 10);
for (j=1;j<16;j++){
var nextId = currentIdNum + j;
if (nextId < 16){
var nextIn = $('#' + nextId).html();
var nextInNum = parseInt(nextIn, 10);
if (currentInNum > nextInNum){
array[i].push(j);
}
}
}
}
checkSum();
}
function checkSum(){
var sum = 0;
for (var a=1; a<16; a++){
var add = array[a].length;
sum = sum + add;
}
var end = sum + 4;
if (end % 2 == 0){}
else {
shuffle();
}
}

jQuery Number array, everything above a certain number

I have a pricing array
pricing = new Array();
pricing[1] = 35;
pricing[2] = 60;
pricing[3] = 84;
pricing[4] = 104;
pricing[5] = 120;
pricing[6] = 132;
pricing[7] = 140;
pricing[8] = 144;
pricing[9] = 153;
pricing[10] = 160;
Everything below 10 has a price, everything above 10 will have the same price as ten
It only goes to 20 so what i did originally was just repeat the price for 11 - 20. But thats wasteful, how can I tell me array that everything > 10 = 160
p.s my final version of this is condensed :)
You can leave your array as is and use a function like:
var getPrice = function(arr, index){
return arr[index > 10 ? 10 : index];
}
var pricing = [], i;
pricing.push(35);
pricing.push(60);
pricing.push(84);
pricing.push(104);
pricing.push(120);
pricing.push(132);
pricing.push(140);
pricing.push(144);
pricing.push(153);
for (i = 0; i < 11; i++) {
pricing.push(160);
}
I also made a JSFiddle for this.
#CD was stating that the push function can take multiple items to append to the array. The code would look like this then:
var pricing = [], value = 160;
pricing.push(35);
pricing.push(60);
pricing.push(84);
pricing.push(104);
pricing.push(120);
pricing.push(132);
pricing.push(140);
pricing.push(144);
pricing.push(153);
pricing.push(value, value, value, value, value, value, value, value, value, value, value);
i=10;
while(i--) { pricing[i+10] = 160; }
You missed the first entry in your array (since it is 0 based). I would change it to this:
pricing = new Array(20);
pricing[0] = 35;
pricing[1] = 60;
pricing[2] = 84;
pricing[3] = 104;
pricing[4] = 120;
pricing[5] = 132;
pricing[6] = 140;
pricing[7] = 144;
pricing[8] = 153;
pricing[9] = 160;
Then you can set the last 10 using this:
for(var x = 10; x < pricing.length; x++) {
pricing[x] = pricing[9];
}
Example fiddle.
pricing = new Array();
var arraySize = 100;
pricing[1] = 35;
pricing[2] = 60;
pricing[3] = 84;
pricing[4] = 104;
pricing[5] = 120;
pricing[6] = 132;
pricing[7] = 140;
pricing[8] = 144;
pricing[9] = 153;
for(var x = 10; x < arraySize; x++)
pricing[x] = 160
console.log(pricing);

For Loops inside For Loops inside For Loops... = Problems

So. I have 4 for loops inside other for loops in JS, and my code appears (FireBug agrees with me) that my code is syntactically sound, and yet it refuses to work. I'm attempting to calculate the key length in a vigenere cipher through the use of the Index of Coincidence, and Kappa tests <- if that helps any.
My main problem is that the task seems to be too computationally intensive for Javascript to run, as Firefox shoots up past 1GB of memory usage, and 99% CPU when I attempt to run the keylengthfinder() function. Any ideas of how to solve this problem, even if it takes much longer to calculate, would be greatly appreciated. Here's a link to the same code - http://pastebin.com/uYPBuZZz - Sorry about any indenting issues in this code. I'm having issues putting it on the page correctly.
function indexofcoincidence(text){
text = text.split(" ").join("").toUpperCase();
var textL = text.length;
var hashtable = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (d=0; d<=25; d++) {
for (i=0; i < textL; i++){
if (text.charAt(i) === alphabet.charAt(d)){
hashtable[d] = hashtable[d] + 1;
}
}
}
var aa = hashtable[0]/textL;
var A = aa*aa;
var bb = hashtable[1]/textL;
var B = bb*bb;
var cc = hashtable[2]/textL;
var C = cc*cc;
var dd = hashtable[3]/textL;
var D = dd*dd;
var ee = hashtable[4]/textL;
var E = ee*ee;
var ff = hashtable[5]/textL;
var F = ff*ff;
var gg = hashtable[6]/textL;
var G = gg*gg;
var hh = hashtable[7]/textL;
var H = hh*hh;
var ii = hashtable[8]/textL;
var I = ii*ii;
var jj = hashtable[9]/textL;
var J = jj*jj;
var kk = hashtable[10]/textL;
var K = kk*kk;
var ll = hashtable[11]/textL;
var L = ll*ll;
var mm = hashtable[12]/textL;
var M = mm*mm;
var nn = hashtable[13]/textL;
var N = nn*nn;
var oo = hashtable[14]/textL;
var O = oo*oo;
var pp = hashtable[15]/textL;
var P = pp*pp;
var qq = hashtable[16]/textL;
var Q = qq*qq;
var rr = hashtable[17]/textL;
var R = rr*rr;
var ss = hashtable[18]/textL;
var S = ss*ss;
var tt = hashtable[19]/textL;
var T = tt*tt;
var uu = hashtable[20]/textL;
var U = uu*uu;
var vv = hashtable[21]/textL;
var V = vv*vv;
var ww = hashtable[22]/textL;
var W = ww*ww;
var xx = hashtable[23]/textL;
var X = xx*xx;
var yy = hashtable[24]/textL;
var Y = yy*yy;
var zz = hashtable[25]/textL;
var Z = zz*zz;
var Kappa = A+B+C+D+E+F+G+H+I+J+K+L+M+N+O+P+Q+R+S+T+U+V+W+X+Y+Z;
var Top = 0.027*textL;
var Bottom1 = 0.038*textL + 0.065;
var Bottom2 = (textL - 1)*Kappa;
var KeyLength = Top/(Bottom2 - Bottom1) ;
return Kappa/0.0385;
}
function keylengthfinder(text){
// Average Function Definition
Array.prototype.avg = function() {
var av = 0;
var cnt = 0;
var len = this.length;
for (var i = 0; i < len; i++) {
var e = +this[i];
if(!e && this[i] !== 0 && this[i] !== '0') e--;
if (this[i] == e) {av += e; cnt++;}
}
return av/cnt;
}
// Begin the Key Length Finding
var textL = text.length;
var hashtable = new Array(0,0,0,0,0,0,0,0,0,0,0,0);
for (a = 0; a <= 12; a++){ // This is the main loop, testing each key length
var stringtable = [];
for (z = 0; z <= a; z++){ // This allows each setting, ie. 1st, 4th, 7th AND 2nd, 5th, 8th to be tested
for (i = z; i < textL; i + a){
var string = '';
string = string.concat(text.charAt(i)); // Join each letter of the correct place in the string
stringtable[z] = indexofcoincidence(string);
}
}
hashtable[a] = stringtable.avg();
}
return hashtable;
}
Your problem is definitely right here
for (i = z; i < textL; i + a){
var string = '';
string = string.concat(text.charAt(i)); // Join each letter of the correct place in the string
stringtable[z] = indexofcoincidence(string);
}
Notice that if a=0 i never changes and therefore you are in an infinite loop.
Array.prototype.avg = function() {...}
should be only done once, and not every time keylengthfinder is called.
var Top = 0.027*textL;
var Bottom1 = 0.038*textL + 0.065;
var Bottom2 = (textL - 1)*Kappa;
var KeyLength = Top/(Bottom2 - Bottom1) ;
return Kappa/0.0385;
Why do you computer those variables if you don't use them at all?
var string = '';
string = string.concat(text.charAt(i)); // Join each letter of the correct place in the string
stringtable[z] = indexofcoincidence(string);
I don't know what you are trying to do in here. The string will always be only one character?
for (i = z; i < textL; i + a) {
...
stringtable[z] = ...
}
In this loop, you are computing values for i from z to textL - but you overwrite the same array item each time. So it would be enough to compute the stringtable[z] for i=textL-1 - or your algorithm is flawed.
A much shorter and more concise variant of the indexofcoincidence function:
function indexofcoincidence(text){
var l = text.replace(/ /g, "").length;
text = text.toUpperCase().replace(/[^A-Z]/g, "");
var hashtable = {};
for (var i=0; i<l; i++) {
var c = text.charAt(i);
hashtable[c] = (hashtable[c] || 0) + 1;
}
var kappa = 0;
for (var c in hashtable)
kappa += hashtable[c] * hashtable[c];
return kappa/(l*l)/0.0385;
}
All right. Now that we found your problem (including the infinite loop in case a=0, as detected by qw3n), let's rewrite the loop:
function keylengthfinder(text) {
var length = text.length,
probabilities = []; // probability by key length
maxkeylen = 13; // it might make more sense to determine this in relation to length
for (var a = 1; a <= maxkeylen; a++) { // testing each key length
var stringtable = Array(a); // strings to check with this gap
// read "a" as stringtable.length
for (var z = 0; z < a; z++) {
var string = '';
for (var i = z; i < textL; i += a) {
string += text.charAt(i);
}
// a string consisting of z, z+a, z+2a, z+3a, ... -th letters
stringtable[z] = string;
}
var sum = 0;
// summing up the coincidence indizes for current stringtable
for (var i=0; i<a; i++) {
sum += indexofcoincidence(stringtable[i]);
}
probabilities[a] = sum / a; // average
}
return probabilities;
}
Every of the loop statements has changed against your original script!
Never forget to declare the running variable to be local (var keyword)
a needs to start at zero - a key must have a minimum length of 1
to run from 1 to n, use i=1; i<=n; i++
to run from 0 to n-1, use i=0; i<n; i++ (nearly all loops, especially on zero-based array indizes).
Other loops than those two never occur in normal programs. You should get suspicious if you have loops from 0 to n or from 1 to n-1...
The update expression needs to update the running variable. i++ is a shortcut for i+=1 is a shortcut for i=i+1. Your expression, i + a, did not assign the new value (apart from the a=0 problem)!

Categories

Resources