Implement tail N lines
Company: Confluent
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
##### Question
Implement a utility `tail(path: string, N: int)` (and an equivalent stream variant) that prints the **last N lines** of input without loading the whole input into memory. Assume variable-length lines, an unknown total line count, and a file that may be many gigabytes.
Your solution must address both input modes and the full set of correctness constraints below:
1. **Seekable / random-access file.** Use either a backward scan (seek to the end and read fixed-size blocks toward the front, counting newlines until you have collected N lines) or a fixed-size ring buffer over a forward read. Avoid re-reading the whole file.
2. **Non-seekable / unbounded stream (stdin or a pipe).** Seeking is impossible and the length is unknown, so maintain only **O(N)** memory — a ring buffer of the last N lines — while reading forward exactly once.
3. **Memory bound.** Never read the entire file into memory; memory must be bounded by N (and one line), not by file size.
4. **Newline conventions.** Correctly handle Unix `LF` (`\n`), Windows `CRLF` (`\r\n`), and classic Mac `CR` (`\r`) line endings, including a mix.
5. **UTF-8 correctness.** Split on line boundaries at the byte level but preserve UTF-8 multibyte characters — never cut a character in the middle when reading or buffering blocks.
6. **Missing trailing newline.** A final line not terminated by a newline must still count as a line and be emitted.
7. **Extremely long lines.** A single line may exceed your buffer/block size; handle lines larger than the read buffer without corruption.
8. State the **time and space complexity** of each approach and give the **key test cases** you would write.
**Follow-ups the interviewer will push on:**
- Extend to `tail -f`: follow the file as it grows, emitting new lines as they are appended.
- Handle **log rotation / truncation** and **symlinks** (detect when the file is replaced or truncated and re-open / reset position).
- Support the `-c N` option: print the last N **bytes** instead of the last N lines.
Overview: Confluent software-engineer technical-screen coding question: implement tail(path, N) to print the last N lines of a possibly multi-GB file or an unbounded stream without loading it into memory. It tests a backward block scan for seekable files versus an O(N) ring buffer for non-seekable streams, plus correct handling of \n/\r\n/\r newlines, UTF-8 multibyte characters, missing trailing newlines, and extremely long lines, with follow-ups on tail -f, log rotation/truncation, and the -c last-N-bytes option.