input: Write a function to implement a Matrix class in Python that can perform various matrix operations like addition, subtraction, multiplication, and transpose. The class should be initialized with the number of rows, columns, and a list of elements for the matrix. The class should also have methods for each operation and a method to print the matrix.
  assert Matrix(2, 2, [1, 2, 3, 4]).add(Matrix(2, 2, [5, 6, 7, 8])).__str__()=="6 8 \n10 12 \n"
  assert Matrix(2, 2, [1, 2, 3, 4]).sub(Matrix(2, 2, [1, 1, 1, 1])).__str__()=="0 1 \n2 3 \n"
  assert Matrix(2, 2, [1, 2, 3, 4]).mul(Matrix(2, 2, [5, 6, 7, 8])).__str__()=="19 22 \n43 50 \n"
  assert Matrix(2, 2, [1, 2, 3, 4]).transpose().__str__()=="1 3 \n2 4 \n"
output: class Matrix:
      def __init__(self, rows, cols, elements):
          self.rows = rows
          self.cols = cols
          self.elements = elements
  
      def add(self, other):
          if self.rows != other.rows or self.cols != other.cols:
              raise ValueError("Matrices must have the same dimensions for addition")
          result_elements = [self.elements[i] + other.elements[i] for i in range(len(self.elements))]
          return Matrix(self.rows, self.cols, result_elements)
  
      def sub(self, other):
          if self.rows != other.rows or self.cols != other.cols:
              raise ValueError("Matrices must have the same dimensions for subtraction")
          result_elements = [self.elements[i] - other.elements[i] for i in range(len(self.elements))]
          return Matrix(self.rows, self.cols, result_elements)
  
      def mul(self, other):
          if self.cols != other.rows:
              raise ValueError("Number of columns in the first matrix must be equal to the number of rows in the second matrix")
          result_elements = []
          for i in range(self.rows):
              for j in range(other.cols):
                  sum = 0
                  for k in range(self.cols):
                      sum += self.elements[i * self.cols + k] * other.elements[k * other.cols + j]
                  result_elements.append(sum)
          return Matrix(self.rows, other.cols, result_elements)
  
      def transpose(self):
          result_elements = []
          for j in range(self.cols):
              for i in range(self.rows):
                  result_elements.append(self.elements[i * self.cols + j])
          return Matrix(self.cols, self.rows, result_elements)
  
      def __str__(self):
          result = ""
          for i in range(self.rows):
              for j in range(self.cols):
                  result += str(self.elements[i * self.cols + j]) + " "
              result += "\n"
          return result