Advanced C Programming

Spring 2023 ECE 264 :: Purdue University

Alchemy details (also sent last week)
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 group with which you were not satisfied, and make it truly “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.

If you choose to do this, we will increase your score to 100% for every component of the assignment group, provided you make it truly exemplary as defined by the requirements below. You must do it for every implementation file in the final stage of the group.

The list of assignment groups is below, along with details and specific requirements for each one. You may only do Alchemy for an entire assignment group—not for just one intermediate step. This offer is not available for any other assignment.

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)
      1. You may include more operators if doing so substantially improves readability. For example, in mintf(…), if(this_char == 'd' || this_char == 'x' || this_char == 'b') { … } is arguably more readable than many alternative ways that could be shortened.
    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/23sp/alchemy.txt), fill in the questionnaire, and submit with your code.

Assignment groups and SLOC targets

mintf
  • Submit to HW05.
  • All implementation files must meet requirements (above).
  • print_integer.c must be ≤24 SLOC.
  • mintf.c must be ≤89 SLOC.
  • If successful, scores for HW02 and HW05 will be increased to 100%.
join_strings
  • Submit to HW09.
  • All implementation files must meet requirements (above).
  • join_strings.c must be ≤40 SLOC.
  • If successful, score for HW09 will be increased to 100%.
tree sort
  • Submit to HW15.
  • All implementation files must meet requirements (above).
  • sorts.c must be ≤52 SLOC.
  • If successful, score for HW15 will be increased to 100%.
JSON
  • Submit to HW14.
  • All implementation files must meet requirements (above).
  • json.c must be ≤153 SLOC.
  • If successful, scores for HW10, HW11, HW13, and HW14 will be increased to 100%.
Huffman
  • Submit to HW21.
  • All implementation files must meet requirements (above).
  • priority_queue.c must be ≤51 SLOC.
  • frequencies.c must be ≤23 SLOC.
  • bit_writer.c must be ≤46 SLOC.
  • huffman.c must be ≤140 SLOC.
  • If successful, scores for HW12, HW16, HW17, HW18, HW19, HW20, and HW21 will be increased to 100%.

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 make submit (or 264submit) by Sun 5/7 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/7 and Mon 5/8 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/7 and Mon 5/8. 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 group should I choose?
    It's up to you. Pick whatever you think will benefit you most (in terms of grade or learning).
  3. How are homework assignments weighted toward the final grade?
    See the syllabus under Grades.
  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 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. May I submit >1 assignment group for Alchemy?
    No. 1 is the most we can handle.
  8. What will happen if I try?
    We'll take the first one we find, in whatever order we happen to find them.
  9. If I submit and then improve my code further, may I resubmit?
    Yes, up to the deadline (Sun 5/7 9:00am).
  10. 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.
  11. Will my Alchemy submission be considered late (i.e., after Sun 5/7 9:00am)?
    No. Even accepting that late is a stretch for us.
  12. 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.
  13. Will there be partial credit?
    Don't count on it. Alchemy is about creating gold, not bronze.
  14. 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.
  15. Does the Homework Bug Bounty (HBB) apply to this?
    No.
  16. 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.
  17. 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.
  18. Is this “amnesty”?
    Not exactly. Alchemy requires doing substantially more than was originally required.
  19. 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.
  20. 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.
  21. 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.
  22. 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.
  23. Do I have to follow the naming conventions in the Code Quality Standards?
    Yes.
  24. What if I don't?
    Alchemy is not required.
  25. What if I don't know what a "noun phrase" is? … "third person simple present tense"?
    This is college.
  26. 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.
  27. 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.
  28. 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.

Updates

In case of any future updates, a note will be added here.