Implement memoizeAsync(fn) that memoizes an async function. Crucially,
concurrent calls with the same key must share the in-flight promise — not
launch separate requests.
solve(callGroups) simulates concurrent callers. Each group is an array of
argument lists that "arrive simultaneously". Return { results, calls }.
Sample tests