I need to convert Double64 to Long64 and back on JavaScript, like Double.doubleToLongBits() and Double.longBitsToDouble() on Java. And the results of methods must be the same as in Java. For example 1435.036452 -> 4654026172507377535 -> 1435.036452, or -1435.036452 -> -4569345864347398273 -> -1435.036452. As I unerstand, my code can convert Double64 to Long64 well, but I can't get back my value.
Double64 to Long64:
function toString64bitFloat(number) {
if(number === undefined || isNaN(number))
return 0;
let result = "";
const dv = new DataView(new ArrayBuffer(8));
dv.setFloat64(0, number, false);
for (let i = 0; i < 8; i++) {
let bits = dv.getUint8(i).toString(2);
if (bits.length < 8)
bits = new Array(8 - bits.length).fill('0').join("") + bits;
result += bits;
}
return result;
}
function stringToLong64(bitString) {
if(bitString === undefined || isNaN(bitString))
return 0;
let result = new BigInt64Array(1);
result[0] = BigInt(0);
if(bitString[0] === "1"){
for(let i = bitString.length; i > 0; i--)
if(bitString[i] === "0")
result[0] += BigInt(Math.pow(2, 63 - i));
result[0] = -result[0] - BigInt(1);
}else{
for(let i = bitString.length; i > 0; i--)
if(bitString[i] === "1")
result[0] += BigInt(Math.pow(2, 63 - i));
}
return result[0];
}
Long64 to Double64:
function toString64bitInt(number) {
let result = "";
let temp = number;
if(temp > 0){
result += "0";
for(let i = 1; i < 64; i++){
if(temp - BigInt(Math.pow(2, 63 - i)) >= 0){
result += "1";
temp -= BigInt(Math.pow(2, 63 - i));
} else {
result += "0"
}
}
} else {
result += "1";
temp = -temp + BigInt(0);
for(let i = 0; i < 63; i++){
if(temp - BigInt(Math.pow(2, 63 - i)) >= 0){
result += "0";
temp -= BigInt(Math.pow(2, 63 - i));
} else {
result += "1"
}
}
}
return result;
}
function stringTofloat64(bitString) {
let result = new Float64Array(1);
result[0] = 0.0;
if(bitString[0] === '1'){
for(let i = 1; i > 12; i++)
if(bitString[i] === '0')
result[0] += Math.pow(2, 11 - i);
for(let i = 12; i > 64; i++)
if(bitString[i] === '0')
result[0] += Math.pow(2, -(52 - i + 12));
result[0] = -result[0];
}else{
for(let i = 1; i > 12; i++){
if(bitString[i] === '1'){
result[0] += Math.pow(2, 11 - i);
}
}
for(let i = 12; i > 64; i++)
if(bitString[i] === '1'){
result[0] += Math.pow(2, -(52 - i + 12));
}
}
return result[0];
}
Related
Not very knowledgeable with coding, I usually use block coding and not typing.
I've used many different Levenshtein distance codes I've found online and most of them didn't work for one reason or another
var levDist = function (s, t) {
var d = []; //2d matrix
// Step 1
var n = s.length;
var m = t.length;
if (n == 0) return m;
if (m == 0) return n;
//Create an array of arrays in javascript (a descending loop is quicker)
for (var i = n; i >= 0; i--) d[i] = [];
// Step 2
for (i = n; i >= 0; i--) d[i][0] = i;
for (var j = m; j >= 0; j--) d[0][j] = j;
// Step 3
for (i = 1; i <= n; i++) {
var s_i = s.charAt(i - 1);
// Step 4
for (j = 1; j <= m; j++) {
//Check the jagged ld total so far
if (i == j && d[i][j] > 4) return n;
var t_j = t.charAt(j - 1);
var cost = (s_i == t_j) ? 0 : 1; // Step 5
//Calculate the minimum
var mi = d[i - 1][j] + 1;
var b = d[i][j - 1] + 1;
var c = d[i - 1][j - 1] + cost;
if (b < mi) mi = b;
if (c < mi) mi = c;
d[i][j] = mi; // Step 6
//Damerau transposition
if (i > 1 && j > 1 && s_i == t.charAt(j - 2) && s.charAt(i - 2) == t_j) {
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost);
}
}
}
// Step 7
return d[n][m];
};
This is all the code I’ve written (including the most recent attempt of getting the levenshtein distance)
var levDist = function (s, t) {
var d = []; //2d matrix
// Step 1
var n = s.length;
var m = t.length;
if (n == 0) return m;
if (m == 0) return n;
//Create an array of arrays in javascript (a descending loop is quicker)
for (var i = n; i >= 0; i--) d[i] = [];
// Step 2
for (i = n; i >= 0; i--) d[i][0] = i;
for (var j = m; j >= 0; j--) d[0][j] = j;
// Step 3
for (i = 1; i <= n; i++) {
var s_i = s.charAt(i - 1);
// Step 4
for (j = 1; j <= m; j++) {
//Check the jagged ld total so far
if (i == j && d[i][j] > 4) return n;
var t_j = t.charAt(j - 1);
var cost = (s_i == t_j) ? 0 : 1; // Step 5
//Calculate the minimum
var mi = d[i - 1][j] + 1;
var b = d[i][j - 1] + 1;
var c = d[i - 1][j - 1] + cost;
if (b < mi) mi = b;
if (c < mi) mi = c;
d[i][j] = mi; // Step 6
//Damerau transposition
if (i > 1 && j > 1 && s_i == t.charAt(j - 2) && s.charAt(i - 2) == t_j) {
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost);
}
}
}
// Step 7
return d[n][m];
};
var S = "Hello World";
var grossWPM;
var Transparency = 1;
var Timer = 60;
var InitialTime = Timer;
var Texts = getColumn("Texts", "Texts");
var TextLength = getColumn("Texts", "Number of Characters");
var Title = getColumn("Texts", "Titles");
var Author = getColumn("Texts", "Authors");
var TextSelector = randomNumber(0, 19);
console.log("Article #" + (TextSelector + 1));
console.log(TextLength[TextSelector] + " Characters in total");
console.log(Title[TextSelector]);
console.log("By: " + Author[TextSelector]);
var Countdown;
var Countdown = 6;
//Texts are obtained from
//https://data.typeracer.com/pit/texts
onEvent("button1", "click", function( ) {
timedLoop(1000, function() {
Countdown = Countdown - 1;
setText("button1", Countdown - 0);
timedLoop(100, function() {
setText("text_area2", "");
});
if (Countdown <= 1) {
stopTimedLoop();
setTimeout(function() {
setText("button1", "GO!");
setText("text_area1", Texts[TextSelector]);
if (getText("button1") == "GO!") {
var TransparentLoop = timedLoop(100, function() {
Transparency = Transparency - 0.1;
setProperty("Warning", "text-color", rgb(77,87,95, Transparency));
if (Transparency <= 0) {
deleteElement("Warning");
showElement("label2");
stopTimedLoop(TransparentLoop);
}
});
var TimerLoop = timedLoop(1000, function() {
Timer = Timer - 1;
setText("label2", Timer);
if (Timer <= 0) {
grossWPM = (TextLength[TextSelector] / 5) / ((InitialTime - Timer) / 60);
console.log(grossWPM);
setScreen("screen2");
if (Timer == 1) {
S = " second";
} else {
S = " seconds";
}
setText("label1", "Your typing speed was approximately " + (Math.round(grossWPM) + (" WPM* with " + (Timer + (S + " left")))));
stopTimedLoop(TimerLoop);
}
});
console.log("Timer Started");
timedLoop(10, function() {
var str = getText("text_area2");
if (str.length == TextLength[TextSelector]) {
stopTimedLoop(TimerLoop);
grossWPM = (TextLength[TextSelector] / 5) / ((InitialTime - Timer) / 60);
setScreen("screen2");
levDist(str, Texts[TextSelector]);
if (Timer == 1) {
S = " second";
} else {
S = " seconds";
}
setText("label1", "Your typing speed was approximately " + (Math.round(grossWPM) + (" WPM* with " + (Timer + (S + " left")))));
if (grossWPM == 69) {
setText("label4", "Nice");
}
stopTimedLoop();
}
});
}
}, 1000);
}
});
});
Obviously not that good at this so can anyone help?
I want to compare two sets of text
Something the user types in.
Paragraph that the user was supposed to type.
This is for a WPM test and I want a way to get a measurement for WPM that includes errors the user makes while typing.
If there is a way to check this besides the Levenshtein distance please tell me, I just looked up a way to do that and Levenshtein distance seemed like the way to do so
The error given by code.org says:
ERROR: Line: 50: TypeError: d[n] is undefined
I fixed the issue, I used this code
function levenshtein(s1, s2) {
if (s1 == s2) {
return 0;
}
var s1_len = s1.length;
var s2_len = s2.length;
if (s1_len === 0) {
return s2_len;
}
if (s2_len === 0) {
return s1_len;
}
// BEGIN STATIC
var split = false;
try {
split = !('0')[0];
} catch (e) {
// Earlier IE may not support access by string index
split = true;
}
// END STATIC
if (split) {
s1 = s1.split('');
s2 = s2.split('');
}
var v0 = new Array(s1_len + 1);
var v1 = new Array(s1_len + 1);
var s1_idx = 0,
s2_idx = 0,
cost = 0;
for (s1_idx = 0; s1_idx < s1_len + 1; s1_idx++) {
v0[s1_idx] = s1_idx;
}
var char_s1 = '',
char_s2 = '';
for (s2_idx = 1; s2_idx <= s2_len; s2_idx++) {
v1[0] = s2_idx;
char_s2 = s2[s2_idx - 1];
for (s1_idx = 0; s1_idx < s1_len; s1_idx++) {
char_s1 = s1[s1_idx];
cost = (char_s1 == char_s2) ? 0 : 1;
var m_min = v0[s1_idx + 1] + 1;
var b = v1[s1_idx] + 1;
var c = v0[s1_idx] + cost;
if (b < m_min) {
m_min = b;
}
if (c < m_min) {
m_min = c;
}
v1[s1_idx + 1] = m_min;
}
var v_tmp = v0;
v0 = v1;
v1 = v_tmp;
}
return v0[s1_len];
}
and I got that code from this question
This is levenshtein distance NOT damerau-levenshtein distance
I have tried many times but I can't find the values, how can I solve this? Here's my code:
var number = prompt("");
for (var count = 1; count <= number; count++) {
if (count % 2 != 0) {
console.log("-");
document.write("-");
// console.log(count);
document.write(count);
} else {
console.log("+");
document.write("+");
// console.log(count);
document.write(count);
}
}
document.write("=", );
Try this out:
var number = prompt("");
var result = 0;
for (var count = 1; count <= number; count++) {
if (count % 2 != 0) {
document.write("-");
document.write(count);
result -= count;
} else {
document.write("+");
document.write(count);
result += count;
}
}
document.write("=" + result);
A declarive solution. (as a fan of declarative programming)
const func = (n) => {
[...Array(n)].map( (_,i) => (
i%2 === 0 ? console.log(`-${i+1}`) : console.log(`+${i+1}`)
))}
func(6)
This should do the trick.
Here's your solution (with fiddle).
function expandString(n) {
let str = '';
for (let i = 1; i <= n; i++) {
if (i % 2 === 1) {
str += `-${i}`; // Even
} else {
str += `+${i}`; // Odd
}
}
return str += ` = ${n}`;
}
console.log(expandString(5));
Hope this will help you.
var flag = true;
var result=0;
var str = "";
var n=10;
for(let i=1;i<n;i++){
if(flag){
str += "-";
result -= i;
}
else{
str += "+";
result += i;
}
str += i;
flag = !flag
}
str += "="+result;
console.log(str);
I made the Vigenère cipher in JavaScript.
if I run my Code in Firefox I'm getting the follow output:
�QZ4Sm0]m
in Google Chrome it looks like this
QZ4Sm0]m
How can I avoid those symbols or how can I make them visible?
What am I doing wrong?
function vigenere(key, str, mode) {
var output = [str.length];
var result = 0;
var output_str;
for (var i = 0; i < str.length; i++) {
if (mode == 1) {
result = ((str.charCodeAt(i) + key.charCodeAt(i % key.length)) % 128);
output[i] = String.fromCharCode(result);
} else if (mode == 0) {
if (str.charCodeAt(i) - key.charCodeAt(i % key.length) < 0) {
result = (str.charCodeAt(i) - key.charCodeAt(i % key.length)) + 128;
} else {
result = (str.charCodeAt(i) - key.charCodeAt(i % key.length)) % 128;
}
output[i] = String.fromCharCode(result);
}
}
output_str = output.join('');
return output_str;
}
console.log(vigenere("Key", "Plaintext", 1))
Your first calculation gives an esc (#27) in all browsers. Visible in Firefox, but not visible in Chrome
This one gives Zpysrrobr: https://www.nayuki.io/page/vigenere-cipher-javascript
function vigenere(key, str, mode) {
var output = [str.length];
var result = 0;
var output_str;
for (var i = 0; i < str.length; i++) {
if (mode == 1) {
result = ((str.charCodeAt(i) + key.charCodeAt(i % key.length)) % 128);
output[i] = String.fromCharCode(result);
console.log(
str[i],key[i],result,output[i])
} else if (mode == 0) {
if (str.charCodeAt(i) - key.charCodeAt(i % key.length) < 0) {
result = (str.charCodeAt(i) - key.charCodeAt(i % key.length)) + 128;
} else {
result = (str.charCodeAt(i) - key.charCodeAt(i % key.length)) % 128;
}
output[i] = String.fromCharCode(result);
}
}
output_str = output.join('');
return output_str;
}
console.log(vigenere("Key", "Plaintext", 1))
Try using this piece of code. Its simpler and quite readable
function vigenereFunc(plainText, key) {
const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let cipherText = "";
for (let i = 0, j = 0; i < plainText.length; i++) {
if (!letters.includes(plainText[i])) {
cipherText += plainText[i];
continue;
}
cipherText += letters[(letters.indexOf(plainText[i]) + letters.indexOf(key[j])) % 26];
if(j === key.length - 1) j = -1;
return cipherText;
}
I'm trying to sum all the variables,
as many times as they appear in the loop,
that is- for example if hitpoints appears
3 times(as in my code) sum -12 + -12 + -12;
And then at the end I need a final result - a
sum of all of the variable values as many
times as they appear.
function calculate(number) {
var hitpoints = -12;
var points1 = 1;
var points3 = 5;
var points5 = 10;
var pointsx = 15;
for (var i =1; i <= number; i++) {
if ( i%10 ===0) {
console.log( i + "-" + hitpoints);
} else if ((i % 3 === 0) && (i% 5 ===0)) {
console.log( i + "-" + pointsx);
} else if (i %3 ===0) {
console.log ( i + "-" + points3);
} else if (i%5 ===0) {
console.log( i + "-" + points5);
} else {
console.log( i + "-" + points1);
}
}
}
calculate(30);
I assume you want the sum of the points.
Declare a variable sum and keep incrementing
function calculate(number) {
var hitpoints = -12;
var points1 = 1;
var points3 = 5;
var points5 = 10;
var pointsx = 15;
var sum=0;
for (var i =1; i <= number; i++) {
if ( i%10 ===0) {
sum += hitpoints;
} else if ((i % 3 === 0) && (i% 5 ===0)) {
sum += pointsx;
} else if (i %3 ===0) {
sum += points3;
} else if(i%5 ===0) {
sum += points5;
} else {
sum += points1;
}
}
console.log(sum)
}
calculate(30);
I'm creating a form where users can input a range. They are allowed to input letters and numbers. Some sample input:
From: AA01
To: AZ02
Which should result in:
AA01
AA02
AB01
AB02
And so on, till AZ02
And:
From: BC01
To: DE01
Should result in:
BC01
BD01
BE01
CC01
CD01
CE01
Etc
I managed to get it working for the input A01 to D10 (for example)
jsFiddle
However, i can't get it to work with multiple letters.
JS code:
var $from = $('input[name="from"]');
var $to = $('input[name="to"]');
var $quantity = $('input[name="quantity"]');
var $rangeList = $('.rangeList');
var $leadingzeros = $('input[name="leadingzeros"]');
$from.on('keyup blur', function () {
$(this).val($(this).val().replace(/[^a-zA-Z0-9]/g, ''));
updateQuantity();
});
$to.on('keyup blur', function () {
$(this).val($(this).val().replace(/[^a-zA-Z0-9]/g, ''));
updateQuantity();
});
$leadingzeros.on('click', function () {
updateQuantity();
});
function updateQuantity() {
var x = parseInt($from.val().match(/\d+/));
var y = parseInt($to.val().match(/\d+/));
var xl = $from.val().match(/[a-zA-Z]+/);
var yl = $to.val().match(/[a-zA-Z]+/);
var result = new Array();
if (xl != null && yl != null && xl[0].length > 0 && yl[0].length > 0) {
xl = xl[0].toUpperCase();
yl = yl[0].toUpperCase();
$rangeList.html('');
var a = yl.charCodeAt(0) - xl.charCodeAt(0);
for (var i = 0; i <= a; i++) {
if (!isNaN(x) && !isNaN(y)) {
if (x <= y) {
var z = (y - x) + 1;
$quantity.val(z * (a + 1));
$rangeList.html('');
for (var b = z; b > 0; b--) {
var c = ((y - b) + 1);
if ($leadingzeros.prop('checked')) {
c = leadingZeroes(c, y.toString().length);
}
result.push(String.fromCharCode(65 + i) + c);
}
} else {
$rangeList.html('');
$quantity.val(0);
}
} else {
$rangeList.html('');
$quantity.val(0);
}
}
} else if (!isNaN(x) && !isNaN(y)) {
if (x < y) {
var z = (y - x) + 1;
$quantity.val(z);
$rangeList.html('');
for (var i = z; i > 0; i--) {
var c = (y - i) + 1;
if ($leadingzeros.prop('checked')) {
c = leadingZeroes(c, y.toString().length);
}
result.push(c);
}
} else {
$rangeList.html('');
$quantity.val(0);
}
} else {
$rangeList.html('');
$quantity.val(0);
}
$rangeList.html('');
for (var i = 0; i < result.length; i++) {
$rangeList.append(result[i] + '<br />');
}
}
function leadingZeroes(number, size) {
number = number.toString();
while (number.length < size) number = "0" + number;
return number;
}
This is perfect for a recursive algorithm:
function createRange(from, to) {
if (from.length === 0) {
return [ "" ];
}
var result = [];
var innerRange = createRange(from.substring(1), to.substring(1));
for (var i = from.charCodeAt(0); i <= to.charCodeAt(0); i++) {
for (var j = 0; j < innerRange.length; j++) {
result.push(String.fromCharCode(i) + innerRange[j]);
}
}
return result;
}
Called as follows:
createRange('BC01', 'DE02'); // Generates an array containing all values expected
EDIT: Amended function below to match new test case (much more messy, however, involving lots of type coercion between strings and integers).
function prefixZeroes(value, digits) {
var result = '';
value = value.toString();
for (var i = 0; i < digits - value.length; i++) {
result += '0';
}
return result + value;
}
function createRange(from, to) {
if (from.length === 0) {
return [ "" ];
}
var result = [];
if (from.charCodeAt(0) < 65) {
fromInt = parseInt(from);
toInt = parseInt(to);
length = toInt.toString().length;
var innerRange = createRange(from.substring(length), to.substring(length));
for (var i = fromInt; i <= toInt; i++) {
for (var j = 0; j < innerRange.length; j++) {
result.push(prefixZeroes(i, length) + innerRange[j]);
}
}
} else {
var innerRange = createRange(from.substring(1), to.substring(1));
for (var i = from.charCodeAt(0); i <= to.charCodeAt(0); i++) {
for (var j = 0; j < innerRange.length; j++) {
result.push(String.fromCharCode(i) + innerRange[j]);
}
}
}
return result;
}
Please note that because of your strict logic in how the value increments this method requires exactly 4 characters (2 letters followed by 2 numbers) to work. Also, this might not be as efficient/tidy as it can be but it took some tinkering to meet your logic requirements.
function generate(start, end) {
var results = [];
//break out the start/end letters/numbers so that we can increment them seperately
var startLetters = start[0] + start[1];
var endLetters = end[0] + end[1];
var startNumber = Number(start[2] + start[3]);
var endNumber = Number(end[2] + end[3]);
//store the start letter/number so we no which value to reset the counter to when a maximum boundry in reached
var resetLetter = startLetters[1];
var resetNumber = startNumber;
//add first result as we will always have at least one
results.push(startLetters + (startNumber < 10 ? "0" + startNumber : "" + startNumber));
//maximum while loops for saefty, increase if needed
var whileSafety = 10000;
while (true) {
//safety check to ensure while loop doesn't go infinite
whileSafety--;
if (whileSafety == 0) break;
//check if we have reached the maximum value, if so stop the loop (break)
if (startNumber == endNumber && startLetters == endLetters) break;
//check if we have reached the maximum number. If so, and the letters limit is not reached
//then reset the number and increment the letters by 1
if (startNumber == endNumber && startLetters != endLetters) {
//reset the number counter
startNumber = resetNumber;
//if the second letter is at the limit then reset it and increment the first letter,
//otherwise increment the second letter and continue
if (startLetters[1] == endLetters[1]) {
startLetters = '' + String.fromCharCode(startLetters.charCodeAt(0) + 1) + resetLetter;
} else {
startLetters = startLetters[0] + String.fromCharCode(startLetters.charCodeAt(1) + 1);
}
} else {
//number limit not reached so just increment the number counter
startNumber++;
}
//add the next sequential value to the array
results.push(startLetters + (startNumber < 10 ? "0" + startNumber : "" + startNumber));
}
return results;
}
var results = generate("BC01", "DE01");
console.log(results);
Here is a working example, which uses your second test case
Using #Phylogenesis' code, i managed to achieve my goal.
jsFiddle demo
function updateQuantity() {
var x = parseInt($from.val().match(/\d+/));
var y = parseInt($to.val().match(/\d+/));
var xl = $from.val().match(/[a-zA-Z]+/);
var yl = $to.val().match(/[a-zA-Z]+/);
var result = new Array();
var r = createRange(xl[0], yl[0]);
var z = (y - x) + 1;
if (x <= y) {
for (var j = 0; j < r.length; j++) {
var letters = r[j];
for (var i = z; i > 0; i--) {
var c = (y - i) + 1;
if ($leadingzeros.prop('checked')) {
c = leadingZeroes(c, y.toString().length);
}
if (i == z) {
r[j] = letters + c + '<br />';
} else {
j++;
r.splice(j, 0, letters + c + '<br />');
}
}
}
} else {
for (var i = 0; i < r.length; i++) {
r[i] += '<br />';
}
}
$quantity.val(r.length);
$rangeList.html('');
for (var i = 0; i < r.length; i++) {
$rangeList.append(r[i]);
}
}
This works for unlimited letters and numbers, as long as the letters are first.
Thanks for your help!