Not expected .map()/.match(regex) output - javascript

First line of the input contains an integer, N. Then N lines follow.
From the second line onwards, each line contains a set of W words separated by a single space.
For every line,
Print (console.log()) 1 if the conversation starts with hackerrank
Print 2 if the conversation ends with hackerrank
Print 0 if the conversation starts and ends with hackerrank
Print -1 if none of the above.
Code (JavaScript)
const processData = (input) =>
input
.split("\n")
.slice(1)
.map((line) => line.match(/^(hackerrank)\b.*(?<!\bhackerrank)$/g) ? console.log(1) : line.match(/ hackerrank$/g) ? console.log(2) : line.match(/^(hackerrank)\b(.*(?<!\bhackerrank))?$/g) ? console.log(0) : console.log(-1));
Input
4
i love hackerrank
hackerrank is an awesome place for programmers
hackerrank
i think hackerrank is a great place to hangout
Expected output
2 1 0 -1
(one number by line... im having a hard time with my markdown)
The output I get
2 1 0 -1 -1
(one number by line... im having a hard time with my md)
what's going on with this last -1?
i've tested this code on codepen and it works but it doesn't work on hackerrank
thank you

You can remove empty lines before parsing with filter.
input.split("\n").slice(1).filter(Boolean)
Alternatively, remove leading and trailing whitespace from the input with String#trim before splitting.
input.trim().split("\n")

Related

Can anyone explain this process with converting decimal numbers to Binary

I have looked around the internet for a way to convert decimal numbers into binary numbers. and i found this piece of code in some forum.
var number = prompt("Type a number!") //Asks user to input a number
var converted = []; // creates an array with nothing in it
while(number>=1) { //While the number the user typed is over or equal to 1 its shoud loop
converted.unshift(number%2); // takes the "number" and see if you can divid it by 2 and if theres any rest it puts a "1" otherwise "0"
number = Math.floor(number/2); // Divides the number by 2, then starts over again
}
console.log(converted)
I'm not understanding everything completely, so i made some comments of what i think the pieces of code do. But anyone that can explain in more detail? or is the way i think the code does correct?
This code is based on a technique for converting decimal numbers to binary.
If I take a decimal number. I divide it by two and get the remainder which will either be 0 or 1. Once you divide 57 all the way down to 0. You get the binary number for example:
57 / 2 = 28 r 1; 28 / 2 = 14 r 0; 14 / 2 = 7 r 0; 7 / 2 = 3 r 1; 3 / 2 = 1 r 1; 1 / 2 = 0 r 1;
The remainders are the binary number. Sorry if it's a bit hard to read. I definitely recommend writing it out on paper. Read from the last remainder to the first, the remainders look like this: 111001
Reverse it to make it correct. array.unshift() can do this or you could use array.push() then array.reverse() after the while loop. Unshift() is probably a better approach.
57 in decimal is equal to 111001, which you can check.
BTW, this algorithm works for other bases, as long you are converting from decimal. Or at least as far as I know.
I hope this helped.
It seems like you've got the gist of it down.
Let's start with a random number:
6 === 110b
Now let's see what the above method does:
The number is geq than 1, hence, let's add the last bit of the number to the output
6%2 === 0 //output [0]
the number we're working with after dividing the number by two, which is essentially just bit-shifting the whole thing to the right is now 11b (from the original 110b). 11b === 3, as you'd expect.
You can alternatively think of number % 2 as a bit-wise AND operation (number & 1):
110
& 1
-----
0
The rest of the loop simply carries the same operation out as long as needed: find the last bit of the current state, add it to the output, shift the current state.

How to parse a string containing text for a number/float in javascript?

I'm trying to build a javascript function capable of parsing a sentence and returning a number.
Here is a jsFiddle I've setup for the test cases below -
'I have 1 pound' -> 1
'I have £3.50 to spend' -> 3.50
'I have 23.00 pounds' -> 23
'£27.33' -> 27.33
'$4345.85' -> 4345.85
'3.00' -> 3
'7.0' -> 7
'Should have 2.0.' -> 2
'Should have 15.20.' -> 15.20
'3.15' -> 3.15
'I only have 5, not great.' -> 5
' 34.23' -> 34.23
'sdfg545.14sdfg' -> 545.14
'Yesterday I spent £235468.13.
Today I want to spend less.' -> 235468.13
'Yesterday I spent
340pounds.' -> 340
'I spent £14.52 today, £17.30 tomorrow' -> 14.52
'I have 0 trees, £11.33 tomorrow' -> 0
16&17 indicate that it should find the first number. I understand that some of the test cases may be tough but I welcome anything that gets me reasonable coverage.
Here is the format I'm using for my function
function parseSentenceForNumber(sentence){
return number; //The number from the string
}
I think I could get 60-80% of the way myself, but I expect a regular expression might be the best solution here and I've never been great at them. Hopefully I have enough test cases but feel free to add any I might of missed.
Your help is much appreciated.
**UPDATE**
Loads of working answers and I need to spend some time looking at them in more detail. Mike Samuel mentioned commas and .5 which leads me to add another couple of test cases
18.'I have 1,000 pound' -> 1000
19.'.5' -> 0.5
And jsalonen mentioned adding test case for no numbers
20.'This sentence contains no numbers' -> null
Here is the updated fiddle using jsalonen's solution, without my changes in spec I'd be 100% there, with the changes I'm 95%. Can anyone offer a solution to number 18 with commas?
**UPDATE**
I added a statement to strip out commas to jsalonen's function and I'm at 100%.
Here is the final function
function parseSentenceForNumber(sentence){
var matches = sentence.replace(/,/g, '').match(/(\+|-)?((\d+(\.\d+)?)|(\.\d+))/);
return matches && matches[0] || null;
}
And the final Fiddle
Really appreciate the help and I have improved my regular expression knowledge along the way. Thanks
Answer that matches all negative and positive numbers with any number of digits:
function parseSentenceForNumber(sentence){
var matches = sentence.match(/(\+|-)?((\d+(\.\d+)?)|(\.\d+))/);
return matches && matches[0] || null;
}
Consider adding negative test cases too, like testing what happens when a string does not have numbers:
test("Test parseSentenceForNumber('This sentence contains no numbers')", function() {
equal( parseSentenceForNumber('This sentence contains no numbers'), null );
});
Full fiddle: http://jsfiddle.net/cvw8g/6/
The regular expression:
\d+(?:\.\d+)?
should do it.
\d+ matches a sequence of digits.
.\d+ matches a decimal point followed by digits.
(?:...)? makes that group optional
This doesn't deal with the special case where the fraction is all zeroes, and you don't want the fraction included in the result, that's difficult with a regexp (I'm not sure if it can even be done, although I'm willing to be proven wrong). It should be easier to handle that after matching the number with the decimal in it.
Once you've matched the number in the string, use parseFloat() to convert it to a number, and toFixed(2) to get 2 decimal places.
The general form of a number in computer readable form is:
/[+\-]?((?:[1-9]\d*|0)(?:\.\d*)?|\.\d+)([eE][+-]?\d+)?/
based on the grammar
number := optional_sign (integer optional_fraction | fraction) optional_exponent;
optional_sign := '+' | '0' | ε;
integer := decimal_digit optional_integer;
optional_integer := integer | ε;
optional_fraction := '.' optional_integer | ε;
fraction := '.' integer;
optional_exponent := ('e' | 'E') optional_sign integer;
so you can do
function parseSentenceForNumber(sentence){
var match = sentence.match(
/[+\-]?((?:[1-9]\d*|0)(?:\.\d*)?|\.\d+)([eE][+-]?\d+)?/);
return match ? +match[0] : null; //The number from the string
}
but this doesn't account for
Locales that use fraction separators other than '.' as in "π is 3,14159..."
Commas to separate groups of digits as in 1,000,000
Fractions
Percentages
Natural language descriptions like "a dozen" or "15 million pounds"
To handle those cases you might search for "entity extraction" since that's the overarching field that tries to find phrases that specify structured data within unstructured text.
One more possible regex:
/\d+\.?\d{0,2}/
This means:
\d: one or more digits
\.?: zero or one period
d{0,2} up to 2 digits
http://jsfiddle.net/cvw8g/7/
No regex, uses parse aswell (so will return NaN if no number found).
Finds the first number in the string, then attempt to parse it from that point.
Passes all of your tests, and returns a number, not a string, so you can immediately use it for comparisons or arithmatic.
function parseSentenceForNumber(str) {
//tacked on to support the new "1,000" -> 1000 case
str = str.replace(',', '');
var index;
//find the first digit
for (index = 0; index < str.length; ++index) {
if (str.charAt(index) >= '0' && str.charAt(index) <= '9')
break;
}
//checking for negative or decimal point (for '.5')
if (index > 0 && (
str.charAt(index - 1) == '-' ||
str.charAt(index - 1) == '.'
))
//go back one character
--index;
//get the rest of the string, accepted by native parseFloat
return parseFloat(str.substring(index));
}
Passes all tests and I think it is a lot more readable:
function parseSentenceForNumber(sentence){
return parseFloat(sentence.replace(/,(?=\d)/g,"").match(/-?\.?\d.*/g));
}
...well almost all tests: it returns 'NaN' instead of 'null' when no number is in sentence. But I think 'NaN' is more informative than a simple 'null'.
Here is the jsFiddle: http://jsfiddle.net/55AXf/

Building an effective js/ jQ 'thousands' comma separator that works for large numbers (10^6+) on key up

I have spent time looking through each of the proposed solutions to the problem of adjusting user input strings as they type to format a large number to have comma separators:
9999999999 --> 9,999,999,999 and so on.
There are several discussions here on stack overflow:
How to print a number with commas as thousands separators in JavaScript
Adding comma as thousands separator (javascript) - output being deleted instead
and many more related queries, I've tested those that I could find, and they worked well for numbers up to a power of 4 or 5, eg 12,345 comes out nicely,
But larger numbers end up with far too many commas:
1,,,,,0,,,0,,,000
for example is the output of the code I currently have implemented. (It also registers backspace as a key stroke, so when I backspace three times it adds a comma...)
function numberWithCommas(n){
var s=n.split('.')[1];
(s) ? s="."+s : s="";
n=n.split('.')[0]
while(n.length>3){
s=","+n.substr(n.length-3,3)+s;
n=n.substr(0,n.length-3)
}
return n+s
}
and then on the input:
onkeyup="this.value=numberWithCommas(this.value);"
Am I using the function incorrectly? Or is it simply not viable for larger numbers. Is there a way it can be adjusted to work for any size of number?
Thanks in advance
You are just adding comas to a value which already as commas after the first iteration... You should just reset the commas at the beginning of your function numberWithCommas:
n = n.replace(/,/g, "");

what's wrong with this regular expression (if else regex)

What I want is, there is a textbox with maximum length of 5. The values allowed are..
any integer // for example 1, 3, 9, 9239 all are valid
real number, with exaclty one point after decimal // eg. 1.2, 93.7 valid and 61.37, 55.67 invalid
it is also allowed to enter only decimal and a digit after that, that is .7 is valid entry (would be considered as 0.7)
I found this page, http://www.regular-expressions.info/refadv.html
So what I thought is that
There is a digit
If there is a digit and a decimal after that, there must be one number after that
If there is no digit there must be a decimal and a digit after that
So, the regex I made is..
a single digit one or more => /d+
an optional decimal point followed by exactly one digit => (?:[.]\d{1})?
if first condition matches => (?(first condition) => (?((?<=\d+)
then, match the option decimal and one exact digit =>(?((?<=\d+)(?:[.]\d{1})?
else => |
find if there is a decimal and one exact digit => (?:[.]\d{1}){1}
check the whole condition globally => /gm
overall expression =>
(?(?<=\d+)(?:[.]\d{1}){1}|(?:[.]\d{1}){1})+/gm
But it doesn't outputs anything..
Here's the fiddle
http://jsfiddle.net/Fs6aq/4/
ps: the pattern1 and pattern2 there, are related to my previous question.
Maybe you are complicating things too much. I did a quick test and unless I'm missing something this regex seems to work fine:
/^\d*\.?\d$/
Demo: http://jsbin.com/esihex/4/edit
Edit: To check the length you can do it without regex:
if ( value.replace('.','').length <= 5 && regex.test( value ) ) {
...
}
Notice that I used replace to remove the dots so they don't count as characters when getting the length.
You can try the following pattern:
/^\d{0,4}\.?\d$/
It seems to fulfil all your requirements:
> /^\d{0,4}\.?\d$/.test(".4")
true
> /^\d{0,4}\.?\d$/.test(".45")
false
> /^\d{0,4}\.?\d$/.test("1234.4")
true
> /^\d{0,4}\.?\d$/.test("12345.4")
false
> /^\d{0,4}\.?\d$/.test("12345")
true
> /^\d{0,4}\.?\d$/.test("123456")
false
This pattern assumes that the number can have a maximum of five digits and an optional decimal point.
If the maximum length of five includes the optional decimal point then the pattern is slightly more complex:
/^(?:\d{1,5}|\d{0,3}\.\d)$/
The first part of the group deals with integer numbers of the required length, the second option of the group deals with real numbers which maximum length (including the decimal point) is five.
Consider this code:
var checkedString = "45.3 fsd fsd fsdfsd 673.24 fsd63.2ds 32.2 ds 32 ds 44 fasd 432 235f d653 dsdfs";
checkedString = " "+checkedString;
var results = checkedString.match(/[\s]{1}(\d+\.*\d{1})(?![\d\.\w])+/gm);
results.map(function(result) {
return result.trim();
});
Couldn't make it in other way because in JS (?<= (lookbehind) regexp is not working.
This will be returned:
["45.3","32.2","32","44","432"]
So probably it's what you've expected.
I don't know what are you trying to do with those conditionals in your regex. I also looked at your jsfiddle, which outputs nothing for me. But I made a two versions of a regex that matches the correct values for the textbox, which are ^(?!(.{6,}))(?:[1-9]\d*)*(?:\.\d*[1-9])?$ and ^(?!(.{6,}))(?:\d*)*(?:\.\d*)?$.
The first disallows to start with zero, or end with zero after the decimal.
Comment if you need explanation of the regex.

javascript: trying to validate a number that has to be 4 digits to see if x<100 (ie 0100)

i hate asking for help as i would rather figure things for myself, or learn from what others have posted or already asked and solved. as such this is my first post on here!
This is either really really simple and im over complicating things or im going about it the wrong way. ive been searching everywhere for over 2 hours now. im not exactly a noob at js but i am still sort of new,i would say learning, ameteur?? anywho....
what i am trying to do:
so i have a number input box <input type="number" maxlength="4" .../> where a user will enter a 4 digit number (needs to be 4 digits) from 100 to 8000. so obviously 100 to 999 would be 0100 - 0999.
no problem so far, i can just use a string to pass the variable through as 4 digits.
the problem i have is that i need to add certain conditions to validate the input. one condition is bugging me. this is what i have so far:
(var x is already set to the form and number input box)
if (x=="" || isNaN(x) || x.length!== 4 && x< 0100 || x>8000)
{alert(please enter the correct amount!}
else {run rest of function}
so they all work execpt for:x<0100
if the user enters 99 it flags up because it is not 4 digits and if they enter 0099 it accepts it and runs the rest of the function code.
i just need it to alert for any amount from 0001 to 0099.
i found another post, How to make 8 digit number in javascript? , sort of relevant but the guy just wants to output a number padded with zeros. i think one of the solutions (code below) may be of use to me but as i am rather tired, brain frazzled and new i cant solve it:
var i = (100).toPrecision(8).split('.').reverse().join('');
i would start by editing it to:
var i = (x).toPrecision(4).split('.').reverse().join('');
(but would this only work if they typed 99 not 0099...if ya see what i mean)
i think it would be like a reverse of the code (split 0099 to 99.00) , and then the statement would be: if(.... && i<==99 || ....) but idk how to write it in JS...
ok so do ya see how this is messing with me mind, being a semi/quarterly noob and all!!
sorry its not formatted correctly and so long, i havent grasped how to use the code functions...
and thanks for your patience in reading this (if you got this far hehe).
THANKS IN ADVANCE
Slappy-x
The number 0100 will be treated as octal value (which is 64 in decimal).
I think you would do fine by just comparing against strings:
x < "0100" || x > "8000"
Otherwise you have to convert the x into a number and compare it against 100:
+x < 100 || +x > 8000
(actually you don't have to explicitly convert x but it does not hurt either and makes it clearer which data types you are comparing)
Update: And you have to replace && with || as far as I can see.
To check if x is between 0001 and 0099, you can do this
if (x.match(/00([1-9][0-9]|0[1-9])/))
Try a combination of these methods.
You want to check that your number is actually a number first (i.e. doesn't contain letters, etc.). Do this by calling this method to confirm your number is a valid numeric value.
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
Once confirmed that you're dealing with a number, you can pad it (if necessary) like this:
function pad(num, size) {
var s = "000" + num;
return s.substr(s.length-size);
}
To work with padded numbers, you actually have to convert the value to a string.

Categories