function(ascii, a, b, c) ascii code puzzle - javascript

I'm working on a code puzzle which uses the following script:
function(ascii,a,b,c) {
for(i=0;i<ascii.length;i++) {
if(i%3==0){ascii[i]=(ascii[i]+a)%256;}
if(i%3==1){ascii[i]=(ascii[i]+b)%256;}
if(i%3==2){ascii[i]=(ascii[i]+c)%256;}
}
return ascii;
}
I think it says: ' for each character in the message (or if the message is an array, for each element i in the array), calculate its position mod3, and depending on the result add either a, b or c to the ascii value for the character, and then return that value mod 256. Is this the correct interpretation?

It seems to be an encoding function which takes an array of numbers representing characters (0-255). Then shifts the characters by the length specified as per a,b, and c by modding by 3. Then the output is modded by 255 so it remains a valid character value. Finally the resulting encoding array of numbers representing characters is returned.
Below is the code:
function encodeIt(ascii,a,b,c) {
for(i=0;i<ascii.length;i++) {
if(i%3==0){ascii[i]=(ascii[i]+a)%256;}
if(i%3==1){ascii[i]=(ascii[i]+b)%256;}
if(i%3==2){ascii[i]=(ascii[i]+c)%256;}
}
return ascii;
}
function encodeString(myString,myAdjustments)
{
var myArray = [];
for(var i=0;i<myString.length;i++)
{
myArray.push(myString.charCodeAt(i));
}
var myArray = encodeIt(myArray,myAdjustments[0],myAdjustments[1],myAdjustments[2]);
var myEncodedString = "";
for(var i=0;i<myArray.length;i++)
{
myEncodedString+=String.fromCharCode(myArray[i]);
}
return myEncodedString;
}
var encodedString = encodeString("Hello World!",[30,80,-13]);
alert(encodedString);
var decodedString = encodeString(encodedString,[-30,-80,13]);
alert(decodedString);
And the fiddle:
https://jsfiddle.net/3p79bxv2/

Related

Uncompress a String, repeat chars `n` times

I have the following problem statement:
Write a function, uncompress, that takes in a string as an argument.
The input string will be formatted into multiple groups according to
the following pattern:
number + char
for example, '2c' or '3a'.
The function should return an uncompressed version of the string where
each 'char' of a group is repeated 'number' times consecutively. You
may assume that the input string is well-formed according to the
previously mentioned pattern.
test_00: uncompress("2c3a1t"); // -> 'ccaaat'
Here is my code which is using a stack. The problem is that it's only returning 'cc' and I can't figure out why. I've console logged what goes into the IF ELSE and I'm hitting both so I don't understand why nothing gets pushed to the stack.
Would really appreciate the help if someone can spot what I'm missing.
const uncompress = (s) => {
const nums = '23456789';
const stack = [];
for (let char of s) {
if (nums.includes(char)) {
stack.push(Number(char));
} else {
const num = stack.pop();
stack.push(char.repeat(num));
};
};
return stack.join('');
};
console.log(uncompress("2c3a1t")); // -> 'ccaaat'
Here's how I would do it:
Split the string up into pairs of numbers and chars:
str.match(/\d+[a-zA-Z]/g)
And reduce that array to a string, while taking each value from the array, getting the char from it (cv.match(/[a-zA-Z]/)[0]) and repeating it according to the number (.repeat(parseInt(cv)))
const uncompress = str => str.match(/\d+[a-zA-Z]/g).reduce((acc, cv) =>
acc + cv.match(/[a-zA-Z]/)[0].repeat(parseInt(cv)), "")
console.log(uncompress("2c3a1t"))
console.log(uncompress("27b1d8g"))
And just like that I was able to write the code which passed the test case:
const nums = '123456789';
const stack = [];
for (let char of s) {
if (nums.includes(char)) {
stack.push(Number(char));
} else {
let num = '';
while (nums.includes(stack[stack.length - 1])) {
num += stack.pop();
}
stack.push(char.repeat(num));
};
};
return stack.join('');
};

Convert an ASCII coded string to normal String - Javascript

I have an ASCII character string and I need to convert it to a normal string.
var asciiString = '84114117116104326510811997121115328710511011532'
function strFunc(str) {
var result = []
var strSplit = str.split('');
var validAscii = ['32'];
for(var i=65; i<=90; i++) {
validAscii.push(i.toString());
}
for(var i=97; i<=122; i++) {
validAscii.push(i.toString());
}
strSplit.forEach((item, index) => {
if(validAscii.includes(parseInt(item))) {
result.push(item)
} else if (validAscii.includes(`${parseInt(strSplit[index])}${parseInt(strSplit[index + 1])}`)){
result.push(item)
}
})
return result.fromCharCodeAt(...result)
}
console.log(strFunc(asciiString))
Why does it return an empty string? I need to split the string into either 2 digit or 3 digits and compare it with the array I built.
The string should be split as [84, 114, 117, 116, 104, 32, 65, ...] which translates to TRUTH A....
Please advice.
I'd do this way
const encodedString = '84114117116104326510811997121115328710511011532';
const codes = [];
for (let i = 0; i < encodedString.length;) {
const numDigits = encodedString[i] === '1' ? 3 : 2;
codes.push(encodedString.substr(i, numDigits));
i += numDigits;
}
const str = String.fromCharCode(...codes);
console.log(`"${str}"`);
Some notes:
It assume values in the encoded string go from 32 to 127. There's no error checking
There's no reason to call parseInt as JavaScript will convert numbers strings to numbers so passing the numbers as strings to String.fromCharCode works.
As for why your code doesn't work, a couple of issues include
it's looping over every character, not every code.
It's looping over 8, 4, 1, 1, 4, ... instead of 84, 114, ...
This means neither test will pass since item will never be something found in validAscii which means result will have nothing pushed to it.
There's no function Array.fromCharCodeAt
result is an array and there is no such function as array.fromCharCodeAt. If result had the correct codes in it then you could use String.fromCharCode(...result)
When you're combining two elements of the string, you need to call parseInt() *on the result of the concatenation, not concatenate the results of parseInt(). So it should be:
} else if (validAscii.includes(parseInt(item + strSplit[index+1]))){
And since ASCII values can be 3 digits, you need another else if that looks for item + strSplit[index+1] + strSplit[index+2].
Another problem is that you're pushing item onto the result string. But to get the corresponding character, you need to use String.fromCharCode() to convert the concatenated ASCII code to a character.
strSplit.forEach((item, index) => {
if (validAscii.includes(parseInt(item))) {
result.push(String.fromCharCode(item))
} else if (validAscii.includes(parseInt(item + strSplit[index+1]))) {
result.push(String.fromCharCode(parseInt(item + strSplit[index+1]))
} else if (validAscii.includes(parseInt(item + strSplit[index+1] + strSplit[index+2]))) {
result.push(String.fromCharCode(parseInt(item + strSplit[index+1] + strSplit[index+2]))
}
})
Note that using forEach like this is probably not a good idea. If there are overlapping items in the input that are both in validAscii, you'll add both of them to the result. E.g. if it contains 678 you'll match both 67 and 78, and add the corresponding characters to the result. Instead, you should use an ordinaryfor` loop, and increment the index by the number of characters that you matched.
You want parseInt around the templated string, not the individual items. You were checking if the string is included in an array filled with numbers.
var asciiString = '84114117116104326510811997121115328710511011532'
function strFunc(str) {
var result = []
var strSplit = str.split('');
var validAscii = [32];
for(var i=65; i<=90; i++) {
validAscii.push(i);
}
for(var i=97; i<=122; i++) {
validAscii.push(i);
}
strSplit.forEach((item, index) => {
if(validAscii.includes(parseInt(item))) {
result.push(item)
} else if (validAscii.includes(parseInt(`${(strSplit[index])}${(strSplit[index + 1])}`))){
result.push(item);
}
})
return result.join('');
}
console.log(strFunc(asciiString))

Array Remove last 2 digits of a number

I would like to create a program that takes a number is input, such as: 12345 and then splits this number into 2 digit numbers and store it in a array. The array must look like this: [0]=45 [1]=23 [2]=1 . This means that the splitting of the numbers must start from the last digit of the number and not the first.
This is what I have until now:
var splitCount = []; // This is the array in which we store our split numbers
//Getting api results via jQuery's GET request
$.get("https://www.googleapis.com/youtube/v3/channels?part=statistics&id=UCJwchuXd_UWNxW-Z1Cg-liw&key=AIzaSyDUzfsMaYjn7dnGXy9ZEtQB_CuHyii4poc", function(result) {
//result is our api answer and contains the recieved data
//now we put the subscriber count into another variable (count); this is just for clarity
count = result.items[0].statistics.subscriberCount;
//While the subscriber count still has characters
while (count.length) {
splitCount.push(count.substr(0, 2)); //Push first two characters into the splitCount array from line 1
count = count.substr(2); //Remove first two characters from the count string
}
console.log(splitCount) //Output our splitCount array
});
but the problem with this is that if there are 5 digits for example: 12345 the the last digit will be in an array by itself like this: [0]=12 [1]=34 [2]=5 but I need the last array to have 2 digits and the first should be the one with one digit instead like this: [0]=1 [1]=23 [2]=45
very crude but this should work assuming the string is always numbers:
input = "12345"
def chop_it_up(input)
o = []
while input.length > 0
if input.length <= 2
o << input
else
o << input[-2..input.length]
end
input = input[0..-3]
chop_it_up(input)
end
return o
end
I probably do sth like this :
int[] fun(int x){
int xtmp = x;
int i = 0;
int len = String.valueOf(x).length();
// this is a function for java, but you can probably find
//an equivalent in whatever language you use
int tab[(len+1)/2];
while(xtmp > 1){
tab[i] = xtmp%100;
xtmp = int(xtmp/100); // here you take the integer part of your xtmp
++i;
}
return tab;
}

When passing number with comma to text box why getElementById truncate the number after the comma

Please check this code :
function CalCPM()
{
var nv = document.getElementById('txtviews').value;
var nc = document.getElementById('txtcost').value;
var result =parseFloat(nc) / parseFloat(nv)/1000;
if(!isNaN(result))
{
document.getElementById('cpm').value = result.toFixed(4);
}
}
it work fine expect when you put comma in the number, means if you put in txtviews 1000000 and in txtcost 3000 you get a correct result that is 3.000
However if you use commas in any of the numbers then the problem starts, like
if you put in txtviews 1,000,000 and in txtcost 3,000
then the result will be 0.000003
OR if you start by putting value for txtcost first
then the result will be 3000.0000
which is not a correct value either way, any idea what is the problem??
I believe you'd have to strip them out, and then add them back in (the commas, that is)..
function CalCPM()
{
var nv = document.getElementById('txtviews').value.replace(',','');
var nc = document.getElementById('txtcost').value.replace(',','');
var result =parseFloat(nc) / parseFloat(nv)/1000;
if(!isNaN(result))
{
document.getElementById('cpm').value = Number(result).toLocaleString('en');
}
}
This can simply solve by using reg-ex :
function CalCPM()
{
var nv = (document.getElementById('txtviews').value).replace(/,/g,'');
var nc = (document.getElementById('txtcost').value).replace(/,/g,'');
var result =parseFloat(nc) / parseFloat(nv)/1000;
if(!isNaN(result))
{
document.getElementById('cpm').value = Number(result).toFixed(4);
}
}

Conversion from Byte Array to hex format using bitcoinjs-min.js

I'm trying to generate the public key from the following x and y of object Q in the browser. The problem is in order to use this public key for verifying a JWT I have to get the hexadecimal format of the key. I'm using keypair from the src="bitcoinjs.min.js" which does not allow me to retrieve the hexadecimal form of public key.
Is there any library or function to convert it into hexadecimal form?
// Taking reference from http://procbits.com/2013/08/27/generating-a-bitcoin-address-with-javascript
var pubX = hdnode.keyPair.Q.x.toByteArrayUnsigned();
var pubY = hdnode.keyPair.Q.y.toByteArrayUnsigned();
var publicKeyBytes = pubX.concat(pubY);
publicKeyBytes.unshift(0x04);
meanwhile I tried
<script src="http://peterolson.github.com/BigInteger.js/BigInteger.min.js"></script>
var publicKeyInt = BigInt.fromByteArrayUnsigned(publicKeyBytes);
but it's not working
Thanks in Advance
Ok so I'm going to expand on my comment
Assume: key is an array or an iterable of bytes
function getHexArray(key) {
function num2hex(num) {
return num > 9 ? num + 55 : num + 48;
}
var hex_key = [];
var lower, upper;
for (var i = 0; i < key.length; i++) {
lower = key[i] & 0x0f;
upper = key[i] >> 4;
return String.fromCharCode(num2hex(upper)) +
String.fromCharCode(num2hex(lower));
}
return hex_key;
}
Note that if you want a long string of hex, you probably want to reverse the order of lower and upper (this is for writing as an array of hex bytes)
This function allows you to put in an array of bytes and will output an array of 2-char strings representing the hex value of the bytes.
WORKING:
below is the piece of working code which is taking a byte array and gives out a hexadecimal string.
function toHexString(bytes) {
return bytes.map(function(byte) {
return (byte & 0xFF).toString(16)
}).join('')
}
Thanks #derekdreery for your help :)

Categories

Resources