CS50 Problem Set 5

CS50 Problem Set 5

King Hua Lv2

CS50 Problem Set 5

Here’s my answer for the CS50 Problem Set 5. Hope that will help you a bit.

Problem 1: Inheritance

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Simulate genetic inheritance of blood type
#define _DEFAULT_SOURCE
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

// Each person has two parents and two alleles
typedef struct person
{
struct person *parents[2];
char alleles[2];
} person;

const int GENERATIONS = 3;
const int INDENT_LENGTH = 4;

person *create_family(int generations);
void print_family(person *p, int generation);
void free_family(person *p);
char random_allele();

int main(void)
{
// Seed random number generator
srandom(time(0));

// Create a new family with three generations
person *p = create_family(GENERATIONS);

// Print family tree of blood types
print_family(p, 0);

// Free memory
free_family(p);
}

// Create a new individual with `generations`
person *create_family(int generations)
{
// TODO: Allocate memory for new person
person *p = malloc(sizeof(person));

// If there are still generations left to create
if (generations > 1)
{
// Create two new parents for current person by recursively calling create_family
person *parent0 = create_family(generations - 1);
person *parent1 = create_family(generations - 1);

// TODO: Set parent pointers for current person
p->parents[0] = parent0;
p->parents[1] = parent1;

// TODO: Randomly assign current person's alleles based on the alleles of their parents
p->alleles[0] = parent0->alleles[random() % 2];
p->alleles[1] = parent1->alleles[random() % 2];
}

// If there are no generations left to create
else
{
// TODO: Set parent pointers to NULL
p->parents[0] = NULL;
p->parents[1] = NULL;

// TODO: Randomly assign alleles
p->alleles[0] = random_allele();
p->alleles[1] = random_allele();
}

// TODO: Return newly created person
return p;

return NULL;
}

// Free `p` and all ancestors of `p`.
void free_family(person *p)
{
// TODO: Handle base case
if (p == NULL)
{
return;
}

// TODO: Free parents recursively
free_family(p->parents[0]);
free_family(p->parents[1]);

// TODO: Free child
free(p);
}

// Print each family member and their alleles.
void print_family(person *p, int generation)
{
// Handle base case
if (p == NULL)
{
return;
}

// Print indentation
for (int i = 0; i < generation * INDENT_LENGTH; i++)
{
printf(" ");
}

// Print person
if (generation == 0)
{
printf("Child (Generation %i): blood type %c%c\n", generation, p->alleles[0],
p->alleles[1]);
}
else if (generation == 1)
{
printf("Parent (Generation %i): blood type %c%c\n", generation, p->alleles[0],
p->alleles[1]);
}
else
{
for (int i = 0; i < generation - 2; i++)
{
printf("Great-");
}
printf("Grandparent (Generation %i): blood type %c%c\n", generation, p->alleles[0],
p->alleles[1]);
}

// Print parents of current generation
print_family(p->parents[0], generation + 1);
print_family(p->parents[1], generation + 1);
}

// Randomly chooses a blood type allele.
char random_allele()
{
int r = random() % 3;
if (r == 0)
{
return 'A';
}
else if (r == 1)
{
return 'B';
}
else
{
return 'O';
}
}

Problem 2: Speller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Implements a dictionary's functionality

#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

#include "dictionary.h"

// Represents a node in a hash table
typedef struct node
{
char word[LENGTH + 1];
struct node *next;
} node;

int word_counter = 0;

// TODO: Choose number of buckets in hash table
const unsigned int N = 26;

// Hash table
node *table[N];

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
// TODO
// Hash the word to obtain its hash value
int hash_value = hash(word);

// Search the hash table at the location specified by the word’s hash value
// Return "true" if the word is found
node *cursor = table[hash_value];
while (cursor != NULL)
{
if (strcasecmp(cursor->word, word) == 0)
{
return true;
}
else
{
cursor = cursor->next;
}
}

return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
// TODO: Improve this hash function
return toupper(word[0]) - 'A';
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
// TODO
// Make sure there is no garbage values
for (int i = 0; i < N; i++)
{
table[i] = NULL;
}

// Open the dictionary file
FILE *dict = fopen(dictionary, "r");
if (dict == NULL)
{
printf("The dictinary does not exist.\n");
return false;
}

// Read strings from file one at a time
char temp_word[LENGTH];

while (fscanf(dict, "%s", temp_word) != EOF)
{
// Create space for a new hash table node
node *new_word = malloc(sizeof(node));

// Copy the word into the new node
strcpy(new_word->word, temp_word);

// Hash the word to obtain its hash value
int hash_value = hash(temp_word);

// Insert the new node into the hash table (using the index specified by its hash value)
new_word->next = table[hash_value];
table[hash_value] = new_word;
word_counter += 1;
}

// close the dictinary file
fclose(dict);

return true;
}

// Returns number of words in dictionary if loaded, else 0 if not yet loaded
unsigned int size(void)
{
// TODO
return word_counter;
}

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
// TODO
for (int i = 0; i < N; i++)
{
node *tmp = table[i];
node *cursor = table[i];

while (cursor != NULL)
{
cursor = cursor->next;
free(tmp);
tmp = cursor;
}
}
return true;
}
  • Title: CS50 Problem Set 5
  • Author: King Hua
  • Created at : 2026-02-16 20:40:38
  • Updated at : 2026-02-16 21:02:24
  • Link: https://kinghua0629.github.io/2026/02/16/CS50-Problem-Set-5/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments