Any Idea on how Should I analyze this Algorithm? [closed] - javascript

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I was wondering if I could get some help on how to analyze an algorithm, my teacher gave us the validation code for some strings. and out project is that we must create a keygen for this validator, and, of course, it must be true when validated. I have been trying by brute force, but I have no luck and It has been working like for 2 hrs. now, so any help, idea, or tip on how to solve this would be perfect.
Thanks in advance.
Here is the code for the validator:
function char2number(chr) {
var code = chr.charCodeAt(0);
if(code<65) code = code-48;
else {
code=code-65+10;
if(code>=11) code++;
if(code>=22) code++;
if(code>=33) code++;
}
return code;
}
function checkdata(code) {
var dig = 0;
var test = 1;
for(var i=0; i<code.length-1;i++) {
dig=dig+(char2number(code.charAt(i))*test);
test*=2;
}
dig = mod(dig,9);
if(dig==code.charAt(code.length-1)) return true;
else return false; }
function mod(X,Y) { var t; t = X % Y; return t < 0 ? t + Y : t; }
function valida() {
var codigo = document.getElementById("code").value;
// Validate the code
if( code == "" || code.length < 15 ) {
alert("Invalid!");
return false;
}
if( ! checkdata(code.toUpperCase()) ) {
alert("Invalid!");
return false;
}
This code is written in Javascript since we have to elaborate our solution in Python and, from python, call the service to validate.
I don't think that making the code is hard, but I 've been thinking on a way to solve this and I just can't find a pattern to get it to work.
Thanks, all!

OK, what's going on inside checkdata? Well, whatever it's doing before the end, after dig = mod(dig, 9) it's got a number from 0 to 8, and it's comparing that to the last character (code.charAt(code.length-1))). Notice that the for loop above does i<code.length-1 rather than i<code.length, so that last character isn't included in the calculation. And (other than the check for length 15+) there's nothing else going on here.
So, you don't even have to understand what the whole for loop is doing. If you can generate 14 or more random characters, run the exact same code on them, and append the result to the end, it'll pass.
One quick and dirty way to do that is to just add an alert (or, maybe better, use console.log and run in node instead of a browser…) right before the end of checkdata that shows you what dig is:
function checkdata(code) {
var dig = 0;
var test = 1;
for(var i=0; i<code.length-1;i++) {
dig=dig+(char2number(code.charAt(i))*test);
test*=2;
}
dig = mod(dig,9);
alert(dig);
if(dig==code.charAt(code.length-1)) return true;
else return false;}
So now, take some random string of 15 or more characters, like "ABC123DEF456GHI789". An alert will pop up saying "2", and it'll fail because 2 and 9 aren't the same. So just use "ABC123DEF456GHI782" instead, and it'll pass.
Now all you have to do is port that checkdata function to Python, change the alert(dig) to return code[:-1] + dig, write the code to generate 15-character random strings, and of course write the code that calls the service. But that's it.
By the way, porting to Python isn't always quite as trivial as it seems; for example:
JS, 2 is a 64-bit floating point number; Python 2 is an unlimited-bit integer.
JS strings are Unicode; Python 2.x strings are not (but 3.x are).
JS strings in some browsers are actually UTF-16, not Unicode.
JS % is sign-preserving; Python % is always-positive.
Fortunately, for writing a keygen, you can generate something that doesn't stray beyond the limits of where any of these things matters, but you should think things through to make sure you do so.
I should add that your teacher may want you to understand what's going on inside the for loop, instead of treating it like a black box. Also, in real life, whoever wrote this silly algorithm would figure out how you cracked it, and make a trivial change that made at least partially understanding the loop necessary (e.g., if they change the <code.length-1 to <code.length).

Related

Why is my script saying '(' === ')' is true?

I was doing this kata on codewars. The question wants the function to return true if the first argument (string) passed in ends with the 2nd argument (also a string). So I wrote my function and everything worked just fine until it compares ':-)' with ':-(' and returns true.
What is wrong? I'm so confident that my code should work that I don't even know what to search for.
function solution(str, ending){
if (!ending) return true; // if ending is a empty string return true (the question wants that)
let ok;
const strArr = str.split(''), endingArr = ending.split('');
for (let i = 0; i < endingArr.length; i++) strArr.reverse()[i] === endingArr.reverse()[i] ? ok = true : ok = false;
return ok;
}
console.log(solution(":-)",":-("));
Your problem is a misunderstanding of what reverse() does. It does not return a reversed copy of the old array, it reverses the existing array and returns that same array. As a result, you keep reversing the arrays back and forth every iteration of the loop, causing some elements to be skipped and some to be checked twice.
Array.prototype.reverse() on MDN
Edit:
As pointed out by others in the comments, both to the question and this answer, there are in fact multiple problems.
reverse() aside, the loop always sets ok to the result of the last comparison, making the function ignore all previous results.
The easier way to implement this is to remove ok altogether. Instead, return false as soon as a mismatch is detected. If the function runs long enough to exit the loop, it means no mismatch was detected and true can be returned.
Edit 2:
Just as a friendly suggestion:
While both reverse() and ok are real issues with the code, I only noticed the first one the first time around due to the formatting of the code. The ok problem was off-screen due to the line being too long. As such, once I spotted the reverse() issue, I assumed that was it and didn't bother scrolling sideways to see the rest of the code.
I am not going to demand that you write your own code in a certain way, but if you format it properly, it allows others to read it more easily. In essence, you help us to more easily help you.
For instance, this line:
for (let i = 0; i < endingArr.length; i++) strArr.reverse()[i] === endingArr.reverse()[i] ? ok = true : ok = false;
...would have been significantly easier to read as...
for (let i = 0; i < endingArr.length; i++) {
if(strArr.reverse()[i] === endingArr.reverse()[i])
ok = true;
else
ok = false;
}
...or some variation thereof. Here, the problem is significantly more visible and obvious.
The other answer explains many of the mistakes you've made. I wanted to point out just how much you've over-thought your solution.
function solution(str, ending){
if (ending === "") return true; // if ending is a empty string return true (the question wants that)
return str.endsWith(ending);
}
console.log(solution(":-)",":-("));
console.log(solution("foo",""));
console.log(solution("foo","bar"));
console.log(solution("foobar","bar"));
Even my solution above is overengineered, str.endsWith("") always returns true. So this can be simplified further.
function solution(str, ending){
return str.endsWith(ending);
}
console.log(solution(":-)",":-("));
console.log(solution("foo",""));
console.log(solution("foo","bar"));
console.log(solution("foobar","bar"));

How to return multiple tokens with Jison lexer

I'm new to lexing and parsing so sorry if the title isn't clear enough.
Basically, I'm using Jison to parse some text and I am trying to get the lexer to comprehend indentation. Here's the bit in question:
(\r\n|\r|\n)+\s* %{
parser.indentCount = parser.indentCount || [0];
var indentation = yytext.replace(/^(\r\n|\r|\n)+/, '').length;
if (indentation > parser.indentCount[0]) {
parser.indentCount.unshift(indentation);
return 'INDENT';
}
var tokens = [];
while (indentation < parser.indentCount[0]) {
tokens.push('DEDENT');
parser.indentCount.shift();
}
if (tokens.length) {
return tokens;
}
if (!indentation.length) {
return 'NEWLINE';
}
%}
So far, almost all of that works as expected. The one problem is the line where I attempt to return an array of DEDENT tokens. It appears that Jison is just converting that array into a string which causes me to get a parse error like Expecting ........, got DEDENT,DEDENT.
What I'm hoping I can do to get around this is manually push some DEDENT tokens onto the stack. Maybe with a function like this.pushToken('DEDENT') or something along those lines. But the Jison documentation is not so great and I could use some help.
Any thoughts?
EDIT:
I seem to have been able to hack my way around this after looking at the generated parser code. Here's what seems to work...
if (tokens.length) {
var args = arguments;
tokens.slice(1).forEach(function () {
lexer.performAction.apply(this, args);
}.bind(this));
return 'DEDENT';
}
This tricks the lexer into performing another action using the exact same input for each DEDENT we have in the stack, thus allowing it to add in the proper dedents. However, it feels gross and I'm worried there could be unforeseen problems.
I would still love it if anyone had any ideas on a better way to do this.
After a couple of days I ended up figuring out a better answer. Here's what it looks like:
(\r\n|\r|\n)+[ \t]* %{
parser.indentCount = parser.indentCount || [0];
parser.forceDedent = parser.forceDedent || 0;
if (parser.forceDedent) {
parser.forceDedent -= 1;
this.unput(yytext);
return 'DEDENT';
}
var indentation = yytext.replace(/^(\r\n|\r|\n)+/, '').length;
if (indentation > parser.indentCount[0]) {
parser.indentCount.unshift(indentation);
return 'INDENT';
}
var dedents = [];
while (indentation < parser.indentCount[0]) {
dedents.push('DEDENT');
parser.indentCount.shift();
}
if (dedents.length) {
parser.forceDedent = dedents.length - 1;
this.unput(yytext);
return 'DEDENT';
}
return `NEWLINE`;
%}
Firstly, I modified my capture regex to make sure I wasn't inadvertently capturing extra newlines after a series of non-newline spaces.
Next, we make sure there are 2 "global" variables. indentCount will track our current indentation length. forceDedent will force us to return a DEDENT if it has a value above 0.
Next, we have a condition to test for a truthy value on forceDedent. If we have one, we'll decrement it by 1 and use the unput function to make sure we iterate on this same pattern at least one more time, but for this iteration, we'll return a DEDENT.
If we haven't returned, we get the length of our current indentation.
If the current indentation is greater than our most recent indentation, we'll track that on our indentCount variable and return an INDENT.
If we haven't returned, it's time to prepare to possible dedents. We'll make an array to track them.
When we detect a dedent, the user could be attempting to close 1 or more blocks all at once. So we need to include a DEDENT for as many blocks as the user is closing. We set up a loop and say that for as long as the current indentation is less than our most recent indentation, we'll add a DEDENT to our list and shift an item off of our indentCount.
If we tracked any dedents, we need to make sure all of them get returned by the lexer. Because the lexer can only return 1 token at a time, we'll return 1 here, but we'll also set our forceDedent variable to make sure we return the rest of them as well. To make sure we iterate on this pattern again and those dedents can be inserted, we'll use the unput function.
In any other case, we'll just return a NEWLINE.

How to distinguish if code in string is a piece of JS or CSS code? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I receive strings of code via simple POST requests, i am looking for a clever way (without having to run the script itself) to distinguish if it's a javascript script or css script, or at least to be quite sure (i'd say 55% possibility it is one of).
These are not files these are strings, so i don't have any information about the code in the string, no file, no file ext, no headers...
Do you have any advice/resource?
thanks a lot.
If this has to work with broken code too, I think your best chance is to search for "typical CSS" and "typical JS" stuff, and compare how much speaks for JS and how much for CSS.
Typical for JS are it's reserved words, and it's operators.
Typical for CSS is the structure: [, seperated selectors] { [ ; seperated key-value pairs] }
First a few utilities that triy to evaluate how much of a passed string is part of a particular language. (very basic approach, therefore should also work with broken code)
//returns **kind of** a percentage of how much of the string has been identified as JS/CSS
function evaluateCode(pattern, commentPattern, correctionalFactor){
correctionalFactor = +correctionalFactor || 1;
return function(string){
//removing comments and compacting whitespace.
//this avoids false hits, and provides a better estimation of how much significant text/code we have (to compute the percentage)
var t = string.replace(commentPattern || "", "").replace(/\s+/, " ");
return correctionalFactor * (t.match(pattern) || []).reduce(sumLengths, 0) / t.length;
}
}
var sumLengths = (acc, match) => acc + match.length;
var evaluateJS = evaluateCode(
/\b(?:function|return|arguments|this|var|const|let|typeof|instanceof|Array|Object)\b|[+\-*/<>&|=]+|[()\[\]\{\}]/g,
/\/\*[\s\S]*\*\/|\/\/[^\n]*/g,
1.5
);
var evaluateCSS = evaluateCode(
/[a-z0-9\.#:\[\]=,\s-]+\{(?:\s*[a-z-]+\s*:[^;]+;?)*\s*\}/gi,
/\/\*[\s\S]*\*\//g
);
And the usage:
var jsRatio = evaluateJS(string),
cssRatio = evaluateCSS(string);
//If there's less than 10% difference between the two estimations, I'd call it "unclear"
if(Math.abs(jsRatio - cssRatio) < .1){
console.log("result is ambigious, but I tend more towards");
}
console.log("%s (probabilities: css %f%, js %f%)", cssRatio > jsRatio? "css": "js", cssRatio, jsRatio);
I use an estimated/guessed "correctional factor" of 1.5 on evaluateJS, because the regex matches only a part of the code,
whereas the css-regex matches almost everything.
This factor only matters when the results are ambigious, usually there should be a huge gap between the two ratios.
Edit: another (probably better) regex to search for CSS:
/[a-z0-9\-]+\s*:[^;{}]+[;}]|(?:[#.]?[a-z]+(?:[#.:\s][a-z0-9-_]+)*\s*[,{])/gi
this is looking only for key-value pairs and "typical" selectors, containing ids and classes, rather than the whole structure, wich should be benefitial, if css-structure is broken or too complex for the fairly simple regex.
You might enclose the returned string in a block that prevents it from being executed (if it's JavaScript) and see if it can be parsed.
function isJavaScript(str)
{
try
{
Function('function(){' + str + '}');
return true; // Looks like valid JS
}
catch (error)
{
// no valid JavaScript, may be CSS
return false;
}
}
I don't think this is 100% foolproof, but it may work for your purpose.

If the execution of the bulk of a function is conditional on the input, which of these is a better way to implement?

I'm wondering which of these is better and why. I often encounter situations in my daily work where I'm like "This algorithm works so long as the input isn't empty" or something like that. I usually just return early because, for some reason, the idea of wrapping almost the entirety of a function in an if conditions seem wrong to me. However, I know that some religions don't believe in early return statements.
Example:
(1)
function combine ( strings , separator )
{
if ( strings.length > 0 )
{
retstring = strings[0];
for ( var i = 1; i < strings.length; ++ i )
retstring += (separator + strings[i]);
}
return retstring;
}
(2)
function combine ( strings , separator )
{
if (strings.length === 0) return undefined;
retstrings = strings[0];
for ( var i = 1; i < strings.length; ++ i )
retstring += (separator + strings[i]);
return retstring;
}
So which is better to go with in such situations?
I'd say that neither is "better"; it's subjective.
And, unlike many subjective programming choices, this one isn't just a matter of personal preference. Rather, I think a good programmer will use both patterns, choosing which one based on what they want to express.
Pattern #1 says "if X do Y". Pattern #2 says "If !X, don't do anything else." Admittedly, those two are equivalent to any browser running your code.
But, to a human reading your code (eg. such as a co-worker who has to modify it) each pattern suggests different things about what is going on. Thus, my recommendation would be to try and determine which of the two patterns best describes what you are trying to communicate, and use that.
For instance, many functions have "if this isn't relevant logic", and that is best expressed with pattern #2:
function doStuffIfLoggedIn(user) {
if (!user.isLoggedIn()) return;
doStuff();
}
But it's also fairly common to do something if a particular option is provided, and that fits better with the first pattern:
function format(word, capitalize) {
if (capitalize) {
word = string.toUpperCase();
}
returns word;
}
If either is equally valid (and I find this happens fairly often) then it does come down to a matter of preference. Personally, in those "either is valid" cases I opt for #2; all else being equal it results in less indentation, which I (subjectively) find easier to read.
But really, the important thing (IMHO) is to think about how your code will look to the person who comes after (and that might even be you, a year later when you've forgotten why you wrote it that way). The browser doesn't care either way, and your co-workers will be able to understand either one, but using the one that best represents the situation can offer a critical clue about the code's function to whoever reads it later.
EDIT
To your point about:
some religions don't believe in early return statements
I think the idea there is that multiple return statements can make the code more complicated. When your function has lots of ways of exiting it can become hard to understand its logic, because to interpret a latter part, you have to reason through whether any of the earlier parts prevented you from getting there.
However, the Stack Overflow consensus is that, while it's a good idea to avoid excessive return statements, using a few properly can make your code more readable, and thus are a good idea.
See:
Should a function have only one return statement?
There is a built-in array method that does what your functions do: join()
function combine(strings, separator) {
return strings.join(separator);
}
console.log(combine(['this','is','a','test'], '...')); //this...is...a...test
But if join() didn't exist, I'd recommend a variation on your first code. You don't have to explicitly return undefined. If you don't include a return statement, the function will automatically return undefined:
function combine(strings, separator) {
if (strings.length) {
var retstring = strings[0];
for (var i = 1; i < strings.length; ++i)
retstring += (separator + strings[i]);
return retstring;
}
}
console.log(combine(['this','is','a','test'], '...')); //this...is...a...test
console.log(combine([], '...')); //undefined

Back tracing an expression in JavaScript source code

Sorry for the title, couldn't come up with a better one.
Let's say we have that JavaScript code string:
var n = Math.floor(Math.random() * 10),
className;
if (n === 1) {
className = "a";
} else if (n === 2) {
className = "b";
} else {
className = "c";
}
document.querySelector("." + className);
The idea is that I want to get all the possible strings sent to that particular function (document.querySelector). So I want to get ['.a', '.b', '.c']. There could also be multiple variables involved, modified several times in the code, so that the list would be much longer.
Now how do I do that in Python? I've looked at PyV8 but there is no documentation, so that's not an option; same for python-spidermonkey which is way outdated.
This is not an easy problem. You're looking for static code analysis to generate all possible paths through your function. Consider the following code and ask yourself how to determine whether an alert will run:
var n = Math.floor(Math.random() * 10),
if (Math.sqrt(n) > n) {
alert('a');
}
The computer doesn't "know" that Math.sqrt(n) will always be smaller than n. Without running the code, how do I determine that the alert won't show up?
In simple cases a library might be able to do it but when your function has numerous possible paths and utilizes many functions you'll need some hefty analysis to get the correct answer.
Well, you could take the Monte Carlo approach: log all arguments passed to document.querySelector and run the code against a variety of inputs.

Categories

Resources