//I need to add one to the total each time the error name is input. For example if I type "S" in the prompt, then it will add 1 to the total steering and if I type "W", it will add to wiper. The loop should run until i entered a null or zero value and calculate the total errors.
<html>
<head><title>Charge Calculator</title></head>
<body>
<script type="text/javascript">
//Declaring Variables
var day;
var data="";
var steering = 0;
var turbo =0;
var wiper =0;
day = prompt("Enter day: ","");
var BR="<br/>";
do
{
data = prompt("Enter Data: ","");
data = input.nextLine();
switch(data)
{
case 'S':
steering++;
break;
case 'T':
turbo++;
break;
case 'W':
wiper++;
break;
}
}
while(data == "")
document.write("day: " +day +BR); //Display destination name
document.write("Steering issue: " +steering +BR);
document.write("turbo Issue: " +turbo +BR);
document.write("wiper Issue: " +wiper +BR);
</script>
</body>
</html>
There are many things to be improved in your code. Be aware that the write() expression will potentially destroy parts of your html-based page. Find out about DOM manipulation commands instead.
The following snippet demonstrates in a very short way how you could collect your inputs. I used your prompt() method simply to show that it can be done but I would always prefer a simple input field instead.
const counts={s:0,t:0,w:0};
while (++counts[prompt("Please enter the error type code (s,t or w):").toLowerCase()]) {}
console.log("steering: "+counts.s+
"\nturbo: "+counts.t+
"\nwipers: "+counts.w);
Everything happens within the expression that calculates the result for the while condition: the input value is converted to lower case and then a property of the object counts will be incremented. This will only work (= return a "truthy" result) for already initialised properties like s, t or w. For all other cases an increment cannot be calculated, resulting in an "NaN" ("not a number") result. This will then end the while loop.
Seems like recursion could be more appropriate solution here. Though #Cartsten's one looks absolutely ok also.
function count() {
const counts = {
s: 0,
t: 0,
w: 0
};
const checkCounts = () => {
let input = prompt(
'Please enter the error type code (s,t or w):'
).toLowerCase();
if (counts[input] !== undefined) {
++counts[input];
return checkCounts();
}
};
checkCounts();
console.log(
`steering: ${counts.s} \n turbo: ${counts.t} \n wipers: ${counts.w}`
);
}
count();
Related
Is anybody here who solves problems on HackerEarth? I am confused with the way they supply the input data.
I have been using Leetcode to date to solve problems and I am pretty happy with them but unfortunately, some people prefer HackerEarth to host coding challenges and I have issues trying to read the input test case properly.
Take this for example https://www.hackerearth.com/practice/algorithms/searching/ternary-search/practice-problems/algorithm/small-factorials/submissions/
I did my research and found their "solution guide" which has the wrong info: https://www.hackerearth.com/docs/wiki/developers/solution-guide/
How would I read the individual lines and output the results in JS (Node v10) judge?
Thank you.
Just logged into and looked it up here.
Seems to be similar to HackerRank which I'm not fond of. (LeetCode's UI is fun and much easier to use.)
On LeetCode, we don't have to print things out, here it seems we have to print the output (for instance in JavaScript we would use console.log not to mention printing inside methods is generally a bad practice coding).
This solution (copied from one of those activities) seems to be passing based on which you can figure things out:
/*
// Sample code to perform I/O:
process.stdin.resume();
process.stdin.setEncoding("utf-8");
var stdin_input = "";
process.stdin.on("data", function (input) {
stdin_input += input; // Reading input from STDIN
});
process.stdin.on("end", function () {
main(stdin_input);
});
function main(input) {
process.stdout.write("Hi, " + input + ".\n"); // Writing output to STDOUT
}
// Warning: Printing unwanted or ill-formatted data to output will cause the test cases to fail
*/
// Write your code here
process.stdin.resume();
process.stdin.setEncoding("utf-8");
var stdin_input = "";
process.stdin.on("data", function (input) {
stdin_input += input;
});
process.stdin.on("end", function () {
main(stdin_input);
});
function main(input) {
input = input.split('\n');
input.shift();
input.forEach(n => {
n = parseInt(n);
let fact = BigInt(1);
while(n){
fact = BigInt(fact) * BigInt(n);
n--;
}
console.log(String(fact).replace('n',''));
});
}
in accessing inputs HackerEarth bit different compare to leetcode and Hacker Rank here you will have to extract inputs from standard input (STDIN) by line number you can find more details here
for example, if the format of the input given as below
Input format:
First line contains integer N.
Second line contains string S.
then you will split the STDIN by new line("\n") and access each input line-wise
below is a sample of how would you access inputs in JavaScript
var input1 = 0;
var input2 = "";
var stdin_input = ""
process.stdin.on("data", function (input) {
// Reading input from STDIN
stdin_input += input;
input1 = stdin_input.split("\n")[0]
input2 = stdin_input.split("\n")[1]
console.log("input1 = ", input1)
console.log("input2 = ", input2)
});
1- First step --> Find the first occurrence of a number using Regex \d+ (No need to add the global flag as the problem stated that the first line always contains a number, thus we are looking for the first number). The + flag is to always match more than one occurrence of a digit like 2,12,21,234, and so on.
2-Second Step --> Cast the matched string to a number to multiply it by two (double it), then cast it back to a string and make the replacement using the regex replace methods.
More about the method can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
process.stdin.resume();
process.stdin.setEncoding("utf-8");
var stdin_input = "";
process.stdin.on("data", function (input) {
stdin_input += input;
});
process.stdin.on("end", function () {
main(stdin_input);
});
function main(input) {
const regex = /(\d+)/g;
let expr = input.replace(regex,(match) => {
return String(Number(match) * 2);
});
process.stdout.write(expr);
}
I am trying to take in the value of an input:text field, then check to see if that string has only valid characters. Valid characters being "G, C, T, A". I am trying to write validation for the string so that if it has invalid letters, it kicks it back to the user and asks for only valid letters.
How would I check against only certain characters in a string?
let rnaTransResult;
let validLetters = ["G", "C", "T", "A"];
runBtn.addEventListener('click', function(){
let dna = userInput.value.toUpperCase();
rnaTranscribe(dna);
result.textContent = rnaTransResult;
});
function rnaTranscribe(dna){
let dnaArray = dna.split('');
for(let x = 0; x < dnaArray.length; x++){
if(dnaArray[x] != validLetters[x]){
console.log("invalid letters");
return false;
} else {
for(let i = 0; i < dnaArray.length; i++){
if(dnaArray[i] === "G"){
// console.log("G swap for C");
dnaArray[i] = "C";
}
}
console.log("end result: " + dnaArray);
rnaTransResult = dnaArray.join('');
console.log("Transcription complete - Result: " + rnaTransResult);
}
};
}
I have tried a few different methods without anything working. I am at a loss at the moment and would love to understand the concept thinking behind approaching this. Thank you in advance!
You could also achieve this using regex.
[^GCTA]
Will match anything that isn't in your allowed characters,so you can do:
if(dnaArray.match(/[^GCTA]/)){//if dnaArray contains anything that isn't G,T,C,A
...
}
You can use the some function:
...
let letter = dnaArray[x];
if (validLetters.some(l => l === letter))
...
As a very naive solution: Loop through the length of the string and compare it to see if the array includes the value at the current index. There are better ways of doing this but this should clearly show what is going on and the logic behind it
let validLetters = ["G", "C", "T", "A"];
let dnaArray = "GCTATAB"
for(let x = 0; x < dnaArray.length; x++){
if(!validLetters.includes(dnaArray[x])){
console.log("invalid letter: " + dnaArray[x]);
}
}
Instead of console logging in your loop- you can set a boolean variable (initially to true- set it to false if there is an invalid letter in the loop then break). If the boolean is false- you know the string contains a letter that is not valid.
Not sure why the code below is not working. It should take in a string and convert a G to a C and an A to a T and vice versa. However, it collects the input string but doesn't provide any output i.e. the alert just says "here is your reverse complement DNA"
var dnaSequence = prompt("Enter your DNA sequence here", "");
var newSequence = reverseComplement(dnaSequence);
alert("here is your reverse complemented DNA: " + newSequence);
function reverseComplement(dnaString) {
var reverseC = [];
var dnaArr = dnaString.split('');
for (var i = 0; i < dnaArr.length; i++) {
switch (dnaArr[i]) {
case 'A':
reverseC.push('T');
break;
case 'T':
reverseC.push('A');
break;
case 'C':
reverseC.push('G');
break;
case 'G':
reverseC.push('C');
break;
}
}
// Reverse and rejoin the the string
return reverseC.reverse().join('');
}
It should take in a string and convert a G to a C and an A to a T and vice versa.
Then you don't need the reverse(), because you are pushing in order.
Also, Make sure that you are entering uppercase letters into the prompt.
Else, you can force the uppercase.
This is the code with the two fixes:
function reverseComplement(dnaString) {
var reverseC = [];
var dnaArr = dnaString.toUpperCase().split('');
for (var i = 0; i < dnaArr.length; i++) {
switch (dnaArr[i]) {
case 'A':
reverseC.push('T');
break;
case 'T':
reverseC.push('A');
break;
case 'C':
reverseC.push('G');
break;
case 'G':
reverseC.push('C');
break;
}
}
// Reverse and rejoin the the string
return reverseC.join('');
}
var dnaSequence = prompt("Enter your DNA sequence here", "");
var newSequence = reverseComplement(dnaSequence);
alert("here is your reverse complemented DNA: " + newSequence);
The main lesson you need here is how to test and debug your JavaScript code.
First, get familiar with the JavaScript debugger in your browser. Instead of wondering why your code doesn't work, you can see directly what it is doing. Every modern browser has built-in JavaScript debugging tools; for example here is an introduction to the Chrome DevTools.
Second, when you are testing a function like this, don't use prompt() or alert(). Instead, provide a hard coded input string and use console.log() to display the output in the JavaScript debug console. This way you can run the same test case repeatedly. After you get one test case to work, you can add others.
There are several JavaScript testing frameworks if you want to get fancy, but to start with, simply using a hard coded input and console.log() output plus inspection in the JavaScript debugger is fine.
To make it easy to debug a function when you first write it, add a debugger; statement at the beginning. Then it will stop in the debugger and you can single-step through the code to see which parts of your function actually get executed and what all your variable values are at each step of the way.
For example (since it sounds like you were mistakenly testing with lowercase input), you might do this:
var dnaSequence = 'actg';
var newSequence = reverseComplement(dnaSequence);
console.log(newSequence);
function reverseComplement(dnaString) {
debugger;
var reverseC = [];
var dnaArr = dnaString.split('');
for (var i = 0; i < dnaArr.length; i++) {
switch (dnaArr[i]) {
case 'A':
reverseC.push('T');
break;
case 'T':
reverseC.push('A');
break;
case 'C':
reverseC.push('G');
break;
case 'G':
reverseC.push('C');
break;
}
}
// Reverse and rejoin the the string
return reverseC.reverse().join('');
}
Now, if you have the DevTools open, it will stop in the debugger at the first line of your function. You can single-step through the function to see which of the case statements it actually goes to, and you will see that it doesn't go to any of them. You can also look at the value of dnaArr[i] and see whether it matches any of the case values.
I'm building a JS news ticker that renders strings on a canvas in pixel letters. When the visual length of the rendered string (measured in pixels and represented in the function below by global variable 'calc_w') exceeds the width (represented by global variable 'w' in function below) of the canvas, I need to put the second half of the rendered string on the next line. I determine where to break the string up based on the number of spaces in the string (represented below by the variable 'spaces').
However I cannot figure out why my little function here is returning undefined in the console instead of a number for the spc_indx[i] variable.
function ins_breaks(str) {
var spaces = 0;
var spc_indx = [];
if (calc_w > w) {
for (var i = 0; i < str.length; i++) {
if (str.charAt(i) == " ") {
spaces++;
spc_indx[i] = spaces; //Tells the switch where to cut the string.
}
}
switch (spaces) {
case 4:
//4 spaces = 5 words.
var line2 = str.substr(spc_indx[2]);
//str.replace(' ', '');
console.log(spc_indx[2])
break;
case 5:
console.log(spc_indx[2])
break;
}
}
}
Logging 'spaces' yielded numbers as expected, yet when I assign spaces to a part of the spc_indx array, it comes back undefined. Why is spc_indx array undefined and not a number like I'm expecting to get back?
Here is the fiddle: https://jsfiddle.net/9u3ez6gu/22/
spc_indx[i] = spaces;
should be
spc_indx[spaces] = i;
I currently receive emails from a specific source with multiple attachments specifically csv attachments. What I need is to retrieve the data from the csv attachment. I've looked into creating a Google App Script which I hear can get the job done based on my research but perhaps there is a better way if so please advice.
I wrote a pseudo code of what I would like the script to do:
Determine who sent the email. If its the source that I need then follow to step 2.
Look at the subject of the email if its the subject that I need then proceed to step 3.
If step 1 and 2 are good then the next step is to retrieve the data from one of the csv attachments(based on the name) this is because there could be more than one attachment in the email.
Open the attachment copy the data and paste it in either a google spreadsheet or excel spreadsheet which is created dynamically OR save the attachment to my google drive in a specific folder but either one could work. The trick here is to loop through all the emails in my inbox in past month and achieve the above task.
Thanks everyone for your help and I hope I was clear in my specifications.
Links I found to be helpful to me but not quite exactly what I need.
Create time-based Gmail filters with Google Apps Script
Trigger Google Apps Script by email
After researching and working along with the google apps script documentation I was able achieve my goal for my task at hand. Please see my code below with comments and hopefully this can help.
Thanks,
function RetrieveAttachment() {
// variables being used i, j, k, n, m, a, d, x
var threads = GmailApp.search('*SubjectName*') //search gmail with the given query(partial name using * as a wildcard to find anything in the current subject name).
var msgs = GmailApp.getMessagesForThreads(threads); //retrieve all messages in the specified threads.
//var sheet = SpreadsheetApp.create('test_filename', 2, 8); //creates a new spreadsheet in case I need to create it on a separate file.
//you can get the id from your own google spreadsheet in your browser bar.
var sheet = SpreadsheetApp.openById('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx').getSheetByName('your sheet name');
sheet.clearContents(); //clears all the data in the specified tab, the code below will recreate the dataset once again.
for (var i = 0; i < msgs.length; i++) {
for (var j = 0; j < msgs[i].length; j++) {
var emailDate = msgs[i][j].getDate();
var attachments = msgs[i][j].getAttachments();
for (var k = 0; k < attachments.length; k++) {
/*search for the attachment by name, stringLen returns the start position number of the word 'filename' ignoring any previous characters, counting starts at 0.
e.g. "test_filename", will output the number 6 "test_" will ends at 5 and 6 will start at "f" for filename. Than we use substring to get the actual name out of
attachment name then we use the stringLen variable as a starting position and also as an end position plus the number of characters in word I'm searching for
to get the attachment name, 8 is used because this is how many letters are in the string. Finally we create the stringValue variable and compare to see which
attachments meet the criteria that we are looking for and return only that attachment.*/
var attachmentName = attachments[k].getName();
var stringLen = attachmentName.search('filename');
var stringValue = attachmentName.substring(stringLen,stringLen + 8);
if (stringValue == 'filename') {
var attachmentData = attachments[k].getDataAsString();
var attachmentClean = attachmentData.split('"').join(',');
var attachmentCleanA = attachmentClean.split(',');
/*input headings into the spreadsheet. This is depending on how many columns or fields the attachment file has. The numbers after the "attachmentCleanA" is the
position number of the field you want is located i.e [1][4][7][10]. The reason it skips the numbers is because the getDataAsString() method returned an array with
multiple separations that had to be parsed by quotations. So [2][3] had an empty string value.*/
sheet.getRange('A1').setValue(attachmentCleanA[1]); //Field One
sheet.getRange('B1').setValue(attachmentCleanA[4]); //Field Two
sheet.getRange('C1').setValue(attachmentCleanA[7]); //Field Three
sheet.getRange('D1').setValue(attachmentCleanA[10]); //Field Four
//Extra fields if you want to add.
sheet.getRange('E1').setValue('Email Date'); //Email Date
sheet.getRange('F1').setValue('Email Month'); //Email Month
sheet.getRange('G1').setValue('Email Year'); //Email Year
sheet.getRange('H1').setValue('Source Name'); //Attachment Name
var n = LastRow(sheet); //calls the LastRow function to get the next empty cell.
var m = attachmentCleanA.length + n;
/*attachmentCleanA.length alone is not useful as a limit in the loop because the n variable ends up being bigger than the actual attachmentCleanA.length.
To fix this I added the "attachmentCleanA" + "n" variable so that the n variable will always be less than the attachmentCleanA.length expression.*/
var range = sheet.getRange('A1:H30000'); //this has to match the number of columns in the above sheet.getRange().setValue methods.
var d = 11;
/*now we loop through each string in the array and place it in each individual row and column. The first string position you want may vary depending
on the file you have. The file I have has the first item and is positioned in the 12th position of the array. The reason variable d shows 11 is because
it will be added before the actual extraction of the value "d++" */
RowLoop:
for (var x = n; x < m; x++) {
for (var a = 1; a < 5; a++) {
var cell = range.getCell(x, a);
d++;
//the reason of the if function is so that when I run into an empty string in the array I can simply ignore it and continue to the next string.
if (attachmentCleanA[d] !== "" && attachmentCleanA[d] !== undefined) {
cell.setValue(attachmentCleanA[d]);
}
else if (attachmentCleanA[d] == "") {
/*the a-- is used so that when I find and empty string in the array I don't want to skip to the next column but continue to stay there until I find
a none empty string.*/
a--;
}
}
/*email date - the reason of the if function is because in my situation it was producing more values at the end of the loop. So I made it stop if in
column A doesn't have a value*/
var setDate = range.getCell(x, 5);
if (range.getCell(x, 1).getValue() !== "") {
setDate.setValue(emailDate);
}
else if (range.getCell(x, 1).getValue() == "") {
break RowLoop;
}
//source name
var attachmentLen = attachmentName.search('filename');
var attachmentValue = attachmentName.substring(0, attachmentLen-1);
var setAttachmentName = range.getCell(x, 8);
setAttachmentName.setValue(attachmentValue);
//email year
var setYear = range.getCell(x, 7);
setYear.setValue(emailDate.getFullYear());
//email month
var setMonth = range.getCell(x, 6);
var monthName = MonthFunc(emailDate.getMonth());
setMonth.setValue(monthName);
}
}
}
}
}
}
function LastRow(sheetName) {
//retrieve the last row position after each attachment data file has been put into the spreadsheet
var column = sheetName.getRange('A:A');
var values = column.getValues(); // get all data in one call
var ct = 0;
while ( values[ct][0] !== "" ) {
ct++;
}
return (ct)+1; // add 1 to get the row which is empty
}
function MonthFunc(inputMonth) {
//this function returns the short name of the month.
var monthNumber = inputMonth
switch (monthNumber) {
case 0:
return "Jan";
break;
case 1:
return "Feb";
break;
case 2:
return "Mar";
break;
case 3:
return "Apr";
break;
case 4:
return "May";
break;
case 5:
return "Jun";
break;
case 6:
return "Jul";
break;
case 7:
return "Aug";
break;
case 8:
return "Sep";
break;
case 9:
return "Oct";
break;
case 10:
return "Nov";
break;
case 11:
return "Dec";
break;
}
}