TimeConvert JavaScript function on Coderbyte - javascript

I am doing a challenge on Coderbyte and I would be grateful for any advice on my question:
I know there is an easier way to solve this(which I found later):
function TimeConvert(num) {
var hours = Math.floor(num / 60);
var minutes = num % 60;
return hours + ":" + minutes;
}
...so TimeConvert(123); would be 2:3
I know my answer is more complicated but why is the way I attempted to answer this question not working? What am I missing? It just returns 0:00 for any number entered:
function TimeConvert(num) {
var hours=0;
var minutes=0;
for(var i=0; i<=num; i+=60) {//loop through number every 60
if(num[i]>=60) { //for every 60 add 1 hour
hours+=1;
}else if(num[i]<60){
minutes=num[i];
}
}
var newMinute=0;
if (minutes<10){
newMinutes="0"+minutes;
}else if(minutes>10){
newMinutes=minutes;
}
return(hours + ":" + newMinutes);
}
Thanks guys!^^

Why you doin num[i]>=60? All you need to check is num>=60 and num<60. num[i] will always be an undefined value and num is not a string. (If it would have been a string it num[i] will print the character corresponding to that index.) So you need to compare num and not num[i].
function TimeConvert(num) {
var hours=0;
var minutes=0;
var times = num;
for(var i=0; i<times; i+=60) {//loop through number every 60
if(num>=60) { //for every 60 add 1 hour
hours+=1;
num -= 60;
}else if(num<60){
minutes=num;
}
}
var newMinute=0;
if (minutes<10){
newMinutes="0"+minutes;
}else if(minutes>10){
newMinutes=minutes;
}
return(hours + ":" + newMinutes);
}
console.log(TimeConvert(123));
Updated Fiddle

Thank you! I actually figured out two ways to solve this. First, I should iterate by 1, not 60, and in the first if statement I need to subtract by 60 for every iteration as so:
function TimeConvert(num) {
var hours=0;
var minutes=0;
for(var i=0; i<=num; i++) {
if(num>=60) { //for every 60 add 1 hour
hours+=1;
num-=60;//makes sure that the loop goes every 60
}else if(num<60){
minutes=num;
}
}
//below not necessary for Coderbyte, added for styling reasons. Same for second answer
var newMinute=0;
if (minutes<10){
newMinutes="0"+minutes;
}else if(minutes>10){
newMinutes=minutes;
}
//write minutes not newMinutes(for Coderbyte). Same for second answer.
return(hours + ":" + newMinutes);
}
And I figured how to do this with a while loop:
function TimeConvert(num) {
var hours=0;
var minutes=0;
var newMinutes=0;
while(num>=60) {
hours+=1;
num-=60;
}
if(num<60){
minutes=num;
}
if (minutes<10){
newMinutes="0"+minutes;
}else if(minutes>10){
newMinutes=minutes;
}
return(hours + ":" + newMinutes);
}

You can also include ES6 Template Literals in addition to Math.floor() for a one-line return statement.
function TimeConvert(num) {
return `${Math.floor(num/60)}:${num%60}`;
}

Related

snail in the well javascript challenge

This is my first question on stack overflow although this question had been answered before I didn't get enough details to understand why the code was written that way and I didn't just want to copy and paste the solution without understanding it.
The snail climbs 7 feet each day and slips back 2 feet each night, How many days will it take the snail to get out of a well with the given depth?
Sample Input
31
Sample Output
6
this is was what i wrote but it didn't work
function main() {
var depth = parseInt(readLine(), 10);
//your code goes here
let climb = 0, days = 0;
for(climb + 7; climb < depth; days++){
climb += 2;
console.log(days);
try this:
var depth = parseInt(readline(), 10);
var day = 0;
for(let climb = 0; climb <= depth;) {
day +=1;
climb += 7;
if(climb >= depth) {
break;
}
climb -= 2;
}
console.log(day);
Just take input and write this
var day= Math.ceil((depth-2)/5);
and output that!
/* day --> 7++
night --> 2-- */
var day = 0;
var total = 0;
var input = 41;
while (input>total){
day++;
total+=7;
if (total>=input){
console.log(day);
break;
}
total = total -2
}
As mentioned in the comments, no need to loop. Just work out the math of the problem an use that.
function snailCalc (depth, dailyGain, nightlyLoss) {
var days = 1;
var netGain = dailyGain-nightlyLoss;
if(depth > dailyGain ) {
//Basic calc based on net gain taking the first day into account
days = (depth-dailyGain)/netGain;
//Add the fist day
days += 1;
//We want whole days so use Mathc.ceil
days = Math.ceil(days)
//Or we could do all that in one line
//days = Math.ceil(((depth-dailyGain)/netGain) + 1);
}
return days;
}
const gain = 7;
const loss = 2
for(var d = 1; d < 31; d++)
{
console.log(`Depth: ${d}, Days: ${snailCalc(d, gain, loss)}` )
}
Bob
function main() {
var depth = parseInt(readLine(), 10);
console.log(Math.round(depth / 5))
}
function main() {
var depth = parseInt(readLine(), 10);
//your code goes here
var days=1;
var level =0;
for(level =0;level<depth;days++){
level+=7
if(level<depth){
level-=2;
} else{
break ;
}
}console.log(days)
}
Try this, I had the same trouble a couple days ago and we find the error is that using js you need to reset the variable where you sum the result before evaluate again if the distance the snail climbed that day is greater than the depth to end the clycle.
depth = 31;
let days = 0;
let climb = 0;
while(climb < depth){
let result = climb + 7;
if(result >= depth){
days++;
break;
}
climb = result - 2;
days++;
//console.log("climb ",climb);
}
console.log(days);
You can change the function input and test the snipet:
for more you can run code and check result ↗
Eg : main(128) // 26
function main(input) {
let depth = input
let climbsUp = 7
let slipsBack = 2
let distance = climbsUp - slipsBack
let days = 0;
let rDepth = Math.round(depth / distance)
for (let i = 0; i < rDepth; i++) {
distance = distance + 5
days = ++days
if (days === 6) {
console.log('days will it take the snail to get out of a well : ' + rDepth)
} else {
console.log('days will it take the snail to get out of a well : ' + rDepth)
break;
}
}
}
main(42);
main(128);

How to fix infinite while loop and create functions

I am trying to make a paycheck program, that utilizes functions and while loops.
In this program, I have to create two functions, one for validating the pay rate and hours, and then one for the calculations.
In addition, I have to have the first function pass the hours and pay rate to the calculation function, and then pass it back to the first function. When I try to run the program with the first function, it seems that if I enter a pay amount under 7.25, it enters an infinite loop.
Here is the code
<script>
function payValidate(x)
{
if(isNaN(payRate) || payRate < 7.25 || payRate > 20)
{
return false;
}
else
{
return true;
}
}
function hoursValidate(x)
{
if(isNaN(hours) || hours < 1 || hours > 60)
{
return false;
}
else
{
return true;
}
}
var grossPay;
var withHolding;
var netPay;
var message;
var payRate = parseInt(prompt("Enter pay rate"));
var payRateOK = payValidate(payRate);
while(!payRateOK)
{
payRate = parseInt(prompt("Invalid pay rate. Enter pay rate again"));
payRateOk = payValidate(payRate);
}
var hours = parseFloat(prompt("Enter hours worked"));
var hoursOK = hoursValidate(hours);
while(!hoursOK)
{
hours = parseFloat(prompt("Invalid hours. Enter hours again"));
hoursOK = hoursValidate(hours);
}
grossPay = payRate * hours;
if(grossPay <= 300)
{
withHolding = grossPay * 0.10;
}
else
{
withHolding = grossPay * 0.12;
}
netPay = grossPay - withHolding;
var message = "Pay Rate: $" + payRate.toFixed(2) +
"\nHours Worked: " + hours +
"\nGross Pay $" + grossPay.toFixed(2) +
"\nWithholding $" + withHolding.toFixed(2) +
"\nNet Pay $" + netPay.toFixed(2);
alert(message);
</script>
You're creating a new variable payRateOk (notice the lower case k) instead of writing to payRateOK, the variable you check in the while loop. So payRateOK will never change, and the loop will execute infinitely.
var payRateOK = payValidate(payRate); // In here you have used "payRateOK"
while(!payRateOK)
{
payRate = parseInt(prompt("Invalid pay rate. Enter pay rate again"));
payRateOk = payValidate(payRate); // In here you have used "payRateok"
}
payRateOK != payRateOk there for you have to use same name for that
other thing is payRate is a float variable. you should use var payRate = parseFloat instead of var payRate = parseInt.
you have used hours as int type there for var hours = parseFloat should be var hours = parseInt

HTML 5 Audio Player remaining time show delay

I have a problem with an audio player, when users press play the start-time timer is showing instantly, but remaining-time timer shows with a delay. I'm relatively new to JS, so I can not identify the problem on my own.
Can someone can help me with synching timers (start and remaining) show on play event?
CodePen
var isSeeking = false;
var seek = document.getElementById("seekObj");
var player = document.getElementById("player");
SetSeekColor();
function calculateTotalValue(length) {
var minutes = Math.floor(length / 60),
seconds_int = length - minutes * 60,
seconds_str = seconds_int.toString(),
seconds = seconds_str.split(".")[0],
temp_min = minutes.toString().length === 1 ? "0" + minutes : minutes,
temp_sec = seconds.toString().length === 1 ? "0" + seconds : seconds;
return temp_min + ":" + temp_sec;
}
function calculateCurrentValue(_seconds) {
function padTime(t) {
return t < 10 ? "0" + t : t;
}
if (typeof _seconds !== "number") return "";
if (_seconds < 0) {
_seconds = Math.abs(_seconds);
//console.log(_seconds);
}
var hours = Math.floor(_seconds / 3600),
minutes = Math.floor((_seconds % 3600) / 60),
seconds = Math.floor(_seconds % 60);
var hour = hours > 0 ? padTime(hours) + ":" : "";
return hour + padTime(minutes) + ":" + padTime(seconds);
}
function setupSeek() {
seek.max = player.duration;
}
function seekAudio() {
isSeeking = true;
player.currentTime = seek.value;
isSeeking = false;
}
var prevcurrentime = 0;
function initProgressBar() {
if (!isSeeking) {
seek.value = player.currentTime;
}
var length = player.duration;
var current_time = player.currentTime;
// calculate total length of value
var totalLength = calculateTotalValue(length);
// calculate current value time
var currentTime = calculateCurrentValue(current_time);
if (player.readyState === 4) {
jQuery(".end-time").html(totalLength);
jQuery(".start-time").html(currentTime);
}
//checking if the current time is bigger than the previous or else there will be sync different between remaining and current
if (currentTime > prevcurrentime) {
//calculate the remaining time
var rem_time = length - current_time;
jQuery(".rem-time").html(calculateCurrentValue(rem_time));
}
//setting the previouscurrent time to this current time
prevcurrentime = currentTime;
if (player.currentTime == player.duration) {
$("#play-btn").removeClass("pause");
}
}
function initPlayers(num) {
// pass num in if there are multiple audio players e.g 'player' + i
for (var i = 0; i < num; i++) {
(function() {
// Variables
// ----------------------------------------------------------
// audio embed object
var playerContainer = document.getElementById("player-container"),
player = document.getElementById("player"),
isPlaying = false,
playBtn = document.getElementById("play-btn");
// Controls Listeners
// ----------------------------------------------------------
if (playBtn != null) {
playBtn.addEventListener("click", function() {
togglePlay();
});
}
// Controls & Sounds Methods
// ----------------------------------------------------------
function togglePlay() {
if (player.paused === false) {
player.pause();
isPlaying = false;
$("#play-btn").removeClass("pause");
} else {
$(".start-time").html("");
player.play();
$("#play-btn").addClass("pause");
isPlaying = true;
}
}
})();
}
}
looking good, this is an error in the html. In this piece of code just replace the class rem-time by end-time.
<small style="float: right; position: relative; right: 21px;" class="end-time" onclick="showhideRemaining(this)"></small>
I think the root of your problem lies within the performance of your code. I can't see a big time difference between the two counters, but here are some suggested improvements:
You have the padTime function, so use it (see point 2)!
function padTime(t) {
return t < 10 ? "0" + t : t;
}
no unnecessary or early conversion to strings:
function calculateTotalValue(length) {
var minutes = Math.floor(length / 60);
var seconds = Math.floor(length - minutes * 60);
// use the padTime function here with numbers
return padTime(minutes) + ":" + padTime(seconds);
}
do not query the elements over and over again:
if (player.readyState === 4) {
jQuery(".end-time").html(totalLength);
jQuery(".start-time").html(currentTime);
}
Here, instead of querying the elements (jQuery(".end-time")) every time in your ontimeupdate callback, save the references in variables outside of the callback function.
limit color updates.
setInterval(function() {
SetSeekColor();
}, 34);
Updating the color every millisecond is just overkill. 34 milliseconds should equal something around 30fps.
I noticed you have are planning to have multiple players on one page (initPlayers(num)). Here a few thoughts:
When you initialise the players, save each single player with its UI elements in an Object
initPlayers(jQuery("#player-container").length);: IDs are (must be) unique in an entire HTML Document. This wont work, change it to a class.

Comparing current and next element of array and returning time difference

This is my array. Its length is about 9000. This is what a small bit of it looks like:
foreach_arr = ["21:07:01.535", "21:07:01.535", "21:07:26.113"]
There are a few occurences where the times diff is greater than a minute, and that is when I want to grab those times. And later use those times to get certain indices from another array. i.e "array"
I'm also using moment.js for time parsing.
Expected result: array = [8127, 9375, 13166, 14182]
Actual result: array = [8127, 13166]
Can't seem to find the issue here, I am getting 2 results when im supposed to be getting 4.
If the whole array is needed for troubleshooting, ill add it if I can.
var xx = foreach_arr.length - 1;
for(var z = 0; z < xx; z++) {
var current_row = foreach_arr[z];
var next_row = foreach_arr[z + 1];
var msElapsedTime = moment(next_row,"HH:mm:ss.SSS").diff(moment(current_row, "HH:mm:ss.SSS")) / 1000;
if(msElapsedTime > 60) {
attempt_indices.push(foreach_arr[z]);
}
}
for(var x = 0; x < attempt_indices.length; x++) {
array.push(newdata.indexOf(attempt_indices[x]));
}
Since the OP doesn't really need my code anymore, I'm posting it here to remove the downvote as much as anything else :)
const foreach_arr = ["21:07:01.535", "21:07:01.535", "21:07:26.113", '22:01:01.000'];
let processedForeach_arr = [];
let gtOneMinuteDiff = [];
foreach_arr.forEach((elem1, index1) => {
// elem1.split(':') turns foreach_arr[0] into ['21', '07', '01.535']
const splitElementArray = elem1.split(':');
let timeInMs = 0;
// this changes ['21', '07', '01.535'] into [75600000, 420000, 1535]
splitElementArray.forEach((elem2, index2) => {
if (index2 === 0) { // elem2 is hours. 3.6M ms per hour.
timeInMs += parseFloat(elem2) * 60 * 60 * 1000;
} else if (index2 === 1) { // elem2 is minutes. 60K ms per minute.
timeInMs += parseFloat(elem2) * 60 * 1000;
} else if (index2 === 2) { // elem2 is seconds. 1K ms per second.
timeInMs += parseFloat(elem2) * 1000;
} else {
throw `Expected array element formatted like HH:MM:SS.ms. Error on
element ${elem1}.`;
}
});
processedForeach_arr.push(timeInMs);
let timeDiff = processedForeach_arr[index1 - 1] - processedForeach_arr[index1];
if (Math.abs(timeDiff) > 60000) {
gtOneMinuteDiff.push(timeDiff);
}
});
To get the difference in milliseconds between foreach_arr[n] and foreach_arr[n+1], this code will
split each element of foreach_arr into 3 strings (hours, minutes, and seconds + milliseconds)
run parseFloat on each of those values to convert them to a number
convert all numbers to milliseconds and add them together
compare each consecutive value and return the difference.
Ok, I got this far and my son needs me. I'll finish out the code asap but you might beat me to it, hopefully the instructions above help.
turns out my code wasn't wrong. Just my idea of the whole proccess.
array = [8127, 13166]
is what I initialy get. With this, I use indexOf on my other array to eventually get my array as expected:
var another_test_arr = [];
for(var v = 0; v < array.length ; v++) {
var find = foreach_arr.indexOf(attempt_indices[v]);
another_test_arr.push(array[v], newdata.indexOf(foreach_arr[find + 1]));
}
Result: array = [8127, 9375, 13166, 14182]

Trying to get timer to start once arrived on the page

I made the following fiddle of what I have right now..
https://jsfiddle.net/r5yj99bs/1/
I'm trying to start right when I get onto a page, but allowing the option to leave the pause/resume option. Then is there anyway to display the remaining time as '5 minutes' instead of '300 seconds' and then count down that way rather than only seconds.
<button class="start-pause">Start</button>
<h2 class="time-left"></h2>
var times = [];
var counter_interval;
var $time_left = $('.time-left');
var $button = $('.start-pause');
// timer length in seconds
var timer_length = 300;
$('body').on('click', '.start-pause', function() {
// are we starting or stopping?
var starting = times.length % 2 == 0;
times.push(Date.now());
if (starting) {
$button.html('Pause');
counter_interval = setInterval(function() {
var time_left = Math.floor(timer_length - sum_elapsed());
if (time_left < 1) {
clearInterval(counter_interval);
return finished();
}
$time_left.html(time_left);
}, 100);
} else {
$button.html('Resume');
clearInterval(counter_interval);
}
});
var sum_elapsed = function() {
sum = 0;
for (var i=0; i<times.length; i++) {
if (i % 2 == 1) {
sum += (times[i] - times[i-1]);
}
if (i == (times.length - 1)) {
sum += (Date.now() - times[i]);
}
}
// convert milliseconds to seconds
return sum / 1000;
};
var finished = function() {
$button.attr('disabled','disabled').html('Finished');
$time_left.html("Time's Up");
};
There is a good time module called moment. You can get it through npm or from moments.com
That can format relative time to human readable strings.
If you want to do it yourself, take the seconds modulus 60 to get the minutes. Using modulus you can extract all info about hours and so on.
You may change the following line:
$time_left.html(time_left);
to:
$time_left.html(secToMinTxt(time_left));
and add the following functions:
function pad(num) {
var str = "" + num;
var pad = "00";
return pad.substring(0, pad.length - str.length) + str;
}
function secToMinTxt(seconds) {
var min = Math.floor(seconds / 60);
var sec = seconds % 60;
return pad(min) + ":" + pad(sec);
}
JSFiddle reference : https://jsfiddle.net/r5yj99bs/2/
If interpret Question correctly, try using Math.round with argument existing time_left variable divided by 60
var time_left = Math.round(Math.floor(timer_length - sum_elapsed()) / 60);
jsfiddle https://jsfiddle.net/r5yj99bs/3/

Categories

Resources