Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue228 fix #296

Open
wants to merge 2 commits into
base: 2024/x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion runoff/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,146 +14,169 @@ def exists():
def compiles():
"""runoff compiles"""
check50.c.compile("runoff.c", lcs50=True)
runoff = re.sub("int\s+main", "int distro_main", open("runoff.c").read())
runoff = re.sub(r"int\s+main", "int distro_main", open("runoff.c").read())
testing = open("testing.c").read()
with open("runoff_test.c", "w") as f:
f.write(runoff)
f.write("\n")
f.write(testing)
check50.c.compile("runoff_test.c", lcs50=True)


@check50.check(compiles)
@check50.hidden("vote function did not return true")
def vote_returns_true():
"""vote returns true when given name of candidate"""
check50.run("./runoff_test 0 0").stdout("true").exit(0)


@check50.check(compiles)
@check50.hidden("vote function did not return false")
def vote_returns_false():
"""vote returns false when given name of invalid candidate"""
check50.run("./runoff_test 0 1").stdout("false").exit(0)


@check50.check(compiles)
@check50.hidden("vote function did not correctly set preferences")
def vote_sets_preference1():
"""vote correctly sets first preference for first voter"""
check50.run("./runoff_test 0 2").stdout("2").exit(0)


@check50.check(compiles)
@check50.hidden("vote function did not correctly set preferences")
def vote_sets_preference2():
"""vote correctly sets third preference for second voter"""
check50.run("./runoff_test 0 3").stdout("0").exit(0)


@check50.check(compiles)
@check50.hidden("vote function did not correctly set preferences")
def vote_sets_all_preferences():
"""vote correctly sets all preferences for voter"""
check50.run("./runoff_test 0 4").stdout("1 0 2").exit(0)


@check50.check(compiles)
@check50.hidden("tabulate function did not produce correct vote totals")
def tabulate1():
"""tabulate counts votes when all candidates remain in election"""
check50.run("./runoff_test 1 5").stdout("3 3 1 0 ").exit(0)


@check50.check(compiles)
@check50.hidden("tabulate function did not produce correct vote totals")
def tabulate2():
"""tabulate counts votes when one candidate is eliminated"""
check50.run("./runoff_test 1 6").stdout("3 3 1 0 ").exit(0)


@check50.check(compiles)
@check50.hidden("tabulate function did not produce correct vote totals")
def tabulate3():
"""tabulate counts votes when multiple candidates are eliminated"""
check50.run("./runoff_test 1 7").stdout("3 4 0 0 ").exit(0)


@check50.check(compiles)
@check50.hidden("tabulate function did not produce correct vote totals")
def tabulate4():
"""tabulate handles multiple rounds of preferences"""
check50.run("./runoff_test 1 22").stdout("3 4 0 0 ").exit(0)


@check50.check(compiles)
@check50.hidden("print_winner did not print winner of election")
def print_winner1():
"""print_winner prints name when someone has a majority"""
check50.run("./runoff_test 2 8").stdout("Bob\n").exit(0)


@check50.check(compiles)
@check50.hidden("print_winner did not print winner and then return true")
def print_winner2():
"""print_winner returns true when someone has a majority"""
check50.run("./runoff_test 2 9").stdout("Bob\ntrue").exit(0)


@check50.check(compiles)
@check50.hidden("print_winner did not return false")
def print_winner3():
"""print_winner returns false when nobody has a majority"""
check50.run("./runoff_test 2 10").stdout("false").exit(0)


@check50.check(compiles)
@check50.hidden("print_winner did not return false")
def print_winner4():
"""print_winner returns false when leader has exactly 50% of vote"""
check50.run("./runoff_test 2 11").stdout("false").exit(0)


@check50.check(compiles)
@check50.hidden("find_min did not identify correct minimum")
def find_min1():
"""find_min returns minimum number of votes for candidate"""
check50.run("./runoff_test 2 12").stdout("1").exit(0)


@check50.check(compiles)
@check50.hidden("find_min did not identify correct minimum")
def find_min2():
"""find_min returns minimum when all candidates are tied"""
check50.run("./runoff_test 2 13").stdout("7").exit(0)


@check50.check(compiles)
@check50.hidden("find_min did not identify correct minimum")
def find_min3():
"""find_min ignores eliminated candidates"""
check50.run("./runoff_test 2 14").stdout("4").exit(0)


@check50.check(compiles)
@check50.hidden("is_tie did not return true")
def is_tie1():
"""is_tie returns true when election is tied"""
check50.run("./runoff_test 2 15").stdout("true").exit(0)


@check50.check(compiles)
@check50.hidden("is_tie did not return false")
def is_tie2():
"""is_tie returns false when election is not tied"""
check50.run("./runoff_test 2 16").stdout("false").exit(0)


@check50.check(compiles)
@check50.hidden("is_tie did not return false")
def is_tie3():
"""is_tie returns false when only some of the candidates are tied"""
check50.run("./runoff_test 2 17").stdout("false").exit(0)


@check50.check(compiles)
@check50.hidden("is_tie did not return true")
def is_tie4():
"""is_tie detects tie after some candidates have been eliminated"""
check50.run("./runoff_test 2 18").stdout("true").exit(0)


@check50.check(compiles)
@check50.hidden("eliminate did not eliminate correct candidates")
def eliminate1():
"""eliminate eliminates candidate in last place"""
check50.run("./runoff_test 2 19").stdout("false false false true ").exit(0)


@check50.check(compiles)
@check50.hidden("eliminate did not eliminate correct candidates")
def eliminate2():
"""eliminate eliminates multiple candidates in tie for last"""
check50.run("./runoff_test 2 20").stdout("true false true false ").exit(0)


@check50.check(compiles)
@check50.hidden("eliminate did not eliminate correct candidates")
def eliminate3():
Expand Down
55 changes: 45 additions & 10 deletions runoff/testing.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#include <stdlib.h>

int main(int argc, string argv[])
{
if (argc != 3)
Expand Down Expand Up @@ -79,31 +77,63 @@ int main(int argc, string argv[])
break;
}

// Allocate strings; used to prevent string literals from being
// shared across the program, which would make it possible to use
// == in place of strcmp and believe yourself correct
char *alice = malloc(strlen("Alice") + 1);
if (alice == NULL) {
perror("Failed to allocate memory");
return 1;
}
strcpy(alice, "Alice");

char *bob = malloc(strlen("Bob") + 1);
if (bob == NULL) {
perror("Failed to allocate memory");
return 1;
}
strcpy(bob, "Bob");

char *charlie = malloc(strlen("Charlie") + 1);
if (charlie == NULL) {
perror("Failed to allocate memory");
return 1;
}
strcpy(charlie, "Charlie");

char *david = malloc(strlen("David") + 1);
if (david == NULL) {
perror("Failed to allocate memory");
return 1;
}
strcpy(david, "David");

// Test
switch(test)
{
case 0:
printf("%s", vote(0, 0, "Bob") ? "true" : "false");
case 0: {
printf("%s", vote(0, 0, bob) ? "true" : "false");
break;
}

case 1:
printf("%s", vote(1, 2, "David") ? "true" : "false");
printf("%s", vote(1, 2, david) ? "true" : "false");
break;

case 2:
vote(0, 0, "Charlie");
vote(0, 0, charlie);
printf("%i", preferences[0][0]);
break;

case 3:
vote(1, 2, "Alice");
vote(1, 2, alice);
printf("%i", preferences[1][2]);
break;

case 4:
vote(1, 0, "Bob");
vote(1, 1, "Alice");
vote(1, 2, "Charlie");
vote(1, 0, bob);
vote(1, 1, alice);
vote(1, 2, charlie);
printf("%i %i %i", preferences[1][0], preferences[1][1], preferences[1][2]);
break;

Expand Down Expand Up @@ -238,4 +268,9 @@ int main(int argc, string argv[])
break;

}

free(alice);
free(bob);
free(charlie);
free(david);
}