CS1010 Notes
  • Welcome
  • Lec/Tut/Lab/Exes
    • Lecture
      • Lec 01 - Computational Problem Solving
      • Lec 02 - Functions and Types
      • Lec 03 - Basic C Programming
      • Lec 04 - Conditionals
      • Lec 05 - Loops
      • Lec 06 - Call Stacks, Arrays
        • Diagnostic Quiz
      • Lec 07 - Pointers, Memory management
        • Diagnostic Quiz
      • Lec 08 - Multi-d Array, Efficiency
        • Diagnostic Quiz
      • Lec 09 - Searching and Sorting
        • Diagnostic Quiz
      • Lec 10 - More Recursion
        • Diagnostic Quiz
      • Lec 11 - Strcut & Standard I/O
        • Diagnostic Quiz
      • Lec 12 - Recap
    • Tutorial
      • Tut 01 - Computational Problem-Solving
      • Tut 02 - Functions and Conditionals
      • Tut 03 - More on Conditionals
      • Tut 04 - Loops
      • Tut 08 - Searching and Sorting
    • Lab
      • Lab 01 - Unix/Vim Setup
      • Lab 02 - Debugging
      • Lab 03 - Assert
      • Lab 04 - Test Cases
      • Lab 05 - Arrays
      • Lab 06 - Memory Errors
      • Lab 07 - Compiling with Clang
      • Lab 08 - C Preprocessor
      • Lab 09 - Backtracking
      • Lab 10 - Struct and Wrap up
    • Exercises
      • Exercise 3 - Fixed-Length Arrays
      • Exercise 4 - Dynamic Arrays and Strings
      • Exercise 6 - Searching and Sorting
      • Exercise 7 - More Recursion
      • Exercise 8 - Struct
  • Past Year Exam
    • Midterm PE
      • PE1 (AY18/19)
      • PE1 (AY20/21)
      • PE1 (AY21/22)
      • PE0 (AY22/23)
      • PE0 (AY23/24)
    • Midterm Paper
      • Midterm (AY18/19)
      • Midterm (AY20/21)
      • Midterm (AY21/22)
      • Midterm (AY22/23)
    • PE1 Review
      • PE1 (AY23/24)
    • PE2 Review
      • PE2 (AY18/19)
      • PE2 (AY20/21)
      • PE2 (AY21/22)
      • PE2 (AY22/23)
      • PE2 (AY23/24)
    • Final Paper
      • Final (AY18/19)
      • Final (AY20/21)
      • Final (AY21/22)
      • Final (AY22/23)
      • Final (AY23/24)
  • Current Year Exam
    • PE0 (AY24/25)
    • PE1 (AY24/25)
    • PE2 (AY24/25)
    • Final (AY24/25)
  • Toolbox
    • Vim & Unix
    • GDB
  • After CS1010
Powered by GitBook
On this page
  • Problems
  • 1. Mirror
  • 2. Nigh
  • 3. Alternate
  • 4. Grammar
  • 5. Pirate
Edit on GitHub
  1. Past Year Exam
  2. PE1 Review

PE1 (AY23/24)

PreviousPE1 ReviewNextPE2 Review

Last updated 7 months ago

Problems

1. Mirror

My solution is to use .

#include "cs1010.h"

int main()
{
  size_t n = cs1010_read_size_t();
  char **left_half = cs1010_read_word_array(n);
  if (left_half == NULL)
  {
    return 1;
  }
  for (size_t i = 0; i < n; i += 1)
  {
    char *temp = left_half[i];
    long length = 0;
    while (*temp != '\0')
    {
      putchar(*temp);
      length += 1;
      temp += 1;
    }
    for (long j = length - 1; j >= 0; j -= 1)
    {
      putchar(left_half[i][j]);
    }
    cs1010_println_string("");
  }
  for (size_t i = 0; i < n; i += 1)
  {
    free(left_half[i]);
  }
  free(left_half);
}

2. Nigh

3. Alternate

This question teaches us an important point: when traversing from end to the start of a string, it is always recommended to cast the loop index to be long! Since size_t will always be 0 and we still need to zero index element, so it will be hard for us to define when to stop!

After reading the comments, I feel like my solution is a bit more elegant.

char *alternate(const char *w1, const char *w2)
{
  size_t len1 = length_of(w1);
  size_t len2 = length_of(w2);
  char *new_word = calloc(len1 + len2 + 1, sizeof(char));
  long temp1 = (long)len1 - 1;
  long temp2 = (long)len2 - 1;
  bool at_w2 = true;
  bool change_di = true;
  for (long i = (long)len1 + (long)len2 - 1; i >= 0; i -= 1)
  {
    if (temp1 == -1 || temp2 == -1)
    {
      change_di = false;
    }
    if (at_w2)
    {
      new_word[i] = w2[temp2];
      if (temp2 >= 0)
      {
        temp2 -= 1;
      }
    }
    else
    {
      new_word[i] = w1[temp1];
      if (temp1 > 0)
      {
        temp1 -= 1;
      }
    }
    if (change_di)
    {
      at_w2 = !at_w2;
    }
  }
  new_word[len1 + len2 - 1] = '\0';
  return new_word;
}    

4. Grammar

But I use a recursive method when doing this question at the first time

bool grammar_check(size_t start, size_t end, char *word)
{
  if (start == end)
  {
    return step_3(word[start]);
  }
  if (word[start] == '%' && word[end] == '#')
  {
    return grammar_check(start + 1, end - 1, word);
  }
  if (word[start] == '@' && word[start + 1] == '@')
  {
    return grammar_check(start + 2, end, word);
  }
  return false;
}

5. Pirate

  1. For Captains, we notice that the captains are all in the diagonal of the 2-D matrix whose value is not -1 (Suppose I initialise all the elements to -1)

  2. For counting crew numbers, we use the recursive thinking, start from the captain, once we find a crew, treat the crew as a new "captain" and find its crew. Until we have iterated every row in each function call. We are done

After reading the comments, I feel the method using a 2-D array is more elegant.

#include "cs1010.h"

void free_mem(size_t start, size_t end, long **tar)
{
  for (size_t i = start; i < end; i += 1)
  {
    free(tar[i]);
  }
  free(tar);
}

long **init_canva(size_t num)
{
  long **canva = calloc(num, sizeof(long *));
  if (canva == NULL)
  {
    return NULL;
  }
  for (size_t i = 0; i < num; i += 1)
  {
    canva[i] = calloc(num, sizeof(long));
    if (canva[i] == NULL)
    {
      free_mem(0, i, canva);
      return NULL;
    }
  }
  for (size_t i = 0; i < num; i += 1)
  {
    for (size_t j = 0; j < num; j += 1)
    {
      canva[i][j] = -1;
    }
  }
  return canva;
}

void update_super(long *super, long **canva, size_t num)
{
  for (size_t i = 0; i < num; i += 1)
  {
    canva[i][super[i]] = super[i];
  }
}

void count_crew(long captain, size_t num, long **canva, long *count, long *super)
{
  for (size_t i = 0; i < num; i += 1)
  {
    if ((long)i != captain && canva[i][super[i]] == captain)
    {
      *count += 1;
      count_crew((long)i, num, canva, count, super);
    }
  }
}

long count_captains(long **canva, size_t num)
{
  long count = 0;
  for (size_t i = 0; i < num; i += 1)
  {
    if (canva[i][i] != -1)
    {
      count += 1;
    }
  }
  return count;
}

int main()
{
  size_t num = cs1010_read_size_t();
  long *super = cs1010_read_long_array(num);
  long **canva = init_canva(num);
  if (canva == NULL)
  {
    return 1;
  }
  update_super(super, canva, num);
  cs1010_println_long(count_captains(canva, num));
  for (size_t i = 0; i < num; i += 1)
  {
    long count = 0;
    if (canva[i][i] != -1)
    {
      cs1010_print_size_t(i);
      cs1010_print_string(" ");
      count_crew((long)i, num, canva, &count, super);
      cs1010_println_long(count + 1);
    }
  }
  for (size_t i = 0; i < num; i += 1)
  {
    free(canva[i]);
  }
  free(canva);
}

This question reminds us the importance of counting the frequency of each digit in a number, which appears in before.

This is actually a problem.

This problem is similar to

Ex3 Q4
Ex5 Q6
char** cs1010_read_word_array(size_t k)
Sliding Window