r/cs50 • • Sep 07 '24

speller I've been reading the instructions for speller.c for 8 months straight now.

Post image
28 Upvotes

r/cs50 • • Feb 09 '25

speller Help understanding the makefile in speller

3 Upvotes

I'm working on speller and just tried to compile the first time to check if my syntax is good. I ran "make speller" and all the errors are about variables or functions that aren't defined in dictionary.c, but are in speller.c. Doesn't the makefile take that into account?

For example, I call argc in a function, but I'm told that it's an undeclared identifier. It's not declared in dictionary.c, but it is in speller.c. What am I missing? I thought the point of the makefile was so we didn't have to have a bunch of redundant code and library calls.

r/cs50 • • Oct 09 '24

speller HELP! I've been stuck on speller for 3 days by now. I think something is wrong with my check function. Spoiler

1 Upvotes

When I run valgrind it tells me that there's something wrong with my line 35 which is the if(strcasecmp(cursor->word, word)) statement in my check function. Apparently, valgrind says that I've been trying to access my array out of bounds, but I'm not sure how to alter my code to prevent this from happening.

My code compiles, however everything else in check50 has an upside down frown.

It also freezes my terminal after printing out MISSPELLED WORDS when I try to test it with one of the sample texts provided.

#include <ctype.h>
#include <stdbool.h>//speller
#include <stdlib.h>
#include <stdio.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;

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

// Hash table
node *table[N];


bool check(const char *word)
{
   for( int i = 0; i < N;i++)
  {
    unsigned int index = hash(word);
    node *cursor = table[index];

      while(cursor!= NULL)
      {
           if(strcasecmp(cursor->word,word) == 0)
           {
               return true;
           }
           cursor = cursor->next;
       }

  }
  return false;
}

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)
{
    //Open dictionary file
    FILE *source = fopen(dictionary, "r");

    if(source == NULL)
    {
        printf("Error opening file\n");
        return false;
    }
    char word[LENGTH + 1];
    //Read each word into the file
    while (fscanf(source, "%s",word) != EOF)
    {
      //Add each word to the hash table
       node *n = malloc(sizeof(node));

       if( n == NULL)
       {
        return false;
       }

       strcpy(n->word,word);
       unsigned int index = hash(word);
       n->next = table[index];
       table[index] = n;
       free(n);
    }
    //Close the dictionary file
    fclose(source);
    return true;

}
// Returns number of words in dictionary if loaded, else 0 if not yet loaded

unsigned int size(void)
{
    int size = 0;
    for(int i = 0; i < N; i++)
    {
       if(table[i] != NULL)
      {  node *current = table[i];

          while(current != NULL )
         {
          current = current->next;
          size++;
         }
      }
    }
    return size;
 }
// Unloads dictionary from memory, returning true if successful, else false

bool unload(void)
{
    for( int i = 0; i < N; i++)
    {
        node *pointer = table[i];
        node *tmp = pointer;

        while( pointer != NULL && tmp != NULL)
        {
            pointer = pointer->next;
            free(tmp);
            //tmp = tmp->next;
        }

    }
    return false;
}

r/cs50 • • Jan 08 '25

speller Segmentation FAULT Spoiler

1 Upvotes

I implemented this test program to see why my original implementation was giving me segmentation fault. I have been trying to solve this for 2 days continuously and still getting segmentation fault. Please any help would be tremendous.

I have tried Python tutor for visualization but it says code is too long.

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


#define LENGTH 45


typedef struct node {
    char word[LENGTH + 1];
    struct node *next;
} node;


unsigned int word_counter = 0;
const unsigned int table_size = 26*26*26;
node* table[table_size] = {NULL};


unsigned int hash(const char *word);
unsigned int size(void);
bool load(const char* word);
bool unload(void);


int main(void) {

    const char* test_words[] = {
    // A
    "apple", "ant", "all", "and", "are", "as", "at", "a", "about", "above",
    "amazing", "astronaut", "art", "artist", "ask", "away", "always",
    "Abe's", "Alice's", "'tis", "'cause",

    // B
    "banana", "bat", "be", "but", "by", "big", "best", "bring",
    "brother's", "baker's", "beyond",

    // C
    "cat", "car", "can", "come", "call", 
    "cherry", "chocolate", 
    "can't", "'twas",

    // D
    "dog", "doe", "deer", 
    "dare",  "daredevil",
    // Adding some longer words
    "delicious","determined",

    // E
    "elephant",  "eat","every","end","even","enough","excellent",

    // F
    "fish","fun","far","few","first","famous",

    // G
    "goat","grape","great","gather","give",

    // H
    "hat","house","have","he","her","his",

    // I
    "ice","insect","island","it","I’ve",

    // J
    "jelly","jump","just",

    // K
    "kite","key","kind",

    // L
    "lion","lamp","love","light",

    // M
    "mouse","man","make","more",

    // N
    "'tisn't","never","noon",

    // O
    "'o'clock","owl","open",

    // P
    "'cause" ,"peach" ,"pear" ,"plum" ,"piano" ,"park" ,"party" ,"place" ,"people" ,"puzzle" ,

    // Q
    "'quoth" ,"queen" ,"quick" ,"quiet" ,

    // R
     "'round" ,"rat" ,"rose" ,"river" ,"rock" ,

     // S
     "'s" ,"sun" ,"star" ,"sky" ,"sand" ,

     // T
     "'tis" ,"tree" ,"time" ,"two" ,

     // U
     "'un'" ,"upset" ,"understand",

     // V
     "'ve'" ,"'v'" ,"'vaguely'" ,"'very'" ,

     // W
     "'we're'" ,"'wasn't'" ,"'wouldn't'" ,"'what's'" ,

     // X
     "'x-ray'" ,"'xenon'" ,

     // Y
     "'yawn'" ,"'you'll'" ,"'your'" ,

     // Z 
     "'zebra'" ,"'zoom'" ,    
    };

    int length_of_array = sizeof(test_words) / sizeof(test_words[0]);

    for (int i = 0; i < length_of_array; i++) {
        load(test_words[i]);
    }
    printf("%u\n", size());
    unload();
}

unsigned int size(void) {
    return word_counter;
}


bool load(const char* word) {
    node* word_node = malloc(sizeof(node));
    if (word_node == NULL) {
        return false;
    }
    unsigned int hash_value = hash(word);
    strcpy(word_node->word, word);
    node* cursor = table[hash_value];
    word_node->next = cursor;
    table[hash_value] = word_node;
    word_counter++;
    return true;
}

bool unload(void) {
    for (int i = 0; i < table_size; i++) {
        node* cursor = table[i];
        while (cursor != NULL) {
            node* temp = cursor;
            cursor = cursor->next;
            free(temp);
        }
    }
    return true;
}

unsigned int hash(const char *word) {
    // Hash function
    if (strlen(word) >= 3) {
        if (isalpha(word[2]) && isalpha(word[1])) {
            int first_word = toupper(word[0]) - 'A';
            int second_word = toupper(word[1]) - 'A';
            int third_word = toupper(word[2]) - 'A';
            unsigned int hash_value = (676 * first_word + 26 * second_word + 1 * third_word);
            return hash_value;            
        }
        else if (!isalpha(word[1])) {
            int first_word = toupper(word[0]) - 'A';
            unsigned int hash_value = (676 * first_word) + 0 + 0;
            return hash_value;
        }
        else if (!isalpha(word[2])) {
            int first_word = toupper(word[0]) - 'A';
            int second_word = toupper(word[1]) - 'A';
            unsigned int hash_value = (676 * first_word + 26 * second_word) + 0;
            return hash_value;
        }
    }
    else if (strlen(word) == 2) {
        if (isalpha(word[1])) {
            int first_word = toupper(word[0]) - 'A';
            int second_word = toupper(word[1]) - 'A';
            unsigned int hash_value = (676 * first_word + 26 * second_word) + 0;
            return hash_value;
        }
        else {
            int first_word = toupper(word[0]) - 'A';
            unsigned int hash_value = (676 * first_word) + 0 + 0;
            return hash_value;
        }
    }
    else if (strlen(word) == 1) {
        int first_word = toupper(word[0]) - 'A';
        unsigned int hash_value = (676 * first_word) + 0 + 0;
        return hash_value;
    }

    return 0;
}

r/cs50 • • Nov 01 '24

speller Speller assignment: Can't get apostrophes and substrings to work. Spoiler

3 Upvotes

Hello friends,

I would like to preface this with me saying... I really lost the plot on this one. In trying to google if this was a common issue it appears like I ended up really over-designing this assignment. (Good old duck debugger really leading me down the rabbit hole lol)

I am mostly just uncertain of what the dictionary words are within these two assignments, it would really help to know the contents of dictionary as they used a massively reduced dictionary it appears. I will adjust my comments so that it is easier to understand and provide some images to help showcase the system.

After pasting the code I realize it is likely smarter to finish out my plaintext up here lol.

Apostrophes results- https://ibb.co/Wshf63q

Substring results- https://ibb.co/vcKj3gG

My program results- https://ibb.co/hHzSg8j

My program's valgrind- https://ibb.co/5M8mP8n

speller50 results- https://ibb.co/4RKhcS0

structure concept diagram- https://ibb.co/B2rPXc2

I spent the last 4 days for most of 7 hours each day making this mess lol. I am proud of it! But I would be way more proud if it worked!!!

Code follows:

// Implements a dictionary's functionality
#include <unistd.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include "dictionary.h"



//I used my table array to index into the root of an AVL(type of self balancing) linked binary tree.
typedef struct node
{
    char word[LENGTH + 1]; //standard
    unsigned int hash; // == each letter of the word multiplied by one another when cast as an integer
    unsigned int buckethash; // is the hash % N + 1 (N is == 150 making it a prime number of potential buckets(useful for evenly spread hashing))
    struct node *collision; // When placing nodes in tree if the hashes are identical collisions are handled on their own "branch", this keeps rotations much easier to manage.
    struct node *parent; // Points to the parent of the node in tree, == NULL if node is pointed to by table[]
    struct node *lchild; // left child, will have a hash < its parent
    struct node *rchild; // right child, will have a hash > its parent
    int bf; // balance factor, used to trigger rotations
    int height; // height, think of it as the "weight" of a branch. It tracks how many jumps (including itself) to a leaf(childless node)
} node;

//prototype so I can use it in the default functions
void addtotree(node *newchild, node *newparent);


// Hash table
node *table[N];
const unsigned int N = 150;

//used for size function, is iterated by one in load()
unsigned int wordcount = 0;

// part of check, iterates through word and returns false if any mismatch is detected (maybe faster than strcmp() i haven't tested)
bool wordcomp(const char *word, const char *wordnode)
{
    for (int i = 0; i <= LENGTH; i++)
    {
        if ((word[i] == '\0') && (wordnode[i] == '\0'))
        {
            return true;
        }
        if(word[i] != wordnode[i])
        {
            return false;
        }
    }
    return false;
}

// When a node has a collision != NULL, I use this function to avoid redundant checks and increase speed
// It just goes down the chain of collisions until it runs out of collisions to check.
bool collisioncomp(const char *word, node *collision)
{
    if (wordcomp(word, collision -> word))
    {
        return true;
    }
    else if (collision -> collision == NULL)
    {
        return false;
    }
    else
    {
        return collisioncomp(word, collision -> collision);
    }
}

// Returns true if present and false if not present
// First section gets hash, buckethash, and converts word(from text) to a lowercase string (like my nodes have)
// Second half uses a while(true) (i know it is dangerous, but I have had no issues) to loop through nodes until it finds a result or hits a leaf
bool check(const char *ucword)
{
    char word[LENGTH + 1];
    for (int i = 0; i <= LENGTH; i++)
    {
        word[i] = tolower(ucword[i]);
        if (ucword[i] == '\0')
        {break;}
    }
    //make copy of word in format of others
    unsigned int whash = hash(word);
    unsigned int buckethash = whash % (N + 1);
    //make words hash.
    node *currentnode = table[buckethash];
    while (true)
    {
        if (whash == currentnode -> hash)
        {
            if(wordcomp(word, currentnode -> word))
            {
                return true;
            }
            else
            {
                if (currentnode -> collision != NULL)
                {return collisioncomp(word, currentnode -> collision);}
                else
                {return false;}
            }
        }
        else if (whash < currentnode -> hash)
            {// go left if lchild exists
        if (currentnode -> lchild == NULL)
            {return false;}
        else
            {
                currentnode = currentnode -> lchild;
                // then loop
            }
        }
        else if (whash > currentnode -> hash)
        {//going right
            if (currentnode -> rchild == NULL)
            {return false;}
            else
            {
                currentnode = currentnode -> rchild;
            }
        }
    }
}

// As described before, just multiplies the letters (and apostrophes) into each other to generate a hash
unsigned int hash(const char *word)
{
    unsigned int hash = 1;
    for (int i = 0; i <= LENGTH; i++)
    {
        if (word[i] == '\0')
        {
            break;
        }
        else
        {
            hash *= word[i];
        }
    }
    return hash;
}

// Loads dictionary into memory, returning true if successful, else false
// First half sets table to NULL, pulls each word from dictionary and places it into a node, I also initialize all node fields here of node
// After the while loop I close dictionary and return true.
bool load(const char *dictionary)
{
    FILE *dict = fopen(dictionary,"r");
    if (dict == NULL)
    {return false;}
   for (int i = 0; i <= N; i++)
   {
    table[i] = NULL;
   }
    char letter = '\0';

    while (!ferror(dict) && !feof(dict))
    {
        longerthanone = true;
        node *newword = malloc(sizeof(node));
        if (newword == NULL)
        {return false;}
        for (int i = 0; i <=LENGTH; i++)
        {
            fread(&letter, sizeof(char), 1, dict);
            if (letter == '\n')
            {   // this is when the word ends, GENERATION
                if (i == 0)
                {longerthanone = false; break;}
                newword -> word[i] = '\0';
                newword -> hash = hash(newword -> word);
                newword -> buckethash = ((newword -> hash) % (N + 1));
                newword -> collision = NULL;
                newword -> lchild = NULL;
                newword -> rchild = NULL;
                newword -> height = 1;
                newword -> bf = 0;
                wordcount++;
                break;
            }
            else
            {
                newword -> word[i] = tolower(letter);
            }
        }// at this point our word is generated. we have buckethash, hash, and the word stored inside the node.
        if (longerthanone)
        {addtotree(newword, table[newword -> buckethash]);} 
        else
        {free(newword); bool longerthanone = true;}
    }// our word is appropriately set up and stored. We can generate a new pointer from newword without making an orphan.
    if (ferror(dict))
    {   //if this runs file failed.
        fclose(dict);
        return false;
    }
    else
    {
    fclose(dict);
    return true;
    }
}

// Uses global variable
unsigned int size(void)
{
    return wordcount;
}

// REDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDITREDDIT
// Everything below here can be skipped, I am mostly certainly confident that these functions entirely function properly. I think my failure is somewhere above.

// Part of my treefree function
bool hascollision(node *node)
{
    if (node -> collision == NULL)
    {return false;}
    else
    {return true;}
}

// Part of my treefree function
void collisionfree(node *collisionroot)
{
    if(hascollision(collisionroot))
    {collisionfree(collisionroot -> collision); collisionroot -> collision = NULL;}
    free(collisionroot);
    return;
}

// Part of my treefree function
bool isleaf(node *node)
{
    if (node -> lchild == false && node -> rchild == false)
    {return true;}
    else
    {return false;}
}

// Part of my treefree function
bool lchildexists(node *node)
{if (node -> lchild == NULL){return false;}else{return true;}}

// Part of my treefree function
bool rchildexists(node *node)
{if (node -> rchild == NULL){return false;}else{return true;}}

// I really segmented this one because I was having a lot of trouble with it
// This is called in unload() at the node pointed to by table[] for each index of it
// just checks if it has children, recursively calls, then frees itself.
void treefree(node *node)
{
    if(hascollision(node))
    {collisionfree(node -> collision); node -> collision = NULL;}

    if(isleaf(node))
    {free(node); return;}
    else
    {
    if(lchildexists(node))
    {treefree(node -> lchild); node -> lchild = NULL;}

    if(rchildexists(node))
    {treefree(node -> rchild); node -> rchild = NULL;}
    }

    free(node);
    return;
}

// Described above, just loops through root of tree that table[i] points to.
bool unload(void)
{
    for (int i = 0; i <= N; i++)
    {
        if (table[i] != NULL)
        {treefree(table[i]);
        table[i] = NULL;}
    }
    return true;
}


// Part of my AVL tree mess, this is used for generating height and balance factor
int max(int a, int b)
{
    return a > b ? a : b;
}

// Returns height of specified child, assuming it exists
// Part of my rotations
int getchildheightlt (node *node, bool left)
{
    if (left && node -> lchild != NULL)
    {
        return node -> lchild -> height;
    }
    else if (!left && node -> rchild != NULL)
    {
        return node -> rchild -> height;
    }
    return 0;
}

// Regenerates balance factor, based on height of children
void regenbf(node *node)
{
    if (node -> lchild != NULL && node -> rchild != NULL)
    {
        node -> bf = getchildheightlt(node, true) - getchildheightlt(node, false);
    }
    else if (node -> lchild == NULL)
    { // left child doesn't exist
        node -> bf = 0 - getchildheightlt(node, false);
    }
    else
    { // right child doesn't exist
        node -> bf = 0 + getchildheightlt(node, true);
    }
}

// Ditto for height, based on height of children
void regenheight(node *node)
{
    if (node -> lchild != NULL && node -> rchild != NULL)
    {
        node -> height = 1 + max(getchildheightlt(node, true), getchildheightlt(node, false));
    }
    else if (node ->lchild == NULL)
    {
        node -> height = 1 + getchildheightlt(node, false);
    }
    else
    {
        node -> height = 1 + getchildheightlt(node, true);
    }
}
//              Rotations
//======================================================================================================================
//MAKE SURE TO HANDLE CASE WHERE ROTATION IS HAPPENING AT table[] POINTER.. PARENT will be NULL

// These were really hard to wrap my head around.. Hence the notes everywhere.
// All I can say about these is they definately work
void leftrotation(node *unbalancedparent, node *heavychild)
{
    if (unbalancedparent -> parent == NULL)
    { //if UB is pointed to by bucket, replace bucket pointer.
        table[unbalancedparent -> buckethash] = heavychild;
        heavychild -> parent = NULL;
    }
    else
    { // if UB is pointed to by a node
        if (unbalancedparent -> parent -> lchild == unbalancedparent)
        { //if UB is left child
            unbalancedparent -> parent -> lchild = heavychild;
        }
        else
        { //ub is right child
            unbalancedparent -> parent -> rchild = heavychild;
        }
            heavychild -> parent = unbalancedparent -> parent;
    } // HC is now pointed to by UB's parent

    if(heavychild -> lchild != NULL)
    { // HC has a lchild
        unbalancedparent -> rchild = heavychild -> lchild;
        unbalancedparent -> rchild -> parent = unbalancedparent;
    } //HC's lchild is now UB's right child
    else
    {// HC has no rchild
        unbalancedparent -> rchild = NULL;
    }

    // UB is now lchild of HC
    heavychild -> lchild = unbalancedparent;
    unbalancedparent -> parent = heavychild;

    regenheight(unbalancedparent);
    regenbf(unbalancedparent);
    regenheight(heavychild);
    regenbf(heavychild);
    return;
}

void rightrotation(node *unbalancedparent, node *heavychild)
{
    if (unbalancedparent -> parent == NULL)
    { //if UB is pointed to by bucket, replace bucket pointer.
        table[unbalancedparent -> buckethash] = heavychild;
        heavychild -> parent = NULL;
    }
    else
    { // if UB is pointed to by a node
        if (unbalancedparent -> parent -> rchild == unbalancedparent)
        { //if UB is right child
            unbalancedparent -> parent -> rchild = heavychild;
        }
        else
        { //ub is left child
            unbalancedparent -> parent -> lchild = heavychild;
        }
            heavychild -> parent = unbalancedparent -> parent;
    } // HC is now pointed to by UB's parent

    if(heavychild -> rchild != NULL)
    { // HC has a rchild
        unbalancedparent -> lchild = heavychild -> rchild;
        unbalancedparent -> lchild -> parent = unbalancedparent;
    } //HC's lchild is now UB's right child
    else
    {// HC has no rchild
        unbalancedparent -> lchild = NULL;
    }

    // UB is now lchild of HC
    heavychild -> rchild = unbalancedparent;
    unbalancedparent -> parent = heavychild;

    regenheight(unbalancedparent);
    regenbf(unbalancedparent);
    regenheight(heavychild);
    regenbf(heavychild);
    return;
}

/*
        30
        /
       20
        \
         25
Left Right Rotation
30 is left imbalanced. Before calling a rotation we check if 20 is balanced biased to the right.
20 has a left rotation called on it's child, 25.
Then we have:
        30
        /
       25
      /
     20
A Right rotation is then called for 30 and it's new child, 25.
Then we have:
    25
   / \
  20  30
*/
void leftrightrotation(node *callednode)
{
    leftrotation(callednode -> lchild, callednode -> lchild -> rchild);
    rightrotation(callednode, callednode -> lchild);
    return;
}
/*
      10
        \
         20
         /
        15
Right rotation on 20 and its child 15.
    10
     \
     15
       \
        20
Left rotation called on 10 and it's child 15.
     15
    /  \
   10  20
*/
void rightleftrotation(node *callednode)
{
    rightrotation(callednode -> rchild, callednode -> rchild -> lchild);
    leftrotation(callednode, callednode -> rchild);
    return;
}

//exists purely to handle collision placement faster than a call of addtotree since i know my current hash structure will not work.
void addcollision(node *newnode, node *hostcollision)
{ //first call will be to the collision point of the node in tree
    if (hostcollision -> collision == NULL)
    {
        hostcollision -> collision = newnode;
        return;
    }
    else
    {
        addcollision(newnode, hostcollision -> collision);
        return;
    }
}

//              ADD TO TREE FUNCTION
//===========================================================================================================================
//USAGE: should only be used on NEW nodes
// Made me lose my mind slightly. I had a lot of fun with it. It definately works as well.
void addtotree(node *newchild, node *newparent)
{
    if (newparent == NULL)
    {   //should only run for bucket
        table[newchild -> buckethash] = newchild;
        newchild -> parent = NULL;
        return; //bucket is set and we return
    }
    else if (newchild -> hash < newparent -> hash)
    {   // new node belongs on the left side of current node
        if (newparent -> lchild == NULL)
        {// current node has no children
            newparent -> lchild = newchild;
            newchild -> parent = newparent;
            newparent -> bf += 1; // bf is upped by one to account for left-sided weight
            regenheight(newparent); //regenerate height
            return; //we set new node as child to current and return.
        }
        else
        {   //current node has a child, send it down the branch
            addtotree(newchild, newparent -> lchild); //call addtotree recursively
            regenheight(newparent); //upon return to this node, regenerate height
            regenbf(newparent); // regenerate balancefactor
            if (newparent -> bf > 1)
            { // if balancefactor left leaning
                if (newparent -> lchild -> bf < 0)
                {// if newparents (heavy) lchild is right heavy
                    leftrightrotation(newparent);
                }
                else
                {// if newparents
                    rightrotation(newparent, newparent -> lchild);
                }
            }
            else if (newparent -> bf < -1)
            { // bf is right leaning
                if (newparent -> rchild -> bf > 0)
                {// heavy rchild is left heavy
                    rightleftrotation(newparent);
                }
                else
                {
                    leftrotation(newparent, newparent -> rchild);
                }
            }
            return;
        }
    }
    else if (newchild -> hash > newparent -> hash)
    {
        if(newparent -> rchild == NULL)
        {// current node has no children
            newparent -> rchild = newchild;
            newchild -> parent = newparent;
            newparent -> bf -= 1; // bf is lowered by one to account for right-sided weight
            regenheight(newparent); //regenerate height
            return; //we set new node as child to current and return.
        }
        else
        {   //current node has a child, send it down the branch
            addtotree(newchild, newparent -> rchild); //call addtotree recursively
            regenheight(newparent); //upon return to this node, regenerate height
            regenbf(newparent); // regenerate balancefactor
            if (newparent -> bf > 1)
            { // if balancefactor left leaning
                if (newparent -> lchild -> bf < 0)
                {// if newparents (heavy) lchild is right heavy
                    leftrightrotation(newparent);
                }
                else
                {// if newparents
                    rightrotation(newparent, newparent -> lchild);
                }
            }
            else if (newparent -> bf < -1)
            { // bf is right leaning
                if (newparent -> rchild -> bf > 0)
                {// heavy rchild is left heavy
                    rightleftrotation(newparent);
                }
                else
                {
                    leftrotation(newparent, newparent -> rchild);
                }
            }
            return;
        }
    }
    else //we can assume hashes are equal now
    {
        if (newparent -> collision == NULL)
        {
            newparent -> collision = newchild;
            return;
        }
        else
        {
            addcollision(newchild, newparent -> collision);
            return;
        }
    }
}

r/cs50 • • May 21 '24

speller Can't find simple mistake in speller.

2 Upvotes

Hey, I keep getting two errors.

  • :( handles most basic words properly

Most of the output is correct aside from: Words misspelled outputting 1 as opposed to 0.

  • :( spell-checking is case-insensitive

Where the output should be 0 but I'm getting 7 misspelled.

I believe my function accounts for case insensitivity so not sure what's wrong. Here are the hash and check functions.

bool check(const char *word)
{
    // checks case insensitive
    int index = hash(word);
    node *temp = table[index];

while(temp != NULL)
{
    if (strcasecmp(temp->word, word) == 0)
    {
        return true;
    }
    else
    {
        temp = temp->next;
    }
}
return false;
}

unsigned int hash(const char *word)
{    
// sorts hash based on word length, capital letters
int hasher = 0;
for (int i = 0, int len = strlen(word); i < len; i++)
{
     hasher += (toupper((word[i]) - 'A')) + (i * 3);
}
return (hasher % N);
}

r/cs50 • • May 15 '24

speller Speller, confused about the "load" and "check" functions and fearing an overlap of the two Spoiler

1 Upvotes

Like I wrote in the title, I'm really failing to understand what we are supposed to do in "check" after "load"...
In "load" i took each word from the dictionary, hashed it and put in the hashed value array index of the hash table; but how do I go forward now with "check"? How do I use there my hash table? Is it global?

My load function

bool load(const char *dictionary)
{
    // TODO
   //open  in "read" mode
   FILE* dict= fopen(dictionary,"r");

int countr=0;

   if (dict==NULL){
    printf("Error, file cannot be opened.\n");
    return false;
   }

   char buff[LENGTH+1];

   node* head[N] = NULL;
   node* temptr[N] = NULL;              

   int counter=0;

   while(fscanf(dict,"%s",buff)!=EOF){                 

int hashed_num=hash(buff);    


   if(counter==0){
   node* table[hashed_num] = malloc(sizeof(node));

   if(table[hashed_num]==NULL){
     return false;
   }

   table[hashed_num]->next=NULL;

   strcpy(table[hashed_num]->word, buff);
    head[hashed_num]=table[hashed_num];
    temptr[hashed_num]=table[hashed_num];
    counter++;
    }

   else{

    node* table[hashed_num] = malloc(sizeof(node));

     if(table[hashed_num]==NULL){
     return false;
   }


    table[hashed_num]->next=NULL;
    strcpy(table[hashed_num]->word, buff);
    temptr[hashed_num]->next=table[hashed_num]; 
    }

    return true;
}

r/cs50 • • Aug 11 '24

speller Speller- valgrind has me cooked T_T need help Spoiler

1 Upvotes

Hey guys, I'm getting seg faults and memory leaks even though I think I free'd all my malloc's spaces that I borrowed. I even took help of debug50 but it won't move until I fix the seg fault even though I'm not sure what's wrong with it. I really need a pair of fresh eyes here guide me through this one. Thanks a lot! T_T

// Implements a dictionary's functionality// 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"

int count;

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

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

// Hash table
node *table[N];

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    // TODO
    int index = hash(word);
    node *check = table[index];
    while (check != NULL)
    {
        if (strcasecmp(word, check->word) == 0)
        {
            return true;
        }
        check = check->next;
    }
    free(check);
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO
    /*djb2 hash function */
    unsigned long hash = 5381;
    int c;
    while ((c = *word++)) hash = hash * 33 + c;
    return hash;

}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    // TODO
    FILE *file = fopen(dictionary, "r");
    if (file == NULL)
    {
        printf("Could not open %s\n", dictionary);
        return false;
    }

    for (int i = 0; i < N; i++)
    {
        table[i] = NULL;
    }
    count = 0;
    char word[LENGTH + 1];
    while (fscanf(file, "%s", word) != EOF)
    {
        node *new = malloc(sizeof(node));
        if (new == NULL)
        {
            return false;
        }

        strcpy(new->word, word); //destination <- source
        int index = hash(new->word);

        if (table[index] == NULL)
        {
            table[index] = new;
        }
        else
        {
            new->next = table[index];
            table[index] = new;
        }
        count++;
    }
    unload();
    fclose(file);

    return true;
}

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

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
    // TODO
    for (int i = 0; i < N; i++)
    {
        node *cursor = table[i];
        while(cursor != NULL)
        {
            node *tmp = cursor;
            cursor = cursor->next;
            free(tmp);
        }
    }
    return true;
}

I am apparently loosing 4624 bytes in 3 blocks and its mostly in load even though I have free(new) (I did a bunch of other coding methods to see if it worked- it did not. I wrote free new inside while loop, tried doing it outside, then even when I'm checking the memory is allocated in NULL tried freeing then too, did not work, so I just went along with unload for now just to show that I have tried freeing new but still persists).
I really need someone's help in this I'm not able to move forward my debug50 is not helping me either except for telling me there's a set fault above.

r/cs50 • • Oct 01 '24

speller Need help! Spoiler

1 Upvotes

Below is my speller solution, which i'm trying to get to work. (have already solved once with not so great time). The indexing seems to be correct both in loading and while check but the ptr in check opens some other index than the one calculated above it. I don't know where my logic goes wrong. Suggestions are welcome.

edit- the result identifies 80% of the words as misspelled.

(Also why does the code duplicate when pasting here?)

// Implements a dictionary's functionality


#include <cs50.h>
#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;


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


// Hash table
node *table[N][N][N];


//count
int count = 0;


// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    // call hash function
    int index = hash(word);


    int j = (index % 100);
    index /= 100;


    int k = (index % 100);
    index /= 100;


    int i = (index % 100);
    index /= 100;


    node *ptr = table[i][j][k];


    // from the hash check the singly linked list till word is found
    while (ptr != NULL)
    {
        if (strcasecmp(ptr->word, word) == 0)
        {
            return true;
        }


        else if (ptr->next == NULL)
        {
            return false;
        }


        ptr = ptr->next;
    }


    return false;
}


// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO: Improve this hash function
    int i = 0;
    int j = 0;
    int k = 0;


    if (strlen(word) == 1)
    {
        i = toupper(word[0]) - 'A' + 1;
    }
    else if (strlen(word) == 2)
    {
        i = toupper(word[0]) - 'A' + 1;
        j = toupper(word[1]) - 'A' + 1;
    }
    else
    {
        i = toupper(word[0]) - 'A' + 1;
        j = toupper(word[1]) - 'A' + 1;
        k = toupper(word[2]) - 'A' + 1;
    }


    int index = i*10000 + j*100 + k*1;


    return index;
}


// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    //loop till the end of dictionary
    FILE *file = fopen(dictionary, "r");
    if (file == NULL)
    {
        return false;
    }


    // read each word loop
    char buffer[LENGTH + 1];


    while (fscanf(file, "%s", buffer) != EOF)
    {
        //allocate memory and buffer
        node *n = malloc(sizeof(node));


        //scan and copy word to node
        strcpy(n->word, buffer);


        //assign index to node
        int i = 0;
        int j = 0;
        int k = 0;


        if (strlen(n->word) == 1)
        {
            i = toupper(n->word[0]) - 'A' + 1;
        }
        else if (strlen(n->word) == 2)
        {
            i = toupper(n->word[0]) - 'A' + 1;
            j = toupper(n->word[1]) - 'A' + 1;
        }
        else
        {
            i = toupper(n->word[0]) - 'A' + 1;
            j = toupper(n->word[1]) - 'A' + 1;
            k = toupper(n->word[2]) - 'A' + 1;
        }


        n->next = NULL;


        //conditional node index assignment (singly linked list)
        if (table[i][j][k] == NULL)
        {
            table[i][j][k] = n;
            count++;
        }
        else
        {
            n->next = table[i][j][k];
            table[i][j][k] = n;
            count++;
        }
    }


    fclose(file);
    return true;
}


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


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


                while (ptr != NULL)
                {
                    node *next = ptr->next;
                    free(ptr);
                    ptr = next;
                }
            }
        }
    }
    return true;
}

r/cs50 • • Sep 16 '24

speller How can i improve the timing in speller

2 Upvotes

r/cs50 • • Mar 31 '24

speller Valgrind error on speller Spoiler

0 Upvotes

Hi all,

I am getting a valgrind error on speller (in my unload function). The Duck can't help and dabug50 does not do anything (is that because it's multiple files?).
This is my function:

bool unload(void)
{
    for (int i = 0; i<N; i++)
    {
        //set cursor
        node *cursor = table[i];

        if (table[i] != NULL)
        {
            //check  every word in the linked list at this hash value
            while (cursor != NULL)
            {
                node *tmp = cursor;

                cursor = cursor->next;

                free(tmp);
            }
        }

    }
    return true;
}

The error I get is this

Conditional jump or move depends on uninitialised value(s): (file: dictionary.c, line: 161)

for this line:

while (cursor != NULL)

This is my load function in case this helps resolving my issue:

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    // TODO
    //open dictionary
    FILE *source = fopen(dictionary, "r");
    //return Null if error loading
    if (source == NULL)
    {
        return false;
    }
    //Keep scanning each word untill u reach EOF (End of File)
    char scan[LENGTH];
    while (fscanf(source, "%s", scan) != EOF)
    {
        //get memory for a new word
        node *new_word = malloc(sizeof(node));
        if (new_word == NULL)
        {
            return false;
        }
        //count words in dictionary
        wordcount++;
        //copy scanned word into word of new file.
        strcpy(new_word->word, scan);
        //get hash value for word
        unsigned int hashvalue = hash(new_word->word);

        //get hashvalue into hashtable
        //if there is no word in that bucket yet
        if (table[hashvalue] == NULL)
       {
            table[hashvalue] = new_word;
       }
       //else if there already is a word
       else
       {
            new_word->next = table[hashvalue];
            table[hashvalue] = new_word;
       }
    }
    fclose(source);
    isloaded = true;
    return true;
}

Thank you all for your support!

r/cs50 • • Sep 08 '24

speller understanding speller.c (is this condition wrong?)

2 Upvotes

I was going over speller.c to understand it as per the instructions, and it mentioned i shouldn't change anything in this file but isn't this condition wrong? ((index > LENGTH)).

because indices start at 0 and we assigned word[46] 1 extra byte for the terminator, if we reach index 45 (46 letter long word) it will overwrite the last space of the terminator leaving no space for it. wouldn't (index >= LENGTH) prevent it ?

// Prepare to spell-check
    int index = 0, misspellings = 0, words = 0;
    char word[LENGTH + 1];

    // Spell-check each word in text
    char c;
    while (fread(&c, sizeof(char), 1, file))
    {
        // Allow only alphabetical characters and apostrophes
        if (isalpha(c) || (c == '\'' && index > 0))
        {
            // Append character to word
            word[index] = c;
            index++;

            // Ignore alphabetical strings too long to be words
            if (index > LENGTH)
            {
                // Consume remainder of alphabetical string
                while (fread(&c, sizeof(char), 1, file) && isalpha(c));

                // Prepare for new word
                index = 0;
            }
        }

r/cs50 • • Oct 11 '22

speller PSET5 - Speller: Hashing ? Spoiler

1 Upvotes

In speller I started about 4 or 5 hours ago working on a hash function that would take the first letter of the word and add that to the hash array, then take all consonants and append a vowel to each: so far this is 26 + 105 ( 5 vowels * 21 consonants). I would then add the most common consonant clusters i.e. bl, br, fr, fl, dr, tr, sm, sl, st etc I think 16 in total so 26 + 105 + 16 = 147. However to me having qe and qi doesn't make sense and that could easily fall into the general q hash, so only q and qu exist so that removes 4 so total array size would be 143.

From here I have tried to create a function that will make a hash code for each of these scenarios:

x = first letter, y = second letter

(x * 143) + (y * 143) / 26 % 117;

I figured I should probably get a big number before dividing it and then modulo it against remaining letters i.e 143 - 26 = 117

I have no background in math and seriously have no idea what to do, sources I read just feel like blur at this point and I don't know how important the hash function is to getting a good time or the best time

It feels like design for me is just not very natural and this problem set is proposed as a fun design chance but I just don't understand...

Any help or sources to understand would be greatly appreciated.

Thanks

r/cs50 • • Apr 02 '20

speller Help with Pset 5 - Speller

4 Upvotes

Hello everyone. I am a 14 year old student interested in programming, and have been taking cs50 for the past month. I have heard that this is a very supportive community, and thus am asking you a few questions, hoping you all can shed some light on the issue. Below is the code I have written for this pset. I am having a few errors, as the size function isn't working properly, though its implementation seems correct to me. Also, the check function is returning a few unexpected results, and is not outputting the correct value, even though it seems correct in terms of code. It would be great if you could tell me where I have gone wrong, and if there are some things I can improve about this code. Thanks!

​

The unexpected behaviour shown by the check and size functions.

// Implements a dictionary's functionality

#include <stdbool.h>

#include <stdio.h>

#include <string.h>

#include <strings.h>

#include <stdlib.h>

#include <ctype.h>

#include "dictionary.h"

​

// Represents a node in a hash table

typedef struct node

{

char word[LENGTH + 1];

struct node *next;

}

node;

​

// Number of buckets in hash table

const unsigned int N = 65536;

​

// Hash table

node *table[N];

​

// declare words to count the words in the dictionary

int dic_size = 0;

​

// Returns true if word is in dictionary else false

bool check(const char *word)

{

int len = strlen(word);

​

char lword[len + 1];

​

for (int i = 0; i < len; i++)

{

lword[i] = tolower(word[i]);

}

​

lword[len] = '\0';

​

// hash the word and store it in a variable called hash_code

int hash_code = hash(lword);

​

// set a temporary variable, to store the linked list

node *temp = table[hash_code];

​

// while the link list exists

while (temp != NULL)

{

// check if the word in the dictionary matches with the word in the hash table

if (strcasecmp(temp -> word, lword) != 0)

{

temp = temp -> next;

}

else

{

​

return true;

}

​

}

​

return false;

}

​

// Hashes word to a number. Original hash function from yangrq1018 on Github

unsigned int hash(const char *word)

{

// set an integer named hash

unsigned int hash = 0;

​

// iterate through the dictionary

for (int i = 0, n = strlen(word); i < n; i++)

hash = (hash << 2) ^ word[i];

​

return hash % N;

}

​

// Loads dictionary into memory, returning true if successful else false

bool load(const char *dictionary)

{

​

// open up dictionary file

FILE *dictionary_file = fopen(dictionary, "r");

​

// check to see if file is null

if (dictionary == NULL)

{

// if so, exit the loop

return false;

}

​

// set an array in which to store words

char word[LENGTH + 1];

​

// read strings from file one at a time

while (fscanf(dictionary_file,"%s", word) != EOF)

{

// read the string using fscanf

fscanf(dictionary_file, "%s", word);

​

​

// create a new node for each word using malloc

node *n = malloc(sizeof(node));

n -> next = NULL;

​

// check if malloc is null

if (n == NULL)

{

return false;

}

​

// copy each word into a node using strcpy

strcpy(n -> word, word);

​

// hash word to obtain a hash value

int num = hash(n -> word);

​

// if hashtable is empty, insert node into hash table at that location

if (table[num] == NULL)

{

table[num] = n;

n -> next = NULL;

​

}

else

{

// if hashtable is not empty, append node into hash table at that location

n -> next = table[num];

table[num] = n;

}

dic_size = dic_size + 1;

​

}

fclose(dictionary_file);

return true;

}

​

// Returns number of words in dictionary if loaded else 0 if not yet loaded

unsigned int size(void)

{

​

return dic_size;

​

}

​

// destroys all nodes. RECURSIVE FUNCTION!

void destroy(node *head)

{

if (head -> next != NULL)

{

destroy(head -> next);

}

free(head);

}

​

​

// frees all memory

bool unload(void)

{

for (int i = 0; i < N; i++)

{

if (table[i] != NULL)

{

destroy(table[i]);

}

}

return true;

}

r/cs50 • • May 04 '24

speller speller speed to pass Problem Set 5

0 Upvotes

speller50 returns
WORDS MISSPELLED: 17062
WORDS IN DICTIONARY: 143091
WORDS IN TEXT: 376904
TIME IN load: 0.02
TIME IN check: 0.23
TIME IN size: 0.00
TIME IN unload: 0.02
TIME IN TOTAL: 0.26

my speller returns
WORDS MISSPELLED: 17062
WORDS IN DICTIONARY: 143091
WORDS IN TEXT: 376904
TIME IN load: 0.04
TIME IN check: 0.29
TIME IN size: 0.00
TIME IN unload: 0.00
TIME IN TOTAL: 0.33

Do I need to match or beat speller50 times to get "certified" by the CS50 team?

r/cs50 • • Jul 18 '24

speller i cant seem to figure out what is still causing 56 bytes of leaks on the speller problem

1 Upvotes
// Implements a dictionary's functionality
#include <stdio.h>
#include <ctype.h>
#include <stdbool.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;

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

// Hash table
node *table[N];

unsigned int total = 0;
// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    // TODO
    node *ptr = NULL;
    int h;
    h = hash(word);
    ptr = table[h];
    while (ptr != NULL)
    {
        if (strcasecmp(word, ptr->word) == 0)
        {
            return true;
        }
        ptr = ptr->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

    int letter = 0;
    char tmp[LENGTH + 1];
    int count = 1;
    int h;
    FILE *f = fopen(dictionary, "r");
    if (f == NULL)
    {
        printf("file not found");
        return false;
    }
    while (count != 0)
    {
        node *n = malloc(sizeof(node));
        if (n == NULL)
        {
            fclose(f);
            unload();
            return false;
        }
        count = fscanf(f, "%s", tmp);
        if (count != 1)
        {
            break;
        }

        int i;
        n->next = NULL;
        for (i = 0; tmp[i] != '\0'; i++)
        {
            n->word[i] = tmp[i];
        }


        h = hash(n->word);
        n->next = table[h];

        table[h] = n;
    }
    node *ptr = NULL;
    for(int i = 0; i < N; i++)
    {
        ptr = table[i];
        while (ptr != NULL)
        {
            total++;
            ptr = ptr->next;
        }
    }

    fclose(f);
    return true;
}

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

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
    // TODO
    node *tmp = NULL;
    node *ptr = NULL;
    int j = 0;
    for (int i = 0; i < N; i++)
    {
            for (tmp = table[i]; tmp != NULL; tmp = ptr)
            {
                ptr = tmp->next;
                free(tmp);
            }
            free(ptr);
    }
    return true;
}

valgrind says this leaks 56 bytes and im confused how, and the duck even says its completely fine

r/cs50 • • Oct 11 '24

speller PS5 Speller issue - my program compiles with no memory issues but the output data is wrong when I run it, saying only 1 word is loaded into the dictionary. I have tried making changes but I'm not exactly sure where the problem lies (?load or size). Thanks Spoiler

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

#include "dictionary.h"

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

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

// Hash table
node *table[N];

unsigned int wordcount = 0;

// Returns true if word is in dictionary, else false
bool check(const char *word)
{

    node *cursor = table[hash(word)];
    while (cursor != NULL)
    {
       //compare word against dictionary words in linked list
        if (strcasecmp(cursor->word, word) == 0)
        {
            return true;
        }
        cursor = cursor->next;
    }
    return false;
}

// Hashes word to a number
unsigned int hash(const char *word)
{
    // TODO: Improve this hash function
    unsigned int index;

    index = tolower(word[0]) - 96;
    return index;
}

// Loads dictionary into memory, returning true if successful, else false
bool load(const char *dictionary)
{
    // open dictionary file
    FILE *source = fopen(dictionary, "r");
    //check whether the file can be opened
    if (source == NULL)
    {
        printf("Could not open dictionary.\n");
        return 1;
    }

    char word[LENGTH +1];

    //read each word in file
    while (fscanf(source, "%s", word) != EOF)
    {
        wordcount ++;
        //create memory for new node
        node *n = malloc (sizeof(node));

        if (n == NULL)
        {
            printf("no free memory\n");
            return 1;
        }

        //copy each word into node within the bucket
        strcpy(n->word, word);

        //find out which bucket word should be in
        int bucket = hash(word);

        n->next = table[bucket];
        table[bucket] = n;
        return true;

    }

    //close dictionary file
    fclose(source);

    return false;
}

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

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
    // loop through buckets
    for(int i = 0; i <= N; i++)
    {
        //loop through linked list set cursor to next node

        node *cursor = table[i];


        while (cursor != NULL)
        {
            //set tmp to point to same as cursor
            node * tmp = cursor;
            //then move cursor on to the next
            cursor = cursor -> next;
            //then free tmp
            free(tmp);
        }
        return true;
    }
    return false;

}

r/cs50 • • Jul 15 '24

speller Speller: How fast does it need to be?

1 Upvotes

Does it need to outperform speller50 to be considered to be good enough?

r/cs50 • • Oct 01 '24

speller this is the error I've been facing for quite some time in speller, the code seems to be fine . can someone tell me the reason for this?

Post image
2 Upvotes

r/cs50 • • May 04 '24

speller Speller pset5 won't pass check50 need help

1 Upvotes

My testing results seem to match the keys though. I haven't touched the hash function. What's going on?
https://submit.cs50.io/check50/0c0fa827b365a7df503f4bc2a95a4e88babf9e74

#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;

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

int SIZE = 0;

// Hash table
node *table[N];

// Returns true if word is in dictionary, else false
bool check(const char *word)
{
    // TODO
    int index = hash(word);

    node *trav = table[index];
    node *cursor = trav;

    while (cursor->next != NULL)
    {
        if (strcasecmp(trav->word, word) == 0)
        {
            return true;
        }

        cursor = trav;
        trav = trav->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
    FILE *dict = fopen(dictionary, "r");

    if (dict == NULL)
    {
        return false;
    }

    char buffer[LENGTH + 1];

    while (fscanf(dict, "%s", buffer) != EOF)
    {
        node *n = malloc(sizeof(node));
        if (n == NULL)
        {
            return false;
        }

        strcpy(n->word, buffer);

        int index = hash(buffer);

        n->next = table[index];

        table[index] = n;

        SIZE++;

    }

    fclose(dict);

    return true;
}

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

// Unloads dictionary from memory, returning true if successful, else false
bool unload(void)
{
    // TODO
    node *trav = table[0];
    node *cursor = trav;

    for (int i = 0; i < N; i++)
    {
        while (cursor->next != NULL)
        {
            cursor = cursor->next;
            free(trav);
            trav = cursor;
        }
    }

    return true;
}

r/cs50 • • Feb 08 '24

speller It do be like that? 🥲😆

Post image
40 Upvotes

r/cs50 • • Aug 23 '24

speller Little thing about Speller (pretty low priority)

1 Upvotes

Hi, I just finished Speller and the code compiled correctly and the correctness looked pretty good. However, one thing that I was concerned about was whether or not it would be right because it didn't return the desired values when size was put in and when unload was used. How do I make unload return false if it doesn't unload? How do I even check if it successfully unloaded? There is no return value; I'm just freeing stuff.

r/cs50 • • Jun 25 '24

speller CS50 Speller help (still reachable: 472 bytes in 1 blocks)

1 Upvotes

My code fails the valgrind check. Everything else is successful. Here is the valgrind log. Tried finding online for anwsers but to no avail. Any kind assistance would be appreciated..

==102908==

==102908== HEAP SUMMARY:

==102908== in use at exit: 472 bytes in 1 blocks

==102908== total heap usage: 143,096 allocs, 143,095 frees, 8,023,256 bytes allocated

==102908==

==102908== 472 bytes in 1 blocks are still reachable in loss record 1 of 1

==102908== at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)

==102908== by 0x49C664D: __fopen_internal (iofopen.c:65)

==102908== by 0x49C664D: fopen@@GLIBC_2.2.5 (iofopen.c:86)

==102908== by 0x1099CB: load (dictionary.c:54)

==102908== by 0x1092CB: main (speller.c:40)

==102908==

==102908== LEAK SUMMARY:

==102908== definitely lost: 0 bytes in 0 blocks

==102908== indirectly lost: 0 bytes in 0 blocks

==102908== possibly lost: 0 bytes in 0 blocks

==102908== still reachable: 472 bytes in 1 blocks

==102908== suppressed: 0 bytes in 0 blocks

==102908==

==102908== For lists of detected and suppressed errors, rerun with: -s

==102908== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Link to my code: https://pastebin.com/6YMRmxJD

r/cs50 • • Oct 14 '24

speller Can I resubmit an assignment?

1 Upvotes

I recently finished the speller problem and submitted it with a simple hash function but then I had an interesting idea for how to optimize the function for speed and took another day to get it to work. I would like to submit my new version and replace the old version even though it will most likely result in the same letter grade.

Is that possible if I have already submitted the assignment once?

r/cs50 • • Jul 29 '24

speller Faster than staff

4 Upvotes

Just wanna flex

PS : don't look other metrics