Advanced C Programming

Spring 2020 ECE 264 :: Purdue University

⚠ This is a PAST SEMESTER (Spring 2020).
PbAu
gold crystals

Alchemy

Creating truly excellent work feels great. We want you to feel that way about something you did in ECE 264. Of course, ECE 264 is a learning experience so you may not always get there the first time. Perfection takes time and iteration.

As this semester draws to a close, we invite you to choose a programming assignment for which you received <100%, and make it “exemplary”. The result should be a show piece of code—something you would feel proud to print out and take to a job interview as an example of what you are now capable of.

For each programming assignment you make exemplary—defined by the requirements below—we will increase your score to 100%. You may do this for up to 3 assignments.

This offer does not apply to the homework assignments that were focused on tools: HW01, HW03, and HW05.

Requirements

Alchemy submissions must meet these requirements:

  1. Pass the pre-tester with 0 errors of any kind.
  2. Follow all Code Quality Standards—except where doing so would diminish readability.
    1. We will be hand-checking all Alchemy submissions. This is a higher standard than usual.
  3. Be human-readable.
    1. All lines can be displayable in a 95-column window (i.e., width ≤ 95 characters).
    2. Each statement may contain ≤3 of these operators: + - * / % != < > <= >= == ! && || (not counting *addr)
    3. Functions may comprise ≤35 "SLOC" and ≤50 LOC.
    4. Code in paragraphs for functions with ≥10 sloc. ◄◄◄ Don't overlook this ◄◄◄
      1. Any block of ≥8 statements at the same indent level should be split into subsections, each preceded by a blank line and a comment.
    5. Every ; and , must be followed by a space or newline. Every { must be preceded by a space, tab, or newline (i.e., beginning of line).
    6. Binary operators should one space on both sides (e.g., a + b, a = b, a -> b), except:
      • You have no space on either side of an operator if it improves readability (e.g., Point p = { .x=5, .y=6 }).
      • You can have ≥1 spaces on either side if it helps you align between lines.
        int a  =  5;
        int b  = 66;
        int cc =  7;
        
  4. Minimize redundancy (i.e., D.R.Y.) by reducing the SLOC in your code to below the “threshold” value below.
    1. You may exclude assert(…) statements and #include <assert.h> from your limit.
  5. Declare your adherence to the requirements and/or instances where you deviated to achieve better code readability.
    1. Copy our template (cp ~ece264/20sp/alchemy.txt .), fill in the questionnaire, and submit with your code.

SLOC Targets

Tightest Threshold
HW01 - - - not eligible
HW02 20 26 hw02.c
HW03 - - - not eligible
HW04 74 97 mintf.c
HW05 - - - not eligible
HW06 111 145 mintf.c
HW07 113 147 cake.c
HW08 69 90 json.c
HW09 127 166 json.c
HW10 51 67 sorts.c
HW11 42 55 huffman.c
HW12 19 25 frequencies.c
HW13 23 30 huffman.c
HW14 51 67 huffman.c
HW15 TBA TBA huffman.c
HW16 TBA TBA huffman.c
HW17 116 151 huffman.c
HW18 57 75 huffman_compress.c
HW19 - - - not eligible
EC01 - - - not eligible
EC02 - - - not eligible

Do not sacrifice readability to shorten your code.

  1. Variable names must be meaningful, should follow the conventions in our Code Quality Standards (as approrpriate).
  2. Variable names that are misleading (e.g., char* i, Node* array) or blatantly cryptic (e.g., char* avr3) are unacceptable.
  3. Avoid abbreviations unless they will be totally clear and unambiguous to anybody connected with this class.
  4. Do not abuse the ?: operator in ways that make your code less clear, just to avoid an if statement.
    • Do not use a ?: expression as a statement by itself.
      Ex: (digit < 10 ? fgetc(…) : fgetc(…));
  5. Do not cram unrelated statements into a for statement.
    • In terms of the basic form, for(init; condition; next), the init, condition, and next components should be clearly related to each other.
    • If your for loop is iterating over a sequence (e.g., elements in an array, nodes in a linked list, characters in a file, etc.), then init should declare and initialize the index or variable for the current object, condition should determine if you are at the end, and next should advance the position to the next object.

Submit

Submit using 264submit by Sun 5/10 9:00am.

Use the same command—including the assignment name (e.g., “HW09”) as you did for the original submission. We will know the alchemy submissions based on the submission date and the presence of a file called alchemy.txt. Be sure to include alchemy.txt and all files that were required according to the current assignment page. We must be able to test your code.

We set the deadline as late as we possibly can so you can focus on your final exams, but still take advantage of this offer.

Repeat: Include all originally required files and alchemy.txt. Submissions without alchemy.txt will not be accepted.

Do not submit your homework on Github or anywhere else publicly accessible.

Scoring

Alchemy is about excellence—i.e., creating gold. Therefore, your submission should be perfect.

We will hand-check every Alchemy submission. A team of TAs and I have blocked off time on Sun 5/10 and Mon 5/11 to go through these.

To check a submission, we will look at your alchemy.txt and verify your responses. As long as you have answered each question faithfully, and given a brief explanation (e.g., 1-2 sentences) for any “[/]”, you will get full credit.

We do not anticipate giving partial credit. Alchemy is about creating gold, not bronze.

Preliminary feedback

We hope the checklist gives you some confidence about your submission. However, you are welcome to drop by Prof. Quinn's office hours for some feedback. TAs can also help you find areas to improve, but will not certify that you are “done”.

As part of our preparation, we will be checking some of the first submissions in the days leading up to Sun 5/10 and Mon 5/11. If we see something awry, you may get an email.

Tips for shortening code

Feel free to suggest more tips. I may add to this, if anything good comes up.

Convert while loop to for loop

long short
int i = 0;
while(i < n) {
  // …
  i++;
}
for(int i = 0; i < n; i++) {
  // …
}

For loop to traverse linked list

long short
Node* curr = head;
while(curr != NULL) {
  // …
  curr = curr -> next;
}
for(Node* curr = head; curr != NULL; curr = curr -> next) {
  // …
}

Combine printf statements

long short
printf("%d", n);
printf("\n");
printf("%d\n", n);

Ternary operator

long short
int sign;
if(x >= 0) {
  sign = 1;
}
else {
  sign = -1;
}
int sign = (x >= 0 ? 1 : -1);

Assignment condition directly to bool variable

long short
bool is_negative;
if(x >= 0) {
  is_negative = false;
}
else {
  is_negative = true;
}
bool is_negative = (x < 0);

Combine multiple heap allocations (malloc(…) calls) into one

long short
void make_person(char* name, int age) {
  Person* person = malloc(sizeof(*person));
  if(person == NULL) {
    return NULL;
  }
  person -> age  = age;
  person->name = malloc(sizeof(*name) * (strlen(name) + 1));
  if(person->name == NULL) {
    free(person);
    return NULL;
  }
  strcpy(person->name, name);
  return person;
}
void make_person(char* name, int age) {
  // Allocate Person and its .name in one block
  Person* person = malloc(sizeof(*person) +
          sizeof(*person->name) * (strlen(name,) + 1));
  if(person != NULL) {
    person -> age  = age;
    person -> name = strcpy((char*)(person + 1), name,);
  }
  return person;
}

Use a 1-line for loop to get the tail of a linked list

long short
// Get head of linked list
Node* tail = head;
while(tail != NULL && tail -> next != NULL) {
  tail = tail -> next;
}
// Get head of linked list
Node* tail = head;
for(; tail != NULL && tail -> next != NULL; tail = tail -> next) {}

Eliminate unnecessary branches by assigning to a Node** instead of Node*

long short
void insert_into_list_at_idx(
          Node** a_head, int value, int idx) {
  // Create new node
  Node* new_node = malloc(sizeof(*new_node));
  new_node -> next = value;

  if(*a_head == NULL) {  // Empty list?
    // Set new node as the sole node in list.
    *a_head = new_node;
    (*a_head) -> next = NULL;
  }
  else {
    // Find the node to insert just after.
    Node* prev = *a_head;
    for(int i = 0; i < idx; i++) {
      if(prev -> next == NULL) {
        break;
      }
      prev = prev -> next;
    }

    // Insert the new node.
    new_node -> next = prev -> next;
    prev -> next = new_node;
  }
}
void insert_into_list_at_idx(
              Node** a_head, int value, int idx) {
  // Create new node.
  Node* new_node = malloc(sizeof(*new_node));
  new_node -> next = value;

  // Find the position to add the new node.
  Node** a_curr = a_head;
  for(int i = 0; i < idx && (*a_curr) != NULL; i++) {
    a_curr = &(*a_curr) -> next;
  }

  // Insert the new node.
  *a_curr = new_node;
}

Eliminate dummy initializations

long short
void foo() {
  // …
  char ch = '\0';
  for(int i = 0; i < n; i++) {
    ch = fgetc(fp);
    bar(ch);
  }
}
void foo() {
  // …
  for(int i = 0; i < n; i++) {
    char ch = fgetc(fp);
    bar(ch);
  }
}
In this example, ch is only used within the for loop, and values are not reused in subsequent iterations. Thus, there is no reason to declare or initialize it outside the loop.

Q&A

  1. Do I have to do this?
    No.
  2. Which homework(s) should I choose?
    It's up to you.
    One strategy could be to pick something where you made “silly mistakes” that can be easily fixed. Then, if you have more time, and are focused on improving your grade, pick another one (or two) with the greatest potential benefit to you.
  3. How are homework assignments weighted toward the final grade?
    See the syllabus under Grades. (Weights were added 3/31. That was announced by email that same day.)
  4. What do “SLOC” and “LOC” mean?
    "SLOC" is the number of source lines of code, excluding comments and blank lines. "LOC" is the number of (physical) lines of code. Wikipedia has a whole article about this.
  5. Can I see an example of “coding in paragraphs”?
    Here's an example from class: append_tidy.c
    Here's a before-and-after example:  bmp.c without paragraphsbmp.c with paragraphs
  6. What if coding in paragraphs would make my code less readable?
    You may ignore that requirement if it would make readability worse (i.e., if the comment would be superfluous). Simply note it a note in your alchemy.txt.
  7. Isn't it too much work to fix three assignments in this time frame?
    Probably. We expect most people will do 0, 1, or maybe 2 of these. We capped it at 3, just in case anybody had some “silly mistake” that is easy to fix, or is unusually motivated.
  8. May I submit >3 homeworks for Alchemy?
    No. 3 is the most we can handle.
  9. What will happen if I try?
    We'll take the first 3 we find, in whatever order we happen to find them.
  10. If I submit and then improve my code further, may I resubmit?
    Yes, up to the deadline (Sun 5/10 9:00am).
  11. Why is this due at 9:00 AM instead of 11:59 PM?
    We wanted to give you as much time as possible before we need to go through them.
  12. Will my Alchemy submission be considered late (i.e., after Sun 5/10 9:00am)?
    No. Even accepting that late is a stretch for us.
  13. How will I know how I did?
    We plan to post the results on your Scores page (time permitting). At any rate, grades will be posted the following Tuesday.
  14. Will there be partial credit?
    Don't count on it. Alchemy is about creating gold, not bronze.
  15. If I put the opening brace of an if/for/… on a line by itself, won't the SLOC increase?
    Yes. You may find it useful to follow the style illustrated in the examples above.
  16. Does the Homework Bug Bounty (HBB) apply to this?
    No.
  17. As I was improving my code, I noticed a flaw in an assignment. Can I receive the Homework Bug Bounty (HBB)?
    No. We do not give HBB for assignments after their (original) due date. However, we always appreciate the feedback so we can make things better.
  18. I got 100% on everything. What's in this for me?
    Fantastic! If you already have 100% on everything, this will not have any benefit for your grade. Then again, you are probably getting an A (or A+), anyway. However, we still encourage you to practice writing excellent code, and clean up at least one assignment as a show piece.
  19. Is this “amnesty”?
    Not exactly. Alchemy requires doing substantially more than was originally required.
  20. Is this unfair to people who did everything perfectly and on-time?
    Nothing is perfectly fair. Before deciding on this, I solicited feedback on how to structure this from several students and discussed with the TAs.
  21. Why not do this for bonus points?
    We want people to choose the homework(s) for which going back and fixing would have the greatest educational benefit—i.e., something you stumbled on the first time, but now feel more comfortable with.
  22. HW07 has the largest # of sloc. Was it the hardest?
    Maybe, maybe not. “Hard” is subjective. The number of sloc in HW07 is somewhat inflated due to the number of functions that was required. There were 8 required functions. In addition, most solutions had at least 4 helper functions. Thus, the function signature and ending } count for 24 of the 130 sloc.
  23. How can I ensure my code lines are ≤95 columns wide?
    In Vim: :set colorcolumn=95 That adds a red bar to the screen as a guide. There are other options which force your code to be ≤95 columns wide, but I find the colorcolumn option easiest to work with.
  24. What if my submission does not meet all of the requirements?
    You must meet all requirements to get credit. We have designed this so that you can confidently judge whether you have met the requirements.
  25. Do I have to follow the naming conventions in the Code Quality Standards?
    Yes.
  26. What if I don't?
    Alchemy is not required.
  27. What if I don't know what a "noun phrase" is? … "third person simple present tense"?
    This is college.
  28. What if following a code quality rule would hurt readability/maintainability?
    As long as you you give a brief explanation, that is still considered as meeting the requirements. We intend to accept all reasonable explanations.
  29. What issues have other students run into?
    When we did this in a previous semester, we saw a lot of issues with improper constants (e.g., 48 instead of '0'), variable names (e.g., int chunks instead of int num_chunks), lack of paragraphs, and lack of space between paragraphs.
  30. Will you check my submission before the deadline?
    Yes! Come to Prof. Quinn's office hours any time. If it passes, you will get your credit immediately. If there are minor issues, you can probably fix it right there, and get your credit immediately. In the near future, Taeuk and Nadia (and possibly the UTAs) will also be able to do this for you.

Updates

4/17/2020 HW10 sloc count was wrong. Will update soon.
5/7/2020 You may exclude assert(…) statements from your total count when checking against the threshold.
Added SLOC target for HW14.