#include <cstring>
#include <limits>
#include <climits>
#include <memory>
#include <cassert>
#include <sstream>
#include <random>

class SimpleBitSet {
 SimpleBitSet(const SimpleBitSet &other) = delete;

 SimpleBitSet &operator=(const SimpleBitSet &other) = delete;

 public:
  using IdxType = size_t;
  using UnitType = uint64_t;
  static constexpr IdxType kBitsPerUnit = CHAR_BIT * sizeof(UnitType);
  static constexpr IdxType kBitsNumOfDiv = __builtin_ctz(kBitsPerUnit);
  static constexpr IdxType kBitsPerUnitMinusOne = kBitsPerUnit - 1;
  static_assert((kBitsPerUnit & kBitsPerUnitMinusOne) == 0,
                "Bits per unit must be power of 2");
  static constexpr UnitType kAllZerosUnit = static_cast<UnitType>(0ull);
  static constexpr UnitType kAllOnesUnit = ~kAllZerosUnit;

  static IdxType BitIndex(IdxType pos) {
    return pos & kBitsPerUnitMinusOne;
  }

  static IdxType UnitIndex(IdxType pos) {
    return pos >> kBitsNumOfDiv;
  }

  static UnitType BitMask(IdxType pos) {
    return UnitType(1) << BitIndex(pos);
  }

  static IdxType UnitNum(IdxType bits_num) {
    return (bits_num >> kBitsNumOfDiv) +
           static_cast<IdxType>((bits_num & kBitsPerUnitMinusOne) != 0);
  }

  static IdxType RoundUpBitsNum(IdxType bits_num) {
    return UnitNum(bits_num) * kBitsPerUnit;
  }

  explicit SimpleBitSet(size_t bits_num = 0)
      : bits_num_(bits_num) {
    size_t unit_num = UnitNum();
    if (!DataInStack()) {
      data_.heap_data_ = new UnitType[unit_num];
    }
    Reset(false);
  }

  ~SimpleBitSet() {
    Destory();
  }

  SimpleBitSet(SimpleBitSet &&other)
      : bits_num_(other.bits_num_), data_(other.data_) {
    other.bits_num_ = 0;
  }

  SimpleBitSet &operator=(SimpleBitSet &&other) {
    Destory();
    data_ = other.data_;
    bits_num_ = other.bits_num_;
    other.bits_num_ = 0;
    return *this;
  }

  size_t Size() const { return bits_num_; }

  size_t UnitNum() const { return UnitNum(bits_num_); }

  void Set(size_t pos, bool val) {
    assert(pos < bits_num_);
    if (val) {
      Data()[UnitIndex(pos)] |= BitMask(pos);
    } else {
      Data()[UnitIndex(pos)] &= ~BitMask(pos);
    }
  }

  void Reset(bool val) {
    if (bits_num_ > 0) {
      std::memset(Data(), (val? 0xFF: 0x00), UnitNum() * sizeof(UnitType));
    }
  }

  bool operator[](size_t pos) const {
    return Data()[UnitIndex(pos)] & BitMask(pos);
  }

  bool Test(size_t pos) const { return (*this)[pos]; }

  void MergeOr(const SimpleBitSet &bs, size_t offset) {
    MergeOr(Data() + (offset >> kBitsNumOfDiv), bs.Data(),
            offset & kBitsPerUnitMinusOne, bs.Size());
  }

  void MergeAnd(const SimpleBitSet &bs, size_t offset) {
    MergeAnd(Data() + (offset >> kBitsNumOfDiv), bs.Data(),
             offset & kBitsPerUnitMinusOne, bs.Size());
  }

  void SliceTo(SimpleBitSet *bs, size_t offset) const {
    auto dst = bs->Data();
    auto src = Data() + (offset >> kBitsNumOfDiv);
    offset = offset & kBitsPerUnitMinusOne;
    auto unit_num = bs->UnitNum();
    if (offset == 0) {
      std::copy(src, src + unit_num, dst);
    } else {
      auto r = offset;
      auto l = kBitsPerUnit - r;
      --unit_num;
      for (auto i = 0; i < unit_num; ++i) {
        dst[i] = (src[i] >> r) | (src[i + 1] << l);
      }
      auto remain_bits = bs->Size() & kBitsPerUnitMinusOne;
      if (remain_bits <= l) {
        dst[unit_num] = src[unit_num] >> r;
      } else {
        dst[unit_num] = (src[unit_num] >> r) | (src[unit_num + 1] << l);
      }
    }
  }

  size_t Count() const { return CountUntil(Size()); }

  size_t CountUntil(size_t until_cursor) const {
    size_t unit_until = UnitNum(until_cursor);
    size_t bit_count = 0u;
    const auto *data = Data();
    for (auto i = 0u; i < unit_until; ++i) {
      bit_count += __builtin_popcountll(data[i]);
    }
    size_t tail_bit = until_cursor & kBitsPerUnitMinusOne;
    if (tail_bit > 0u) {
      bit_count -= __builtin_popcountll(data[unit_until - 1] >> tail_bit);
    }
    return bit_count;
  }

  std::string ToString() const {
    std::ostringstream oss;
    for (IdxType i = 0u; i < bits_num_; ++i) {
      oss << std::to_string((*this)[i]);
    }
    return oss.str();
  }

  void RandomInit() {
    std::random_device rd;
    std::mt19937_64 gen(rd());
    std::uniform_int_distribution<uint64_t> distribution;
    for (IdxType i = 0u; i < UnitNum(); ++i) {
      Data()[i] = distribution(gen);
    }
  }

 private:
  static void MergeOr(UnitType *dst, const UnitType *src, IdxType offset,
                      IdxType bits_num) {
    if (bits_num <= kBitsPerUnit - offset) {
      UnitType mask = kAllOnesUnit >> (kBitsPerUnit - bits_num);
      dst[0] |= (src[0] & mask) << offset;
    } else {
      dst[0] |= src[0] << offset;
      IdxType remain_bits = bits_num - (kBitsPerUnit - offset);
      IdxType unit_num = UnitNum(remain_bits);
      UnitType mask =
          !(remain_bits & kBitsPerUnitMinusOne)
              ? kAllOnesUnit
              : kAllOnesUnit >>
                    (kBitsPerUnit - (remain_bits & kBitsPerUnitMinusOne));
      if (unit_num == 1u) {
        dst[1u] |= offset == 0u ? (src[1u] & mask)
                                : (((src[0u] >> (kBitsPerUnit - offset)) |
                                    (src[1u] << offset)) &
                                   mask);
      } else if (!!offset) {
        IdxType l = offset, r = kBitsPerUnit - l;
        for (IdxType i = 1u; i < unit_num; ++i) {
          dst[i] |= (src[i - 1] >> r) | (src[i] << l);
        }
        dst[unit_num] |=
            ((src[unit_num - 1] >> r) | (src[unit_num] << l)) & mask;
      } else {
        for (IdxType i = 1u; i < unit_num; ++i) {
          dst[i] |= src[i];
        }
        dst[unit_num] |= src[unit_num] & mask;
      }
    }
  }

  static void MergeAnd(UnitType *dst, const UnitType *src, IdxType offset,
                       IdxType bits_num) {
    if (bits_num <= kBitsPerUnit - offset) {
      UnitType mask = (kAllOnesUnit >> (kBitsPerUnit - bits_num)) << offset;
      dst[0] = (dst[0] & (src[0] << offset) & mask) | (dst[0] & ~mask);
    } else {
      dst[0u] &=
          !!offset
              ? ((src[0] << offset) | (kAllOnesUnit >> (kBitsPerUnit - offset)))
              : (src[0] << offset);
      IdxType remain_bits = bits_num - (kBitsPerUnit - offset);
      IdxType unit_num = UnitNum(remain_bits);
      UnitType mask =
          !!(remain_bits & kBitsPerUnitMinusOne)
              ? (kAllOnesUnit << (remain_bits & kBitsPerUnitMinusOne))
              : kAllZerosUnit;
      if (unit_num == 1u) {
        dst[1u] &= !!offset ? ((src[0u] >> (kBitsPerUnit - offset)) |
                               (src[1u] << offset) | mask)
                            : (src[1u] | mask);
      } else if (!!offset) {
        IdxType l = offset, r = kBitsPerUnit - l;
        for (IdxType i = 1u; i < unit_num; ++i) {
          dst[i] &= (src[i - 1u] >> r) | (src[i] << l);
        }
        dst[unit_num] &=
            ((src[unit_num - 1u] >> r) | (src[unit_num] << l)) | mask;
      } else {
        for (IdxType i = 1u; i < unit_num; ++i) {
          dst[i] &= src[i];
        }
        dst[unit_num] &= src[unit_num] | mask;
      }
    }
  }

  UnitType *Data() {
    if (DataInStack()) {
      return &(data_.stack_data_[0]);
    } else {
      return data_.heap_data_;
    }
  }

  const UnitType *Data() const {
    if (DataInStack()) {
      return &(data_.stack_data_[0]);
    } else {
      return data_.heap_data_;
    }
  }

  bool DataInStack() const {
    return bits_num_ <=  (7 * kBitsPerUnit);
  }

  void Destory() {
    if (!DataInStack()) {
      delete [] data_.heap_data_;
    }
  }

  size_t bits_num_;
  union {
    UnitType stack_data_[7];
    UnitType *heap_data_;
  } data_;
};

Implement a `SimpleBitSet` in c++, which is similar to a `std::bitset`, but it provides additional features, such as its size is not specified by a template parameter, but by a parameter. In addition, it adds extra optimization for small bitsets and is friendly to cache line：
1. No other third-party libraries can be referenced for implementation, but types provided by `std` can be used.
2. Provide a constructor `SimpleBitSet(size_t bits_num = 0)` to configure the initial size of `SimpleBitSet`.
3. Provide a move copy function and move assignment function, and prohibit copy constructors and copy assignment functions.
4. Implement the interface `size_t Size()`, which indicates how many bits the `SimpleBitSet` has.
5. Implement the interface `void Set(size_t pos, bool val)`, which sets the `bit` at the specified `pos` of the `SimpleBitSet` to `val`.
6. Implement the interface `void Reset(bool val = false)`, which sets all values in `SimpleBitSet` to `val`.
7. Overload the operator `[]` for easy access to specific bit position.
8. Implement the interface `void MergeOr(const SimpleBitSet &bs, size_t offset)`, which performs the `Or` operation on the `SimpleBitSet` from the starting position of `offset` and `bs`, and the number of `bit` operations is the same as `bs`'s `Size()`.
9. Implement the interface `void MergeAnd(const SimpleBitSet &bs, size_t offset)`, which performs the `And` operation on the `SimpleBitSet` from the starting position of `offset` and `bs`, and the number of `bit` operations is the same as `bs`'s `Size()`.
10. Implement the interface `void SliceTo(SimpleBitSet *bs, size_t offset)`, which copies the content of the `SimpleBitSet` from the starting position of `offset` to `bs`, and the number of `bit` operations is the same as `bs`'s `Size()`.
11. Implement the interface `size_t Count() const`, which represents how many positions are `true` in `SimpleBitSet`.
12. Implement the interface `size_t CountUntil(size_t until_cursor) const`, which shows how many `true` positions are in the `SimpleBitSet` within the index range of `[0, until_cursor)`.

#include <bits/stdc++.h>
#<INSERT>

#include <cassert>
#include <thread>
#include <vector>

void testcase() {
  SimpleBitSet bs(65);
  assert(bs.ToString() == std::string(65, '0'));
  for (auto i = 6; i < 10; ++i) {
    bs.Set(i, true);
  }
  assert(bs.Count() == 4u);
  for (auto i = 0u; i <= 6u; ++i) {
    assert(bs.CountUntil(i) == 0u);
  }
  assert(bs.CountUntil(7u) == 1u);
  assert(bs.CountUntil(8u) == 2u);
  assert(bs.CountUntil(9u) == 3u);
  assert(bs.CountUntil(10u) == 4u);
  bs.Set(2, true);
  bs.Set(3, true);
  bs.Set(9, true);
  assert(bs.UnitNum() == 2);
  assert(bs.ToString() == "0011001111" + std::string(65 - 10, '0'));
  assert(bs.Count() == 6u);
  for (auto i = 0u; i <= 2u; ++i) {
    assert(bs.CountUntil(i) == 0u);
  }
  assert(bs.CountUntil(3u) == 1u);
  for (auto i = 4u; i <= 6u; ++i) {
    assert(bs.CountUntil(i) == 2u);
  }
  for (auto i = 1; i <= 4; ++i) {
    assert(bs.CountUntil(6 + i) == 2 + i);
  }
  assert(bs.UnitNum() == 2);
  assert(bs.Count() == 6u);
  assert(bs.ToString() == "0011001111" + std::string(65 - 10, '0'));
  for (auto i = 11; i <= 65; ++i) {
    assert(bs.CountUntil(i) == 6);
  }
  bs.Reset(true);
  for (auto i = 0; i < 65; ++i) {
    assert(bs.Test(i));
  }
  {
    std::vector<uint32_t> offsets{10, 23, 62, 62};
    std::vector<uint32_t> bits_nums0{129, 4099, 1024, 2112};
    std::vector<uint32_t> bits_nums1{20, 2030, 456, 66};
    for (size_t k = 0; k < 2; k++) {
      for (size_t i = 0; i < bits_nums0.size(); ++i) {
        SimpleBitSet bs0(bits_nums0[i]);
        SimpleBitSet bs1(bits_nums1[i]);
        bs0.RandomInit();
        bs1.RandomInit();
        SimpleBitSet bs2(bs0.Size());
        for (size_t i = 0; i < bs0.Size(); ++i) {
          bs2.Set(i, bs0[i]);
        }
        assert(bs0.ToString() == bs2.ToString());

        size_t offset = offsets[i];
        if (k == 0) {
          bs0.MergeOr(bs1, offset);
          for (size_t i = 0; i < bs1.Size(); ++i) {
            bs2.Set(offset + i, bs2[offset + i] | bs1[i]);
          }
        } else {
          bs0.MergeAnd(bs1, offset);
          for (size_t i = 0; i < bs1.Size(); ++i) {
            bs2.Set(offset + i, bs2[offset + i] & bs1[i]);
          }
        }
        for (size_t i = 0; i < bs0.Size(); ++i) {
          assert(bs0[i] == bs2[i]);
        }
      }
    }
  }
}

int main() {
  testcase();
  return 0;
}


#include <functional>
#include <atomic>
#include <chrono>
#include <ctime>
#include <list>
#include <memory>
#include <mutex>
#include <cassert>

template <template <class...> class MapImpl, class Key, class Value,
          class HashFn = std::hash<Key>, class KeyEqualFn = std::equal_to<Key>>
class TtlShardCache {
  struct ItemTtlMeta {
    ItemTtlMeta(uint32_t expired_ts, int64_t kv_size, bool lease_ttl_on_touch)
        : expired_ts(expired_ts),
          kv_size(kv_size),
          lease_ttl_on_touch(lease_ttl_on_touch) {}

    uint32_t expired_ts = 0u;
    const int64_t kv_size = 0ull;
    const bool lease_ttl_on_touch;
  };

  struct KvRef {
    KvRef(const Key& key, ItemTtlMeta* ttl_meta)
        : key(key), ttl_meta(ttl_meta) {}

    Key key;
    ItemTtlMeta* ttl_meta;
  };

  struct CacheItem {
    template <
        typename T,
        std::enable_if_t<
            std::is_same<Value, typename std::remove_reference<T>::type>::value,
            bool> = true>
    CacheItem(T&& value, uint32_t expired_ts, int64_t kv_size,
              bool lease_ttl_on_touch)
        : value(std::forward<T>(value)),
          ttl_meta(std::make_unique<ItemTtlMeta>(expired_ts, kv_size,
                                                 lease_ttl_on_touch)) {}
    Value value;
    typename std::list<KvRef>::iterator lru_itr;
    std::unique_ptr<ItemTtlMeta> ttl_meta;
  };

  class CacheShard {
   public:
    CacheShard(int64_t capacity, std::atomic<int64_t>* cached_size,
               HashFn hash_fn, KeyEqualFn key_equal_fn)
        : cached_size_(cached_size),
          capacity_(capacity),
          shard_size_(0),
          cache_map_(8192, hash_fn, key_equal_fn) {}

    bool Load(const Key& key, Value* value, uint32_t cur_ts, uint32_t ttl) {
      std::unique_lock<std::mutex> lk(mu_);

      auto itr = cache_map_.find(key);
      if (itr != cache_map_.end()) {
        auto& cache_item = itr->second;
        auto& ttl_meta = *(cache_item.ttl_meta);
        if (ttl_meta.lease_ttl_on_touch) {
          ttl_meta.expired_ts = std::max(cur_ts + ttl, ttl_meta.expired_ts);
          lru_list_.erase(cache_item.lru_itr);
          cache_item.lru_itr =
              lru_list_.insert(lru_list_.end(), KvRef(itr->first, &ttl_meta));
          *value = cache_item.value;
          return true;
        } else if (ttl_meta.expired_ts > cur_ts) {
          *value = cache_item.value;
          return true;
        } else {
          (*cached_size_) -= ttl_meta.kv_size;
          shard_size_ -= ttl_meta.kv_size;
          lru_list_.erase(cache_item.lru_itr);
          cache_map_.erase(itr);
        }
      }
      return false;
    }

    template <
        typename T,
        std::enable_if_t<
            std::is_same<Value, typename std::remove_reference<T>::type>::value,
            bool> = true>
    bool Store(const Key& key, T&& value, uint32_t expired_ts, int64_t kv_size,
               bool lease_ttl_on_touch, bool update_if_exist) {
      std::unique_lock<std::mutex> lk(mu_);
      auto itr = cache_map_.find(key);
      bool key_exist = itr != cache_map_.end();
      if (!key_exist || update_if_exist) {
        CacheItem cache_item(std::forward<T>(value), expired_ts, kv_size,
                             lease_ttl_on_touch);
        auto* ttl_meta = cache_item.ttl_meta.get();
        kv_size -= key_exist ? itr->second.ttl_meta->kv_size : 0ll;
        if (cached_size_->fetch_add(kv_size) + kv_size <= capacity_) {
          if (key_exist) {
            lru_list_.erase(itr->second.lru_itr);
            lru_list_.emplace_back(key, ttl_meta);
            itr->second = std::move(cache_item);
            itr->second.lru_itr = --lru_list_.end();
          } else {
            auto ret = cache_map_.emplace(key, std::move(cache_item));
            assert(ret.second);
            lru_list_.emplace_back(key, ttl_meta);
            ret.first->second.lru_itr = --lru_list_.end();
          }
          shard_size_ += kv_size;
          return true;
        } else {
          cached_size_->fetch_sub(kv_size);
          return false;
        }
      } else {
        return false;
      }
    }

    void Evict(uint32_t cur_ts, bool force) {
      int64_t evict_size = 0u;
      std::unique_lock<std::mutex> lk(mu_);
      auto itr = lru_list_.begin();
      while (itr != lru_list_.end() &&
             (itr->ttl_meta->expired_ts <= cur_ts || force)) {
        const auto& key = itr->key;
        evict_size += itr->ttl_meta->kv_size;
        cache_map_.erase(key);
        lru_list_.pop_front();
        itr = lru_list_.begin();
        force = false;
      }
      (*cached_size_) -= evict_size;
      shard_size_ -= evict_size;
    }

    void Clear() {
      std::unique_lock<std::mutex> lk(mu_);
      cache_map_.clear();
      lru_list_.clear();
      (*cached_size_) -= shard_size_;
      shard_size_ = 0;
    }

   private:
    std::mutex mu_;
    std::atomic<int64_t>* cached_size_;
    const int64_t capacity_;
    uint64_t shard_size_;
    MapImpl<Key, CacheItem, HashFn, KeyEqualFn> cache_map_;
    std::list<KvRef> lru_list_;
  };

 public:
  TtlShardCache(int64_t capacity, uint32_t shard_num, uint32_t ttl,
           HashFn hash_fn = HashFn(), KeyEqualFn key_equal_fn = KeyEqualFn())
      : capacity_(capacity),
        shard_num_(shard_num),
        ttl_(ttl),
        last_gc_ts_(0u),
        cached_size_(0u),
        hash_fn_(hash_fn) {
    auto alloc_bytes = shard_num_ * sizeof(CacheShard);
    int ret = posix_memalign(reinterpret_cast<void**>(&mem_placeholder_),
                             alignof(CacheShard), alloc_bytes);
    assert(ret == 0);
    for (auto i = 0u; i < shard_num_; i++) {
      new (&At(i)) CacheShard(capacity_, &cached_size_, hash_fn_, key_equal_fn);
    }
  }

  ~TtlShardCache() {
    for (auto i = 0u; i < shard_num_; ++i) {
      At(i).~CacheShard();
    }
    free(mem_placeholder_);
  }

  bool Load(const Key& key, Value* value, uint32_t cur_ts = time(nullptr)) {
    return GetCacheShard(key).Load(key, value, cur_ts, ttl_);
  }

  template <
      typename T,
      std::enable_if_t<
          std::is_same<Value, typename std::remove_reference<T>::type>::value,
          bool> = true>
  bool Store(const Key& key, T&& value, int64_t kv_size,
             bool lease_ttl_on_touch,
             bool force, bool update_if_exist) {
    uint32_t cur_ts = time(nullptr);
    EvictIfNeed(cur_ts, kv_size, force);
    return (cached_size_.load(std::memory_order_acquire) + kv_size <=
                capacity_ ||
            update_if_exist)
               ? GetCacheShard(key).Store(
                     key, std::forward<T>(value), cur_ts + ttl_, kv_size,
                     lease_ttl_on_touch, update_if_exist)
               : false;
  }

  uint32_t Size() const { return cached_size_.load(std::memory_order_acquire); }

  void Clear() {
    for (auto i = 0u; i < shard_num_; i++) {
      At(i).Clear();
    }
  }

  void EvictIfNeed(uint32_t cur_ts, int64_t reserve_size, bool force) {
    auto last_gc_ts = last_gc_ts_.load(std::memory_order_acquire);
    auto cached_size = cached_size_.load(std::memory_order_acquire);
    force &= (reserve_size + cached_size) > capacity_;
    if ((last_gc_ts < cur_ts &&
         last_gc_ts_.compare_exchange_strong(last_gc_ts, cur_ts)) || force) {
      for (auto i = 0u; i < shard_num_; ++i) {
        At(i).Evict(cur_ts, force);
      }
    }
  }

 private:
  CacheShard& At(uint32_t i) {
    return *(reinterpret_cast<CacheShard*>(mem_placeholder_ +
                                           i * sizeof(CacheShard)));
  }

  CacheShard& GetCacheShard(const Key& key) {
    return At((hash_fn_(key) >> 16u) % shard_num_);
  }

  const int64_t capacity_;
  const uint32_t shard_num_;
  const uint32_t ttl_;
  std::atomic<uint32_t> last_gc_ts_;
  std::atomic<int64_t> cached_size_;
  char* mem_placeholder_;
  HashFn hash_fn_;
};

Implement a new data structure `TtlShardCache` using C++, which needs to meet the following requirements,
1. This `TtlShardCache` supports concurrent reading and writing, its `API` is thread-safe.
2. The implementation of `Map` is template-based, allowing the user to customize flexibly.
3. The implementation of `Key, Value, HashFunc, EqualFunc` is also templated.
3. Implement the interface `bool Load(const Key& key, Value* value, uint32_t cur_ts = time(nullptr))`, which means to load a `Value` according to the `Key`.
4. Implement the interface `bool Store(const Key& key, T&& value, int64_t kv_size, bool lease_ttl_on_touch, bool force, bool update_if_exist)`, which means to store a KV pair into the `Cache`.

Question: Write a piece of python code to achieve the following function.
Find the maximum perfect square number that is less than the nth Fibonacci number.
The function's name is max_square_number, and the input is an integer n.

Answer:
```python
def max_square_number(n):
    if n <= 2:
        return 0  # For the first two numbers in the Fibonacci sequence, no complete square numbers can be used.

    fibs = [0, 1]  # Store the first two numbers of the Fibonacci sequence
    squares = []  # Store the list of perfect square numbers

    max_square = 0
    i = 2

    while i <= n:
        fibs.append(fibs[i-1] + fibs[i-2])  # Calculate the next Fibonacci number
        i += 1

    fib = fibs[-1]
    perfect_squares = [i**2 for i in range(1, int(math.sqrt(fib)) + 1)]
    max_square = max(filter(lambda x: x < fib, perfect_squares))
    return max_square
```

----------------

#include <bits/stdc++.h>
#<INSERT>
#include <unordered_map>
#include <thread>
#include <cassert>

void testcase() {
  {
    const uint32_t cache_shard_num = 2;
    const uint32_t cache_capacity = 2;
    const uint32_t ttl = 30;
    TtlShardCache<std::unordered_map, int, int> cache(cache_capacity, cache_shard_num,
                                                 ttl);

    uint32_t cur_ts = time(nullptr);
    int k1 = 1, v1 = 11, k2 = 2, v2 = 22, k3 = 3, v3 = 33;
    int ret = 1000;
    assert(!cache.Load(k1, &ret, cur_ts));
    assert(!cache.Load(k2, &ret, cur_ts));
    cache.EvictIfNeed(cur_ts, 1, false);
    assert(0u == cache.Size());
    assert(cache.Store(k1, v1, 1, true, false, false));
    cache.EvictIfNeed(cur_ts, 1, false);
    assert(1 == cache.Size());
    assert(!cache.Store(k1, 3, 1, true, false, false));
    cache.EvictIfNeed(cur_ts, 1, false);
    assert(1 == cache.Size());
    assert(cache.Store(k2, k2, 1, false, false, false));
    cache.EvictIfNeed(cur_ts, 1, false);
    assert(2 == cache.Size());

    assert(cache.Load(k1, &ret, cur_ts));
    assert(v1 == ret);
    assert(cache.Store(k1, v3, 1, true, false, true));
    assert(cache.Load(k1, &ret, cur_ts));
    assert(v3 == ret);
    assert(!cache.Store(k1, v3, 1, true, false, false));
    assert(!cache.Store(k3, v3, 1, true, false, false));
    assert(!cache.Store(k3, v3, 1, true, false, true));
    assert(!cache.Load(k2, &ret, cur_ts + ttl + 1));
    cache.EvictIfNeed(cur_ts, 1, false);
    assert(1 == cache.Size());
  }
  {
    std::string cache_value = "cache_value";
    const uint32_t cache_shard_num = 2;
    const uint32_t cache_capacity = 20;
    const uint32_t ttl = 3;
    uint32_t cur_ts = 0u;
    TtlShardCache<std::unordered_map, int, int> cache(cache_capacity, cache_shard_num,
                                                 ttl);
    for (int i = 0; i < 20; ++i) {
      assert(cache.Store(i, i, 1, false, false, false));
    }
    for (int i = 20; i < 100; ++i) {
      assert(!cache.Store(i, i, 1, false, false, false));
    }
    cache.EvictIfNeed(cur_ts, 1, false);
    assert(cache_capacity == cache.Size());
  }
  {
    const uint32_t cache_capacity = 200;
    const uint32_t cache_shard_num = 2;
    const uint32_t ttl = 3;
    uint32_t cur_ts = 0u;
    TtlShardCache<std::unordered_map, int, int> cache(cache_capacity, cache_shard_num,
                                                 ttl);

    std::thread t1([&cache, cur_ts]() {
      for (int i = 0; i < 100; i += 2) {
        assert(cache.Store(i, i, 1, false, false, false));
      }
    });
    std::thread t2([&cache, cur_ts]() {
      for (int i = 1; i < 100; i += 2) {
        assert(cache.Store(i, i, 1, false, false, false));
      }
    });

    t1.join();
    t2.join();
    cache.EvictIfNeed(cur_ts, 1, false);
    assert(100 == cache.Size());

    for (int i = 0; i < 100; ++i) {
      int ret = -1;
      assert(cache.Load(i, &ret, cur_ts));
      assert(i == ret);
    }
  }
}

int main() {
  testcase();
  return 0;
}


#include <type_traits>
#include <vector>
#include <cassert>

template <typename T, size_t kSize = 8>
class AutoVec {
 public:
  AutoVec() = default;

  AutoVec(size_t size, const T default_value = T()) {
    if (size > 0) {
      std::uninitialized_fill_n(&(stack_vec_[0]), std::min(size, kSize), default_value);
      if (size > kSize) {
        heap_vec_.resize(size - kSize, default_value);
      }
    }
  }

  AutoVec(const AutoVec &other)
      : num_stack_size_(other.num_stack_size_),
        heap_vec_(other.heap_vec_) {
    if (num_stack_size_ > 0) {
      std::uninitialized_copy_n(&(other.stack_vec_[0]), num_stack_size_,
                                &(stack_vec_[0]));
    }
  }

  AutoVec &operator=(const AutoVec &other) {
    DtorVec(&(stack_vec_[0]), num_stack_size_);
    if (other.num_stack_size_ > 0) {
      std::uninitialized_copy_n(&(other.stack_vec_[0]), other.num_stack_size_,
                                &(stack_vec_[0]));
    }
    num_stack_size_ = other.num_stack_size_;
    heap_vec_ = other.heap_vec_;
    return *this;
  }

  AutoVec(AutoVec &&other)
      : num_stack_size_(other.num_stack_size_),
        heap_vec_(std::move(other.heap_vec_)) {
    if (num_stack_size_ > 0) {
      std::uninitialized_move_n(&(other.stack_vec_[0]), num_stack_size_,
                                &(stack_vec_[0]));
    }
  }

  AutoVec &operator=(AutoVec &&other) {
    DtorVec(&(stack_vec_[0]), num_stack_size_);
    if (other.num_stack_size_ > 0) {
      std::uninitialized_move_n(&(other.stack_vec_[0]), other.num_stack_size_,
                                &(stack_vec_[0]));
    }
    num_stack_size_ = other.num_stack_size_;
    heap_vec_ = std::move(other.heap_vec_);
    return *this;
  }

  ~AutoVec() { Clear(); }

  const T &operator[](size_t idx) const {
    if (idx < kSize) {
      return stack_vec_[idx];
    } else {
      return heap_vec_[idx - kSize];
    }
  }

  T &operator[](size_t idx) {
    if (idx < kSize) {
      return stack_vec_[idx];
    } else {
      return heap_vec_[idx - kSize];
    }
  }

  template <class... Args>
  void EmplaceBack(Args &&...args) {
    if (num_stack_size_ < kSize) {
      ::new (&(stack_vec_[num_stack_size_++])) T(std::forward<Args>(args)...);
    } else {
      heap_vec_.emplace_back(std::forward<Args>(args)...);
    }
  }

  void PushBack(T &&v) {
    if (num_stack_size_ < kSize) {
      ::new (&(stack_vec_[num_stack_size_++])) T(std::move(v));
    } else {
      heap_vec_.push_back(std::move(v));
    }
  }

  void PushBack(const T &v) {
    if (num_stack_size_ < kSize) {
      ::new (&(stack_vec_[num_stack_size_++])) T(v);
    } else {
      heap_vec_.push_back(v);
    }
  }

  void PopBack() noexcept {
    assert(num_stack_size_ > 0);
    if (!heap_vec_.empty()) {
      heap_vec_.pop_back();
    } else {
      DtorVec(&(stack_vec_[--num_stack_size_]), 1);
    }
  }

  T &Front() {
    assert(num_stack_size_ > 0);
    return stack_vec_[0];
  }

  const T &Front() const {
    assert(num_stack_size_ > 0);
    return stack_vec_[0];
  }

  T &Back() {
    assert(num_stack_size_ > 0);
    if (num_stack_size_ <= kSize) {
      return stack_vec_[num_stack_size_ - 1];
    } else {
      return heap_vec_.back();
    }
  }

  const T &Back() const {
    assert(num_stack_size_ > 0);
    if (num_stack_size_ <= kSize) {
      return stack_vec_[num_stack_size_ - 1];
    } else {
      return heap_vec_.back();
    }
  }

  size_t Size() const { return num_stack_size_ + heap_vec_.size(); }

  bool IsEmpty() const { return Size() == 0; }

  void Resize(size_t new_size, const T default_value = T()) {
    size_t old_size = Size();
    if (new_size < old_size) {
      if (new_size > kSize) {
        heap_vec_.resize(new_size - kSize);
      } else {
        heap_vec_.clear();
        DtorVec(&stack_vec_[new_size], kSize - new_size);
      }
    } else if (new_size > old_size) {
      if (new_size > kSize) {
        heap_vec_.resize(new_size - kSize, default_value);
      } else {
        std::uninitialized_fill_n(&(stack_vec_[old_size]),
                                  new_size - old_size, default_value);
      }
    }
  }

  void Clear() {
    heap_vec_.clear();
    DtorVec(&(stack_vec_[0]), num_stack_size_);
  }

 private:
  static void DtorVec(T *t, size_t num) {
    if (!std::is_trivially_destructible<T>::value &&
        std::is_destructible<T>::value && num > 0) {
      while (num > 0) {
        t->~T();
        t++;
        --num;
      }
    }
  }

  size_t num_stack_size_ = 0;
  T stack_vec_[kSize];
  std::vector<T> heap_vec_;
};

Implement the template class `template <typename T, size_t kSize = 8> class AutoVec` in C++, similar to `std::vector`. `AutoVec` will place the first part of the array on the `stack` and the tail of the array on the `heap`, enhancing the performance of short `vector`.
1. Implement a constructor `AutoVec(size_t size, const T default_value = T())`, which constructs an `AutoVec` with `size` number of `default_value`.
2. Implement copy constructor/copy assignment function/move constructor/move assignment function.
3. Overload the subscript operator for easier element access.
4. Implement the interface `template <class... Args> void EmplaceBack(Args&&... args)` to insert an element at the end of the buffer.
5. Implement the interface `void PopBack()` to delete an element from the end.
6. Implement the interface `T &Front(), const T &Front() const` to get the front element.
7. Implement the interface `T &Back(), const T &Back() const` to get the end element.
8. Implement the interface `T& GetBack(), const T& GetBack() const` to get the end element.
9. Implement the interface `bool IsEmpty() const` to check whether `AutoVec` is empty.
10. Implement the interface `size_t Size()` to get the element count.
11. Implement the interface `void Clear()` to clear the buffer.
12. Implement the interface `void Resize(size_t new_size, const T default_value = T())` which sets the `AutoVec` size to `size`. If the size is increased, elements are removed from the end. If the buffer gets bigger, elements are inserted at the end and default constructed with `default_value`.
13. Implement the interface `void Clear()` to clear the array.

#include <bits/stdc++.h>
#include <ctime>
#include <thread>

#<INSERT>

#include <cassert>

void testcase() {
  AutoVec<int, 2> auto_vec;
  auto_vec.PushBack(1);
  auto_vec.PushBack(2);
  auto_vec.PushBack(3);
  auto_vec.EmplaceBack(4);
  assert(auto_vec[0] == 1);
  assert(auto_vec[1] == 2);
  assert(auto_vec[2] == 3);
  assert(auto_vec[3] == 4);
  assert(auto_vec.Size() == 4);
  auto_vec.Resize(2);
  assert(auto_vec.Size() == 2);
  auto_vec.Resize(4, 10);
  assert(auto_vec.Size() == 4);
  assert(auto_vec[2] == 10);
  assert(auto_vec[3] == 10);
  assert (auto_vec.Size() == 4);
}

int main() {
  testcase();
  return 0;
}


#include <utility>
#include <cassert>
#include <cstddef>

template <class T>
class CircularBuffer {
 public:
  explicit CircularBuffer(size_t capacity = 0): capacity_(capacity) {
    if (capacity) {
      storage_ = new ElementStorage[capacity];
    }
  }

  ~CircularBuffer() {
    while (!IsEmpty()) {
      PopFront();
    }
    if (storage_) {
      delete[] storage_;
    }
  }

  CircularBuffer(const CircularBuffer& other)
      : CircularBuffer(other.capacity_) {
    for (size_t i = 0; i < other.GetSize(); ++i) {
      EmplaceBack(other[i]);
    }
  }

  CircularBuffer(CircularBuffer&& other) : CircularBuffer() { Swap(&other); }

  CircularBuffer& operator=(const CircularBuffer& other) {
    assert(other.GetSize() <= GetCapacity());
    Clear();
    for (size_t i = 0; i < other.GetSize(); ++i) {
      EmplaceBack(other[i]);
    }
    return *this;
  }

  CircularBuffer& operator=(CircularBuffer&& other) {
    CircularBuffer tmp(std::move(other));
    Swap(&tmp);
    return *this;
  }

  T& operator[](size_t i) {
    assert(i < size_);
    return storage_[(read_index_ + i) % capacity_].o;
  }

  const T& operator[](size_t i) const {
    assert(i < size_);
    return storage_[(read_index_ + i) % capacity_].o;
  }

  template <class... Args>
  void EmplaceBack(Args&&... args) {
    assert(size_ < capacity_);
    new (storage_ + write_index_) T(std::forward<Args>(args)...);
    write_index_ = (write_index_ + 1) % capacity_;
    ++size_;
  }

  template <class... Args>
  void EmplaceFront(Args&&... args) {
    assert(size_ < capacity_);
    if (read_index_ == 0) {
      read_index_ = capacity_ - 1;
    } else {
      --read_index_;
    }
    new (storage_ + read_index_) T(std::forward<Args>(args)...);
    ++size_;
  }

  void PopBack() {
    assert(!IsEmpty());
    if (write_index_ == 0) {
      write_index_ = capacity_ - 1;
    } else {
      --write_index_;
    }
    storage_[write_index_].o.~T();
    --size_;
  }

  void PopFront() {
    assert(!IsEmpty());
    storage_[read_index_].o.~T();
    read_index_ = (read_index_ + 1) % capacity_;
    --size_;
  }

  T& GetFront() {
    assert(!IsEmpty());
    return storage_[read_index_].o;
  }

  const T& GetFront() const {
    assert(!IsEmpty());
    return storage_[read_index_].o;
  }

  T& GetBack() {
    assert(!IsEmpty());
    return storage_[write_index_ == 0 ? (capacity_ - 1) : (write_index_ - 1)].o;
  }

  const T& GetBack() const {
    assert(!IsEmpty());
    return storage_[write_index_ == 0 ? (capacity_ - 1) : (write_index_ - 1)].o;
  }

  size_t GetCapacity() const { return capacity_; }

  bool IsEmpty() const { return size_ == 0; }

  bool IsFull() const { return size_ == capacity_; }

  size_t GetSize() const { return size_; }

  void Clear() {
    while (!IsEmpty()) {
      PopFront();
    }
  }

  void Resize(size_t size, const T& value) {
    assert(size <= capacity_);
    while (size < size_) {
      PopBack();
    }
    while (size > size_) {
      EmplaceBack(value);
    }
  }

  void Resize(size_t size) {
    assert(size <= capacity_);
    while (size < size_) {
      PopBack();
    }
    while (size > size_) {
      EmplaceBack();
    }
  }

  void Swap(CircularBuffer* other) {
    std::swap(storage_, other->storage_);
    std::swap(write_index_, other->write_index_);
    std::swap(read_index_, other->read_index_);
    std::swap(size_, other->size_);
    std::swap(capacity_, other->capacity_);
  }

 private:
  union ElementStorage {
    ElementStorage() {}
    ~ElementStorage() {}

    T o;
    char buf[sizeof(T)];
  };

  ElementStorage* storage_ = nullptr;
  size_t write_index_ = 0;
  size_t read_index_ = 0;
  size_t size_ = 0;
  size_t capacity_;
};

Implement the `CircularBuffer` class in C++ to represent a circular buffer. It needs to be implemented by templates to support the definition of different types of objects.
1. Implement the constructor `CircularBuffer(std::size_t capacity)` to represent the maximum length of the buffer.
2. Implement copy constructor/copy assignment function/move constructor/move assignment function.
3. Overload the subscript operator for convenient access to elements by index.
4. Implement the interface `template <class... Args> void EmplaceBack(Args&&... args)` to insert an element at the end of the buffer.
5. Implement the interface `template <class... Args> void EmplaceFront(Args&&... args)` to insert an element at the beginning of the buffer.
6. Implement the interface `void PopBack()` to remove an element from the end.
7. Implement the interface `void PopFront()` to remove an element from the beginning.
8. Implement the interface `T& GetFront(), const T& GetFront() const` to get the first element.
9. Implement the interface `T& GetBack(), const T& GetBack() const` to get the last element.
10. Implement the interface `bool IsFull()` to indicate whether the buffer is full.
11. Implement the interface `bool IsEmpty()` to indicate whether the buffer is empty.
12. Implement the interface `size_t GetSize()` to indicate the number of elements in the buffer.
13. Implement the interface `size_t GetCapacity()` to indicate the capacity of the buffer.
14. Implement the interface `void Clear()` to clear the buffer.
15. Implement the interface `void Resize(size_t size, const T& value)` to reset the size of the buffer to `size`. If the buffer becomes smaller, remove elements from the bottom of the buffer. If the buffer becomes larger, insert elements at the top of the buffer and use `value` for default construction.
16. Implement the interface `void Resize(size_t size)` to reset the size of the buffer to `size`. If the buffer becomes smaller, remove elements from the bottom of the buffer. If the buffer becomes larger, insert elements at the top of the buffer and use `T`'s default constructor for construction.
17. Implement the interface `void Swap(CircularBuffer* other)` to swap the contents of the two buffers.

#include <bits/stdc++.h>
#<INSERT>
#include <cassert>
#include <cassert>
#include <string>

void testcase() {
  CircularBuffer<std::string> cb(3);
  assert(cb.IsEmpty());
  assert(!cb.IsFull());
  assert(cb.GetSize() == 0U);
  assert(cb.GetCapacity() == 3U);

  cb.EmplaceBack("abc");
  assert(!cb.IsEmpty());
  assert(!cb.IsFull());
  assert(cb.GetSize() == 1U);
  assert(cb.GetCapacity() == 3U);
  assert(cb.GetFront() == "abc");
  assert(cb.GetBack() == "abc");
  assert(cb[0] == "abc");

  cb.EmplaceFront("101");
  assert(!cb.IsEmpty());
  assert(!cb.IsFull());
  assert(cb.GetSize() == 2U);
  assert(cb.GetCapacity() == 3U);
  assert(cb.GetFront() == "101");
  assert(cb.GetBack() == "abc");
  assert(cb[0] == "101");
  assert(cb[1] == "abc");

  cb.EmplaceBack("123");
  assert(!cb.IsEmpty());
  assert(cb.IsFull());
  assert(cb.GetSize() == 3U);
  assert(cb.GetCapacity() == 3U);
  assert(cb.GetFront() == "101");
  assert(cb.GetBack() == "123");
  assert(cb[0] == "101");
  assert(cb[1] == "abc");
  assert(cb[2] == "123");

  cb.PopBack();
  assert(!cb.IsEmpty());
  assert(!cb.IsFull());
  assert(cb.GetSize() == 2U);
  assert(cb.GetCapacity() == 3U);
  assert(cb.GetFront() == "101");
  assert(cb.GetBack() == "abc");
  assert(cb[0] == "101");
  assert(cb[1] == "abc");

  cb.PopFront();
  assert(!cb.IsEmpty());
  assert(!cb.IsFull());
  assert(cb.GetSize() == 1U);
  assert(cb.GetCapacity() == 3U);
  assert(cb.GetFront() == "abc");
  assert(cb.GetBack() == "abc");
  assert(cb[0] == "abc");

  cb.Clear();
  assert(cb.IsEmpty());
  assert(!cb.IsFull());
  assert(cb.GetSize() == 0U);
  assert(cb.GetCapacity() == 3U);

  cb.Resize(1);
  assert(cb.GetSize() == 1U);
  assert(cb.GetFront().empty());

  std::string s("101");
  cb.Resize(2, s);
  assert(cb.GetSize() == 2U);
  assert(cb[0] == "");
  assert(cb[1] == "101");

  CircularBuffer<std::string> cb2(cb);
  assert(cb2.GetSize() == 2U);
  assert(cb2.GetCapacity() == 3U);
  assert(cb2[0] == "");
  assert(cb2[1] == "101");

  cb2.Clear();
  cb2 = cb;
  assert(cb2.GetSize() == 2U);
  assert(cb2[0] == "");
  assert(cb2[1] == "101");

  CircularBuffer<std::string> cb3(std::move(cb));
  assert(cb.IsEmpty());
  assert(cb3.GetSize() == 2U);
  assert(cb3[0] == "");
  assert(cb3[1] == "101");

  cb = std::move(cb3);
  assert(cb3.IsEmpty());
  assert(cb.GetSize() == 2U);
  assert(cb[0] == "");
  assert(cb[1] == "101");
}

int main() {
  testcase();
  return 0;
}


#include <functional>
#include <limits>
#include <memory>
#include <cassert>
#include <climits>

template <class Key, class HashFn = std::hash<Key>,
          class KeyEqualFn = std::equal_to<Key>>
class DeDupper {

  struct Config {
    static constexpr auto kIllgalBucket = std::numeric_limits<uint32_t>::max();

    static constexpr auto kLoadFactor = 0.75F;
  };

  struct HTItem {
    HTItem() = default;
    explicit HTItem(const Key &key) : key(key) {}
    explicit HTItem(const Key &key, uint32_t version, uint32_t uniq_idx)
        : key(key), version(version), uniq_idx(uniq_idx) {}
    Key key;
    uint32_t version{0};
    uint32_t uniq_idx{0};
  };

  struct HTIdx {
    HTIdx(uint32_t item_pos, uint32_t insert_pos)
        : item_pos(item_pos), insert_pos(insert_pos) {}
    uint32_t item_pos;
    uint32_t insert_pos;
  };

  struct HTMeta {
    bool Init(uint32_t new_bucknum) {
      bucknum = new_bucknum;
      num_elements = 0;
      return (0 == cur_version++);
    }

    uint32_t bucknum = 0;
    uint32_t buckcap = 0;
    uint32_t num_elements = 0;
    uint32_t cur_version = 0;
  };

  using HTItemPtr = HTItem*;
  using CHTItemPtr = const HTItem*;

 public:
  DeDupper() = default;

  ~DeDupper() { DtorProbTable(prob_table_, ht_meta_.buckcap); }

  uint32_t DeDup(const Key &key) {
    auto hv = hash_fn_(key);
    const auto hi = FindPosition(key, prob_table_, ht_meta_.bucknum - 1,
                                 hv, ht_meta_.cur_version);
    if (hi.item_pos != Config::kIllgalBucket) {
      return prob_table_[hi.item_pos].uniq_idx;
    } else {
      prob_table_[hi.insert_pos] =
          HTItem(key, ht_meta_.cur_version, ht_meta_.num_elements);
      return ht_meta_.num_elements++;
    }
  }

  void PrepareDeDup(const uint32_t capacity) {
    size_t min_cap = static_cast<size_t>(capacity) / Config::kLoadFactor;
    size_t new_buckcap = RoundUpToNextHighestPowerOf2(min_cap);
    assert(new_buckcap < Config::kIllgalBucket);
    if (new_buckcap > ht_meta_.buckcap) {
      DtorProbTable(prob_table_, ht_meta_.buckcap);
      prob_table_ = CreateProbTable(new_buckcap);
      ht_meta_.buckcap = new_buckcap;
      ht_meta_.Init(new_buckcap);
    } else if (ht_meta_.Init(new_buckcap)) {
      FillRangeWithEmpty(prob_table_, new_buckcap);
    }
  }

 private:
  static size_t RoundUpToNextHighestPowerOf2(size_t v) {
    size_t shift_bits = sizeof(size_t) * CHAR_BIT - 1 - __builtin_clzll(v);
    size_t ret = static_cast<size_t>(1) << shift_bits;
    return ret < v ? (ret << 1) : ret;
  }

  static HTItemPtr CreateProbTable(uint32_t num_capacity) {
    assert((num_capacity & (num_capacity - 1)) == 0);
    auto table = reinterpret_cast<HTItemPtr>(malloc(num_capacity * sizeof(HTItem)));
    FillRangeWithEmpty(table, num_capacity);
    return table;
  }

  static void DtorProbTable(HTItemPtr prob_table, uint32_t num_capacity) {
    if (!!prob_table && num_capacity > 0 &&
        !std::is_trivially_destructible<HTItem>::value &&
        std::is_destructible<HTItem>::value) {
      for (auto bi = 0; bi < num_capacity; ++bi) {
        prob_table[bi].~HTItem();
      }
    }
  }

  HTIdx FindPosition(const Key &key, CHTItemPtr table,
                     uint32_t buckidx_mask, uint32_t hv,
                     uint32_t version) {
    uint32_t buckidx = hv & buckidx_mask;
    while (true) {
      auto& item = table[buckidx];
      if (TestEqual(item, key, version)) {
        return HTIdx(buckidx, Config::kIllgalBucket);
      } else if (TestEmpty(item, version)) {
        return HTIdx(Config::kIllgalBucket, buckidx);
      }
      buckidx = (buckidx + 1) & buckidx_mask;
    }
  }

  static void FillRangeWithEmpty(const HTItemPtr prob_table,
                                 uint32_t num_capacity) {
    static HTItem empty_item(Key(), 0, 0);
    std::uninitialized_fill_n(prob_table, num_capacity, empty_item);
  }

  static bool TestEmpty(const HTItem& ht_item, uint32_t cur_version) {
    return ht_item.version != cur_version;
  }

  bool TestEqual(const HTItem& ht_item, const Key &key,
                 uint32_t cur_version) {
    return key_equal_fn_(ht_item.key, key) && ht_item.version == cur_version;
  }

 private:
  HTMeta ht_meta_;
  HTItemPtr prob_table_{nullptr};
  HashFn hash_fn_;
  KeyEqualFn key_equal_fn_;
};

Implement the `DeDupper` type in C++, with the main function of deduplicating some elements.
1. Template implementation of `Key, Value, HashFunc, EqualFunc`, allowing users to customize.
2. Implement the interface `void PrepareDeDup(const uint32_t capacity)` to reserve memory space based on the number of keys to be deduplicated and get ready for preprocessing.
3. Implement the interface `uint32_t DeDup(const Key &key)` to deduplicate the `key`. If the key already exists, return the number of deduplicated elements; otherwise, insert the key and return the total number of deduplicated elements.

#include <bits/stdc++.h>
#<INSERT>
#include <cassert>

void testcase() {
  DeDupper<uint64_t> dedupper;
  uint32_t fid_num = 10;
  dedupper.PrepareDeDup(fid_num);
  assert(dedupper.DeDup(0) == 1);
  assert(dedupper.DeDup(1) == 2);
  assert(dedupper.DeDup(2) == 3);
  assert(dedupper.DeDup(2) == 2);
  assert(dedupper.DeDup(3) == 4);
  assert(dedupper.DeDup(2) == 2);
  dedupper.PrepareDeDup(fid_num);
  assert(dedupper.DeDup(4) == 1);
  assert(dedupper.DeDup(5) == 2);
  assert(dedupper.DeDup(2) == 3);
}

int main() {
  testcase();
  return 0;
}


#include <functional>
#include <list>
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <string>
#include <unordered_map>
#include <vector>

template <typename K, typename V> struct KeyValue {
  K key;
  V value;

  KeyValue(const K &k, const V &v) : key(k), value(v) {}
};

template <typename K, typename V, typename Hash = std::hash<K>> class LruCache {
public:
  typedef std::list<KeyValue<K, V>> ListType;
  typedef std::unordered_map<K, typename ListType::iterator, Hash> MapType;

  /**
   * 显式构造函数，指定最大容量
   */
  explicit LruCache(size_t max_size) : max_size_(max_size) {}

  LruCache(const LruCache &) = delete;
  const LruCache &operator=(const LruCache &) = delete;
  virtual ~LruCache() {}

  size_t size() {
    std::shared_lock lock(mutex_);
    return cache_.size();
  }

  size_t max_size() const { return max_size_; }

  bool empty() { return size() == 0; }

  void reserve(size_t reserve_size = 0) {
    if (reserve_size == 0) {
      reserve_size =
          max_size_ +
          1; // 不传参的时候默认是reserve
             // max_size+1，+1为了防止到达边界时触发rehash，留1个buffer
    }
    std::unique_lock lock(mutex_);
    cache_.reserve(reserve_size);
  }

  /**
   * 增加一条记录，如果 cache 容量满了，会淘汰掉最旧的
   */
  void add(const K &k, const V &v) {
    std::vector<KeyValue<K, V>> drops;
    {
      std::unique_lock lock(mutex_);
      _add_no_lock(k, v, drops);
    }
  }

  /**
   * 获取 k 对应的 value，存储到 result 中
   * 如果不存在，返回 false，否则返回 true
   *
   * NOTE: 这个访问会将该记录挪到最前，当成最近的记录
   */
  bool get(const K &k, V &result) {
    std::unique_lock lock(mutex_);
    return _get_no_lock<true>(k, result);
  }

  /**
   * 取 k 对应的 value，存储到 result 中
   * 如果不存在，返回 false，否则返回 true
   *
   * NOTE: 和 get 的区别是: 这里并不将记录挪动，因此只需要挂读锁，
   *       并发性和性能会更好
   */
  bool peek(const K &k, V &result) {
    std::shared_lock lock(mutex_);
    return _get_no_lock<false>(k, result);
  }

  /**
   * 删除一条记录，存在，则返回 true，否则返回 false
   */
  bool remove(const K &k) {
    std::vector<KeyValue<K, V>> drops;
    {
      std::unique_lock lock(mutex_);
      const auto &iter = cache_.find(k);
      if (iter == cache_.end()) {
        return false;
      }
      drops.emplace_back(*(iter->second));
      list_.erase(iter->second);
      cache_.erase(iter);
    }
    return true;
  }

  /**
   * 返回是否存在某个 key
   */
  bool contains(const K &k) {
    std::shared_lock lock(mutex_);
    return cache_.find(k) != cache_.end();
  }

  void clear() {
    ListType drops;
    {
      std::unique_lock lock(mutex_);
      cache_.clear();
      drops.swap(list_);
    }
  }

  /**
   * 访问 cache 中所有的 key value 对
   * f 是 void (const K&, const V&) 类型的
   */
  void iter_all(std::function<void(const K &, const V &)> f) {
    std::shared_lock lock(mutex_);
    for (auto &kv : list_) {
      f(kv.key, kv.value);
    }
  }

private:
  template <bool move_to_front = false>
  bool _get_no_lock(const K &k, V &result) {
    const auto &iter = cache_.find(k);
    if (iter == cache_.end())
      return false;
    if (move_to_front) {
      list_.splice(list_.begin(), list_, iter->second);
    }
    result = iter->second->value;
    return true;
  }

  void _add_no_lock(const K &k, const V &v) {
    const auto &iter = cache_.find(k);
    if (iter != cache_.end()) {
      iter->second->value = v;
      list_.splice(list_.begin(), list_, iter->second);
    } else {
      list_.emplace_front(KeyValue<K, V>(k, v));
      cache_[k] = list_.begin();
    }

    while (cache_.size() > max_size_) {
      cache_.erase(list_.back().key);
      list_.pop_back();
    }
  }

  void _add_no_lock(const K &k, const V &v,
                    std::vector<KeyValue<K, V>> &drops) {
    const auto &iter = cache_.find(k);
    if (iter != cache_.end()) {
      iter->second->value = v;
      list_.splice(list_.begin(), list_, iter->second);
    } else {
      list_.emplace_front(KeyValue<K, V>(k, v));
      cache_[k] = list_.begin();
    }

    while (cache_.size() > max_size_) {
      drops.emplace_back(list_.back());
      cache_.erase(list_.back().key);
      list_.pop_back();
    }
  }

private:
  MapType cache_;
  ListType list_;
  size_t max_size_;
  std::shared_mutex mutex_;
};

Implement a lru cache that supports thread-safety and the following interfaces:
1. `LruCache (size_t max_size)`: constructor, specifying the maximum capacity.
2. `size_t size()`: get the current cache size.
3. `void add(const K &k, const V &v)`: add a record. If the cache is full, the oldest one will be eliminated.
4. `bool get(const K &k, V &result)`: this access will move the record to the most recent location.
5. `bool peek(const K &k, V &result)`: the difference from get is that it does not move the record and only needs a read lock.
6. `void iter_all(std::function<void(const K &, const V &)> f)`: access all key value pairs in the cache.

#include <bits/stdc++.h>
#<INSERT>

#include <atomic>
#include <cassert>
#include <iostream>
#include <memory>
#include <unordered_map>
#include <vector>

void testcase() {
  LruCache<int, int> cache(3);

  cache.add(1, 1);
  cache.add(2, 2);
  cache.add(3, 3);
  cache.add(1, 1);
  cache.add(4, 4);

  assert(3 == cache.size());
  std::vector<std::pair<int, int>> vecs;
  auto func = [&](const int &k, const int &v) {
    vecs.push_back(std::make_pair(k, v));
  };
  cache.iter_all(func);
  assert(vecs.size() == 3);
  assert(vecs[0] == std::make_pair<>(4, 4));
  assert(vecs[1] == std::make_pair<>(1, 1));
  assert(vecs[2] == std::make_pair<>(3, 3));
}

int main() {
  testcase();
  return 0;
}


#include <atomic>
#include <chrono>
#include <cstdint>
#include <thread>
#include <cassert>

class TokenBucket final {
 public:
  TokenBucket(double tokens_per_sec, uint64_t capacity,
              uint64_t initial_tokens = 0)
      : tokens_per_sec_(tokens_per_sec), capacity_(capacity) {
    ns_per_token_ = 1000000000 / tokens_per_sec;
    capacity_ns_ = ns_per_token_ * capacity;
    last_update_time_ns_.store(
        NowNs() - initial_tokens * ns_per_token_,
        std::memory_order_relaxed);
  }

  bool TryConsume(uint64_t tokens = 1) {
    return Consume(tokens, false /*wait*/) == 0;
  }

  static int64_t NowNs() {
    return std::chrono::duration_cast<std::chrono::nanoseconds>(
        std::chrono::steady_clock::now().time_since_epoch()
      ).count();
  }

  void Consume(uint64_t tokens = 1) { Consume(tokens, true /*wait*/); }

  int64_t ConsumeWithBorrow(uint64_t tokens = 1) {
    assert(tokens <= capacity_);
    auto old_ts_ns = last_update_time_ns_.load(std::memory_order_relaxed);
    auto tokens_ns = tokens * ns_per_token_;
    uint64_t now_ns = NowNs();
    for (;;) {
      auto new_ts_ns = old_ts_ns;
      if (old_ts_ns < now_ns && now_ns - old_ts_ns > capacity_ns_) {
        new_ts_ns = now_ns - capacity_ns_;
      }
      new_ts_ns += tokens_ns;
      if (last_update_time_ns_.compare_exchange_weak(old_ts_ns, new_ts_ns,
                                                     std::memory_order_relaxed)) {
        return new_ts_ns > now_ns
               ? new_ts_ns - now_ns
               : 0;
      }
      now_ns = NowNs();
    }
  }

  int64_t GetWaitTime(uint64_t tokens = 1) {
    return Consume(tokens, false /*wait*/);
  }

  void Return(uint64_t tokens = 1) {
    auto old_ts_ns = last_update_time_ns_.load(std::memory_order_relaxed);
    uint64_t returned_ns = tokens * ns_per_token_;
    uint64_t new_ts_ns{0};
    do {
      if (old_ts_ns > returned_ns) {
        new_ts_ns = old_ts_ns - returned_ns;
      }
    } while (!last_update_time_ns_.compare_exchange_weak(
        old_ts_ns, new_ts_ns, std::memory_order_relaxed));
  }

  double GetTokensPerSec() const { return tokens_per_sec_; }

  uint64_t GetCapacity() const { return capacity_; }

 private:
  int64_t Consume(uint64_t tokens, bool wait) {
    assert(tokens <= capacity_);
    auto tokens_ns = tokens * ns_per_token_;
    assert(tokens_ns <= capacity_ns_);
    int64_t now_ns = NowNs();
    auto old_ts_ns = last_update_time_ns_.load(std::memory_order_relaxed);
    for (;;) {
      int64_t avail_ns = 0;
      uint64_t extra_ns = 0;
      avail_ns = static_cast<int64_t>(now_ns) -
                 static_cast<int64_t>(old_ts_ns);
      if (avail_ns > static_cast<int64_t>(capacity_ns_)) {
        extra_ns = avail_ns - capacity_ns_;
        avail_ns = capacity_ns_;
      }
      if (avail_ns < static_cast<int64_t>(tokens_ns)) {
        if (!wait) {
          return tokens_ns - avail_ns;
        }
        std::this_thread::sleep_for(std::chrono::nanoseconds(tokens_ns - avail_ns));
        old_ts_ns = last_update_time_ns_.load(std::memory_order_relaxed);
      } else {
        if (last_update_time_ns_.compare_exchange_strong(
              old_ts_ns, old_ts_ns + extra_ns + tokens_ns,
              std::memory_order_relaxed)) {
          return static_cast<int64_t>(0);
        }
      }
      now_ns = NowNs();
    }
  }

  double tokens_per_sec_;
  uint64_t capacity_;

  std::atomic<uint64_t> last_update_time_ns_;
  uint64_t ns_per_token_;
  uint64_t capacity_ns_;
};

Implement a token bucket `TokenBucket` in C++, which is an algorithm for traffic control. It can limit the rate of data transmission to prevent data from being transmitted too quickly or too slowly.
1. Implement a constructor based on raw pointers `TokenBucket(double tokens_per_sec, uint64_t capacity, uint64_t initial_tokens = 0)`, where `double tokens_per_sec` generates how many tokens per second, `uint64_t capacity` represents how many tokens there are at most, and `uint64_t initial_tokens` represent how many tokens there are at the beginning.
2. Implement interface `bool TryConsume(uint64_t tokens = 1)` to try to get `tokens`. Return `false` means need to wait, return `true` means already acquired.
3. Implement interface `int64_t ConsumeWithBorrow(uint64_t tokens = 1)` to get `tokens` and wait for how many nanoseconds.
4. Implement interface `int64_t GetWaitTime(uint64_t tokens = 1)` to get so many `tokens` and wait for how many nanoseconds.
5. Implement interface `void Return(uint64_t tokens = 1)` to return how many `tokens`.
6. Implement interface `double GetTokensPerSec() const ` to generate how many tokens per second.
7. Implement interface `uint64_t GetCapacity() const` to display the total number of tokens.

#include <bits/stdc++.h>
#<INSERT>

#include <chrono>
#include <cassert>

void testcase() {
  {
    TokenBucket tb(100, 10, 0);
    assert(tb.GetTokensPerSec() == 100.);
    assert(tb.GetCapacity() == 10U);
    auto start = TokenBucket::NowNs();
    for (int i = 0; i < 10; ++i) {
      tb.Consume(1);
    }
    assert(!tb.TryConsume());
    auto ms = (TokenBucket::NowNs() - start) / 1000000.0;
    assert(ms >= 50);
    assert(ms <= 150);
    std::this_thread::sleep_for(std::chrono::milliseconds(20));
    assert(tb.TryConsume());
  }
  {
    TokenBucket tb(1000, 1000, 1000);
    assert(tb.GetTokensPerSec() == 1000.);
    assert(tb.GetCapacity() == 1000U);
    auto start = TokenBucket::NowNs();
    auto r = tb.ConsumeWithBorrow(1000);
    assert(r == 0);
    r = tb.ConsumeWithBorrow(1000);
    auto ms = (TokenBucket::NowNs() - start) / 1000000.0;
    auto need_wait_time = r / 1000000.0;
    assert(need_wait_time <= 1000);
    assert(need_wait_time >= 500 - ms);

    need_wait_time = tb.GetWaitTime(1) / 1000000.0;
    ms = (TokenBucket::NowNs() - start) / 1000000.0;
    assert(need_wait_time >= 500 - ms);
  }
}

int main() {
  testcase();
  return 0;
}


#include <deque>
#include <functional>
#include <memory>
#include <mutex>

// ObjectCreater 封装了构造函数和初始化过程。默认实现为调用默认构造函数。
template <class T> struct DefaultObjectCreater {
  template <class... Args> T *operator()() { return new T(); }
};

// ObjectPool 必须以shared_ptr方式使用，才能保证Pool和对象都正确析构
template <class T, class N = DefaultObjectCreater<T>>
class ObjectPool : public std::enable_shared_from_this<ObjectPool<T, N>> {
public:
  using std::enable_shared_from_this<ObjectPool<T, N>>::shared_from_this;

  // 默认情况下可以申请的object无穷多个，池子总保留的object可以无穷多个
  // =0 等价于不设上限
  ObjectPool(size_t max_idle_object_num = 0, size_t max_total_object_num = 0)
      : _max_idle_object_num(max_idle_object_num),
        _max_total_object_num(max_total_object_num), _object_creater() {}

  // 使用传入的构造器
  ObjectPool(const N &creater, size_t max_idle_object_num = 0,
             size_t max_total_object_num = 0)
      : _max_idle_object_num(max_idle_object_num),
        _max_total_object_num(max_total_object_num), _object_creater(creater) {}

  // 使用移动传入的构造器
  ObjectPool(N &&creater, size_t max_idle_object_num = 0,
             size_t max_total_object_num = 0)
      : _max_idle_object_num(max_idle_object_num),
        _max_total_object_num(max_total_object_num),
        _object_creater(std::move(creater)) {}

  virtual ~ObjectPool() {
    for (auto &pobject : _objects) {
      delete pobject;
      pobject = nullptr;
    }
  }

  std::shared_ptr<T> get() {
    T *pobject = nullptr;
    bool create = false;
    {
      std::lock_guard<std::mutex> lock(_mutex);
      if (!_objects.empty()) {
        pobject = _objects.front();
        _objects.pop_front();
        --_idle_object_num;
      } else {
        if (_max_total_object_num == 0 ||
            _total_object_num < _max_total_object_num) {
          ++_total_object_num;
          create = true;
        }
      }
    }
    if (create) {
      pobject = _object_creater();
    }
    return std::shared_ptr<T>(pobject, ObjectDeleter(shared_from_this()));
  }

  void warmup(size_t num) {
    std::lock_guard<std::mutex> lock(_mutex);
    for (size_t i = 0;
         i < num &&
         (_max_total_object_num == 0 ||
          _total_object_num < _max_total_object_num) &&
         (_max_idle_object_num == 0 || _objects.size() < _max_idle_object_num);
         i++) {
      ++_total_object_num;
      auto pobject = _object_creater();
      _objects.push_back(pobject);
      ++_idle_object_num;
    }
  }

  size_t total_object_num() const { return _total_object_num; }

  size_t idle_object_num() const { return _idle_object_num; }

protected:
  void put(T *pobject) {
    if (!pobject)
      return;
    bool destroy = false;
    {
      std::lock_guard<std::mutex> lock(_mutex);
      if (_max_idle_object_num > 0 && _objects.size() >= _max_idle_object_num) {
        --_total_object_num;
        destroy = true;
      } else {
        _objects.push_back(pobject);
        ++_idle_object_num;
      }
    }
    if (destroy) {
      delete pobject;
    }
  }

  class ObjectDeleter {
  public:
    ObjectDeleter(std::shared_ptr<ObjectPool<T, N>> pool)
        : _pool(std::move(pool)) {}

    void operator()(T *pobject) { _pool->put(pobject); }

  private:
    std::shared_ptr<ObjectPool<T, N>> _pool;
  };

protected:
  std::deque<T *> _objects;
  volatile size_t _total_object_num = 0;
  volatile size_t _idle_object_num = 0;

  const size_t _max_idle_object_num;
  const size_t _max_total_object_num;

  std::mutex _mutex;
  N _object_creater;
};

template <class T, class N = DefaultObjectCreater<T>>
using ObjectPoolPtr = std::shared_ptr<ObjectPool<T, N>>;

Implement an object pool `ObjectPool` with C++ to avoid a large number of repeated object allocations/releases. It provides the following features:
1. Constructor: `ObjectPool(size_t max_idle_object_num = 0, size_t max_total_object_num = 0)`
    a. By default, there can be an infinite number of objects that can be requested, and the pool can always store an infinite number of objects;
    b. =0 is equivalent to no upper limit;
2. It supports passing in the custom object constructor;
2. `std::shared_ptr<T> get()`: It supports taking out an element from the objectpool, if it doesn't exist in the buffer pool, it will call the default constructor or pass in the constructor to construct the object
3. `void warmup(size_t num)`: It supports using num to warmup the objectpool to avoid start-up latency jitter.

#include <bits/stdc++.h>
#<INSERT>
#include <atomic>
#include <cassert>
#include <iostream>
#include <memory>

std::atomic_int32_t new_count = 0, delete_count = 0;

class Test {
public:
  Test() {
    new_count++;
    value_ = new_count;
  }
  ~Test() { delete_count++; }
  int get_value() const { return value_; }

public:
  int value_ = 0;
};

struct TestObjectCreater {
  Test *operator()() {
    Test *res = new Test();
    res->value_ = 42;
    return res;
  }
};

void testcase() {
  {
    ObjectPoolPtr<Test, TestObjectCreater> pool =
        std::make_shared<ObjectPool<Test, TestObjectCreater>>();
    pool->warmup(2);
    auto r1 = pool->get();
    assert(pool->total_object_num() == 2);
    assert(pool->idle_object_num() == 1);
    auto r2 = pool->get();
    assert(pool->idle_object_num() == 0);
    auto r3 = pool->get();
    assert(pool->idle_object_num() == 0);
    assert(pool->total_object_num() == 3);

    // recycle object
    r3.reset();
    r2.reset();
    assert(pool->idle_object_num() == 2);
    assert(pool->total_object_num() == 3);

    // get object again
    r2 = pool->get();
    assert(pool->idle_object_num() == 1);
    assert(pool->total_object_num() == 3);

    // check alloc & delloc count
    assert(new_count == 3);
    assert(delete_count == 0);

    // release obj pool
    pool.reset();
  }

  assert(new_count == 3);
  std::cout << delete_count << std::endl;
  assert(delete_count == 3);
}

int main() {
  testcase();
  return 0;
}


#include <iostream>
#include <math.h>
#include <unordered_map>
#include <utility>
#include <vector>

static const double EPS = 1e-8;

class CSRMatrix {
public:
  std::vector<double> values;
  std::vector<int> col_indices;
  std::vector<int> row_ptr;
  int numRows, numCols;
  CSRMatrix(int rows, int cols) : numRows(rows), numCols(cols) {
    row_ptr.resize(rows + 1, 0);
  }
  std::vector<std::vector<double>> to_dense() {
    std::vector<std::vector<double>> res(numRows,
                                         std::vector<double>(numCols, 0.0));
    for (int row = 0; row < numRows; ++row) {
      for (int index = row_ptr[row]; index < row_ptr[row + 1]; ++index) {
        res[row][col_indices[index]] = values[index];
      }
    }
    return res;
  }
  void from_dense(const std::vector<std::vector<double>> &matrix) {
    numRows = matrix.size();
    numCols = matrix[0].size();
    row_ptr.resize(numRows + 1, 0);
    values.clear();
    col_indices.clear();
    row_ptr[0] = 0;
    for (size_t i = 0; i < matrix.size(); ++i) {
      for (size_t j = 0; j < matrix[i].size(); ++j) {
        if (fabs(matrix[i][j]) > EPS) {
          col_indices.emplace_back(j);
          values.emplace_back(matrix[i][j]);
        }
      }
      row_ptr[i + 1] = values.size();
    }
  }
};

class CSCMatrix {
public:
  std::vector<double> values;
  std::vector<int> row_indices;
  std::vector<int> col_ptr;
  int numRows, numCols;

  CSCMatrix(int rows, int cols) : numRows(rows), numCols(cols) {
    col_ptr.resize(cols + 1, 0);
  }
  std::vector<std::vector<double>> to_dense() {
    std::vector<std::vector<double>> res(numRows,
                                         std::vector<double>(numCols, 0.0));

    for (int col = 0; col < numCols; ++col) {
      for (int index = col_ptr[col]; index < col_ptr[col + 1]; ++index) {
        res[row_indices[index]][col] = values[index];
      }
    }
    return res;
  }

  void from_dense(const std::vector<std::vector<double>> &matrix) {
    numRows = matrix.size();
    numCols = matrix[0].size();
    col_ptr.resize(numCols + 1, 0);
    values.clear();
    row_indices.clear();
    col_ptr[0] = 0;
    for (int col = 0; col < numCols; ++col) {
      for (int row = 0; row < numRows; ++row) {
        if (fabs(matrix[row][col]) > EPS) {
          row_indices.emplace_back(row);
          values.emplace_back(matrix[row][col]);
        }
      }
      col_ptr[col + 1] = values.size();
    }
  }
};

void sparseMatrixMultiply(const CSCMatrix &A, const CSRMatrix &B,
                          CSRMatrix &C) {
  if (A.numCols != B.numRows) {
    throw std::out_of_range("A.numCols != B.numRows");
  }
  C.numRows = A.numRows;
  C.numCols = B.numCols;
  C.row_ptr.resize(A.numRows + 1, 0);

  std::vector<std::vector<double>> dense_matrix(
      C.numRows, std::vector<double>(C.numCols, 0));
  for (int col = 0; col < A.numCols; ++col) {
    for (int index = A.col_ptr[col]; index < A.col_ptr[col + 1]; ++index) {
      const int &rowA = A.row_indices[index];
      const double &valA = A.values[index];
      // M1[rowA][col] = valA;
      // find M2[col][colB] = valB
      for (int k = B.row_ptr[col]; k < B.row_ptr[col + 1]; ++k) {
        const int &colB = B.col_indices[k];
        const double &valB = B.values[k];
        dense_matrix[rowA][colB] += valA * valB;
      }
    }
  }
  C.from_dense(dense_matrix);
}

Implement the multiplication of two sparse matrices, taking into account performance, we need to implement `CSCMatrix` and `CSRMatrix` respectively, and express the resulting outcome in `CSRMatrix` format.
1. For easy viewing and debugging, it is required to support the conversion between `CSRMatrix` and `CSCMatrix` and dense matrices
    Function signatures are: `std::vector<std::vector<double>> to_dense()` and `void from_dense(std::vector<std::vector<double>>)`
2. Support a multiplication function for a single sparse matrix alone: `void sparseMatrixMultiply(const CSCMatrix& A, CSRMatrix const & B, CSRMatrix& C)`

#include <bits/stdc++.h>
#<INSERT>

#include <atomic>
#include <cassert>
#include <iostream>
#include <memory>

std::vector<std::vector<double>>
multiply(const std::vector<std::vector<double>> &a,
         const std::vector<std::vector<double>> &b) {
  if (a[0].size() != b.size()) {
    throw std::out_of_range("A.numCols != B.numRows");
  }
  std::vector<std::vector<double>> res;
  res.resize(a.size(), std::vector<double>(b[0].size(), 0));
  for (int i = 0; i < a.size(); ++i) {
    for (int k = 0; k < b[0].size(); ++k) {
      for (int j = 0; j < a[0].size(); ++j) {
        res[i][k] += a[i][j] * b[j][k];
      }
    }
  }
  return res;
}

void print(const std::vector<std::vector<double>> &a) {
  for (int i = 0; i < a.size(); ++i) {
    for (int j = 0; j < a[i].size(); ++j) {
      printf("%lf%c", a[i][j], " \n"[j + 1 == a[i].size()]);
    }
  }
}

void testcase() {
  std::vector<std::vector<double>> A{
      {0, 1, 2, 3},
      {2, 3, 4, 5},
  };
  std::vector<std::vector<double>> B{
      {0, 1},
      {2, 3},
      {4, 5},
      {6, 7},
  };
  auto res = multiply(A, B);
  printf("dense matrix result:\n");
  print(res);

  CSCMatrix cscA(2, 4);
  CSRMatrix csrB(4, 2), csrC(2, 2);
  cscA.from_dense(A);
  csrB.from_dense(B);

  sparseMatrixMultiply(cscA, csrB, csrC);
  printf("cscA matrix:\n");
  print(cscA.to_dense());
  printf("csrB matrix:\n");
  print(csrB.to_dense());
  printf("csrC matrix:\n");
  print(csrC.to_dense());

  assert(res == csrC.to_dense());
}

int main() {
  testcase();
  return 0;
}


#include <functional>
#include <cassert>
#include <iostream>
#include <memory>
#include <thread>
#include <vector>
#include <mutex>
#if defined(__linux__)
#include <sched.h>
#elif defined(__APPLE__)
#include <mach/mach.h>
#include <mach/thread_act.h>
#include <pthread.h>
#endif

using namespace std;

template <template <class...> class MapImpl, class Key, class Value,
          class HashFn = hash<Key>, class KeyEqualFn = equal_to<Key>>
class ReadMostMap {
  static constexpr size_t kNoFalseSharingBytes =
#if __cplusplus >= 201703L and __cpp_lib_hardware_interference_size
    hardware_destructive_interference_size;
#elif defined(__arm__)
    64;
#else
    128;
#endif

 public:
  ReadMostMap(const size_t bucket_num,
              HashFn hash_fn = HashFn(),
              KeyEqualFn key_equal_fn = KeyEqualFn())
      : map_impl_(bucket_num, hash_fn, key_equal_fn),
        cpu_core_num_(thread::hardware_concurrency()),
        mem_placeholder_(nullptr) {
    assert(cpu_core_num_ > 0);
    int rv = posix_memalign(reinterpret_cast<void**>(&mem_placeholder_),
                            kNoFalseSharingBytes, cpu_core_num_ * MutexOccupyBytes());
    if (rv != 0) {
      throw std::bad_alloc();
    }
    assert(mem_placeholder_ != nullptr);
    for (auto i = 0u; i < cpu_core_num_; i++) {
      new (AtMutex(i)) std::mutex();
    }
  }

  ~ReadMostMap() {
    for (auto i = 0u; i < cpu_core_num_; ++i) {
      AtMutex(i)->~mutex();
    }
    free(mem_placeholder_);
  }

  bool Get(const Key& key, Value* value) {
    auto lk = Acquire();
    auto itr = map_impl_.find(key);
    if (itr != map_impl_.end()) {
      *value = itr->second;
      return true;
    } else {
      return false;
    }
  }

  void Set(const Key& key, const Value& value) {
    auto lock_vec = AcquireAll();
    map_impl_[key] = value;
  }

 private:
  static constexpr size_t MutexOccupyBytes() {
    return ((sizeof(mutex) + kNoFalseSharingBytes - 1)
            / kNoFalseSharingBytes * kNoFalseSharingBytes);
  }

  mutex* AtMutex(uint32_t i) const {
    assert(i < cpu_core_num_);
    return reinterpret_cast<mutex*>(mem_placeholder_ +
                                    i * MutexOccupyBytes());
  }

  vector<unique_lock<mutex>> AcquireAll() {
    vector<unique_lock<mutex>> lock_vec;
    lock_vec.reserve(cpu_core_num_);
    for (auto i = 0; i < cpu_core_num_; ++i) {
      lock_vec.emplace_back(Acquire(i));
    }
    return lock_vec;
  }

  unique_lock<mutex> Acquire(uint32_t i) {
    return unique_lock<mutex>(*AtMutex(i));
  }

  unique_lock<mutex> Acquire() {
    return Acquire(get_cpu_id());
  }

  static int get_cpu_id() {
#if defined(__linux__)
    return sched_getcpu();
#elif defined(__APPLE__)
    auto thread = mach_thread_self();

    thread_basic_info_data_t info;
    mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
    kern_return_t kr = thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)&info, &count);
    mach_port_deallocate(mach_task_self(), thread);

    if (kr != KERN_SUCCESS) {
      cerr << "Failed to get thread info: " << kr << endl;
      return 0;
    }
    return info.cpu_usage;
#else
    return 0;
#endif
  }

  MapImpl<Key, Value, HashFn, KeyEqualFn> map_impl_;
  const uint32_t cpu_core_num_;
  char* mem_placeholder_;
};

Implement the read-write lock type `ReadMostMap` in C++, which needs to meet the following requirements:
1. This `Map` supports concurrent reading and writing, and it is a scenario where reading is much more frequent than writing, with a read-to-write ratio of `>1000:1`. It needs to have excellent multi-core scalability.
2. The hash index implementation can be customized through templates.
3. The implementation of `Map` is template-based, allowing users to customize it flexibly.
4. The implementation of `Key, Value, HashFunc, EqualFunc` is template-based.
5. Implementing the interface `bool Get(const Key &key, Value *value)` for querying a 'Value' with a 'Key'. Returning 'true' means it has been found, while returning 'false' means the 'Key' does not exist.
6. Implement the interface `void Set(const Key &key, const Value &value)` that stores a 'Key/Value Pair' in the `Map`.
7. Support both Linux and MacOS platforms.

#include <bits/stdc++.h>
#<INSERT>

#include <cassert>
#include <unordered_map>
#include <string>

void testcase() {
  ReadMostMap<std::unordered_map, std::string, std::string> rm_map(1);
  std::string key = "k", value = "v";
  rm_map.Set(key, value);
  {
    std::string test_value;
    assert(rm_map.Get(key, &test_value));
    assert(test_value == value);
  }
  assert(!rm_map.Get(value, &key));
}

int main() {
  testcase();
  return 0;
}


#include <thread>
#include <memory>
#include <iostream>
#include <cassert>
#include <functional>

#if defined(__linux__)
#include <sched.h>
#elif defined(__APPLE__)
#include <mach/mach.h>
#include <mach/thread_act.h>
#include <pthread.h>
#endif

template <class T>
class CpuLocalStorage final {
  static constexpr size_t kNoFalseSharingBytes =
#if __cplusplus >= 201703L and __cpp_lib_hardware_interference_size
    hardware_destructive_interference_size;
#elif defined(__arm__)
    64;
#else
    128;
#endif

 public:
  template <class... Args>
  CpuLocalStorage(Args &&...args)
      : cpu_core_num_(std::thread::hardware_concurrency()),
        mem_placeholder_(nullptr) {
    assert(cpu_core_num_ > 0);
    int rv = posix_memalign(reinterpret_cast<void**>(&mem_placeholder_),
                            kNoFalseSharingBytes, cpu_core_num_ * ObjectOccupyBytes());
    if (rv != 0) {
      throw std::bad_alloc();
    }
    assert(mem_placeholder_ != nullptr);
    for (auto i = 0u; i < cpu_core_num_; ++i) {
      new (&At(i)) T(std::forward<Args>(args)...);
    }
  }

  ~CpuLocalStorage() {
    for (auto i = 0u; i < cpu_core_num_; ++i) {
      At(i).~T();
    }
  }

  T& At() { return At(get_cpu_id()); }

  T& At(uint32_t id) {
    assert(id < cpu_core_num_);
    return *(reinterpret_cast<T*>(mem_placeholder_ +
                                  id * ObjectOccupyBytes()));
  }

  const T& At() const { return At(get_cpu_id()); }

  const T& At(uint32_t id) const {
    assert(id < cpu_core_num_);
    return *(reinterpret_cast<const T*>(mem_placeholder_ +
                                        id * ObjectOccupyBytes()));
  }

  void ForEach(const std::function<void(const T&)>& cb) const {
    for (uint32_t i = 0; i < cpu_core_num_; ++i) {
      cb(At(i));
    }
  }

  void ForEach(const std::function<void(T*)>& cb) {
    for (uint32_t i = 0; i < cpu_core_num_; ++i) {
      cb(&At(i));
    }
  }

  uint32_t GetCpuNum() const {
    return cpu_core_num_;
  }

 private:
  static constexpr size_t ObjectOccupyBytes() {
    return ((sizeof(T) + kNoFalseSharingBytes - 1)
            / kNoFalseSharingBytes * kNoFalseSharingBytes);
  }

  static int get_cpu_id() {
#if defined(__linux__)
    return sched_getcpu();
#elif defined(__APPLE__)
    auto thread = mach_thread_self();

    thread_basic_info_data_t info;
    mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
    kern_return_t kr = thread_info(thread, THREAD_BASIC_INFO, (thread_info_t)&info, &count);
    mach_port_deallocate(mach_task_self(), thread);

    if (kr != KERN_SUCCESS) {
      std::cerr << "Failed to get thread info: " << kr << std::endl;
      return 0;
    }
    return info.cpu_usage;
#else
    return 0;
#endif
  }

  const uint32_t cpu_core_num_;
  char* mem_placeholder_;
};

Implement a local storage type `CpuLocalStorage` for `CPU` using C++. This concept is similar to Thread Local Storage (TLS), but it targets the CPU rather than the thread. In some high-performance computations, the CpuLocal type can help reduce competition between threads, thus improving performance. The following requirements need to be met:

1. Do not reference other third-party libraries to implement, but you can use the types provided in std.
2. It needs to be a template type used to store any type.
3. Implement the interface `T& At(), const T& At() const` to represent the object corresponding to the cpu id on which the thread is running.
4. Implement the interface `T& At(uint32_t cpu_id), const T& At(uint32_t cpu_id) const` to represent the object on the specified cpu.
5. Implement the interface `void ForEach(const std::function<void(T*)>& cb), void ForEach(const std::function<void(const T&)>& cb) const` to traverse and process the objects on each cpu.
6. Implement the interface `uint32_t GetCpuNum() const` for users to get the number of `CPU`.
7. Support both Linux and MacOS platforms.

#include <bits/stdc++.h>
#<INSERT>

#include <cassert>
#include <thread>

void testcase() {
  CpuLocalStorage<int> cpu_local_int(0);
  uint32_t cpu_num = cpu_local_int.GetCpuNum();
  uint32_t all_sum = 0;
  cpu_local_int.ForEach([&all_sum](const int &i) {
                          all_sum += i;
                        });
  assert(all_sum == 0);
  {
    uint32_t cpu_id = 0;
    cpu_local_int.ForEach([&cpu_id](int *i) {
                            *i = cpu_id++;
                          });
  }
  for (auto i = 0; i < cpu_num; ++i) {
    assert(cpu_local_int.At(i) == i);
  }
  auto cpu_id = cpu_local_int.At();
  assert(cpu_local_int.At(cpu_id) == cpu_id);
}

int main() {
  testcase();
  return 0;
}


#include <iostream>
#include <optional>
#include <string>
#include <utility>

class Status {
public:
  // 枚举类型表示状态代码
  enum Code { OK = 0, ERROR = 1 };

  // 默认构造函数表示成功状态
  Status() : code_(OK), message_("OK") {}

  const Status &status() const { return *this; }

  // 用指定的状态代码和消息构造 Status 对象
  Status(Code code, const std::string &message)
      : code_(code), message_(message) {}

  // 判断是否为成功状态
  bool ok() const { return code_ == OK; }

  // 获取状态代码
  Code code() const { return code_; }

  // 获取状态消息
  const std::string &message() const { return message_; }

  // 静态成员函数用于创建成功状态
  static Status OKStatus() { return Status(); }

  // 静态成员函数用于创建错误状态
  static Status ErrorStatus(const std::string &message) {
    return Status(ERROR, message);
  }

private:
  Code code_;
  std::string message_;
};

template <typename T> class Result {
public:
  // 成功结果构造函数
  Result(const T &value) : status_(Status::OKStatus()), value_(value) {}

  // 成功结果移动构造函数
  Result(T &&value) : status_(Status::OKStatus()), value_(std::move(value)) {}

  // 错误结果构造函数
  Result(const Status &status) : status_(status) {
    if (status.ok()) {
      throw std::invalid_argument(
          "Status must be an error for this constructor");
    }
  }

  // 错误结果构造函数
  Result(Status &&status) : status_(std::move(status)) {
    if (status_.ok()) {
      throw std::invalid_argument(
          "Status must be an error for this constructor");
    }
  }

  // 检查结果是否成功
  bool ok() const { return status_.ok(); }

  // 获取状态对象
  const Status &status() const { return status_; }

  // 获取返回值
  const T &value() const {
    if (!ok()) {
      throw std::runtime_error(
          "Result does not contain a value due to error status");
    }
    return *value_;
  }

  // 获取返回值（移动语义）
  T &&value() {
    if (!ok()) {
      throw std::runtime_error(
          "Result does not contain a value due to error status");
    }
    return std::move(*value_);
  }

private:
  Status status_;
  std::optional<T> value_;
};

#define RETURN_IF_ERROR(result)                                                \
  do {                                                                         \
    auto _result = (result);                                                   \
    if (!_result.ok()) {                                                       \
      return _result.status();                                                 \
    }                                                                          \
  } while (0)

#define CHECK_OR_RETURN(condition, message)                                    \
  do {                                                                         \
    if (!(condition)) {                                                        \
      return Status::ErrorStatus(message);                                     \
    }                                                                          \
  } while (0)

Implement a generic `Result` class using C++, which can wrap any type of return value, provide status information, and ensure as low overhead as possible via move semantics. This `Result` class will include a `Status` object, which is used to represent the operation status, as well as an optional return value.

#include <bits/stdc++.h>
#<INSERT>

#include <atomic>
#include <cassert>
#include <iostream>
#include <memory>

int v1 = 0, v2 = 0, v3 = 0;

Result<int> f1() {
  v1 = 42;
  return 42;
}

Result<int> f2() {
  v2 = 55;
  return Status::ErrorStatus("Error in f2");
}

Result<int> f3() {
  v3 = 100;
  return 100;
}

Result<int> t1() {
  auto r = f1();
  RETURN_IF_ERROR(r);

  r = f2();
  RETURN_IF_ERROR(r);

  r = f3();
  RETURN_IF_ERROR(r);

  return r;
}

Result<int> t2() {
  int ret = 0;
  auto r = f1();
  RETURN_IF_ERROR(r);
  ret += r.value();

  r = f3();
  RETURN_IF_ERROR(r);
  ret += std::move(r.value());

  return ret;
}

void testcase() {
  auto res = t1();
  assert(!res.ok());
  assert(v1 == 42 && v2 == 55 && v3 == 0);
  res = t2();
  assert(res.ok() && res.value() == 142 && v3 == 100);
}

int main() {
  testcase();
  return 0;
}


#include <memory>
#include <queue>
#include <sstream>
#include <stack>
#include <string>

using std::to_string;
// General to_string for individual elements
// template <typename T>
// std::string to_string(const T& value) {
//     std::ostringstream oss;
//     oss << value;
//     return oss.str();
// }

// Specialization for std::pair (used in map)
template <typename K, typename V>
std::string to_string(const std::pair<K, V> &p) {
  std::ostringstream oss;
  oss << p.first << ": " << p.second;
  return oss.str();
}

// Helper to check if a type has a const_iterator
template <typename T, typename = void>
struct has_const_iterator : std::false_type {};

template <typename T>
struct has_const_iterator<T, std::void_t<typename T::const_iterator>>
    : std::true_type {};

// General case for iterable containers
template <typename T> struct is_iterable : has_const_iterator<T> {};

// to_string for iterable containers
template <typename T>
std::string to_string(const T &container,
                      std::enable_if_t<is_iterable<T>::value, int> = 0) {
  std::ostringstream oss;
  oss << "{";
  for (auto it = container.begin(); it != container.end(); ++it) {
    oss << to_string(*it);
    if (std::next(it) != container.end())
      oss << ", ";
  }
  oss << "}";
  return oss.str();
}

template <typename Container>
std::string to_string(
    Container c,
    std::enable_if_t<
        std::is_same<Container,
                     std::queue<typename Container::value_type>>::value ||
            std::is_same<Container,
                         std::stack<typename Container::value_type>>::value,
        int> = 0) {
  std::ostringstream oss;
  std::deque<typename Container::value_type> temp;
  if constexpr (std::is_same<
                    Container,
                    std::queue<typename Container::value_type>>::value) {
    while (!c.empty()) {
      temp.push_back(c.front());
      c.pop();
    }
  } else if constexpr (std::is_same<
                           Container,
                           std::stack<typename Container::value_type>>::value) {
    while (!c.empty()) {
      temp.push_back(c.top());
      c.pop();
    }
  }
  oss << "{";
  for (auto it = temp.begin(); it != temp.end(); ++it) {
    oss << to_string(*it);
    if (std::next(it) != temp.end())
      oss << ", ";
  }
  oss << "}";
  return oss.str();
}

Please implement a function named to_string in C++, which should be able to accept various C++ container types as parameters, and return a stringified version.

Your implementation should support at least the following C++ container types:
- std::vector
- std::list
- std::deque
- std::set
- std::map
- std::queue
- std::stack

For each container type, the returned string format should comply with the following rules:
- For std::vector, std::list, std::deque, std::set and std::queue, the contents should be displayed in the order of their insertion, and returned in the form of "{item1, item2, ..., itemN}", where item1 to itemN are the elements in the container.
- For std::map, the contents should be returned in the form of "{key1: value1, key2: value2, ..., keyN: valueN}".
- For std::stack, the elements should be displayed in the order from the top of the stack to the bottom.

Note that your implementation should also work correctly when handling empty containers, and be able to return a string representing an empty container, namely "{}".

#include <bits/stdc++.h>
#<INSERT>

#include <atomic>
#include <cassert>
#include <iostream>
#include <memory>
#include <vector>
#include <list>
#include <deque>
#include <set>
#include <map>
#include <queue>
#include <stack>

void testcase() {

    // Vector
    std::vector<int> v{1, 2, 3, 4, 5};
    assert(to_string(v) == "{1, 2, 3, 4, 5}");

    // List
    std::list<int> l{1, 2, 3, 4, 5};
    assert(to_string(l) == "{1, 2, 3, 4, 5}");

    // Deque
    std::deque<int> d{1, 2, 3, 4, 5};
    assert(to_string(d) == "{1, 2, 3, 4, 5}");

    // Set
    std::set<int> s{1, 2, 3, 4, 5};
    assert(to_string(s) == "{1, 2, 3, 4, 5}");

    // Map
    std::map<int, std::string> m{{1, "one"}, {2, "two"}, {3, "three"}};
    assert(to_string(m) == "{1: one, 2: two, 3: three}");

    // Queue
    std::queue<int> q; q.push(1); q.push(2); q.push(3);
    assert(to_string(q) == "{1, 2, 3}");

    // Stack
    std::stack<int> s2; s2.push(1); s2.push(2); s2.push(3);
    std::cout << to_string(s2) << std::endl;
    assert(to_string(s2) == "{3, 2, 1}");
}

int main() {
  testcase();
  return 0;
}


#include <iostream>
#include <stdexcept>
#include <utility>

template <typename T> class SimpleVector {
public:
  SimpleVector() : size_(0), capacity_(1), data_(new T[capacity_]) {}

  ~SimpleVector() { delete[] data_; }

  SimpleVector(const SimpleVector &other)
      : size_(other.size_), capacity_(other.capacity_),
        data_(new T[other.capacity_]) {
    for (size_t i = 0; i < size_; ++i) {
      data_[i] = other.data_[i];
    }
  }

  SimpleVector(SimpleVector &&other) noexcept
      : size_(other.size_), capacity_(other.capacity_), data_(other.data_) {
    other.size_ = 0;
    other.capacity_ = 0;
    other.data_ = nullptr;
  }

  SimpleVector &operator=(const SimpleVector &other) {
    if (this != &other) {
      delete[] data_;
      size_ = other.size_;
      capacity_ = other.capacity_;
      data_ = new T[capacity_];
      for (size_t i = 0; i < size_; ++i) {
        data_[i] = other.data_[i];
      }
    }
    return *this;
  }

  SimpleVector &operator=(SimpleVector &&other) noexcept {
    if (this != &other) {
      delete[] data_;
      size_ = other.size_;
      capacity_ = other.capacity_;
      data_ = other.data_;
      other.size_ = 0;
      other.capacity_ = 0;
      other.data_ = nullptr;
    }
    return *this;
  }

  void push_back(const T &value) {
    if (size_ == capacity_) {
      resize(2 * capacity_);
    }
    data_[size_++] = value;
  }

  void push_back(T &&value) {
    if (size_ == capacity_) {
      resize(2 * capacity_);
    }
    data_[size_++] = std::move(value);
  }

  T &operator[](size_t index) {
    if (index >= size_) {
      throw std::out_of_range("Index out of range");
    }
    return data_[index];
  }

  const T &operator[](size_t index) const {
    if (index >= size_) {
      throw std::out_of_range("Index out of range");
    }
    return data_[index];
  }

  size_t size() const { return size_; }
  size_t capacity() const { return capacity_; }

private:
  void resize(size_t new_capacity) {
    T *new_data = new T[new_capacity];
    for (size_t i = 0; i < size_; ++i) {
      new_data[i] = std::move(data_[i]);
    }
    delete[] data_;
    data_ = new_data;
    capacity_ = new_capacity;
  }

  size_t size_;
  size_t capacity_;
  T *data_;
};

Please implement a SimpleVector class in C++ to simulate part of the functionality of std::vector. This class uses doubling capacity as its capacity expansion strategy and supports the following interfaces and functions:

1. `void push_back(const T& value)`: Used to add a lvalue element to the end of the dynamic array.
2. `void push_back(T&& value)`: Used to add a rvalue element to the end of the dynamic array.
3. `T& operator[](size_t index)` and `const T& operator[](size_t index) const`: Used to access the element at the specified index of the dynamic array. The former is used to get the element at the specified location of the non-const object, and the latter is used to get the element at the specified location of the const object.
4. `size_t size()` and `size_t capacity()`: The former is used to get the current number of elements in the dynamic array, and the latter is used to get the current capacity of the dynamic array.
5. Implement the copy constructor and move constructor based on the class itself.

Note: The terms "lvalue" and "rvalue" are new concepts introduced after C++11. Lvalues typically represent the identity of an object (i.e., a location in memory), whereas rvalues are either rvalues that do not have an object identity or lvalues that have been moved (represented by std::move).

For the above interfaces, please ensure memory safety during implementation to avoid memory leaks. Also, the class should provide strong exception safety, meaning that the state of the class remains consistent in case of an exception.

#include <bits/stdc++.h>
#<INSERT>

#include <atomic>
#include <cassert>
#include <iostream>
#include <memory>

void testcase() {
  SimpleVector<int> vec;
  vec.push_back(1);
  vec.push_back(2);
  int x = 3;
  vec.push_back(std::move(3));

  SimpleVector<int> vec2 = vec;
  SimpleVector<int> vec3 = std::move(vec);

  assert(vec.size() == 0);
  assert(vec2.size() == 3);
  assert(vec3.size() == 3);
  assert(vec2.capacity() == 4);
  assert(vec3.capacity() == 4);
  for (int i = 0; i < 3; ++i) {
    assert(vec2[i] == i + 1);
    assert(vec3[i] == i + 1);
  }
}

int main() {
  testcase();
  return 0;
}


#include <chrono>
#include <condition_variable>
#include <list>
#include <mutex>
#include <optional>
#include <thread>
#include <unordered_map>

template <typename K, typename V> class ExpiringLruCache {
public:
  using Clock = std::chrono::steady_clock;
  using TimePoint = Clock::time_point;

  explicit ExpiringLruCache(size_t capacity, std::chrono::seconds ttl)
      : capacity(capacity), ttl(ttl), stop(false) {
    cleanerThread = std::thread(&ExpiringLruCache::cleaner, this);
  }

  ~ExpiringLruCache() {
    {
      std::lock_guard<std::mutex> lock(mtx);
      stop = true;
    }
    cv.notify_all();
    cleanerThread.join();
  }

  void add(const K &k, const V &v) {
    std::lock_guard<std::mutex> lock(mtx);
    auto now = Clock::now();
    auto it = cache.find(k);
    if (it != cache.end()) {
      it->second.value = v;
      it->second.timestamp = now;
      usage.splice(usage.begin(), usage, it->second.usageIt);
      return;
    }
    if (cache.size() >= capacity) {
      auto last = usage.end();
      last--;
      cache.erase(*last);
      usage.pop_back();
    }
    usage.push_front(k);
    cache[k] = {v, now, usage.begin()};
  }

  std::optional<V> get(const K &key) {
    std::lock_guard<std::mutex> lock(mtx);
    auto now = Clock::now();
    auto it = cache.find(key);
    if (it == cache.end() || (now - it->second.timestamp) > ttl) {
      return std::nullopt;
    }
    usage.splice(usage.begin(), usage, it->second.usageIt);
    it->second.timestamp = now;
    return it->second.value;
  }

  size_t size() const {
    std::lock_guard<std::mutex> lock(mtx);
    return cache.size();
  }

private:
  struct CacheItem {
    V value;
    TimePoint timestamp;
    typename std::list<K>::iterator usageIt;
  };

  void cleaner() {
    while (true) {
      {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait_for(lock, ttl, [this] { return stop; });
        if (stop)
          break;
      }
      cleanUp();
    }
  }

  void cleanUp() {
    auto now = Clock::now();
    std::lock_guard<std::mutex> lock(mtx);
    for (auto it = cache.begin(); it != cache.end();) {
      if ((now - it->second.timestamp) > ttl) {
        usage.erase(it->second.usageIt);
        it = cache.erase(it);
      } else {
        ++it;
      }
    }
  }

  size_t capacity;
  std::chrono::seconds ttl;
  mutable std::mutex mtx;
  std::condition_variable cv;
  std::unordered_map<K, CacheItem> cache;
  std::list<K> usage;
  std::thread cleanerThread;
  bool stop;
};

Implement an ExpiringLruCache using C++, which supports thread safety, supports elimination by time, and supports the following interfaces:
1. `ExpiringLruCache(size_t capacity, std::chrono::seconds ttl)`: Constructor, specifies maximum capacity and expiration time.
2. `size_t size()`: Gets the current cache size.
3. `void add(const K &k, const V &v)`: Adds a record. If the cache is full, the oldest is eliminated.
4. `std::optional<Value> get(const Key &key)`: This access moves the record to the front, treating it as the most recent record.

#include <bits/stdc++.h>
#<INSERT>

#include <atomic>
#include <cassert>
#include <chrono>
#include <iostream>
#include <memory>
#include <thread>

void testcase() {
  ExpiringLruCache<int, std::string> cache(3, std::chrono::seconds(1));

  cache.add(1, "value1");
  cache.add(2, "value2");
  cache.add(3, "value3");

  auto value = cache.get(2);
  assert(value.has_value() && value.value() == "value2");

  std::this_thread::sleep_for(std::chrono::seconds(2));

  value = cache.get(2);
  assert(!value.has_value());
}

int main() {
  testcase();
  return 0;
}


#include <iostream>
#include <math.h>
#include <unordered_map>
#include <vector>

static const double EPS = 1e-8;

class CSRMatrix {
public:
  std::vector<double> values;
  std::vector<int> col_indices;
  std::vector<int> row_ptr;
  int numRows, numCols;
  CSRMatrix(int rows, int cols) : numRows(rows), numCols(cols) {
    row_ptr.resize(rows + 1, 0);
  }
  std::vector<std::vector<double>> to_dense() {
    std::vector<std::vector<double>> res(numRows,
                                         std::vector<double>(numCols, 0.0));
    for (int row = 0; row < numRows; ++row) {
      for (int index = row_ptr[row]; index < row_ptr[row + 1]; ++index) {
        res[row][col_indices[index]] = values[index];
      }
    }
    return res;
  }
  void from_dense(const std::vector<std::vector<double>> &matrix) {
    numRows = matrix.size();
    numCols = matrix[0].size();
    row_ptr.resize(numRows + 1, 0);
    values.clear();
    col_indices.clear();
    row_ptr[0] = 0;
    for (size_t i = 0; i < matrix.size(); ++i) {
      for (size_t j = 0; j < matrix[i].size(); ++j) {
        if (fabs(matrix[i][j]) > EPS) {
          col_indices.emplace_back(j);
          values.emplace_back(matrix[i][j]);
        }
      }
      row_ptr[i + 1] = values.size();
    }
  }
};

void sparseMatrixMultiply(const CSRMatrix &A, const CSRMatrix &B,
                          CSRMatrix &C) {
  if (A.numCols != B.numRows) {
    throw std::out_of_range("A.numCols != B.numRows");
  }
  C.numRows = A.numRows;
  C.numCols = B.numCols;
  C.row_ptr.resize(A.numRows + 1, 0);
  C.row_ptr[0] = 0;
  for (int row = 0; row < A.numRows; ++row) {
    std::unordered_map<int, double> row_result;
    for (int index = A.row_ptr[row]; index < A.row_ptr[row + 1]; ++index) {
      const int &colA = A.col_indices[index];
      const double &valA = A.values[index];
      // M1[row][colA] = valA;
      // find colB that have M2[colA][colB] = valB
      for (int k = B.row_ptr[colA]; k < B.row_ptr[colA + 1]; ++k) {
        const int &colB = B.col_indices[k];
        const double &valB = B.values[k];
        row_result[colB] += valA * valB;
      }
    }
    for (const auto &iter : row_result) {
      C.col_indices.emplace_back(iter.first);
      C.values.emplace_back(iter.second);
    }
    C.row_ptr[row + 1] = C.values.size();
  }
}

Implement a matrix `CSRMatrix` expressed in CSR format in C++, and implement the multiplication of these two sparse matrices, with the resulting output represented in the `CSRMatrix` format.
1. In order to facilitate inspection and debug, it is necessary to support the conversion of `CSRMatrix` into its dense matrix form in `CSRMatrix`. The function signatures are: `std::vector<std::vector<double>> to_dense()` and `void from_dense(const std::vector<std::vector<double>> &matrix)`
2. Individually support a multiplication function for a sparse matrix: `void sparseMatrixMultiply(const CSRMatrix& A, const CSRMatrix& B, CSRMatrix& C)`

#include <bits/stdc++.h>
#include <vector>
#<INSERT>

#include <atomic>
#include <cassert>
#include <iostream>
#include <memory>

std::vector<std::vector<double>>
multiply(const std::vector<std::vector<double>> &a,
         const std::vector<std::vector<double>> &b) {
  if (a[0].size() != b.size()) {
    throw std::out_of_range("A.numCols != B.numRows");
  }
  std::vector<std::vector<double>> res;
  res.resize(a.size(), std::vector<double>(b[0].size(), 0));
  for (int i = 0; i < a.size(); ++i) {
    for (int k = 0; k < b[0].size(); ++k) {
      for (int j = 0; j < a[0].size(); ++j) {
        res[i][k] += a[i][j] * b[j][k];
      }
    }
  }
  return res;
}

void print(const std::vector<std::vector<double>> &a) {
  for (int i = 0; i < a.size(); ++i) {
    for (int j = 0; j < a[i].size(); ++j) {
      printf("%lf%c", a[i][j], " \n"[j + 1 == a[i].size()]);
    }
  }
}

void testcase() {
  std::vector<std::vector<double>> A{
      {0, 1, 2, 3},
      {2, 3, 4, 5},
  };
  std::vector<std::vector<double>> B{
      {0, 1},
      {2, 3},
      {4, 5},
      {6, 7},
  };
  auto res = multiply(A, B);
  printf("dense matrix result:\n");
  print(res);

  CSRMatrix csrA(2, 4), csrB(4, 2), csrC(2, 2);
  csrA.from_dense(A);
  csrB.from_dense(B);
  sparseMatrixMultiply(csrA, csrB, csrC);
  printf("csrA matrix:\n");
  print(csrA.to_dense());
  printf("csrB matrix:\n");
  print(csrB.to_dense());
  printf("csrC matrix:\n");
  print(csrC.to_dense());

  assert(res == csrC.to_dense());
}

int main() {
  testcase();
  return 0;
}