JavaScript: Guessing password - javascript

Another JavaScript question I found on the internet, but I couldn't figure out how it works. The question basically asks what is the password. The password doesn't depend on external resources and it doesn't change over time (do not depends on current date or time). Also, question says that there is exactly one correct password. I am JavaScript begginer, so I apologize if this is a simple standard interview question. This is the function:
const checkPassword = a => {
if(a !== (a += '')) return false;
if(a !== (a = a.replace(/[^a-z]/g, ''))) return false;
a = (a.match(/^.{6}|.+/g) || []).join(({} + {})[7]);
a = [...a].reverse().join([] + []);
try{
Function('\'' + a + '\';++1..a')();
return false;
}catch(a){
return true;
}
};
alert(checkPassword(prompt('Enter password:')) ? 'Correct password.' : 'Wrong. Try again.');
At first, this didn't look hard too me, because everything is open, so I can simply follow code line by line and figure out how does it work. Ok, I understand that in the first line of check function they check if password is a string (why? Can it be something else?). Then, if I understood that regex well, they check if script consists only of small alphabet letters (or am I wrong?). So, for now I know I know it must consists only of letters. After that they perform some weird regex I cannot fully understand. It seems to me that this regex will match whole string, so why they are joining it?
Then they reverse string and join by an empty array (is it same as normally reversing string or what?). After that in try block I cannot understand what is happening? What does Function constructor actually do here? What is the meaning of ++1..a? Im just wondering how to approach questions like this one?

I'll jump straight to the key line:
Function('\'' + a + '\';++1..a')();
It creates and then immediately executes a new function with a function body set from that weird-looking string. If the variable a is, say, 'abcde' then the new function's body will be:
'\'' + 'abcde' + '\';++1..a'
which is like having this function:
function() {
'abcde';++1..a
}
Or with some whitespace:
function() {
'abcde';
++1..a
}
Note that the string on the first line is dynamically set based on what is in the a variable, but the ++1..a part is hardcoded.
Now, noting that the function is inside a try/catch() block, if the new function runs without error then checkPassword() will return false, but if the new function crashes checkPassword() returns true. In other words, it is expected that the behaviour of that dynamic function will change to crash or not depending on what is in the string from the a variable.
So what string, by itself on the first line of a function, can possibly change the behaviour of the function? There is only one possibility, and that is (hover to reveal spoiler):
'use strict' ...which would have to be entered as the password 'tcirtsesu' because of the first few lines of the function doing the .match() and .reverse().
With that in mind it doesn't even really matter what the ++1..a part does, but it is basically taking the .a property of 1, which is undefined, and trying to increment it, which...
is an error in strict mode but not in non-strict mode.
For completeness, a very brief explanation of these lines:
a = (a.match(/^.{6}|.+/g) || []).join(({} + {})[7]);
a = [...a].reverse().join([] + []);
The .match() function returns an array. /^.{6}|.+/g matches the first six characters, OR any number of characters, which means that "abcdefghijkl".match(/^.{6}|.+/g) returns ["abcdef", "ghijkl"]. Then ({} + {})[7] is basically just a space character because {} + {} is the string "[object Object][object Object]". So that line basically inserts a space after the sixth character.
The .reverse() line then reverses the result of that.

Related

Create function REGEX for optimization

I've been asked to optimize the speed of my query. I currently have this regex in my query, which is checking for a pattern and returning substring within that pattern. To clarify I have a table with multiple columns that I have to look through to check for this value: [v= and return the numbers within that list.
This is looking through several 'name..' columns that look something like this: xyzzy [v=123] but I only want to return 123, the below works:
COALESCE(REGEXP_SUBSTR(NAME, '[[]v=([0-9]+)', 1, 1, 'ie'),
REGEXP_SUBSTR(NAME_5, '[[]v=([0-9]+)', 1, 1, 'ie'),
REGEXP_SUBSTR(NAME_4, '[[]v=([0-9]+)', 1, 1, 'ie')) as display_vertical_code
but to optimize this, I thought of maybe creating a function unfortunately I don't know javascript :/ and I don't know if the formatting is correct I'm having some difficulties creating it, this is what I've tried, can someone tell me if I'm missing something?
CREATE OR REPLACE FUNCTION dfp.regex(NAME VARCHAR)
RETURNS OBJECT
LANGUAGE javascript
STRICT AS '
return new RegExp(NAME,"[[]v=([0-9]+)",1 ,1,"ie")
';
When I try to use the above function in my below query:
COALESCE(
GET(DFP.REGEX(NAME)),
GET(DFP.REGEX(NAME_5)),
GET(DFP.REGEX(NAME_4)),
GET(DFP.REGEX(NAME_3)),
GET(DFP.REGEX(NAME_2)),
GET(DFP.REGEX(NAME_1)),
GET(DFP.REGEX(NAME_0))
) as display_vertical_code
I see this error:
error line 3 at position 8 not enough arguments for function
[GET(REGEX(Tablename.NAME))], expected 2, got 1
This should do it.
CREATE OR REPLACE FUNCTION regex(NAME VARCHAR)
RETURNS string
LANGUAGE javascript
STRICT IMMUTABLE AS
$$
const regex = /[[]\s{0,5}v\s{0,5}=\s{0,5}([0-9]+)/i;
let s = NAME.match(regex);
if (s != null) {
return s[0].split('=')[1].trim();
} else {
return null;
}
$$;
select regex('xyzzy [v=123]');
-- Alternate permutation
select regex('xyzzy [ v = 123]');
You want to return a string, not an object. Adding the IMMUTABLE option tells Snowflake that the same input results in the same output every time. It can sometimes help with performance.
Edit... This one's a bit more fault tolerant and allows whitespace (if that could be a problem). If you want to get rid of allowing whitespace, delete the \s{0,5} expressions.

Using regex to test out of 4 words in an array has a perfect match

I was tasked with a project of creating a CV site were the user uploads a .docx file and the details is extracted from the file and is automatically inputted in the template designed by me,
I have been able to extract the details .docx file with JavaScript and the extracted details was kept in an array to make it easy to identify words with indexing. For example
[Adeola Emmanuel, adeolaemmanuel#gmail.com, pharmacist, 2 ketu ikorodu lagos, etc].
where i need help is not all CV uploaded by the user has the name coming first or email coming second but its sure that they come within 0,6 of the array so i decided to write a function that will help with that but its not working
var email = email(text.slice(0, 5));
function email(email) {
var re = /.{1,}#[^.]{1,}/ig;
if (!re.test(email)) {
email = text.slice(0, 1);
return email;
} else if (re.test(email)) {
email = text.slice(3, 5);
return email;
}
}
You can use the find array method:
function getEmail(arr) {
let re = /\S#[^.\s]/;
return arr.find(str => re.test(str));
}
let text = ["Adeola Emmanuel", "adeolaemmanuel#gmail.com", "pharmacist", "2 ketu ikorodu lagos"];
let email = getEmail(text.slice(0, 5));
console.log(email);
Some remarks:
{1,} in regular expressions can be shortened to just +
You actually don't need to test for multiple occurrences with +, since you would already accept one occurrence. So that also means you would be OK with just one non-point character after the #.
Neither of the regex suffixes (ig) have any use in your regex.
The .test method should get a string as argument, not an array. So you need to pass it email[0] for example.
For a full test of whether some string is a valid email address, the regular expression would be way more complex
When an if condition is false, there is no need to test the exact opposite in the else block: by exclusion that opposite condition will always be true when it gets executed.
The slice of an array is still an array, so returning text.slice(3, 5); in the else block does not make sense. You want to return a string.
You need a loop to inspect other array elements for as long as you don't have a match and have not reached the end of the array. So some loop construct is needed. You can use for, while, or any of the array methods that do such looping. find is particular useful in this case.
Don't give your function the same name as another variable (email) as only one value can be assigned to that variable (a function, a string, or still something else). So in your case you'll lose the function definition by the var initialisation.

How to access the first two digits of a number

I want to access the first two digits of a number, and i have tried using substring, substr and slice but none of them work. It's throwing an error saying substring is not defined.
render() {
let trial123 = this.props.buildInfo["abc.version"];
var str = trial123.toString();
var strFirstThree = str.substring(0,3);
console.log(strFirstThree);
}
I have tried the above code
output of(above code)
trial123=19.0.0.1
I need only 19.0
How can i achieve this?
I would split it by dot and then take the first two elements:
const trial = "19.0.0.1"
console.log(trial.split(".").slice(0, 2).join("."))
// 19.0
You could just split and then join:
const [ first, second ] = trial123.split('.');
const result = [ first, second ].join('.');
I have added a code snippet of the work: (explanation comes after it, line by line).
function getFakePropValue(){
return Math.round(Math.random()) == 0 ? "19.0.0.1" : null;
}
let trial123 = getFakePropValue() || "";
//var str = trial123.toString();
// is the toString() really necessary? aren't you passing it along as a String already?
var strFirstThree = trial123.split('.');
//var strFirstThree = str.substring(0,3);
//I wouldn't use substring , what if the address 191.0.0.1 ?
if(strFirstThree.length >= 2)
console.log(strFirstThree.splice(0,2).join("."));
else
console.error("prop was empty");
Because you are using React, the props value was faked with the function getFakePropValue. The code inside is irrelevant, what I am doing is returning a String randomly, in case you have allowed in your React Component for the prop to be empty. This is to show how you an create minimal robust code to avoid having exceptions.
Moving on, the following is a safety net to make sure the variable trial123 always has a string value, even if it's "".
let trial123 = getFakePropValue() || "";
That means that if the function returns something like null , the boolean expression will execute the second apart, and return an empty string "" and that will be the value for trial123.
Moving on, the line where you convert to toString I have removed, I assume you are already getting the value in string format. Next.
var strFirstThree = trial123.split('.');
That creates an array where each position holds a part of the IP addrss. So 19.0.0.1 would become [19,0,0,1] that's thanks to the split by the delimiter . . Next.
if(strFirstThree.length >= 2)
console.log(strFirstThree.splice(0,2).join("."));
else
console.error("prop was empty");
This last piece of code uses the conditional if to make sure that my array has values before I try to splice it and join. The conditional is not to avoid an exception, since splice and join on empty arrays just returns an empty string. It's rather for you to be able to raise an error or something if needed. So if the array has values, I keep the first two positions with splice(0,2) and then join that array with a '.'. I recommend it more than the substr method you were going for because what if you get a number that's 191.0.0.1 then the substr would return the wrong string back, but with splice and join that would never happen.
Things to improve
I would strongly suggest using more human comprehensible variables (reflect their use in the code)
The right path for prop value checking is through Prop.Types, super easy to use, very helpful.
Happy coding!

Javascript Unnecessarily Compact Array Operations

So, for my own knowledge, and because I love looking at things from a different perspective...
I have the following bite of Javascript code, which for this problem's intents and purposes will only ever receive strings formatted like this: "wordone wordtwo":
function inName(inputName) {
return inputName.split(" ")[1].toUpperCase();
}
However, this only returns half of what I want ("WORDTWO"). I desire to return the original string with a single change: the space-separated second word returned through the toUpperCase(); and then re-concatenated to the untouched first word.
I also want to unnecessarily run all of the operations on the return line. My brain says this is possible, given how as the compiler reads the line from left to right and makes adjustments to the available member functions based on what has resolved. Also everything in Javascript is an object, correct?
Help me out for my own curiosity's sake, or bash me over the head with my own misconceptions.
Here is a solved version of the above question using 'normal' statements:
function inName(inputName) {
var nameArray=inputName.split(" ");
nameArray[1]=nameArray[1].toUpperCase();
return nameArray.join(" ");
}
One line with substr, indexOf and a variable on the fly ;-)
function inName(inputName) {
return inputName.substr(0, (index = inputName.indexOf(' '))) + inputName.substr(index).toUpperCase();
}
Here's another option which avoids the regular expression:
function inName(inputName) {
return inputName.split(' ').map(function(v,i){return i?v.toUpperCase():v;}).join(' ');
}
This does the same split as the original code, then maps the parts to a function which returns the value at index 0 unchanged but the value at index 1 in upper case. Then the two results are joined back together with a space.
As others have said, a longer, clearer version is better in practice than trying to come up with a clever one-liner. Defining a function inside the return statement feels like cheating anyway ;-)
Something like this almost seems like it belongs on Code Golf, but here's my take:
function inName(inputName) {
return inputName.replace(/ .*/,function(m) {return m.toUpperCase();});
}
Interesting. Here is my take on the problem
function justDoIt(str){
return [str = str.split(" ") , str.pop().toUpperCase()].join(" ");
}
Creates a new array, str is split and reassigned as an array, and the first item of the new array, then the second new array item pops the last word, makes it uppercase, puts it into the new array. Then joins the array [["wordOne"],"WORDTWO"].join(" ")

how can I fix this regular expression function?

This is the first part of my code in a function:
var pattern = new RegExp(myTypedString,"gi");
The goal is to populate results as I type in a text field. Everytime an input event is triggered I loop through an array of strings and check if my typed string exists in my array of strings using this code:
return pattern.test(myArrayString);
but luckily I've realised that one of the results was wrong and it was only happening to this particular case: when I type "t" or "T" I don't have a match in "Trafalgar Square" (a string from myArrayString), so I did a few debugging in the console and when I check the variable pattern doing console.log(pattern) it outputs this string: /t/gi, which i think it's where my problem relies... (later on this)
when I tried to replicate the problem typing:
var pattern = new RegExp('t',"gi")
and:
pattern.test('Trafalgar Square')
which gives me true at a first try, BUT... if I type this again:
pattern.test('Trafalgar Square')
the result will be false and if I continue, true, false, true, false,...
One of the first things that came into my mind is that the /t in the regex /t/gi might be a rule but I couldn't find anything about it.
I would like to know an explanation for this unexpected result but I'm also concerned that my function is not flawless, so I ask you how can I improve this function? thanks
It alternates between true and false because it matches the first time (true), then tries a second match, which fails because there’s only one T in Trafalgar Square. When you call it again, it loop back, thus the true, false, true, etc.
To fix that, update its cursor before matching:
var p = new Regexp('t', 'gi') // same as `p = /t/gi`
// ...
p.lastIndex = 0;
p.test("Trafalgar Square"); // true
// try again:
p.lastIndex = 0;
p.test("Trafalgar Square"); // true -> it works
Here is a relevant jsfiddle with a couple examples.
I do not know why it alternates between true and false (i can reproduce it, too). The /t/ should not be anything special in the regex. It is not a special character like { or \ or [ and should just be a literal character t.
But you could use another function to achieve more or less the same:
'Trafalgar Square'.match(pattern)
=> Array [ "T" ]
'lalala'.match(pattern)
=> null
match takes slightly more resources than test would, but this is usually not a problem. The result will be an Array for matches or null when nothing matches, so you can just return that and the rest of your code will probably work just fine. Array... will be a truthy value and null will be a falsy value.

Categories

Resources