Implement the core of tail -n for a seekable file that may be many gigabytes without scanning it all when the requested suffix is small. Work through backward block reads, chunk boundaries, trailing-newline semantics, bounded memory, binary-versus-text handling, safe decoding, and mutation assumptions.
# Implement tail -n for a Very Large File
Design and implement the core of `tail -n`: given a seekable file and a non-negative integer `n`, return the final `n` logical lines without reading the entire file when the requested suffix is small.
The file may be many gigabytes. Explain binary-versus-text handling, newline semantics, chunk boundaries, decoding, and complexity. You may first solve for bytes with `\n` as the delimiter, then explain how decoded text is produced safely.
### Constraints & Assumptions
- The file is seekable and its size can be queried.
- Reads should occur in bounded chunks from the end toward the beginning.
- A file may be empty or may end with or without a newline.
- `n == 0` returns an empty result.
### Clarifying Questions to Ask
- Does a trailing newline create an additional empty logical line?
- Which encoding is used, and how should invalid byte sequences be handled?
- Must output preserve exact line-ending bytes?
- Can the file change while it is being read?
### What a Strong Answer Covers
- Backward block reads with correct prepending and stopping conditions
- No lost or duplicated bytes at chunk boundaries
- Explicit trailing-newline and empty-file behavior
- Decoding only after complete byte ranges are assembled
- Worst-case complexity and snapshot or mutation assumptions
### Follow-up Questions
- What changes for a non-seekable stream?
- How would you implement follow mode for an actively growing file?
- How would file rotation be detected?
- What test cases expose off-by-one newline bugs?
Quick Answer: Implement the core of tail -n for a seekable file that may be many gigabytes without scanning it all when the requested suffix is small. Work through backward block reads, chunk boundaries, trailing-newline semantics, bounded memory, binary-versus-text handling, safe decoding, and mutation assumptions.
Design and implement the core of tail -n: given a seekable file and a non-negative integer n, return the final n logical lines without reading the entire file when the requested suffix is small.
The file may be many gigabytes. Explain binary-versus-text handling, newline semantics, chunk boundaries, decoding, and complexity. You may first solve for bytes with \n as the delimiter, then explain how decoded text is produced safely.
Constraints & Assumptions
The file is seekable and its size can be queried.
Reads should occur in bounded chunks from the end toward the beginning.
A file may be empty or may end with or without a newline.
n == 0
returns an empty result.
Clarifying Questions to Ask Guidance
Does a trailing newline create an additional empty logical line?
Which encoding is used, and how should invalid byte sequences be handled?
Must output preserve exact line-ending bytes?
Can the file change while it is being read?
What a Strong Answer Covers Guidance
Backward block reads with correct prepending and stopping conditions
No lost or duplicated bytes at chunk boundaries
Explicit trailing-newline and empty-file behavior
Decoding only after complete byte ranges are assembled
Worst-case complexity and snapshot or mutation assumptions
Follow-up Questions Guidance
What changes for a non-seekable stream?
How would you implement follow mode for an actively growing file?