EDIT: Here's a rephrase of the question for clarity (apologies for confusion):
QUESTION : Given an array limits and an array punct_arr where both are sorted, return an output array of values separation_index where separation_index[i] is the closest value in punct_arr to limits[i]. It follows that separation_index will be of the same size as limits.
So, say I have two arrays:
limits = [280, 560]
punct_arr = [5, 99, 151, 159, 255, 352, 462, 502, 519, 531, 556, 602]
Expected Outcome: [255, 556]
The outcome should always be the same length as the limits array.
Here's what I got so far:
for (var limit = 0; limit < limits.length; limit++) {
for (var punct = 0; punct < punct_arr.length; punct++) {
if (Math.abs(punct_arr[punct - 1] - limits[limit]) < (Math.abs(punct_arr[punct] - limits[limit])) && (Math.abs(punct_arr[punct] - limits[limit]) < (Math.abs(punct_arr[punct] - limits[limit + 1])))) {
separation_index.push(punct_arr[punct-1]);
}
}
}
Thanks in advance!
Here's a decomposed approach where we start writing at a high-level and define auxiliary helper functions along the way -
function closest (limits, inputs) {
return limits.map(v => closest1(v, inputs))
}
function closest1 (one, many) {
return many.reduce((r, v) =>
delta(r, one) < delta(v, one) ? r : v,
-Infinity
)
}
function delta (a, b) {
return Math.abs(a - b)
}
const limits = [280, 560]
const inputs = [5, 99, 151, 159, 255, 352, 462, 502, 519, 531, 556, 602]
console.log(closest(limits, inputs))
[ 255, 556 ]
Here's one way. I just adjusted a bit your code.
const limits = [280, 560]
const punct_arr = [5, 99, 151, 159, 255, 352, 462, 502, 519, 531, 556, 602]
function closestLimits(limits, arr) {
const diff = []
const separation_index = []
let closest
for (var limit = 0; limit < limits.length; limit++) {
diff.length = 0
for (var punct = 0; punct < arr.length; punct++) {
var m = Math.abs(arr[punct] - limits[limit]);
diff.push(m)
if (m <= Math.min(...diff)) {
smallest = arr[punct]
}
}
separation_index.push(smallest);
}
return separation_index
}
console.log(closestLimits(limits, punct_arr))
I have the following code and the logic seems to be correct. However, when I run the last console.log ( 'console.log(bills)'), nothing shows up for its output.
const bills = [22, 295, 176, 440, 37, 105, 10, 1100, 86, 52]
const tipsTotal = [];
let sum = 0;
const calcTip = function(bill) {
return bill >= 50 && bill <= 300 ? bill * .15 : bill * .20;
}
for (let i = 0; i < bills.length; i++) {
const value = calcTip(bills[i]);
calcTip(tipsTotal.push(value));
}
console.log(tipsTotal);
const calcAverage = function(arr) {
for (let i = 0; arr.length; i++) {
sum = sum + arr[i];
}
let average = sum / arr.length;
return average;
}
console.log(calcAverage(bills));
The sum variable should be declared inside calcAverage.
You forgot to check if the loop index reached the end of the array: i < arr.length
const bills = [22, 295, 176, 440, 37, 105, 10, 1100, 86, 52];
const tipsTotal = [];
const calcTip = function(bill) {
return bill >= 50 && bill <= 300 ? bill * .15 : bill * .20;
}
for (let i = 0; i < bills.length; i++) {
const value = calcTip(bills[i]);
calcTip(tipsTotal.push(value));
}
console.log(tipsTotal);
const calcAverage = function(arr) {
let sum = 0;
for (let i = 0; i < arr.length; i++) {
sum = sum + arr[i];
}
let average = sum / arr.length;
return average;
}
console.log(calcAverage(bills));
Reduce works great in these cases
const bills = [22, 295, 176, 440, 37, 105, 10, 1100, 86, 52];
const sum = bills.reduce((sum,bill) => {
const tip = bill >= 50 && bill <= 300 ? bill * .15 : bill * .20;
sum += (bill+tip);
return sum;
},0)
console.log(sum.toFixed(2),(sum/bills.length).toFixed(2));
Having Data in array of arrays with duplicate arrays of Oth position.
explanation
Compare arrays with its zero th position and make the result accurately.
let array = [["2018-03-09", 10, 11, 0],["2018-03-10", 100, 101, 105],["2018-03-15", 20, 0, 25],["2018-03-09", 0, 0, 15],["2018-03-15", 0, 10, 0]]
let output = [];
for (let i = 0; i < array.length; i++) {
let key = array[i][0]
let index = output.findIndex(x => x[0] == key)
if (index >= 0) {
for (let k = 1; k < array[i].length; k++) {
if (array[i][k] >= output[index][i]) {
output[index][k] = array[i][k]
} else {
output[index][k] = output[index][i]
}
}
} else {
output.push(array[i])
}
}
console.log(output)
Required Output
output=[["2018-03-09",10,11,15],["2018-03-10",100,101,105],["2018-03-15",20,10,25]]
How can I achieve this?
You could use a lookup object to find previous entries with the same values, then merge them. Array destructuring is helpful to make the code clean:
const byDate = {};
const result = [];
for(const [date, ...values] of array) {
if(byDate[date]) {
values.forEach((v, i) => byDate[date][i + 1] = Math.max(byDate[date][i + 1], v));
} else {
result.push(byDate[date] = [date, ...values]);
}
}
For better readability, you can update the array in a separate function (I kept the for loop method you used, although we could use here a forEach() call).
Here, updateEntry will look in an output array (entries argument) for an existing entry, updating it if found otherwise it will append it to the output array.
Below a working snippet.
function updateEntry(entries, entry) {
for (let i = 0; i < entries.length; i++) {
if (entry[0] != entries[i][0]) continue;
for (let j = 1; j < entry.length; j++) {
if (entry[j] >= entries[i][j])
entries[i][j] = entry[j];
}
return;
}
entries.push(entry);
}
let array = [
["2018-03-09", 10, 11, 0],
["2018-03-10", 100, 101, 105],
["2018-03-15", 20, 0, 25],
["2018-03-09", 0, 0, 15],
["2018-03-15", 0, 10, 0]
];
let output = [];
for (let i = 0; i < array.length; i++) {
updateEntry(output, array[i]);
}
console.log(output);
Use array.reduce to build an object with the identifier (the date) as the keys, which sums the other three values. Then, use Object.values to return your desired array output.
let array = [["2018-03-09", 10, 11, 0],["2018-03-10", 100, 101, 105],["2018-03-15", 20, 0, 25],["2018-03-09", 0, 0, 15],["2018-03-15", 0, 10, 0]];
let output = Object.values(array.reduce((r, e) => {
var k = e[0];
if (!r[k]) r[k] = [k, 0, 0, 0];
r[k][1] += e[1];
r[k][2] += e[2];
r[k][3] += e[3];
return r;
}, {}));
console.log(output);
I have written a function to perform wave-sort as shown below. The resulting array should begin with a number bigger than the next one but my code is not doing that. For example if the input is:
[73, 80, 40, 86, 14, 96, 10, 56, 61, 84, 82, 36, 85]
...it gives an output of
[ 86, 96, 84, 85, 80, 82, 61, 73, 40, 56, 14, 36, 10 ]
instead of starting with a bigger number than the next, which is 96.
function waveSort(arr){
arr = arr.sort(function(a, b) {
return b - a;
});
for (var i = 1; i < arr.length; i += 2) {
if (arr[i-1] > arr[i]) {
var temp = arr[i];
arr[i] = arr[i-1];
arr[i-1] = temp;
}
if (i+1 < arr.length && arr[i+1] > arr[i]) {
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
return arr;
}
You have explicitly designed your function to start with a lower value.
In the first if you detect a situation where the first value is greater than the second, and if so, you swap them (when i = 1):
if (arr[i-1] > arr[i]) {
So it is normal you end up with a smaller value at index 0 than at index 1.
If you want your array to start with a "wave high", then change the conditions in your two ifs:
function waveSort(arr){
arr = arr.sort(function(a, b) {
return b - a;
});
for (var i = 1; i < arr.length; i += 2) {
if (arr[i-1] < arr[i]) {
var temp = arr[i];
arr[i] = arr[i-1];
arr[i-1] = temp;
}
if (i+1 < arr.length && arr[i+1] < arr[i]) {
temp = arr[i];
arr[i] = arr[i+1];
arr[i+1] = temp;
}
}
return arr;
}
var waved = waveSort([73, 80, 40, 86, 14, 96, 10, 56, 61, 84, 82, 36, 85]);
console.log(JSON.stringify(waved));
function waveSort(arr){
arr.sort((a,b)=>b-a);
for(var i=1;i<arr.length;i+=2){
var tmp = arr[i];
arr[i]=arr[i+1];
arr[i+1]=tmp;
}
return arr;
}
var wavesorted = waveSort([73, 80, 40, 86, 14, 96, 10, 56, 61, 84, 82, 36, 85]);
console.log(wavesorted);
Another way would be to define a swap function and call it within the actual function like:
const swap = (arr, i, j) => ([arr[i], arr[j]] = [arr[j], arr[i]]);
const waveSort = (arr) => {
arr = arr.sort((a, b) => b - a);
for(let i = 1; i < arr.length; i += 2){
if(arr[i-1] < arr[i]) {
swap(arr, i-1, i)
}
if(i+1 < arr.length && arr[i+1] < arr[i]) {
swap(arr, i+1, i)
}
}
return arr;
}
var waved = waveSort([73, 80, 40, 86, 14, 96, 10, 56, 61, 84, 82, 36, 85]);
console.log(JSON.stringify(waved));
`
The following code procedure bytes = parseHexString (createHexString (bytes)) leads to updated of bytes, what I would like to avoid. And as a result calculations are not correct.
<html>
<head>
<SCRIPT SRC="http://eu.static.mega.co.nz/sjcl_1.js"></SCRIPT>
<SCRIPT SRC="http://eu.static.mega.co.nz/crypto_1.js"></SCRIPT>
<SCRIPT SRC="http://eu.static.mega.co.nz/rsa_1.js"></SCRIPT>
<SCRIPT SRC="http://eu.static.mega.co.nz/hex_1.js"></SCRIPT>
<SCRIPT>
function parseHexString(str) {
var result = [];
while (str.length >= 2) {
result.push(parseInt(str.substring(0, 2), 16));
str = str.substring(2, str.length);
}
return result;
}
function createHexString(arr) {
var result = "";
for (i in arr) {
var str = arr[i].toString(16);
str = str.length == 0 ? "00" :
str.length == 1 ? "0" + str :
str.length == 2 ? str :
str.substring(str.length-2, str.length);
result += str;
}
return result;
}
function t()
{
var json_k = 'aOrP5yLtNQT53WMQfufSlA';
var json_csid = 'CABD6JUMldvI_eqP0537xl9P8x7kgk2OjOq99Fy7kosphj6AFUtlbwRRDpg4EIifXRLO6FNpdD22WwtUlJ_1Mgye2Y87trEqLCbhahuEFJVQNMDtNbIem7xY2ER9uF-cdgBXZWuzp7XIBybSh7W8MSUlv_eGS6LcLGJ81Q49dSzVhcswHTJ_IJl04p3c0axR6ZIJ8dH5bJ_vXvgQsypUVVtdfMacKhB9cXdEtRZ6iWLKCKqscXdo6CNXlbIdzRhro0gxfmhfB_miysFAiSQrbtuYnIgYBU3i9p3jRlPD4ti3CUcnj0SomV61w1aEYNvo56HPMUZlVkVHA7BFzvHGHo0J';
var json_privk = 'K7LDtk2M2QhjJx_v_Hqf0LKUBaZx76U_vBDjQty9HpFDy2MntF5HxxuyHQ9-1HmXeYzbL1pZnAxsZ7LRUbDnkR6qtJVaGdWuQhrytkuq0l5zBp-O--gZxoQPRGTsVgVRdAvpsRTkQI_q8fxADLCe0womFxtvvnD_FJgjaMsm7vkYchXkoq33WWyHijb3JMkymjl0_GtiSamT0qEL6sm_l5Z1lehqBGUEHfYAa0ub8IDx_yqy2R9Nh8Lwzmz4s24sShVxjaNsMBlSE-sEvTziOsnNWK1Zl_XUYadlENkweuIoxYx_lt8XIV71TzjEFuVTd-pXhzVlqePmIu3SM3bO1Kzq_DnGfB62RmzlmbtHU4iyw4Hd1wQFRhTeSRrvMjsMPFKN-SIIQU7CRNaMuaDxZbNZcOKhMg_h9mApM0rRS3VZaGZzFTL9rSaDMYHw4pL3aOkSFPMY3w785Tss7Zqwuo9HFUWUVbnYAb97JkgCohlMotORrMMtual1dQ4sG1sIYXyWTckAGGL0ZAGurhtSKiyz1m8Lb39pXPacqFh_nCHqqb2_RdrKTj0PdGZESKkU8YedeqC1I9nR4v38DuQc-pBBR5DOwgNjJMvzvsUehs_PxIL8THjgIcr7ONc4hWV9o2v_l81Vo2cCW2I99Iz84IFN2fV1dTqHIG_tnLzz8ljBVygETUqrFdZ0JlQJkurZ7RBku5krm-k9CZmDezCIzPPil-RcYzVIk00gNYAxfiZE48Or4WEiGjgKLnHCYVtSlvlMF4bPGB4SVCZ-68j49EjfSWaMK0OoMkpGhqf7KchgxYBZq6o3AhLgp4t0BClvsdee6VTz1SFqc3m2A-TMG6fNdbCT_Q9nYCYdZIROdOc';
var aes = new sjcl.cipher.aes( prepare_key_pw("oEyoo9cQcw") );
k = decrypt_key(aes, base64_to_a32(json_k) );
aes = new sjcl.cipher.aes(k);
var t = mpi2b(base64urldecode(json_csid));
var privk = a32_to_str(decrypt_key(aes,base64_to_a32(json_privk)));
var rsa_privk = Array(4);
for (var i = 0; i < 4; i++)
{
var l = ((privk.charCodeAt(0)*256+privk.charCodeAt(1)+7)>>3)+2;
rsa_privk[i] = mpi2b(privk.substr(0,l));
if (typeof rsa_privk[i] == 'number') break;
privk = privk.substr(l);
}
var p = parseHexString(createHexString(rsa_privk[0])); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!
var q = parseHexString(createHexString(rsa_privk[1])); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!
var d = parseHexString(createHexString(rsa_privk[2])); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!
var u = parseHexString(createHexString(rsa_privk[3])); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!
sid = base64urlencode(b2s(RSAdecrypt(t,d,p,q,u)).substr(0,43));
if (sid!=='tajetAbW0qTQGFlwp8iD5lQ0TFV1QUZJZFVvjRX7Xx-bPzYBoau7qog09w')
console.log("ERROR");
p = rsa_privk[0];
q = rsa_privk[1];
d = rsa_privk[2];
u = rsa_privk[3];
sid = base64urlencode(b2s(RSAdecrypt(t,d,p,q,u)).substr(0,43));
if (sid=='tajetAbW0qTQGFlwp8iD5lQ0TFV1QUZJZFVvjRX7Xx-bPzYBoau7qog09w')
console.log("OK");
}
</script>
</head>
<body onload="t();"></body>
</html>
I am not javascript developer, and not one found in google code did not work on this data.
Update 1
console.log(createHexString(rsa_privk[0])); = e5d109c673d8ef03df564beb9e36e9983a23842b0a724efa45ff76bbe5ad72ed62d2757968
But if do
parseHexString('e5d109c673d8ef03df564beb9e36e9983a23842b0a724efa45ff76bbe5ad72ed62d2757968');
then code if (sid!== ... make error
Update 2
console.log(rsa_privk[0].toString(16));
output:
123676133,198914513,129998601,245147334,11918451,206998232,96766191,75984899,177840095,106709334,10180427,208237547,119814814,127003446,189062377,84099480,220452154,250519075,267883908,115471915,165124106,238628722,169382478,42320122,95982405,80725759,89608310,85166267,200925925,254033325,86971506,191278317,127411298,180195794,142776693,188738169,39016
Update 3
console.log(parseHexString(createHexString(rsa_privk[0])));
console.log(rsa_privk[0]);
output:
[229, 209, 9, 198, 115, 216, 239, 3, 223, 86, 75, 235, 158, 54, 233, 152, 58, 35, 132, 43, 10, 114, 78, 250, 69, 255, 118, 187, 229, 173, 114, 237, 98, 210, 117, 121, 104]
[123676133, 198914513, 129998601, 245147334, 11918451, 206998232, 96766191, 75984899, 177840095, 106709334, 10180427, 208237547, 119814814, 127003446, 189062377, 84099480, 220452154, 250519075, 267883908, 115471915, 165124106, 238628722, 169382478, 42320122, 95982405, 80725759, 89608310, 85166267, 200925925, 254033325, 86971506, 191278317, 127411298, 180195794, 142776693, 188738169, 39016]
Convert a hex string to a byte array and vice versa
note: implementation from crypto-js, though now out of date and slightly altered
// Convert a hex string to a byte array
function hexToBytes(hex) {
let bytes = [];
for (let c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
}
// Convert a byte array to a hex string
function bytesToHex(bytes) {
let hex = [];
for (let i = 0; i < bytes.length; i++) {
let current = bytes[i] < 0 ? bytes[i] + 256 : bytes[i];
hex.push((current >>> 4).toString(16));
hex.push((current & 0xF).toString(16));
}
return hex.join("");
}
Update: Scroll down for solution... Live Demo
The issue: you are using a lossy conversion to hex, which cannot be reversed.
var p = parseHexString(createHexString(rsa_privk[0]));
This will never be same as rsa_privk[0].
Because, createHexString() only uses the last 2 bytes from each array element.
Example:
rsa_privk[0] : [123676133, 198914513, 129998601, 245147334, 11918451, 206998232, 96766191, 75984899, 177840095, 106709334, 10180427, 208237547, 119814814, 127003446, 189062377, 84099480, 220452154, 250519075, 267883908, 115471915, 165124106, 238628722, 169382478, 42320122, 95982405, 80725759, 89608310, 85166267, 200925925, 254033325, 86971506, 191278317, 127411298, 180195794, 142776693, 188738169, 39016]
createHexString(rsa_privk[0]) : e5d109c673d8ef03df564beb9e36e9983a23842b0a724efa45ff76bbe5ad72ed62d2757968
parseHexString(createHexString(rsa_privk[0])) : [229, 209, 9, 198, 115, 216, 239, 3, 223, 86, 75, 235, 158, 54, 233, 152, 58, 35, 132, 43, 10, 114, 78, 250, 69, 255, 118, 187, 229, 173, 114, 237, 98, 210, 117, 121, 104]
Update : Working Solution...
The two functions... the hex always contains 8 byte blocks, each for each element in the array...
function parseHexString(str) {
var result = [];
while (str.length >= 8) {
result.push(parseInt(str.substring(0, 8), 16));
str = str.substring(8, str.length);
}
return result;
}
function createHexString(arr) {
var result = "";
var z;
for (var i = 0; i < arr.length; i++) {
var str = arr[i].toString(16);
z = 8 - str.length + 1;
str = Array(z).join("0") + str;
result += str;
}
return result;
}
Test code...
function test() {
a = [123676133, 198914513, 129998601, 245147334, 11918451, 206998232, 96766191, 75984899, 177840095, 106709334, 10180427, 208237547, 119814814, 127003446, 189062377, 84099480, 220452154, 250519075, 267883908, 115471915, 165124106, 238628722, 169382478, 42320122, 95982405, 80725759, 89608310, 85166267, 200925925, 254033325, 86971506, 191278317, 127411298, 180195794, 142776693, 188738169, 39016];
console.log("Input");
console.log(a);
b = createHexString(a);
console.log("Hex");
console.log(b);
c = parseHexString(b);
console.log("Output");
console.log(c);
if(checkIfEqual(a, c)) {
alert("Same");
}
}
function checkIfEqual(arr1, arr2) {
if (arr1.length != arr2.length) {
return false;
}
//sort them first, then join them and just compare the strings
return arr1.sort().join() == arr2.sort().join();
}
I just wanted to chime in that there is a library at https://github.com/dcodeIO/bytebuffer.js to easily help with conversions like this, and thus you don't need to write your own functions (which could possibly not be the most optimal, or be more optimal if your solution was reviewed through the open source community on GitHub).
var ByteBuffer = require("bytebuffer");
var bb = ByteBuffer.fromHex(yourHexString);
// need to convert it to base 64?
// bb.toBase64();
See https://github.com/dcodeIO/bytebuffer.js/wiki/API#bytebufferfromhexstr-littleendian-noassert for the API documention and more insight on the methods I used above.
Just to clarify, if you simply want to hex decode a simple string such as 48656C6C6F20576F726C6421 (Hello World!) you can use the OP function but instead of using a length of 8 you should use a length of 2.
Code:
var DecodeHexStringToByteArray = function (hexString) {
var result = [];
while (hexString.length >= 2) {
result.push(parseInt(hexString.substring(0, 2), 16));
hexString = hexString.substring(2, hexString.length);
}
return result;
}
Output will be [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33]
I know that this code is already in the OP question, but it's not in the accepted answer. My intent here is only to give a straight answer to the first part of the question being asked (How to convert a hex string into a bytes array).
I found solution over here enter link description here
function hexStringToByteArray(hexString) {
if (hexString.length % 2 !== 0) {
throw "Must have an even number of hex digits to convert to bytes";
}
var numBytes = hexString.length / 2;
var byteArray = new Uint8Array(numBytes);
for (var i=0; i<numBytes; i++) {
byteArray[i] = parseInt(hexString.substr(i*2, 2), 16);
}
return byteArray;
}
once again thank you http://www.java2s.com
Here is a live sample for this test.
http://jsfiddle.net/vincentwang2020/eks1z4g2/
function testcreateHexString()
{
alert('test function createHexString');
var key = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];
var result = createHexString(key);
alert ('Hex value:' + result);
alert('test function parseHexString');
var key2 = parseHexString(result);
if (key.sort().join() == key2.sort().join())
alert ('Matched');
}