Skip to main content

Tutorial 1

Problem Set 1 Discussion

We will start by discussing Problem Set 1. Here are some questions that we are going to discuss. Nevertheless, feel free to raise more questions that you want answered!

  1. How do you implement Stack and Queue efficiently?
  2. What changes do you make in the skeleton code?
  3. Where do you put checkRepresentation in your code?
  4. What graph representation did you choose to use?
  5. For the Tree ADT, did you extend your Graph ADT or did you write from scratch?
  6. Discuss your experience with Test Driven Development on implementing your Graph ADT.

Tutorial Questions

  1. Let us create a function in Swift that reads a CSV file and deserialises it into an array of structs. Refactor this code to improve its coding style.

    struct Person {
    let name: String
    let age: Int
    }

    func des(s: String) -> [Person] {
    var people = s.split(separator: "\n")
    var array: [Person] = []
    for p in people {
    let pSplit = p.split(separator: ",")
    array.append(Person(name: String(pSplit[0]), age: Int(pSplit[1])!))
    }

    return array
    }
  2. There are several ways for functions in Swift to indicate that something bad has occured. For example, one can return a special value (e.g. -1), return nil, or throw an exception.

    1. Why and when is one method preferred over the other?
    2. For these scenarios, suggest which method you think should be used.
      1. Parsing JSON function, on receiving invalid input.
      2. A function takes in a file name and outputs the contents of the file. The function receives a file name, but the file does not exist.
      3. Adding an element to a set, but the element already exists in the set.
      4. Passing an unsorted array into a binary search function.
  3. Consider the code snippet below. Identify which comments are useful, and which ones are not so useful.

    /// This function computes the square root of the number passed in.
    /// Uses the Newton-Raphson method, set for 100 stages. It converges
    /// for virtually all possible input.
    ///
    /// - Parameter num: the number to be passed in
    /// - Returns: The square root of the number
    func squareRoot(_ num: Double) -> Double? {
    // Check if num is negative
    if (num < 0) {
    return nil // No square root
    }

    var result: Double = 1 // Initialise to 1
    for _ in 0..<100 { // Run 100 times
    result = (result + num / result) / 2 // One Newton-Raphson step
    }

    return result
    }
  4. Many programming languages have different ways to parse strings to integers. Here are some of them:

    • In Swift, one uses e.g. Int("345"), which returns an Int?
    • In C++, one uses e.g. std::stoi("345")
    • In Ruby, one uses e.g. "345".to_i

    Discuss about these different approaches: when is one preferable than the other? Why did the language designer decide to implement one over the other? If you were to create your own struct and you wish to convert a string to your struct, which one do you prefer?