===== ISTEM =====
Solve the following programming task.

TASK: Deep Clone an Object

Write a function 'deepClone(obj)' that deeply copies a given JavaScript object or array (including nested objects, arrays and primitives) without sharing references. It must also clone Date and RegExp objects.

STARTER CODE (javascript):
function deepClone(obj) {
  // Write your code here
}

module.exports = { deepClone };


RULES:
- Keep the function name and signature EXACTLY as given.
- Return working code only. No explanations.
- Put the code in a single ``` block.
- Try to solve it first. If you genuinely cannot, write only this single
  line instead of producing faulty code: CANNOT_SOLVE

===== HAM YANIT =====
```javascript
function deepClone(obj) {
  const seen = new Map();

  function clone(value) {
    if (value === null || typeof value !== 'object') {
      return value;
    }

    if (seen.has(value)) {
      return seen.get(value);
    }

    if (value instanceof Date) {
      const d = new Date(value.getTime());
      seen.set(value, d);
      return d;
    }

    if (value instanceof RegExp) {
      const r = new RegExp(value.source, value.flags);
      r.lastIndex = value.lastIndex;
      seen.set(value, r);
      return r;
    }

    if (value instanceof Map) {
      const m = new Map();
      seen.set(value, m);
      value.forEach((v, k) => {
        m.set(clone(k), clone(v));
      });
      return m;
    }

    if (value instanceof Set) {
      const s = new Set();
      seen.set(value, s);
      value.forEach((v) => {
        s.add(clone(v));
      });
      return s;
    }

    if (Array.isArray(value)) {
      const arr = [];
      seen.set(value, arr);
      for (let i = 0; i < value.length; i++) {
        if (i in value) {
          arr[i] = clone(value[i]);
        }
      }
      return arr;
    }

    const proto = Object.getPrototypeOf(value);
    const result = Object.create(proto);
    seen.set(value, result);

    const keys = Object.keys(value);
    for (let i = 0; i < keys.length; i++) {
      const key = keys[i];
      result[key] = clone(value[key]);
    }

    const symbols = Object.getOwnPropertySymbols(value);
    for (let i = 0; i < symbols.length; i++) {
      const sym = symbols[i];
      if (Object.prototype.propertyIsEnumerable.call(value, sym)) {
        result[sym] = clone(value[sym]);
      }
    }

    return result;
  }

  return clone(obj);
}

module.exports = { deepClone };
```