jsbn2 modInverse returns undefined - javascript

I have found this library for big integers called jsbn2 by Tom Wu,
and it seemed to work well until I had to use modInverse method.
For some reason it returns undefined no matter what.
The method in the library is:
bnModInverse(m) {
var ac = m.isEven();
if((this.isEven() && ac) || m.signum() == 0) return new BigInteger(0);
var u = m.clone(), v = this.clone();
var a = new BigInteger(1), b = new BigInteger(0), c = new BigInteger(0), d = new BigInteger(1);
while(u.signum() != 0) {
while(u.isEven()) {
u.rShiftTo(1,u);
if(ac) {
if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
a.rShiftTo(1,a);
}
else if(!b.isEven()) b.subTo(m,b);
b.rShiftTo(1,b);
}
while(v.isEven()) {
v.rShiftTo(1,v);
if(ac) {
if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
c.rShiftTo(1,c);
}
else if(!d.isEven()) d.subTo(m,d);
d.rShiftTo(1,d);
}
if(u.compareTo(v) >= 0) {
u.subTo(v,u);
if(ac) a.subTo(c,a);
b.subTo(d,b);
}
else {
v.subTo(u,v);
if(ac) c.subTo(a,c);
d.subTo(b,d);
}
}
if(v.compareTo( BigInteger.ONE ) != 0) return new BigInteger(0);
if(d.compareTo(m) >= 0) return d.subtract(m);
if(d.signum() < 0) d.addTo(m,d); else return d;
// MODIFIED BY ATS 2008/11/22 FOR COMPATIBILITY TO Flash ActionScript
// if(d.signum() < 0) return d.add(m); else return d;
if(d.signum() < 0) return d.ope_add(m); else return d;
};
I used it with very long numbers, for ex.
var a = new BigInteger("26243431849380303664210129223718904471391758038739441955848319764858899645035");
var b = new BigInteger("fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 16);
(fixed b value, ty Rudy Velthuis)
But the a.modInverse(b) returns undefined.
Is there something wrong with the method, that needs to be fixes?
How can I make it work?

OK.. after like hundreds of logs and stuff I finally found what is the problem in my case.
While the example value that I gave in question itself seems to actually work, there is a different problem with the method modInverse (again.. sorry if that mislead someone).
The problem with it (the modInverse method in jsbn2) is that it doesn't know what to do with negative numbers (while the Java modInverse knows).
My solution to this was to check if the value that I will give it is positive and if not, I prepared it (thanks to this topic for explaining how):
if(a.compareTo(ZERO)<0)
{
a = a.negate(); //make it positive
a = a.mod(b); //get modulo
a = b.subtract(a); //get remainder of modulo
}
I don't know if this is the best solution to it (surely not) but it seems to work.
The result values that I tested are now equal to those of Java's modInverse.
Hope this helps anyone who get lost just like me here :3

Related

On the Leetcode Palindrome problem (number 234), why is my JavaScript solution not passing all the test cases?

I'm working on the palindrome question, and failing the [1,2] test case. Below is my code:
var isPalindrome = function(head) {
var listLength = head.length ? head.length : 0;
if (listLength === 0 || listLength === 1) return true;
var curNode = head[0];
var tailNode = head[listLength - 1];
if (listLength === 2) {
// if (curNode === tailNode) return true;
// return false;
return curNode === tailNode;
}
if (curNode !== tailNode) return false;
head.shift();
head.pop();
return (isPalindrome(head));
};
When I run the test case in vscode on my device, I get false for [1,2] (which is the expected result) but the uploaded version on leetcode is failing that test and returning true instead. I have no clue why. My solution is by no means the best solution but I tried a handful of tests on my local and it seemed to get the job done. Any advice on how to fix this, or insight as to why I'm failing the test case on leetcode?
Initially I thought it was the way I structured my conditional when listLength is 2, but I changed that to something I'm sure would work and it didn't change the outcome.
edit: link to leetcode question https://leetcode.com/problems/palindrome-linked-list/
As #JoshuaWood pointed out, I was operating under the assumption that my list had array properties native to JavaScript arrays, but this is an incorrect way of viewing the problem. I had to quite literally handle the list with the pointer and data they provided me. (see definition below)
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* #param {ListNode} head
* #return {boolean}
*/
Once I realized I wouldn't be able to use any array properties, and just use the properties given to me in the definition above, I was able to reformat my solution and come up with this:
var isPalindrome = function(head) {
let curr = head;
var len = 0;
let last = null;
let secondToLast = null;
if (curr.val !== null) len = 1;
if (curr && curr.next === null) return true;
while (curr.next !== null) {
len++;
secondToLast = curr;
curr = curr.next;
}
last = curr;
if (len === 2) {
if (head.val === last.val) return true;
return false;
}
if (head.val === last.val) {
secondToLast.next = null;
last.val = null;
last = null;
return isPalindrome(head.next);
} else {
return false;
}
}
Basically I can navigate to the end of the list, store what's at the end, compare it to the beginning, and pop off those values if they are equal. If they're not equal, then the list is not a Palindrome. If they are, then I iterate to the next entry in the list and pop off the end. This continues until you either reach a list with only 1 or 2 left, does the final comparison if there are two, or simply returns true if there's only one node left since that node will be equal to itself.
Hope this helps! Once I realized that of course they wouldn't have array properties, it all made a lot more sense.

input box asking for two specific words

I'm new to this, so I hope I can explain well enough what my problem is.
I've got a quiz and for an answer I created an input box. To get to another link you have to put two words in there but the order should not matter aka. it shouldn't matter if you write down "word1 word2" or "word2 word1", there should be only one rule: both words should be mentioned.
Is that possible?
My code so far:
function checkText()
{
var textwunf_1 = document.getElementById("wunf").value;
if(textwunf_1.toLowerCase() == "word1" && "word2"){
window.open("URL","_self");
}
else{
xxx
}
}
It does not work.
Before I only wanted to check if one word is used, like that:
var textwunf_2 = 'word1';
function checkText()
{
var textwunf_1 = document.getElementById("wunf").value;
if(textwunf_1.toLowerCase().indexOf(textwunf_2) == -1){
xxx
}
else{
window.open("URL","_self");
}
}
This worked but I can't use it for two words, because if I write
var textwunf_2 = 'word1 word2';
the order can't be 'word2 word1'...
Is there a solution to my problem?
Hopefully anyone can understand and help me, thank you!
Based on this commentary from the OP:
if the user types 3 words and two of them match with the answer, it should be also okay! even better if even 3 words or more are possible, as long as the user puts my two words in it..
You can check if both words are whitin the text using two conditions on the if:
textwunf_1.toLowerCase().indexOf("word1") >= 0
AND
textwunf_1.toLowerCase().indexOf("word2") >= 0
Try with the next code:
var textwunf_2 = 'word1';
var textwunf_3 = 'word2';
function checkText()
{
var textwunf_1 = document.getElementById("wunf").value;
if ((textwunf_1.toLowerCase().indexOf(textwunf_2) >= 0) &&
(textwunf_1.toLowerCase().indexOf(textwunf_3) >= 0))
{
window.open("URL","_self");
}
else
{
// xxx
}
}
Another approach:
var words = ["word1", "word2"];
function CheckWords() {
var inputWords = document.getElementById("wunf").value.split(' ');
var allWordsFound = true;
if (inputWords.length !== words.length) { return false; }
inputWords.forEach(function(word) {
if (words.indexOf(word.toLowerCase()) === -1) {
allWordsFound = false;
return;
}
});
return allWordsFound;
}
console.log(CheckWords());
I am creating a function that receive the text and check if include the answers(xx and yy), it doesn't matter the order. The ans list, can have 1,2 or more words, it will work.
let ans = ['xx','yy'];
function check(text){
text = text.toLowerCase();
let counter = 0;
ans.forEach((x) => {text.includes(x) && counter++ })
return counter === ans.length
}
console.log(check("aa bb")) // false
console.log(check("xx bb")) // false
console.log(check("aa yy")) // false
console.log(check("xx yy")) // true
console.log(check("yy xx")) // true

Search within a decimal range

var a = {28.82:0, 28.91:0, 29.11:0, 30.11:0, 32.22:0, 32.23:0, 32.24:0};
function check(range) // range = 28.90;
if (a[range]){
// do stuff here...
}
In the above scenario as you can notice, the condition will never hold true. I want to write a logic where it takes into account +/- 0.01 of the range to check inside the array.
I had figured driving all array elements through a range check function but that would be too expensive.
Any thoughts?
Let's see if I understand you correctly.
You need to define a tolerance:
var a = [28.82, 28.91, 29.11, 30.11, 32.22, 32.23, 32.24];
function check(range) { // range = 28.90;
for (var i = 0; i < a.length; i++) {
if (Math.abs(a[i] - range) <= 0.01) {
// do stuff here...
}
}
}
a[i] - range will produce the difference between the value and number you're seeking. 0.01 is the set tolarance.
Maybe I'm misunderstanding, but couldn't you do this?
var a = {28.82:"a", 28.91:"b", 29.11:"c", 30.11:"d", 32.22:"e", 32.23:"f", 32.24:"g"};
function check(range){
if (a[range] || a[range+0.01] || a[range-0.01]){
// do stuff here...
}
}
Or is that the approach that you were worried would be too expensive?
Note the logical check if(a[range]) will return false if the value at a[range] equals zero or false. If you want the code to run as long as the property exists, no matter its value, you'll need to modify your condition a bit to account for those edge cases.
Edit: As #SaniHuttunen points out in the comments, you can accomplish this with if(a[range] !== undefined)
function check(range){
function propExists(key){
return a[key] !== undefined;
}
if (propExists(range) || propExists(range+0.01) || propExists(range-0.01){
// do stuff here...
}
}
Would it help to know which two elements it falls between?
var a = [28.82, 28.91, 29.11, 30.11, 32.22, 32.23, 32.24];
function check(arr, range) {
var match = [];
arr.reduce(function(prev, curr){
if ( prev <= range && range <= curr ) { match = [prev, curr]; }
return curr;
})
return match;
}
console.log(check(a, 30.90));
// [30.11, 32.22]
JSFiddle demo.

getting values and assigning them to a hidden field

I have the following function that is suppose to take a value from a field in a form and assign it to a hidden field when its called. for some reason its not working and I cant give you more details on why its not working simply because javascript doesnt really tell you much about whats wrong.
function clickChange(stype){
if(stype == '1'){
var fValue = document.getElementById('checkB1').value;
if(fCatValue == 0){
fCatValue = fValue;
}else{
fCatValue = 0;
}
document.getElementById('cat_1').value = fCatValue;
}elseif(stype == '2'){
var sValue = document.getElementById('checkB2').value;
if(sCatValue == 0){
sCatValue = sValue;
}else{
sCatValue = 0;
}
document.getElementById('cat_2').value = sCatValue;
}
}
You need to convert the values to integer, or treat them as a string:
either:
var fValue = parseInt(document.getElementById('checkB1').value)
if(fCatValue == 0){....
or
var fValue = document.getElementById('checkB1').value;
if(fCatValue =='0'){...
Because of the placement of your declaration of the variable sCatValue it looks like sCatValue goes out of scope (or doesn't get declared at all).It would probably be easier on you if you declare all of your function scoped variables at the beginning of your function and cut down on the number of nested if statements.
I'd also recommend you use self explanatory variable names to cut down on confusing yourself. Also I'd recommend walking through your code with the use of a javascript debugger like firebug or ie 9's built in one. (surprising I know). And using jshint to help out with the common rules.
I found some other bugs and cleaned things up a bit and this is what I got
function clickChange(stype) {
//declared at the start so no scope undefined issues
var sValue = document.getElementById('checkB2').value;
var fValue = document.getElementById('checkB1').value;
//changed the comparision op from == to ===
//in javascript '===' throws false if the types compared are not the
//same otherwise it attemps to preform implicit casting for you
if (stype === '1') {
//parsing to insure that the types are matching
//the 10 is a radix param. It insures your number is formatted as a decimal
if (parseInt(fCatValue,10)=== 0) {
fCatValue = fValue;
} else {
fCatValue = 0;
}
document.getElementById('cat_1').value = fCatValue;
} else if (stype === '2') {
if (parseInt(sCatValue,10)=== 0) {
sCatValue = sValue;
} else {
sCatValue = 0;
}
document.getElementById('cat_2').value = sCatValue;
}
}

Simpler way to format if statement?

I have an if statement:
if(firstString == "no" && secondString == "no" && thirdString == "no"){
// Do stuff here
}
Is there a prettier way to format this? Using false instead of "no" is not an option, since the data I'm checking is from an AJAX request and I don't control its output. Otherwise I'd write it this way:
if(!firstString && !secondString && !thirdString){
// Do stuff here
}
Thanks
UPDATE:
I know this is totally ridiculous, but it occurred to me that this might actually be the shortest way:
if(firstString + secondString + thirdString == "nonono"){
// Do stuff here
}
Given that the number of strings is known in advance, then you have 2 options as far as I can see..
Leave it as it is. The if statement isn't hard to read, and any alternate formats will either be as complicated or more complicated.
convert the strings to booleans when you retrieve the data from the AJAX request, so that you're storing TRUE or FALSE instead of "yes" and "no". That would allow you to use a your preferred if statement format, and might be more efficient than many string comparisons if you do a lot of them.
In the end, which you do is up to you, but personally I think it would be better to just stick with what you've got. Don't worry about formatting an if statement, it's pretty obvious what it does, and in my opinion doesn't need to change.
If( "no" == firstString && firstString == secondString && secondString == thirdString )
It was a little difficult to determine exactly what you are evaluating to true or false, but this can be tweaked a tad to get what you're looking for.
var checkStrings = function() {
var no = "no",
args = Array.prototype.slice.call(arguments);
for (var i = 0, len = args.length; i < len; i++) {
if (args[i] !== no) {
return false;
}
}
return true;
};
if (checkStrings(firstString, secondString, thirdString)) {
// Do stuff here
}
Sorry, wasn't thinking--this is if you were checking whether ANY were 'no'
if ($.inArray('no', [firstString, secondString, thirdString]) >= 0) {
// Do something if the value is 'no'
}
UPDATED ANSWER
Unfortunately, jQuery doesn't have the reduce() function (another Array extra introduced in JS 1.6, but not available in older browsers) which would do the trick nicely.
Here's one way to check if all are 'no':
var found = true;
$.each([firstString, secondString, thirdString], function (i, str) {
if (str !== 'no') {
found = false;
}
});
It may seem uglier, but it should be shorter if you have a lot more strings to check.
If you want it wrapped in a function you could do:
function allTrue (arr, checkStr) {
var found = true;
$.each(arr, function (i, str) {
if (str !== checkStr) {
found = false;
}
});
return found;
}
if (allTrue([firstString, secondString, thirdString], 'no')) {
// ...
}
function F(var value){
return value === "no";
}
if(F(firstString) && F(secondString) && F(thirdString)){
// Do stuff here
}
Another option, using jQuery.unique:
var uniques = $.unique([firstString, secondString, thirdString]);
if (uniques.length === 1 && uniques[0] === "no") {
// do stuff
}

Categories

Resources