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:
- Pass the pre-tester with 0 errors of any kind.
-
Follow all Code Quality Standards—except where doing so would
diminish readability.
- We will be hand-checking all Alchemy submissions. This is a higher standard than usual.
- Be human-readable.
- All lines can be displayable in a 95-column window (i.e., width ≤ 95 characters).
-
Each statement may contain ≤3 of these operators:
+ - * / % != < > <= >= == ! && ||
(not counting*
addr)- 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.
- You may include more operators if doing so substantially improves readability.
For example, in
- Functions may comprise ≤35 "SLOC" and ≤50 LOC.
-
Code in paragraphs for functions with ≥10 sloc.
◄◄◄ Don't overlook this ◄◄◄
- Any block of ≥8 statements at the same indent level should be split into subsections, each preceded by a blank line and a comment.
-
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). -
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;
-
You have no space on either side of an operator if it improves readability
(e.g.,
-
Minimize redundancy
(i.e., D.R.Y.)
by reducing the SLOC in your code to below the “threshold” value below.
-
You may exclude
assert(…)
statements and#include <assert.h>
from your limit.
-
You may exclude
-
Declare your adherence to the requirements and/or instances where you
deviated to achieve better code readability.
-
Copy our template
(
cp ~ece264/23sp/alchemy.txt
), fill in the questionnaire, and submit with your code.
-
Copy our template
(
Assignment groups and SLOC targets
mintf |
|
|
join_strings |
|
|
tree sort |
|
|
JSON |
|
|
Huffman |
|
|
Do not sacrifice readability to shorten your code.
- Variable names must be meaningful, should follow the conventions in our Code Quality Standards (as approrpriate).
- Variable names that are misleading (e.g., char* i, Node* array) or blatantly cryptic (e.g., char* avr3) are unacceptable.
- Avoid abbreviations unless they will be totally clear and unambiguous to anybody connected with this class.
-
Do not abuse the
▒?▒:▒
operator in ways that make your code less clear, just to avoid anif
statement.-
Do not use a
▒?▒:▒
expression as a statement by itself.
Ex:(digit < 10 ? fgetc(…) : fgetc(…));
✘
-
Do not use a
-
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.
-
In terms of the basic form,
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);
}
}
|
Q&A
-
Do I have to do this?
No. -
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). -
How are homework assignments weighted toward the final grade?
See the syllabus under Grades. -
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. -
Can I see an example of “coding in paragraphs”?
Here's a before-and-after example: bmp.c without paragraphs → bmp.c with paragraphs -
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. -
May I submit >1 assignment group for Alchemy?
No. 1 is the most we can handle. -
What will happen if I try?
We'll take the first one we find, in whatever order we happen to find them. -
If I submit and then improve my code further, may I resubmit?
Yes, up to the deadline (Sun 5/7 9:00am). -
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. -
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. -
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. -
Will there be partial credit?
Don't count on it. Alchemy is about creating gold, not bronze. -
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. -
Does the Homework Bug Bounty (HBB) apply to this?
No. -
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. -
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. -
Is this “amnesty”?
Not exactly. Alchemy requires doing substantially more than was originally required. -
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. -
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. -
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. -
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. -
Do I have to follow the naming conventions in the Code Quality Standards?
Yes. -
What if I don't?
Alchemy is not required. -
What if I don't know what a "noun phrase" is? … "third person simple present tense"?
This is college. -
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. -
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 ofint num_chunks
), lack of paragraphs, and lack of space between paragraphs. -
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.