Convert string to array of integers and vice versa in JavaScript - javascript

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

Related

Javascript Vernam Cipher - ensure output between unicode 32 and 126

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!

how to fix: found a substring in string

i have this problem
strArr is ["aaabaaddae", "aed"] then the smallest substring of N that contains the characters a, e, and d is "dae" located at the end of the string. So for this example your program should return the string dae
strArr is ["aabdccdbcacd", "aad"] then the smallest substring of N that contains all of the characters in K is "aabd" which is located at the beginning of the string. Both parameters will be strings ranging in length from 2 to 50 characters and all of K's characters will exist somewhere in the string N. Both strings will only contains lowercase alphabetic characters.
i used js but now i am trying to use swift
Input:["ahffaksfajeeubsne", "jefaa"]
Output:"aksfaje"
this works with js
function MinWindowSubstring(strArr){
var min = null;
var n = strArr[0];
var k = strArr[1];
for (var i = 0; i < n.length; i++) {
for (var j = i + 1; j <= n.length; j++) {
var sub = n.slice(i, j);
if(checkK(sub, k)){
if (min === null || sub.length < min.length){
min = sub;
}
}
}
}
return min;
}
function checkK(sub, k){
var h = k.split('');
for (var i = 0; i < sub.length; i++) {
var char = sub[i];
var index = h.indexOf(char);
if(index > -1){
h.splice(index, 1);
}
}
if(h.length === 0){
return true;
} else {
return false;
}
}
console.log(MinWindowSubstring(["aabdccdbcacd", "aad"])); // aabd
console.log(MinWindowSubstring(["ahffaksfajeeubsne", "jefaa"])); // aksfaje
this is my code with swift
func indexChar(str:String, char: Character) -> Int
{
let index = str.firstIndex(of: char)
if index?.encodedOffset != nil
{
return (index?.encodedOffset)!
}
else
{
return 0
}
}
var arrStr = ["ahffaksfajeeubsne", "jefaa"]
var str1 = arrStr[0]
var str2 = arrStr[1]
var arrIndex = [Int]()
for letra in str2
{
var index = indexChar(str: str1, char: letra)
arrIndex.append(index)
}
print(String(Array(str1)[arrIndex.min()!...arrIndex.max()!]))
with js
Input:["ahffaksfajeeubsne", "jefaa"]
Output:"aksfaje"
with swift
input ["ahffaksfajeeubsne", "jefaa"]
output ahffaksfaje

Why am I getting random undefined chars in my decryption output in my Vigenere Cipher algorithm?

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

JavaString loop through string and break string into sub strings

I want to loop through set of strings and break them into sub strings by removing two characters and storing them into an array.
lets say two stings are returned, the number of characters will always be multiple of 2.
AADDFFCC
GGDD
The first string will give me AADDFF,AADD,AA
The second string will give me GG.
i want to store all sub string into a single array.
So based upon above example i should end up with.
subString = ["AADDFF","AADD","AA","GG"]
This is my incomplete attempt.
var StringArray = ["AADDFFCC","GGDD"] //this could be indefinite length
var subString = [];
var StringArrayLength = StringArray.length;
var loopCurrentString;
var loopCurrentSubString
for (var i = 0; i < StringArrayLength; i += 2) {
loopCurrentString = StringArray[i];
loopCurrentSubString = loopCurrentString.substring(0, loopCurrentString.length - 2);
}
for (var i = 0; i < StringArrayLength; i ++) {
//get element
loopCurrentString = StringArray[i];
//add substrings in the array
while(loopCurrentString.length>2){
loopCurrentSubString = loopCurrentString.substring(0, loopCurrentString.length - 2);
substring.push(loopCurrentSubString);
}
}
Here is an implementation with nested for loops:
const data = ["AADDFFCC", "GGDD"]
const endResult = []
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < data[i].length; j += 2) {
if (j != 0)
endResult.push(data[i].slice(0, data[i].length - j))
}
}
console.log(endResult)
You could do this by using reduceRight to chunk the array into the desired pieces starting from the right side:
const data = ["AADDFFCC","GGDD"]
const chunkBy = (arr, by=2) => [...arr].reduceRight((r,c,i,a) =>
((((a.length-1) - i)%by == 0 && a.length-1 != i) ?
r.push(a.slice(0, i+1).reduce((r,c) => `${r}${c}`)) :
0, r),[])
console.log(data.reduce((r,c) => [...chunkBy(r), ...chunkBy(c)]))
And on the end stitch them together via ES6 spread operator.

I am trying to loop through an array of all the alphabets and capitalize every other alphabet. any solutions?

this is the code i came up with:
var alpha = "abcdefghijklmnopqrstuvwxyz".split('');
// console.log(alpha);
// console.log(alpha.length);
for(i=0; i < alpha.length + 1; i++){
if (alpha.indexOf('a', +1) % 2 === 0){
console.log(indexOf('a'));
} else {
console.log("didn't work");
}
};
A simple loop with a step:
for (var i = 0; i < alpha.length; i+=2) {
alpha[i] = alpha[i].toUpperCase();
}
alpha.join(''); // AbCdEfGhIjKlMnOpQrStUvWxYz
If aBcDeFgHiJkLmNoPqRsTuVwXyZ is what you want to achieve, than you can do something like this:
var alpha = 'abcdefghijklmnopqrstuvwxyz';
var result = '';
for (var i = 0; i < alpha.length; i++) {
if ((i + 1) % 2 === 0){
result += alpha[i].toUpperCase();
} else {
result += alpha[i];
}
}
console.log(result);
You can map your array and upper case every second character:
var alpha = "abcdefghijklmnopqrstuvwxyz".split('').map(function(ch, i) {
return i % 2 ? ch.toUpperCase() : ch;
});
console.log(alpha);
The issue with strings is that you can't edit them, once created they stay the same. Most actions on them create a new string.
To avoid doing this lots of times, we do the following
var alpha = 'abcdefghijklmnopqrstuvwxyz'.split('');
Convert the string into an an array
for (var i = 0; i< alpha.length; i++) {
if(i % 2 == 0) {
go down the array, and for every other entry (i % 2 gives us 0 every other time).
alpha[i] = alpha[i].toUpperCase();
convert it to upper case
}
}
var newString = alpha.join('');
and finally make a new string by joining all the array elements together. We have to provide a null string ie '' because if we didn't provide anything we would join with commas (,)
var alpha = "abcdefghijklmnopqrstuvwxyz".split('');
for(i=0; i < alpha.length; i++){
console.log(alpha[i].toUpperCase());
//If you want to update
alpha[i] = alpha[i].toUpperCase();
};

Categories