#include <iostream>
#include <ctime>
#include <random>
#include <cmath>
using namespace std;
#define NOT -1
#define INF 100000
const int N = 320;
const int M = 32;
const int clear_time = 50;
struct Menory
{
int id;
}p[M+9];
struct Page
{
int id;
int in;
int time;
int counter;
}pg[M+9];
int a[N+9], cnt;
int page[N+9], offset[N+9];
int diseffect;
void init();
void FIFO(int);
void LRU(int);
void LFU(int);
void NRU(int);
void OPT(int);
int main(){
srand(time(0));
for (int i = 0; i < N; i+=4) {
int m = rand() % N;
a[cnt++] = m + 1;
int m2 = rand() % (m + 2);
a[cnt++] = m2 + 1;
a[cnt++] = a[cnt-1] + 1;
int m3 = rand() % (N - (m2 + 2)) + m2 + 2;
a[cnt++] = m3 + 1;
}
for (int i = 0; i < cnt; i++) {
page[i] = a[i] / 10;
offset[i] = a[i] % 10;
cout << page[i] << " ";
}
cout << endl;
//LFU(8);
for (int i = 4; i <= 32; i++) {
cout << "---" << i << " page frames---" << endl;
FIFO(i);
LRU(i);
LFU(i);
NRU(i);
OPT(i);
cout << endl;
}
return 0;
}
void debug(int x) {
for (int i = 0; i < x; i++) {
cout << p[i].id << " ";
}
cout << endl;
}
void init() {
diseffect = 0;
for (int i = 0; i < M; i++) {
pg[i].in = -1;
pg[i].id = i;
pg[i].time = -1;
pg[i].counter = 0;
}
for (int i = 0; i < M; i++) {
p[i].id = i;
}
}
void FIFO(int size) {
init();
int head = 0;
bool full = 0;
for (int i = 0; i < cnt; i++) {
if (pg[page[i]].in == NOT) {
diseffect += 1;
if (full) {
pg[p[head].id].in = -1;
p[head].id = page[i];
pg[page[i]].id = head;
pg[page[i]].in = 1;
head++;
head %= size;
}
else {
p[head].id = page[i];
pg[page[i]].id = head;
pg[page[i]].in = 1;
head++;
head %= size;
if (head == 0) full = 1;
}
}
//debug(size);
}
printf("FIFO:%6.4lf\n", 1.0 - (double)diseffect / 320.0);
}
void OPT(int size) {
init();
int now_size = -1;
int dis[N+9];
for (int i = 0; i < cnt; i++) {
if (pg[page[i]].in == NOT) {
diseffect++;
if (now_size == size - 1) {
for (int j = 0; j < M; j++) {
dis[j] = INF;
}
int max_dis = 0;
int swap_id = 0;
for (int j = i + 1; j < cnt; j++) {
if (pg[page[j]].in != NOT) {
dis[page[j]] = __min(dis[page[j]], j - i);
}
}
for (int j = 0; j < size; j++) {
if (max_dis < dis[p[j].id]) {
max_dis = dis[p[j].id];
swap_id = p[j].id;
}
}
//cout << page[i] << endl;
//for (int j = 0; j < size; j++) cout << p[j].id<<":"<<dis[p[j].id] << " ";
//cout << endl;
p[pg[swap_id].id].id = page[i];
pg[page[i]].id = pg[swap_id].id;
pg[swap_id].in = -1;
}
else p[++now_size].id = page[i], pg[page[i]].id = now_size;
pg[page[i]].in = 1;
}
//debug(size);
}
printf("OPT:%6.4lf\n", 1.0 - (double)diseffect / 320.0);
}
void LRU(int size) {
init();
int now_size = -1;
int pre_time = 0;
for (int i = 0; i < cnt; i++) {
if (pg[page[i]].in == NOT) {
diseffect++;
if (now_size == size - 1) {
int min_time = INF;
int swap_id = 0;
//cout << page[i] << endl;
for (int j = 0; j < size; j++) {
//cout << p[j].id << ":" << pg[p[j].id].time << " ";
if (min_time > pg[p[j].id].time) {
min_time = pg[p[j].id].time;
swap_id = p[j].id;
}
}
//cout << endl;
p[pg[swap_id].id].id = page[i];
pg[swap_id].time = -1;
pg[swap_id].in = -1;
pg[page[i]].id = pg[swap_id].id;
pg[page[i]].in = 1;
pg[page[i]].time = pre_time;
}
else {
pg[page[i]].time = pre_time;
p[++now_size].id = page[i];
pg[page[i]].id = now_size;
}
pg[page[i]].in = 1;
}
else pg[page[i]].time = pre_time;
pre_time++;
//debug(size);
}
printf("LRU:%6.4lf\n", 1.0 - (double)diseffect / 320.0);
}
void NRU(int size) {
init();
int now = 0;
int now_size = -1;
for (int i = 0; i < cnt; i++) {
if (pg[page[i]].in == NOT) {
diseffect++;
if (now_size == size - 1) {
bool flag = 1;
int old = now;
while (flag) {
if (pg[now].counter == 0 && pg[now].in != NOT) {
flag = 0;
}
else {
now++;
now %= M;
if (now == old) {
for (int j = 0; j < M; j++) {
pg[j].counter = 0;
}
}
}
}
//cout << page[i] << " " << now << endl;
p[pg[now].id].id = page[i];
pg[page[i]].id = pg[now].id;
pg[now].in = -1;
}
else p[++now_size].id = page[i], pg[page[i]].id = now_size;
pg[page[i]].in = 1;
}
else {
pg[page[i]].counter = 1;
}
if (i%clear_time == 0) {
for (int j = 0; j < M; j++) {
pg[j].counter = 0;
}
}
//debug(size);
}
printf("NRU:%6.4lf\n", 1.0 - (double)diseffect / 320.0);
}
void LFU(int size) {
init();
int now_size = -1;
for (int i = 0; i < cnt; i++) {
if (pg[page[i]].in == NOT) {
diseffect++;
if (now_size == size - 1) {
int min_counter = INF;
int swap_id = 0;
for (int j = 0; j < M; j++) {
if (pg[j].in != NOT&&pg[j].counter<min_counter) {
min_counter = pg[j].counter;
swap_id = j;
}
else if (pg[j].in != NOT) {
pg[j].counter >>= 1;
}
}
//cout << page[i] << " " << swap_id << endl;
p[pg[swap_id].id].id = page[i];
pg[page[i]].id = pg[swap_id].id;
pg[page[i]].counter = 1;
pg[swap_id].in = -1;
}
else {
p[++now_size].id = page[i], pg[page[i]].id = now_size;
pg[page[i]].counter++;
}
pg[page[i]].in = 1;
}
else pg[page[i]].counter++;
//debug(size);
}
printf("LFU:%6.4lf\n", 1.0 - (double)diseffect / 320.0);
}