Improving first coding project

9 vues (au cours des 30 derniers jours)
Christoph Weichenhain
Christoph Weichenhain le 28 Oct 2022
Commenté : Star Strider le 31 Oct 2022
I just started with MATLAB and completed the MATLAB Onramp course. Now I thought of a small project to practice for myself.
The given input should be a matrix with two columns. The first column shows the times when a device was unlocked. The second column shows the times when the device was locked again. We want to calculate the total screentime of the day.
We define the matrix as given data and also call it like that. The entries have the format string.
If the screen is unlocked during midnight and then locked at the next day, it will stil save the locked time. This is the case in the last row.
The program does not cover the case when the device is unlocked for more than 24 hours.
I know that it says as a "Don't" "Include code for an entire project" but because of the fact that my project contains 18 lines of code I hope that it is okay. The code is the following:
data = ["07:54" "08:01"; "10:22" "11:49"; "16:34" "19:11"; "23:50" "03:40"];
% This is the given data as a matrix.
total_minutes = 0;
% Defining a number for the total screentime in minutes. I will use that later.
for x = 1:size(data,1)
% Defining a for loop. Iterating through every row of the matrix.
turned_on = data(x,1)
% Time when device was turned on. String.
turned_on_hour = str2double(extract(turned_on,1) + extract(turned_on,2));
% Time - just the hours - when device was turned on. Double.
turned_on_minute = str2double(extract(turned_on,4) + extract(turned_on,5));
% Time - juste the minutes - when device was turned on. Double.
turned_off = data(x,2)
% Time when device was turned off. String.
turned_off_hour = str2double(extract(turned_off,1) + extract(turned_off,2));
% Time - just the hours - when device was turned off. Double.
turned_off_minute = str2double(extract(turned_off,4) + extract(turned_off,5));
% Time - juste the minutes - when device was turned off. Double.
% Checking if the device was turned on during midnight.
if turned_off_hour < turned_on_hour || (turned_off_hour == turned_on_hour && turned_off_minute < turned_on_minute)
turned_off_hour = turned_off_hour + 24;
% Correcting turned_off_hour so that the calculatiosn are made correctly.
end
screenminutes = turned_off_hour*60+turned_off_minute-turned_on_hour*60-turned_on_minute
% Calculating the scree minutes of the current row.
% Transforming everything into plain minutes and then subtracting from each other.
total_minutes = total_minutes + screenminutes
% Adding the screen minutes that were calculated in this row to the total screen minutes.
end
disp("The screen time is " + floor(total_minutes/60) + " hour(s) and " + ...
(total_minutes/60 - floor(total_minutes/60))*60 + " minute(s).")
% Output of the result.
I would look forward to some ideas on how to improve this code. For example in the aspects of using better functions or calculations.
Of course I know this is a lot of work, I am not expecting anything. But some may have fun correcting it.
If it is indeed a problem I won't hesitate to delete the post.
  1 commentaire
Christoph Weichenhain
Christoph Weichenhain le 28 Oct 2022
Modifié(e) : Christoph Weichenhain le 28 Oct 2022
The time is displayed as usual in Europe. So no am and pm input.

Connectez-vous pour commenter.

Réponses (2)

John D'Errico
John D'Errico le 28 Oct 2022
Modifié(e) : John D'Errico le 28 Oct 2022
+1. This is what I would call a good post. You are looking to learn MATLAB, so you chose a problem (one that interests you) that seems within your grasp, but one that would push you a little.
A quick glance at your code sees variable names that mean something in context, making your code readable. Lots of comments. All great ideas. My goal for comments is often one line of comment for every line of code.
It looks like you missed a semi-colon or two at the end of the lines. Good as long as you are debugging the code, but not so eventually, as it can totally junk up the command window.
How would I improve it? Honestly, code that works, does what it is designed to do, and lacks bugs is already correct code, loops or not. Only when those loops become a problem due to too much time do you look for something more efficient, and even then remember that loops are often reasonably efficient in MATLAB these days. (More so than many years past.)
The obvious question is if it does work correctly. Then, if you could do the entire task without a loop.
data = ["07:54" "08:01"; "10:22" "11:49"; "16:34" "19:11"; "23:50" "03:40"];
turned_on = data(1,1)
turned_on = "07:54"
turned_on_hour = str2double(extract(turned_on,1) + extract(turned_on,2))
turned_on_hour = 7
% Time - just the hours - when device was turned on. Double.
turned_on_minute = str2double(extract(turned_on,4) + extract(turned_on,5))
turned_on_minute = 54
Ok, so you are pulling out the minutes and hours as two characters, then recombining them. 7:54 did work nicely. But, could you have done the same without a loop? For example:
T = data(:,1)
T = 4×1 string array
"07:54" "10:22" "16:34" "23:50"
extract(T,1) + extract(T,2)
ans = 4×1 string array
"07" "10" "16" "23"
So that works well enough.
str2double(extract(T,1) + extract(T,2))
ans = 4×1
7 10 16 23
So you could have done the same thing for each of those times in one operation. No need for a loop there. There are surely many things you might have done differently. For example, you can see Star took a dlightly different approach, converting the times into MATLAB's own time scheme, then working with tools like diff and sum, to compute the target results. All good ideas.
The point is to start to think in terms of vectors and arrays of times, rather than dropping down to scalars for everything. This is how your code will begin to improve.
  3 commentaires
John D'Errico
John D'Errico le 30 Oct 2022
Modifié(e) : John D'Errico le 30 Oct 2022
I have to smile (not at you), because this is a characteristic we see many times in a forum. Anyone who comes to MATLAB with a background in another programming language wants to then use programming constructs and styles that are specific to their background. So C programmers want to do one thing, Fortran prgrammers another. Even Excel coders want to code as if they are using a spreadsheet. Somehow, you need to forget what you knew from your past, and that is not always easy. :) I know that, because long ago, the language I used most heavily before MATLAB was APL, yet another language that has both strong similarities with MATLAB, but also vast differences.
A good thing is Python actually has a lot in common with MATLAB too, so only a few things will be tripping you up.
What did you do? Originally, you had a loop, So you were effectively operating on scalar elements. Each pass through the loop operated on just one time. And there an if statement is correct. But when you have a vector of times, an if statement no longer works. For example, you cannot write this:
x = 1:5;
if x > 3, x = 3; end
But you can do things like this in MATLAB:
x(x > 3) = 3;
The latter form acts only on the elements of x that are greater than 3, then replacing them by 3. In your problem, we might do something similar. For example:
wrongtimes = time_off_hour < time_on_hour | ...
(time_off_hour == time_on_hour & time_off_minute < time_on_minute);
time_off_hour(wrongtimes) = time_off_hour(wrongtimes) + 24;
Look carefully at what I wrote. The first line creates a boolean vector. Note that I used | and &, not their cousins || and &&. The latter apply essentially only to tests in an if or while statement. But when we have vectors or arrays of times, and-ing and or-ing the results, we use | and &.
So wrongtimes contains a boolean vector, indicating where there is a time problem. Then you can use a boolean vector as a vector index itself. Lets go back to the simple example I showed above.
x = 1:5
x = 1×5
1 2 3 4 5
wrongx = x > 3
wrongx = 1×5 logical array
0 0 0 1 1
So wrongx is now true, whereever x satisfied the test. And we can use wrongx, as an index into x.
x(wrongx) = 3
x = 1×5
1 2 3 3 3
It works exactly as if I had done this: (this time, I will replace those elements with 7, so you can see it worked)
x(find(wrongx)) = 7
x = 1×5
1 2 3 7 7
Christoph Weichenhain
Christoph Weichenhain le 31 Oct 2022
Thank you very much for the detailed answer. To be fair, in the end I found a solution that does not need this kind of checking. It was presented in the solution of Star Stried, who deleted his/her answer in the meanwhile.
time_on = time_on_hour*60 + time_on_minute;
time_off = time_off_hour*60 + time_off_minute;
time_difference = time_off - time_on;
time_difference(time_difference < 0) = time_difference(time_difference < 0) + 60*24;
screentime = sum(time_difference);
So here we calculate first the difference and then we check if it is negative. If so, we add 60*24 minutes.
Star Strider also presented a whole different solution. It looks like this:
DTdata = datetime(data, 'InputFormat','HH:mm');
DTdiff = diff(DTdata, [], 2);
DTdiff(DTdiff<0) = DTdiff(DTdiff<0) + hours(24);
screentime = sum(DTdiff)
It is very slim.
I still implemented the vector(condition) = vector(condition) + 24 solution and made a comment out of it.
I put all the three solutions (for loop, nor for loop, time functions) in the attachments.
Thank you very much for helping.

Connectez-vous pour commenter.


Star Strider
Star Strider le 31 Oct 2022
I deleted my answer because the other one was upvoted, meaning that in all likelihood, since the other is so long, even though I posted imine first, it would not even be seen.
It was simply:
data = ["07:54" "08:01"; "10:22" "11:49"; "16:34" "19:11"; "23:50" "03:40"];
ddata = datetime(data, 'InputFormat','HH:mm', 'Format','HH:mm')
ddata = 4×2 datetime array
07:54 08:01 10:22 11:49 16:34 19:11 23:50 03:40
difdata = diff(ddata,[],2)
difdata = 4×1 duration array
00:07:00 01:27:00 02:37:00 -20:10:00
difdata(difdata<0) = difdata(difdata<0)+hours(24)
difdata = 4×1 duration array
00:07:00 01:27:00 02:37:00 03:50:00
.
  2 commentaires
Christoph Weichenhain
Christoph Weichenhain le 31 Oct 2022
Unfortunately, I cannot accept two different answers as a solution. So, I would proceed to mark no answer as a solution, but both works equally.
Star Strider
Star Strider le 31 Oct 2022
O.K.

Connectez-vous pour commenter.

Catégories

En savoir plus sur Startup and Shutdown dans Help Center et File Exchange

Produits


Version

R2022b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by