Return to Sender
This is an interactive problem.
A sender must reliably deliver a message over a network that may reorder, drop, and duplicate packets.
Real protocols like TCP solve this through sequence numbers, acknowledgments, and retransmission. In this problem, you will implement a minimal reliable transfer protocol on top of an unreliable network.
Packet Format
Packet {
src, dst, seq, payload
}
srcis the source of the packet (either"S"for Sender or"R"for Receiver).dstis the destination of the packet (either"S"or"R", must differ fromsrc).seqis a non-negative integer sequence number chosen by the sender of the packet.payloadis an arbitrary string.
Network API
net_send(packet)
net_recv(id)
- This API is already provided (you do not need to implement it).
net_sendenqueues a packet into the network.net_recv(id)returns the next packet whosedst == id, or a sentinel value if none are available. See the Notes section for the language-specific sentinel.- Packets may be dropped, reordered, or duplicated by the network. You cannot observe which packets are dropped.
Classes to Implement
Sender {
Sender(id, receiver_id, message)
tick()
done()
}
Receiver {
Receiver(id, sender_id)
tick()
result()
}
Sender
- The constructor takes in:
id: the Sender's identifier string ("S").receiver_id: the Receiver's identifier string ("R").message: the full byte string to be delivered.
tick()is called repeatedly by the judge. Returns nothing.done()returnstrueiff the Sender believes all data has been acknowledged by the Receiver.
Receiver
- The constructor takes in:
id: the Receiver's identifier string ("R").sender_id: the Sender's identifier string ("S").
tick()is called repeatedly by the judge. Returns nothing.result()returns the fully reconstructed message as a string once all data has arrived in order, or an empty string if reconstruction is incomplete.
Protocol
You may design your own protocol. However, it must satisfy the following requirements:
- The Sender splits
messageinto chunks and sends each chunk as an individual packet to the Receiver. Each packet may carry at most 1024 bytes of message data. Chunk sequence numbers must be contiguous non-negative integers starting from0. - The Receiver sends acknowledgment packets back to the Sender.
- The Sender uses acknowledgments to determine which chunks have been delivered, and retransmits chunks that appear to be lost. Any chunk not acknowledged within a fixed number of ticks must be retransmitted — the Sender must not wait indefinitely.
- The Receiver reconstructs the message in order from the received chunks.
- Duplicate chunks (same
seqreceived more than once) must be silently ignored by the Receiver.
The specific format of acknowledgment packets (their seq and payload fields) is up to you. You may also use the payload field of data packets to carry metadata alongside the message data. The Receiver has no other means of knowing the total message length or chunk count, so your protocol must communicate this explicitly — for instance, by including the total chunk count in every data packet's payload.
tick Semantics
The judge runs the simulation in discrete steps called ticks.
In each tick:
- Zero or more packets may already be available via
net_recv()(possibly out of order or duplicated). - The judge calls
sender.tick()andreceiver.tick()(order is unspecified). - Any packets the Sender or Receiver choose to send must be sent using
net_send()during theirtick()call.
Your tick() must:
- increment an internal tick counter (starting at
0) at the very start of each call, - repeatedly call
net_recv(my_id)until it returns the sentinel value, - process any packets addressed to that participant,
- update internal protocol state accordingly,
- send any required packets using
net_send().
Your tick() must not:
- block or wait for future packets,
- use real sockets or sleeping,
- assume packets arrive in order, exactly once, or at all.
Progress happens across multiple calls to tick().
Behavioral Requirements
Sender Rules
- The Sender must chunk the message before any
tick()is called. - The Sender must retransmit any chunk that has not been acknowledged within a fixed number of ticks. The Sender must not wait indefinitely for an acknowledgment.
- The Sender must not retransmit a chunk that has already been acknowledged.
done()must returntrueonly after the Sender has received evidence that all chunks have been delivered. Oncedone()returnstrue, it must remaintruefor all subsequent calls.
Receiver Rules
- The Receiver must send at least one acknowledgment per received data chunk.
- The Receiver must reconstruct the message in order:
result()must return the chunks concatenated in ascending order of their sequence numbers. - The Receiver must not include the payload of a duplicate chunk more than once in the reconstruction.
result()must return an empty string until the full message has been reconstructed. Onceresult()returns a non-empty string, it must always return that same string on all subsequent calls.tick()may continue to be called after reconstruction is complete. The Receiver must continue drainingnet_recv()and sending acknowledgments so the Sender can reachdone().
Out-of-Order, Dropped, and Duplicate Packets
Your implementation must be safe under any delivery pattern.
- If the Receiver gets chunk
seq = 5before chunks0–4, it must buffer chunk 5 and wait. - If a chunk is dropped entirely, the Sender must detect this via timeout and retransmit it.
- If the Receiver gets the same chunk twice, it must ignore the second copy.
- If the Sender gets the same acknowledgment twice, it must not retransmit an already-acknowledged chunk because of it.
- Any packet that does not match the expected protocol state (unrecognized payload format, wrong
src, wrongdst, or aseqthat has no meaning in the current context) must be silently ignored.
Network Model
The network has three parameters, hidden from you at runtime:
- Loss rate
p: each packet is independently dropped with probabilityp. - Reorder window
w: a delivered packet may be delayed by up towadditional ticks. - Duplication rate
d: a delivered packet may be delivered again with probabilityd.
You are guaranteed: 0 ≤ p ≤ 0.4, 0 ≤ w ≤ 5, 0 ≤ d ≤ 0.1.
Determinism
For the same sequence of delivered packets, your implementation must behave deterministically. You may not use randomness, real clocks, or OS-level timing. Use tick count as your notion of time.
Input / Output Format
The judge will compile and run your Sender and Receiver implementation in a hidden harness.
You do not need to write any custom input or output parsing.
Test Groups
| Group | Message size | p |
w |
d |
|---|---|---|---|---|
| 1 | ≤ 1024 B | 0 | 0 | 0 |
| 2 | ≤ 8192 B | 0 | 0–2 | 0 |
| 3 | ≤ 32768 B | 0–0.2 | 0–3 | 0 |
| 4 | ≤ 65536 B | 0–0.4 | 0–5 | 0–0.1 |
A test case is passed when sender.done() returns true, receiver.result() equals the original message, and both conditions are met within the tick limit of 10,000 ticks.
Notes
- You may not use OS networking APIs (no real sockets).
- You must implement the chunking, sequencing, acknowledgment, and retransmission logic yourself.
- At most 16
net_sendcalls (combined across Sender and Receiver) are allowed per tick. The judge will discard excess sends beyond this limit. - Each packet's
payloadmust not exceed 1100 bytes in total length. This gives 1024 bytes for message data and 76 bytes of headroom for any metadata your protocol requires. - At most 32
net_recvcalls are allowed per participant per tick. - The Sender and Receiver share the same process and the same tick timeline. Think of your
tick()implementations as two coroutines running in lockstep. net_recvsentinel by language: in C++,net_recvreturnsstd::optional<Packet>— check withif (!pkt)orwhile (auto pkt = net_recv(id)); in Python,net_recvreturnsNonewhen no packet is available — check withif pkt is None.
Running custom tests...