std::string Compressor::Compress(Point &point, Dimension &dimension) const {
  assert((dimension.num_rows >= 1) && (dimension.num_columns >= 1));

  if ((dimension.num_rows == 1) && (dimension.num_columns == 1)) {
    return data_.Get(point);
  }

  std::string res;
  auto top_left_dim = dimension.TopLeft();
  res += Compress(point, top_left_dim);

  if (dimension.num_columns > 1) {
    auto top_right_begin = ComputeTopRight(point, top_left_dim);
    auto top_right_dim = dimension.TopRight();
    res += Compress(top_right_begin, top_right_dim);
  }

  if (dimension.num_rows > 1) {
    auto bottom_left_begin = ComputeBottomLeft(point, top_left_dim);
    auto bottom_left_dim = dimension.BottomLeft();
    res += Compress(bottom_left_begin, bottom_left_dim);
  }

  if ((dimension.num_columns > 1) && (dimension.num_rows > 1)) {
    auto bottom_right_begin = ComputeBottomRight(point, top_left_dim);
    auto bottom_right_dim = dimension.BottomRight();
    res += Compress(bottom_right_begin, bottom_right_dim);
  }

  if (AllSame(res)) {
    char data[2]{res[0], '\0'};
    return std::string(data);
  }

  return "D" + res;
}