Programming Fundamentals

Q1

#include <stdio.h>

#define NUM_ROWS 4
#define MAX_COLS 100

// Return the number of rows that add up to 0
int count_neutral_rows(int size, int array[NUM_ROWS][MAX_COLS]) {
    int row = 0;
    int count = 0;
    while (row < NUM_ROWS) {
        int sum = 0;
        int col = 0;
        while (col < size) {
            sum += array[row][col];
            col++;
        }

        if (sum == 0) {
            count++;
        }

        row++;
    }

    return count;
}

// This is a simple main function which could be used
// to test your count_neutral_rows function.
// It will not be marked.
// Only your count_neutral_rows function will be marked.

int main(int argc, char *argv[]) {

    return 0;
}

Q2

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

struct node {
    struct node *next;
    int          data;
};

int product(struct node *head1, struct node *head2);
int member(int i, struct node *head);
struct node *strings_to_list(int len, char *strings[]);

int main(int argc, char *argv[]) {
    // create two linked lists from command line arguments
    int dash_arg = argc - 1;
    while (dash_arg > 0 && strcmp(argv[dash_arg], "-") != 0) {
        dash_arg = dash_arg - 1;
    }
    struct node *head1 = strings_to_list(dash_arg - 1, &argv[1]);
    struct node *head2 = strings_to_list(argc - dash_arg - 1, &argv[dash_arg + 1]);

    int result = product(head1, head2);
    printf("%d\n", result);

    return 0;
}


// product should the sum of the elements in list1 multiplied by
// the corresponding element in list2
// if one list is longer than the other, the extra list elements are ignored
int product(struct node *head1, struct node *head2) {
    int product = 0;
    struct node *curr1 = head1;
    struct node *curr2 = head2;

    while (curr1 != NULL && curr2 != NULL) {
        product += curr1->data * curr2->data;
        curr1 = curr1->next;
        curr2 = curr2->next;
    }

    return product;
}



// create linked list from array of strings
struct node *strings_to_list(int len, char *strings[]) {
    struct node *head = NULL;
    for (int i = len - 1; i >= 0; i = i - 1) {
        struct node *n = malloc(sizeof (struct node));
        assert(n != NULL);
        n->next = head;
        n->data = atoi(strings[i]);
        head = n;
    }
    return head;
}

Q3

#include <stdio.h>

int main(void) {
    int nums[10000];
    int len = 0;
    while (scanf("%d", &nums[len]) == 1 && nums[len] != 0) {
        len++;
    }

    // First, print the even numbers...
    int i = 0;
    while (i < len) {
        printf("%d ", nums[i]);
        i += 2;
    }

    // then, print the odds...
    i = 1;
    while (i < len) {
        printf("%d ", nums[i]);
        i += 2;
    }

    printf("\n");
}

Q4

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

struct node {
    struct node *next;
    int          data;
};

int mixed(struct node *head);
int member(int i, struct node *head);
struct node *strings_to_list(int len, char *strings[]);

int main(int argc, char *argv[]) {
    // create linked list from command line arguments
    struct node *head = strings_to_list(argc - 1, &argv[1]);

    int result = mixed(head);
    printf("%d\n", result);

    return 0;
}

// mixed should return 1 if list contains both even and odd numbers
// mixed should return 0 otherwise
int mixed(struct node *head) {
    struct node *curr = head;
    while (curr != NULL && curr->next != NULL) {
        if (curr->data % 2 != curr->next->data % 2) {
            return 1;
        }
        curr = curr->next;
    }

    return 0;
}


// create linked list from array of strings
struct node *strings_to_list(int len, char *strings[]) {
    struct node *head = NULL;
    for (int i = len - 1; i >= 0; i = i - 1) {
        struct node *n = malloc(sizeof (struct node));
        assert(n != NULL);
        n->next = head;
        n->data = atoi(strings[i]);
        head = n;
    }
    return head;
}

Q5

#include <stdio.h>

#define MAX_LETTERS 100

int main(void) {

    char my_arr[MAX_LETTERS];
    printf("Enter string: ");
    while (fgets(my_arr, MAX_LETTERS, stdin) != NULL) {
        printf("Input received: %s", my_arr);
        printf("Enter string: ");
    }
    return 0;
}

Q6

#include <stdio.h>

#define MAX_SIZE 100

int main(void) {
    int scanned_length;
    int length_count = 0;
    int scanned_value;
    int scanned_num[MAX_SIZE];

    // Prompt user for the specific number of integers to be taken from input
    printf("How many numbers: ");
    scanf("%d", &scanned_length);

    // Take in scanned_length number of integers
    printf("Please enter numbers: ");
    while (length_count < scanned_length) {
        scanf("%d", &scanned_value);
        scanned_num[length_count] = scanned_value;

        length_count++;
    }

    // Iterate over the array and print the minimum and maximum values in the array
    int index = 0;
    if (scanned_length > 0) {
        int minimum = scanned_num[index];
        int maximum = scanned_num[index];

        while (index < scanned_length) {
            if (scanned_num[index] < minimum) {
                minimum = scanned_num[index];
            } else if (scanned_num[index] > maximum) {
                maximum = scanned_num[index];
            }

            index++;
        }

        printf("Minimum: %d\nMaximum: %d\n", minimum, maximum);
    }

    return 0;
}

Q7

#include <stdio.h>

struct time {
    int days;
    int hours;
    int minutes;
};

void increment_time(struct time *current_time);

int main(void) {

    struct time current_time;
    current_time.days = 3;
    current_time.hours = 4;
    current_time.minutes = 59;

    printf("One minute ago: %d days, %d hours and %d minutes\n",
        current_time.days, current_time.hours, current_time.minutes);

    increment_time(&current_time);

    printf("Now: %d days, %d hours and %d minutes\n",
        current_time.days, current_time.hours, current_time.minutes);

    return 0;
}

// increments the time by 1 minute
void increment_time(struct time *current_time) {
    current_time->minutes++;
    if (current_time->minutes == 60) {
        current_time->minutes = 0;
        current_time->hours++;
    }

    if (current_time->hours == 24) {
        current_time->hours = 0;
        current_time->days++;
    }
}

Q8

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

#define MAX_LIST_LEN 100

struct node {
    int         data;
    struct node *next;
};

struct node *delete_last(struct node *head);
void print_list(struct node *head);
struct node *array_to_list(int len, int array[]);

// DO NOT CHANGE THE MAIN FUNCTION
int main(void) {

    // Get list size
    int list_size;
    printf("Total numbers: ");
    scanf(" %d", &list_size);

    // Read in numbers
    int list[MAX_LIST_LEN] = {0};
    int index_count = 0;
    while (index_count < list_size && scanf(" %d", &list[index_count])) {
        index_count++;
    }

    // Create linked list from input numbers
    struct node *head = NULL;
    if (index_count > 0) {
        // List has elements
        head = array_to_list(list_size, list);
    }

    struct node *new_head = delete_last(head);
    print_list(new_head);

    return 0;
}

// Delete the last element from a given linked list
struct node *delete_last(struct node *head) {

    if (head == NULL) {
        return head;
    }

    struct node *prev = NULL;
    struct node *curr = head;

    while (curr->next != NULL) {
        prev = curr;
        curr = curr->next;
    }

    if (prev == NULL) {
        free(curr);
        return NULL;
    }

    prev->next = curr->next;
    free(curr);
    return head;
}

// DO NOT CHANGE THIS FUNCTION
// prints the given linked list
void print_list(struct node *head) {
    struct node *curr = head;
    while (curr != NULL) {
        printf("%d -> ", curr->data);
        curr = curr->next;
    }
    printf("X\n");
}

// DO NOT CHANGE THIS FUNCTION
// create linked list from array of strings
struct node *array_to_list(int len, int array[]) {
    struct node *head = NULL;
    int i = len - 1;
    while (i >= 0) {
        struct node *n = malloc(sizeof (struct node));
        assert(n != NULL);
        n->next = head;
        n->data = array[i];
        head = n;
        i -= 1;
    }
    return head;
}

Q9

#include <stdio.h>
#include <ctype.h>
#include <assert.h>
int main(int argc, char *argv[]) {
    int both_lines = 0;
    int letter_count[26] = {0};
    char line1[1024];
    char line2[1024];
    assert(fgets(line1, sizeof line1, stdin));
    assert(fgets(line2, sizeof line2, stdin));
    for (int i = 0; line1[i]; i++) {
        if (isalpha(line1[i])) {
            letter_count[tolower(line1[i]) - 'a']++;
        }
    }
    for (int i = 0; line2[i]; i++) {
        if (isalpha(line2[i])) {
            int index = tolower(line2[i]) - 'a';
            if (letter_count[index]) {
                both_lines++;
                letter_count[index] = 0;
            }
        }
    }
    printf("%d\n", both_lines);
    return 0;
}

Q10

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <stdbool.h>

#define MAX_LEN 4096

struct card {
    int num;
    struct card *next;
};

struct card *deck_read(int player_num);
void print_deck(struct card *deck);

int main(void) {
    struct card *player1 = deck_read(1);
    struct card *player2 = deck_read(2);
    struct card *pile = NULL;

    struct card *curr = player1;
    bool has_snapped = false;
    while (player1 && player2 && !has_snapped) {

        struct card *popped = curr;
        if (curr == player1) {
            player1 = player1->next;
            curr = player2;
        } else {
            player2 = player2->next;
            curr = player1;
        }
        popped->next = pile;
        pile = popped;

        if (pile && pile->next && pile->num == pile->next->num) {
            printf("Snap! Matched card %d\n", pile->num);
            has_snapped = true;
        }
    }
    if (!has_snapped) {
        if (!player1) {
            printf("Player 2 has won!\n");
        } else if (!player2) {
            printf("Player 1 has won!\n");
        }
    }
    printf("Player 1's deck: ");
    print_deck(player1);
    printf("Player 2's deck: ");
    print_deck(player2);
    printf("Pile: ");
    print_deck(pile);

    return 0;
}

void print_deck(struct card *deck) {
    while (deck != NULL) {
        printf("%d -> ", deck->num);
        deck = deck->next;
    }
    printf("X\n");
}

// Function to create a deck for the specified player.
// Returns a pointer to the top card in the deck.
struct card *deck_read(int player_num) {
    int num;
    printf("Enter Player %d's deck values:\n", player_num);
    struct card *head = NULL;
    struct card *tail = NULL;
    while (scanf("%d", &num) == 1) {
        if (num == -1) break;
        struct card *new_card = malloc(sizeof(struct card));
        new_card->num = num;
        new_card->next = NULL;
        if (head == NULL) {
            head = tail = new_card;
        } else {
            tail = tail->next = new_card;
        }
    }
    return head;
}

Q11

#include <stdio.h>
#include <stdlib.h>

#define MAXDIGITS 1500

typedef struct bignum {
    char digits[MAXDIGITS];
} bignum;

void
add(bignum *op0, bignum *op1, bignum *op2, bignum *result) {
    int i, carry = 0;
    for (i = 0; i < MAXDIGITS; i++) {
        int sum = op0->digits[i] + op1->digits[i] + op2->digits[i] + carry;
        result->digits[i] = sum % 10;
        carry = sum / 10;
    }
    if (carry > 0) {
        printf("Overflow\n");
        exit(1);
    }

}

void
print(bignum *b) {
    int i;
    for (i = MAXDIGITS - 1; i > 0 && b->digits[i] == 0; i--)
        ;
    for (; i >= 0; i--) {
        printf("%d", b->digits[i]);
    }
    printf("\n");
}

int
main(int argc, char *argv[]) {
    bignum x0 = {{1}}, x1 = {{1}}, x2 = {{1}}, x3 = {{1}};
    for (int i = atoi(argv[1]); i > 0; i--) {
        x0 = x1;
        x1 = x2;
        x2 = x3;
        add(&x0, &x1, &x2, &x3);
    }
    print(&x0);
    return 0;
}