aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAbigail <abigail@abigail.be>2021-03-14 18:35:42 +0100
committerAbigail <abigail@abigail.be>2021-03-14 19:59:46 +0100
commit5f0e63208b7989972d90eb3c62eabae9577659a1 (patch)
treef300fa6dcb771de0320810ad7d12bf8a8d9e7358
parentcc9c06d6417c7a55db2a2740f852c9c056f2a77d (diff)
downloadperlweeklychallenge-club-5f0e63208b7989972d90eb3c62eabae9577659a1.tar.gz
perlweeklychallenge-club-5f0e63208b7989972d90eb3c62eabae9577659a1.tar.bz2
perlweeklychallenge-club-5f0e63208b7989972d90eb3c62eabae9577659a1.zip
C solution for week 103, part 2
-rw-r--r--challenge-103/abigail/README.md1
-rw-r--r--challenge-103/abigail/c/ch-2.c142
2 files changed, 143 insertions, 0 deletions
diff --git a/challenge-103/abigail/README.md b/challenge-103/abigail/README.md
index 4059ddea7e..9d90314025 100644
--- a/challenge-103/abigail/README.md
+++ b/challenge-103/abigail/README.md
@@ -124,6 +124,7 @@ Output:
### Solutions
* [GNU AWK](awk/ch-2.awk)
+* [C](c/ch-2.c)
* [Lua](lua/ch-2.lua)
* [Perl](perl/ch-2.pl)
* [Python](python/ch-2.py)
diff --git a/challenge-103/abigail/c/ch-2.c b/challenge-103/abigail/c/ch-2.c
new file mode 100644
index 0000000000..f776892e0c
--- /dev/null
+++ b/challenge-103/abigail/c/ch-2.c
@@ -0,0 +1,142 @@
+# include <stdlib.h>
+# include <stdio.h>
+# include <string.h>
+# include <unistd.h>
+
+/*
+ * See ../README.md
+ */
+
+/*
+ * Run as: cc -o ch-2.o ch-2.c; ./ch-2.o < input-file
+ */
+
+/*
+ * Return a malloced string of the given size, or die with
+ * an error message if it fails.
+ */
+char * malloc_char (size_t size) {
+ char * string = (char *) malloc (size * sizeof (char));
+ if (string == NULL) {
+ perror (NULL);
+ exit (1);
+ }
+ return (string);
+}
+
+int main (void) {
+ char * line = NULL;
+ size_t len = 0;
+ size_t str_len;
+ struct track {
+ long long run_time;
+ char * title;
+ };
+
+ while ((str_len = getline (&line, &len, stdin)) != -1) {
+ long long start_time;
+ long long current_time;
+ long long time_diff;
+ char * file_name = malloc_char (str_len);
+ size_t index;
+ /*
+ * Parse input
+ */
+ if (sscanf (line, "%lld %lld %s",
+ &start_time, &current_time, file_name) != 3) {
+ fprintf (stderr, "Failed to parse input\n");
+ exit (1);
+ }
+
+ /*
+ * Switch to milliseconds
+ */
+ time_diff = (current_time - start_time) * 1000;
+
+ /*
+ * Open the file, and count the number of lines. Then seek back.
+ */
+ FILE * media_file = fopen (file_name, "r");
+ char ch;
+ size_t number_of_tracks = 0;
+ while ((ch = fgetc (media_file)) != EOF) {
+ if (ch == '\n') {
+ number_of_tracks ++;
+ }
+ }
+
+ if (fseek (media_file, 0, SEEK_SET) == -1) {
+ perror ("Fseek failed");
+ exit (1);
+ }
+
+ /*
+ * Allocate memory for the track info.
+ */
+ struct track * tracks = (struct track *)
+ malloc (number_of_tracks * sizeof (struct track));
+
+ if (tracks == NULL) {
+ perror ("Mallocing tracks failed");
+ exit (1);
+ }
+
+ /*
+ * Read the file, line by line, and store it on tracks.
+ */
+ char * mline = NULL;
+ size_t mlen = 0;
+ size_t slen = 0;
+ size_t i = 0;
+ long long total_time = 0;
+ while ((slen = getline (&mline, &mlen, media_file)) != -1) {
+ long long run_time = atoll (mline);
+ char * title = malloc_char (slen);
+ strncpy (title, mline, slen);
+ while (* title != ',') {
+ title ++;
+ }
+ title ++;
+ struct track this_track = {run_time, title};
+ tracks [i ++] = this_track;
+
+ total_time += run_time;
+ }
+
+ /*
+ * Skip complete loops.
+ */
+ time_diff %= total_time;
+
+ /*
+ * Find the right track.
+ */
+ for (size_t i = 0; i < number_of_tracks; i ++) {
+ struct track this_track = tracks [i];
+ if (time_diff - this_track . run_time < 0) {
+ printf ("%s", this_track . title);
+ /*
+ * C uses integer division, which is quite handy here.
+ */
+ time_diff /= 1000;
+ int hours = time_diff / 3600;
+ int minutes = (time_diff % 3600) / 60;
+ int seconds = time_diff % 60;
+ if (hours > 0) {
+ printf ("%02d:%02d:%02d\n", hours, minutes, seconds);
+ }
+ else {
+ printf ( "%02d:%02d\n", minutes, seconds);
+ }
+ break;
+ }
+ else {
+ time_diff -= this_track . run_time;
+ }
+ }
+
+ }
+ free (line);
+
+ return (0);
+}