exercism / c

Exercism exercises in C.
https://exercism.org/tracks/c
MIT License
292 stars 182 forks source link

Implement the exercise "high-scores" #901

Closed keiravillekode closed 1 year ago

keiravillekode commented 1 year ago

I would like to contribute an implementation for the high-scores practice exercise.

As discussed on the forum, it is to be one of the proposed featured exercises for Jurassic July.

github-actions[bot] commented 1 year ago

Hello. Thanks for opening an issue on Exercism. We are currently in a phase of our journey where we have paused community contributions to allow us to take a breather and redesign our community model. You can learn more in this blog post. As such, all issues and PRs in this repository are being automatically closed.

That doesn't mean we're not interested in your ideas, or that if you're stuck on something we don't want to help. The best place to discuss things is with our community on the Exercism Community Forum. You can use this link to copy this into a new topic there.


Note: If this issue has been pre-approved, please link back to this issue on the forum thread and a maintainer or staff member will reopen it.

siebenschlaefer commented 1 year ago

I did play with this exercise a little bit and did not see a way for a straightforward translation.

In the original tests there's some "object" that gets initialized with a number of scores, and there are three four methods:

The "comments" at the beginning of the canonical-data.json say:

This is meant to be an easy exercise to practise:

  • arrays as simple lists
  • instantiating a class

I don't see a way to keep the solution simple and uses arrays and use some kind of class.

If I'd want to keep the exercise simple I would require two three independent functions that take some scores: latest(scores, scores_len) would return the last element of scores, personal_best(scores, scores_len) would return the greatest element of scores, personal_top_three(scores, scores_len, &result) would write the three highest scores to the output variable result, and scores() wouldn't make sense at all because it would just return its argument.

If I'd want personal_top_three() (and maybe scores()) to "return" an array I would either need one or two output-parameters (because I would need to communicate the array and its length to the caller), or I'd have to create a struct that holds the array and its length. And the array might need to be dynamically allocated and later deallocated.

If I'd want to have some class-like structure I'd have to take care of the lifetimes of the arrays, maybe copy or allocate/deallocate them.

Do you have an idea how to keep the C translation close in line with the tests and objectives ("easy", "arrays", "class")?

[edited, i forgot one of the four functions]

keiravillekode commented 1 year ago

To honour the 'class' objective, we can use an opaque data type:

struct table_impl;
typedef struct table_impl* table;

table create_table(int* scores, size_t scores_len);
int latest(table t);
int personal_best(table t);
size_t personal_top_three(table t, int* dest);
void destroy_table(table t);
#include "high_scores.h"

struct table_impl {
};

scores() is omitted as it is not 'easy'.

keiravillekode commented 1 year ago

As most students will be familiar with the use of FILE*, it might be better to use

struct table;
typedef struct table TABLE;

TABLE* create_table( . . . );
#include "high_scores.h"

struct table {
};
siebenschlaefer commented 1 year ago

An opaque type is another thing that I wouldn't call "easy". And if you consider dynamic memory allocation (and deallocation), pointers as output parameters, and opaque types as easy then (almost) all exercises on the C track are easy.
I've asked on the forum if somebody has ideas.

BTW: Whether you want to call the type alias table or TABLE is IMHO a minor detail (although I always try to reserve identifiers in "ALL_CAPS" for the preprocessor).

keiravillekode commented 1 year ago

We can omit the 'class' objective, as in Awk and Fortran.

int latest(const int* scores, size_t scores_len);
int personal_best(const int* scores, size_t scores_len);
size_t personal_top_three(const int* scores, size_t scores_len, int* dest);
siebenschlaefer commented 1 year ago

We can omit the 'class' objective, as in Awk and Fortran.

I'd be OK with that, I think that might be the simplest option.

ryanplusplus commented 1 year ago

We can omit the 'class' objective, as in Awk and Fortran.

I'd be OK with that, I think that might be the simplest option.

Agreed. Going much further than this approach brings in a lot of complexity.

keiravillekode commented 1 year ago

PR #902 is ready for review. It was automatically closed.