package com.freetymekiyan.algorithms.level.hard;
/**
* The API: int read4(char *buf) reads 4 characters at a time from a file.
* <p>
* The return value is the actual number of characters read. For example, it returns 3 if there is only 3 characters
* left in the file.
* <p>
* By using the read4 API, implement the function int read(char *buf, int n) that reads n characters from the file.
* <p>
* Note:
* The read function may be called multiple times.
* <p>
* Company Tags: Bloomberg, Google, Facebook
* Tags: String
* Similar Problems: (E) Read N Characters Given Read4
*/
public class ReadNCharactersGivenRead42 {
/**
* The read4 API is defined in the parent class Reader4.
* int read4(char[] buf);
*/
public class Solution extends Reader4 {
private int bufPtr = 0;
private int bufCnt = 0;
private char[] buffer = new char[4];
/**
* Read from the file into an intermediate buffer.
* Write from that buffer to the outside buffer.
* If that buffer is used up, read from file again.
* If that buffer still has characters, keep for the next time.
* Return when we reach the end of file, or we reach n.
* | readBytes -> 0
* | while readBytes < n:
* | if bufPtr == 0:
* | Refill buffer and update bufCnt.
* | if bufCnt == 0, end of file and break.
* | while readBytes < n and bufPtr < bufCnt, means n not reached, buffer not used up.
* | Write from cache to outside buffer.
* | If bufPtr == bufCnt, reach the end:
* | Reset bufPtr for the next refill.
*/
public int read(char[] buf, int n) {
int readBytes = 0;
while (readBytes < n) {
if (bufPtr == 0) { // Refill intermediate buffer if needed.
bufCnt = read4(buffer);
}
if (bufCnt == 0) { // End of file.
break;
}
while (readBytes < n && bufPtr < bufCnt) { // Copy to outside buffer.
buf[readBytes++] = buffer[bufPtr++];
}
if (bufPtr == bufCnt) { // Intermediate buffer used up.
bufPtr = 0;
}
}
return readBytes;
}
}
/**
* What is the difference between call once and call multiple times?
* When you call read4() which reads 4 bytes into your buffer you might read more than you need.
* So you want to store those bytes.
* And next time you call read will start from those stored bytes, then read more from the file.
* <p>
* Example:
* You have 4 chars "a, b, c, d" in the file, and you want to call your function twice like this:
* read(buf, 1); // should return 'a'
* read(buf, 3); // should return 'b, c, d'
* All the 4 chars will be consumed in the first call of read4().
* So the tricky part of this question is:
* how can you preserve the remaining 'b, c, d' to the second call.
* https://discuss.leetcode.com/topic/36179/what-is-the-difference-between-call-once-and-call-multiple-times
*/
private class Reader4 {
int read4(char[] buf) {
return 0;
}
}
}