I've implemented the below as mask for some data:
function jEncryptDecrypt(data,key) {
let jKey = ''
let bytKey = [];
let bytData = [];
for (let i = 1; i < (data.length/key.length) +1; i++) {
jKey = jKey + key;
}
let str = jKey.substring(0, data.length);
for (let i = 0; i < str.length; ++i) {
var code = str.charCodeAt(i);
bytKey = bytKey.concat([code & 0xff, code / 256 >>> 0]);
}
let str2 = data
for (let i = 0; i < str2.length; ++i) {
var code = str2.charCodeAt(i);
bytData = bytData.concat([code & 0xff, code / 256 >>> 0]);
}
for (let i = 0; i < bytData.length; ++i) {
bytData[i] = bytData[i] ^ bytKey[i];
}
str3 = String.fromCharCode(...bytData)
str3 = str3.replace(/\0/g, '');
return str3;
}
For some outputs the bytes in bytData map to escape characters - depending on where I run the code I either get the character (JSFiddle) or I get \uXXXX (third party application). The output could end up being dealt with on different platforms/languages, so ideally I'd like to avoid special characters and just have characters in the 32 to 126 unicode range?
Is this possible? The application I'm implementing this in is pretty restrictive, so I can't use any libraries, just pure JS.
Edit
I've changed the code to the below, which outputs an array of numbers on the encrypt, and accepts them as an input on the decrypt
function jEncryptDecrypt(data,key) {
let jKey = ''
let bytKey = [];
let bytData = [];
//expand key to cover length of input
for (let i = 1; i < (data.length/key.length) +1; i++) {
jKey = jKey + key;
}
//shorten key to same lenght as input
let str = jKey.substring(0, data.length);
//loop over key to create array of numbers from unicode value
for (let i = 0; i < str.length; ++i) {
var code = str.charCodeAt(i);
bytKey = bytKey.concat([code & 0xff, code / 256 >>> 0]);
}
//if data input is array no need to do anything
if (Array.isArray(data)) {
bytData = data;
//otherwise loop over data to create array of numbers from unicode value
} else {
let str2 = data
for (let i = 0; i < str2.length; ++i) {
var code = str2.charCodeAt(i);
bytData = bytData.concat([code & 0xff, code / 256 >>> 0]);
}
}
//XOR each data value with each key value in turn
for (let i = 0; i < bytData.length; ++i) {
bytData[i] = (bytData[i] ^ bytKey[i]);
}
//if input was array return string, otherwise return array
if (Array.isArray(data)) {
str3 = String.fromCharCode(...bytData)
str3 = str3.replace(/\0/g, '');
return str3;
} else {
return bytData;
}
}
It's clunky and hacky but works for my needs. If there is an answer to the original question that would still be much appreciated!
Related
This address has 4 octets where each octet is a single byte (or 8 bits).
Because the above IP address has 32 bits, we can represent it as the unsigned 32 bit number: 2149583361
Complete the function that takes an unsigned 32 bit number and returns a string representation of its IPv4 address.
Examples
2149583361 - "128.32.10.1"
32 - "0.0.0.32"
0 - "0.0.0.0"
I tried to implement this way. It works on some tests, but for example, the program crashes on the number 1069972272 (because it starts translating everything from the beginning, not the end). How can I fix this program? I know it can be easier, but I would like to finish my version
function int32ToIp(int32){
let binaryNumber = int32.toString(2);
let buffer = [];
let result = [];
let i = 8;
for (let index = 0; index < 4; index++) {
buffer[index] = binaryNumber.slice(i - 8,i);
i += 8;
if(!buffer[index]) {
buffer[index] = '0';
}
}
for (let i = 0; i < buffer.length; i++) {
result[i] = parseInt(buffer[i], 2);
}
return result.toString().replace(/,/g, '.');
}
You need to left-pad the binary string with leading zeroes so that it is always 32 characters in length otherwise your code to extract the octet values doesn't work.
For example:
function int32ToIp(int32) {
let binaryNumber = int32.toString(2).padStart(32, '0');
let buffer = [];
let result = [];
let i = 8;
for (let index = 0; index < 4; index++) {
buffer[index] = binaryNumber.slice(i - 8, i);
i += 8;
if (!buffer[index]) {
buffer[index] = '0';
}
}
for (let i = 0; i < buffer.length; i++) {
result[i] = parseInt(buffer[i], 2);
}
return result.toString().replace(/,/g, '.');
}
console.log(int32ToIp(2149583361), 'expect', '128.32.10.1');
console.log(int32ToIp(1069972272), 'expect', '63.198.123.48');
I am working on my own Vigenere Cipher in JavaScript. I enjoy it. Anyway, the encryption and decryption is the same except decrypt() is '-' keyStr instead of '+' towards the bottom. The encryption works perfectly. But, for some reason, when decrypting, some of the chars come out as undefined randomly. I know the algorithm works for C++, Python, Java, and Swift. What is the error here?
I have tried printing the char indices in the alphabet array and the index values in decrypt() come out odd and I can't figure out why.
function ascii(x) {
return x.charCodeAt(0);
}
function decrypt() {
var alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var msgStr = "";
var keyTemp = "";
var keyStr = "";
var output = "";
var input = document.getElementById("inMsg").value;
var key = document.getElementById("key").value;
input = input.toUpperCase();
key = key.toUpperCase();
for(let i = 0; i < input.length; i++) {
for(let x = 0; x < alpha.length; x++) {
if (input[i] == alpha[x]) {
msgStr += alpha[x];
}
}
}
for(let i = 0; i < msgStr.length; i++) {
keyTemp += key[i % key.length]
}
for(let i = 0; i < keyTemp.length; i++) {
for(let x = 0; x < alpha.length; x++) {
if (keyTemp[i] == alpha[x]) {
keyStr += alpha[x];
}
}
}
for(let i = 0; i < msgStr.length; i++) {
let x = (ascii(msgStr[i]) - ascii(keyStr[i])) % 26;
output += alpha[x];
}
document.getElementById("outMsg").value = output;
}
The problem you are having is being caused by this line:
let x = (ascii(msgStr[i]) - ascii(keyStr[i])) % 26;
because
ascii(msgStr[i]) - ascii(keyStr[i])
can be negative.
The % operator isn't really a modulus operator in javascript its a remainder operator and it works a little differently.
From the link above, you should be able to do something more like this to get it to work:
let x = ((ascii(msgStr[i]) - ascii(keyStr[i])) % 26) + 26) % 26
I am looking for this stackoverflow question to be answered in Javascript.
So if my input is "word", the function should return:
word,
Word,
wOrd,
WOrd,
woRd,
WoRd,
etc..
here's what i have so far but it only produces the permutations (doesn't capitalize anything)
var perm = function(str){
var results = [];
var combos = function(reference, appendTo){
appendTo = appendTo || "";
if(reference.length === 0) {
results.push(appendTo);
}
for(var i = 0; i < reference.length; i++){
var current = reference.splice(i, 1);
combos(reference, appendTo+current);
reference.splice(i, 0, current)
}
}
combos(str.split(""));
return results;
}
perm("word");
One option would be generating capitalization permutations via binary logic.
As a simple example of the snippet below, consider the following table where the left column is the binary representation of the current permutation and the right column is the resulting capitalization:
0000 | word
1000 | Word
0100 | wOrd
1100 | WOrd
...
1111 | WORD
// Used to display the results
const write = (msg) => {
document.body.appendChild(document.createElement('div')).innerHTML = msg;
};
const input = "word";
const letters = input.split("");
const permCount = 1 << input.length;
for (let perm = 0; perm < permCount; perm++) {
// Update the capitalization depending on the current permutation
letters.reduce((perm, letter, i) => {
letters[i] = (perm & 1) ? letter.toUpperCase() : letter.toLowerCase();
return perm >> 1;
}, perm);
const result = letters.join("");
write(result);
}
Note that theoretically this approach would work all the way up to Number.MAX_SAFE_INTEGER, up to inputs of length 52, but realistically you'll run into performance issues.
var s = "word";
var sp = s.split("");
for (var i = 0, l = 1 << s.length; i < l; i++) {
for (var j = i, k = 0; j; j >>= 1, k++) {
sp[k] = (j & 1) ? sp[k].toUpperCase() : sp[k].toLowerCase();
}
var st = sp.join("");
var d = document.createElement("p");
d.appendChild(document.createTextNode(st));
document.body.appendChild(d);
}
With Nit's solution in mind, I wanted to offer a slightly refactored solution that may be easier to follow
var perm = function(str){
var results = [];
var arr = str.split("");
var len = Math.pow(arr.length, 2);
for( var i = 0; i < len; i++ ){
for( var k= 0, j = i; k < arr.length; k++, j >>=1){
arr[k] = ( j & 1 ) ? arr[k].toUpperCase() : arr[k].toLowerCase();
}
var combo = arr.join("");
results.push(combo);
}
return results;
}
perm("word");
// NOT AN ANWSER JUST WANT TO RUN CODE ON CHROMEBOOK
// Used to display the results
const write = (msg) => {
document.body.appendChild(document.createElement('div')).innerHTML = msg;
};
const input = "word";
const letters = input.split("");
const permCount = 1 << input.length;
for (let perm = 0; perm < permCount; perm++) {
// Update the capitalization depending on the current permutation
letters.reduce((perm, letter, i) => {
letters[i] = (perm & 1) ? letter.toUpperCase() : letter.toLowerCase();
return perm >> 1;
}, perm);
const result = letters.join("");
write(result);
}
I have an array, each cell of which can keep 4 bytes (2**32). This array presents memory of my VM I write in JS. Also I have string. Only one place I can keep this string - memory which I describe above.
I decided to present strings in memory as C-strings (with special symbol NUL as the end of string). My current implementation looks ugly and I asking you advice, is there any way to improve this approach? Maybe there are any other way to do it?
Part of code, which converts string to array:
// demoMemory presents memory model
var DEMO_VOLUME = 16;
var demoMemory = new Array(DEMO_VOLUME);
for (var i = 0; i < DEMO_VOLUME; i++) demoMemory[i] = 0;
// convert string to hexidecimal string
var string = "Hello, World!", hexString = "";
for (var i = 0; i < string.length; i++) {
hexString += string.charCodeAt(i).toString(16);
}
// convert hexidecimal string to array of strings
// each element of this array presents 4 symbols
var hexStringArray = hexString.match(/.{1,8}/g);
// add NUL (0x00) symbols to complete strings
while (hexStringArray[hexStringArray.length - 1].length != 8) {
hexStringArray[hexStringArray.length - 1] += "00";
}
// convert to integer array
for (var i = 0; i < hexStringArray.length; i++) {
demoMemory[i] = parseInt(hexStringArray[i], 16);
}
...and back to string:
// decode back to string
var resultString = "", decSymbolCode = 0;
for (var i = 0; i < demoMemory.length; i++) {
hexString = demoMemory[i].toString(16);
var hexSymbolCodeArray = hexString.match(/.{1,2}/g);
for (var j = 0; j < hexSymbolCodeArray.length; j++) {
decSymbolCode = parseInt(hexSymbolCodeArray[j], 16);
resultString += String.fromCharCode(decSymbolCode);
}
}
This code is inappreciable because I'm using JS Strings to build hexadecimal strings. I think it is possible to do with bitwise operations and masks, but I don't know, how. Maybe I'm wrong.
Here is a code that converts string to array of 32bit numbers and vice versa using masks and bitwise operations:
var demoMemory = [];
function stringToArray(str) {
var i,
length = str.length,
arr = [];
for(i=0; i<length; i+=4) {
arr.push(
(((str.charCodeAt(i) || 0) << 24)
|((str.charCodeAt(i+1) || 0) << 16)
|((str.charCodeAt(i+2) || 0) << 8)
|((str.charCodeAt(i+3) || 0)))
);
}
if(length % 4 === 0) {
arr.push(0);
}
return arr;
}
function arrayToString(arr) {
var i, j, chrCode,
length = arr.length,
str = [];
label:
for(i=0; i<length; i++) {
for(j=24; j>=0; j-=8) {
chrCode = (arr[i] >> j) & 0xFF;
if(chrCode) {
str.push(String.fromCharCode(chrCode));
} else {
break label;
}
}
}
return str.join('');
}
console.log(demoMemory = stringToArray('Hello, World!')); // => [1214606444, 1865162839, 1869769828, 553648128]
console.log(arrayToString(demoMemory)); // "Hello, World!"
Working example you can find here: http://jsbin.com/aselug/2/edit
I'm looking for the fastest method I can use to search a body of text for the indexes of multiple characters.
For example:
searchString = 'abcdefabcdef';
searchChars = ['a','b'];
// returns {'a':[0,6], 'b':[1,7]}
You should be able to use a regular expression to find all occurances of each character. Something like:
function findIndexes(find, str) {
var output = {};
for (var i = 0; i < find.length; i++) {
var m = [];
var r = new RegExp('.*?' + find[i], 'g');
var ofs = -1;
while ((x = r.exec(str)) != null) {
ofs += x[0].length;
m.push(ofs);
}
output[find[i]] = m;
}
return output;
}
Edit:
Did some changes, and now it works. :) However, as Javascript doesn't have a matches method to get all matches at once, it's not really any improvment over using indexOf... :P
Edit 2:
However, you can use a regular expression to find any of the characters, so you only need to loop the string once instead of once for each character. :)
function findIndexes(find, str) {
var output = {};
for (var i = 0; i < find.length; i++) output[find[i]] = [];
var r = new RegExp('.*?[' + find.join('') + ']', 'g');
var ofs = -1;
while ((x = r.exec(str)) != null) {
ofs += x[0].length;
output[x[0].substr(x[0].length-1,1)].push(ofs);
}
return output;
}
Assuming few letters to search for and many letters to search against (i.e. low number of letter, long strings), the latter is the most efficient, since you only go through the string once, and then test each letter.
The other one goes through the string as many times as there are letters to search for.
After timing a few single pass algorithms and Guffa's regex, I ended up going with this:
function findIndexesMultiPass(str,find) {
var x, output = {};
for (var i = 0; i < find.length; i++) {
output[find[i]] = [];
x = 0;
while ((x = str.indexOf(find[i], x)) > -1) {
output[find[i]].push(x++);
}
}
return output;
}
var searchString = "abcd abcd abcd";
var searchChars = ['a', 'b'];
var result = findIndexesMultiPass(searchString, searchChars);
// {'a':[0,5,10], 'b':[1,6,11]}
This turned out to be pretty slow:
function findIndexesOnePass(str,find) {
var output = {};
for (var i = 0; i < find.length; i++) {
output[find[i]] = [];
}
for (var i = 0; i < str.length; i++) {
var currentChar = str.charAt(i);
if (output[currentChar] !== undefined) {
output[currentChar].push(i);
}
}
return output;
}
var searchString = "abcd abcd abcd";
var searchChars = ['a', 'b'];
var result = findIndexesOnePass(searchString, searchChars);
// {'a':[0,5,10], 'b':[1,6,11]}
Rough times (indexes of 3 characters)
Google Chrome (Mac)
findIndexesMultiPass: 44ms
findIndexesOnePass: 799ms
findIndexesRegEx: 95ms
Safari
findIndexesMultiPass: 48ms
findIndexesOnePass: 325ms
findIndexesRegEx: 293ms
Firefox
findIndexesMultiPass: 56ms
findIndexesOnePass: 369ms
findIndexesRegEx: 786ms