Middle · Trace · State contracts

Trace the complete program for bound duplicate-request decisions honestly. State the exact stdout, then justify the state transitions and relevant edge conditions.

Think through your answer before opening the explanation.

Coding interviews

using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

var ledger=new Ledger(2);
Console.WriteLine(ledger.Accept("x",10)); Console.WriteLine(ledger.Accept("x",10)); Console.WriteLine(ledger.Accept("x",11));
Console.WriteLine(ledger.Accept("y",20)); Console.WriteLine(ledger.Accept("z",30));
sealed class Ledger(int capacity) {
    private readonly Dictionary<string,int> values=new(StringComparer.Ordinal);
    public string Accept(string key,int amount) {
        if(string.IsNullOrEmpty(key) || amount<0 || capacity<1) return "invalid";
        if(values.TryGetValue(key,out int previous)) return previous==amount?"replay":"conflict";
        if(values.Count==capacity) return "full";
        values.Add(key,amount); return "accepted";
    }
}
Reveal answer and reasoning

The output lines, in order, are “accepted”; “replay”; “conflict”; “accepted”; “full”. x with amount ten is accepted, then repeated as replay. x with eleven conflicts with the saved amount. y fills the second entry and z cannot be admitted. Lookup happens before the capacity check, so a repeat does not require another slot. The printed outcomes come from actual dictionary state, not a mocked network service.

The third x request does not overwrite ten with eleven, so later replay still refers to the original accepted amount. After y is accepted, rejecting z leaves the dictionary unchanged. This ordering makes rejection nonmutating and keeps subsequent behavior predictable under the stated single-owner assumption.

Expected lookup and insertion cost are O(1) dictionary operations plus key hashing. Retained entry count is bounded by capacity, but key lengths and payload representation still affect memory. There is no eviction policy; dropping old keys would change the period over which retries can be recognized. This local dictionary is not thread-safe and cannot provide distributed exactly-once effects. Accepting a record before or after an external payment leaves a failure window unless storage and effect ownership are designed together.

A key reused with changed payload must not silently replay an unrelated result.

What a strong answer covers

  • Exact output: accepted | replay | conflict | accepted | full
  • x with amount ten is accepted, then repeated as replay.
  • This local dictionary is not thread-safe and cannot provide distributed exactly-once effects.

Common pitfall

This local dictionary is not thread-safe and cannot provide distributed exactly-once effects. Accepting a record before or after an external payment leaves a failure window unless storage and effect ownership are designed together. A key reused with changed payload must not silently replay an unrelated result.

Follow-up questions

  1. Replay x after the ledger is full and verify replay rather than full. Hint: capacity limits new ownership, not lookup of already owned decisions. Add invalid empty-key and negative-amount cases.
  2. What does idempotency-key expiry mean for a retry arriving after the retention horizon?

Self-review

Choose what to revisit. These marks are your own assessment and are separate from lesson completion.

Primary references

Open lesson and code ↗

← All interview questions