# 23. 文件缓存系统
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
class fileCacheSys() {
constructor(maxCacheSize) {
this.maxCacheSize = maxCacheSize;
this.currentCacheSize = 0;
this.cache = {};
this.minHeap= [];
this.time = 0;
}
compare(a, b) {
if (a.accessCount === b.accessCount) {
return a.lastAccessTime - b.lastAccessTime;
}
return a.accessCount - b.accessCount;
}
minHeapify(index) {
let smallest = index;
const leftChild = 2*index+1;
const rightChild = 2*index+2;
if(leftChild < this.minHeap.length && this.compare(this.minHeap[leftChild], this.minHeap[smallest]) < 0) {
smallest = leftChild;
}
if (rightChild < this.minHeap.length && this.compare(this.minHeap[rightChild], this.minHeap[smallest]) < 0) {
smallest = rightChild;
}
if (smallest !== index) {
[this.minHeap[smallest], this.minHeap[index]] = [this.minHeap[index], this.minHeap[smallest]]
this.minHeapify(smallest);
}
}
minHeapInsert(file) {
this.minHeap.push(file);
let index = this.minHeap.length - 1;
let parentIndex = Math.floor((index - 1)/2);
while(index >0 && this.compare(this.minHeap[index], this.minHeap[parentIndex]) < 0) {
[this.minHeap[parentIndex], this.minHeap[index]] = [this.minHeap[index], this.minHeap[parentIndex]]
index = parentIndex;
parentIndex = Math.floor((index - 1)/2);
}
}
minHeapPop() {
if (this.minHeap.length === 0) return null;
const minItem = this.minHeap[0];
this.minHeap[0] = this.minHeap[this.minHeap.length - 1];
this.minHeap.pop();
this.minHeapify(0);
return minItem;
}
minHeapRemove(file) {
const index = this.minHeap.findIndex(f => f.name === file.name)
if (index === -1) return;
this.minHeap[index] = this.minHeap[this.minHeap.length-1];
this.minHeap.pop();
this.minHeapify(index);
}
put(fileName, fileSize) {
if (fileSize > this.maxCacheSize) return;
const currentTime = Date.now();
if (this.cache[fileName]) {
this.get(fileName);
return;
}
while(this.currentCacheSize + fileSize > this.maxCacheSiz) {
const toRemove = this.minHeapPop();
if (toRemove) {
delete this.cache[toRemove.name];
this.currentCacheSize -= toRemove.size;
}
}
const file = {name: fileName, size: fileSize, accessCount: 1, lastAccessTime: currentTime};
this.cache[fileName] = file;
this.minHeapInsert(file);
this.currentCacheSize += fileSize;
}
get(fileName) {
if (!this.cache[fileName]) return;
const file = this.cache[fileName];
this.minHeapRemove(file);
file.accessCount++;
file.lastAccessTime = Date.now();
this.minHeapInsert(file);
}
getCurrentCache() {
const files = Object.keys(this.cache);
files.sort();
return files;
}
}
const lines = [];
rl.on('line', (line) => {
lines.push(line);
});
rl.on('close', () => {
const maxCacheSize = parseInt(lines[0]);
const opCount = parseInt(lines[1]);
const cacheSystem = new FileCacheSystem(maxCacheSize);
for(let i=2; i<opCount+2; i++) {
const input= lines[i].split(' ');
const op = input[0];
const fileName = input[1];
if (op === 'put') {
const fileSize = parseInt(input[2]);
cacheSystem.put(fileName, fileSize);
} else if (op === 'get') {
cacheSystem.get(fileName);
}
}
const currentCache = cacheSystem.getCurrentCache();
if (currentCache.length === 0) {
console.log('NONE');
} else {
console.log(currentCache.join(','));
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121