Showing
10 changed files
with
229 additions
and
0 deletions
.gitignore
0 → 100644
1 | +node_modules | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
package.json
0 → 100644
src/allocate.js
0 → 100644
1 | +const { assign } = require("./tools"); | ||
2 | + | ||
3 | +function searchBlock(state, process) { | ||
4 | + let candidates = state | ||
5 | + .map((block, key) => assign(block, { key })) | ||
6 | + .filter(block => block.id == -1 && block.size >= process.size); | ||
7 | + | ||
8 | + candidates.sort((blockX, blockY) => { | ||
9 | + const x = blockY.size; | ||
10 | + const y = blockY.size; | ||
11 | + if (x < y) return -1; | ||
12 | + else if (x > y) return 1; | ||
13 | + else return 0; | ||
14 | + }); | ||
15 | + | ||
16 | + return candidates.length != 0 ? candidates[0].key : -1; | ||
17 | +} | ||
18 | + | ||
19 | +const getCapacity = state => | ||
20 | + state | ||
21 | + .filter(block => block.id == -1) | ||
22 | + .reduce((capacity, block) => capacity + block.size, 0); | ||
23 | + | ||
24 | +function insert(state, process, target) { | ||
25 | + const bound = target.from + process.size; | ||
26 | + | ||
27 | + return target.size == process.size | ||
28 | + ? [assign(target, { id: process.id })] | ||
29 | + : [ | ||
30 | + assign(target, { id: process.id, size: process.size }), | ||
31 | + assign(target, { size: target.size - process.size }) | ||
32 | + ]; | ||
33 | +} | ||
34 | + | ||
35 | +function compact(state) { | ||
36 | + const size = getCapacity(state); | ||
37 | + return [...state.filter(block => block.id != -1), { id: -1, size }]; | ||
38 | +} | ||
39 | + | ||
40 | +function allocate(state, process) { | ||
41 | + const capacity = getCapacity(state); | ||
42 | + | ||
43 | + if (capacity < process.size) { | ||
44 | + throw new Error("OUT OF MEMORY"); | ||
45 | + } | ||
46 | + | ||
47 | + let idx = searchBlock(state, process); | ||
48 | + | ||
49 | + if (idx == -1) { | ||
50 | + state = compact(state); | ||
51 | + idx = searchBlock(state, process); | ||
52 | + } | ||
53 | + | ||
54 | + const target = state[idx]; | ||
55 | + const nextState = [ | ||
56 | + ...state.slice(0, idx), | ||
57 | + ...insert(state, process, target), | ||
58 | + ...state.slice(idx + 1) | ||
59 | + ]; | ||
60 | + const offset = idx; | ||
61 | + return nextState; | ||
62 | +} | ||
63 | + | ||
64 | +module.exports = allocate; |
src/free.js
0 → 100644
1 | +const { assign } = require("./tools"); | ||
2 | + | ||
3 | +function coalscence(state) { | ||
4 | + const last = xs => xs[xs.length - 1]; | ||
5 | + const join = (state, block) => [ | ||
6 | + ...state.slice(0, -1), | ||
7 | + { id: -1, size: block.size + last(state).size } | ||
8 | + ]; | ||
9 | + | ||
10 | + const [firstBlock, ...restBlock] = state; | ||
11 | + | ||
12 | + let idx = -1; | ||
13 | + let offset = 0; | ||
14 | + const nextState = restBlock.reduce( | ||
15 | + (nextState, block) => { | ||
16 | + offset += block.size; | ||
17 | + if (last(nextState).id == -1 && block.id == -1) { | ||
18 | + idx = offset; | ||
19 | + return join(nextState, block); | ||
20 | + } else { | ||
21 | + return [...nextState, block]; | ||
22 | + } | ||
23 | + }, | ||
24 | + [firstBlock] | ||
25 | + ); | ||
26 | + return nextState; | ||
27 | +} | ||
28 | + | ||
29 | +function free(state, pid) { | ||
30 | + const nextState = state.map( | ||
31 | + block => (block.id == pid ? assign(block, { id: -1 }) : block) | ||
32 | + ); | ||
33 | + return coalscence(nextState); | ||
34 | +} | ||
35 | + | ||
36 | +module.exports = free; |
src/index.js
0 → 100644
1 | +const allocate = require("./allocate"); | ||
2 | +const free = require("./free"); | ||
3 | +const { printMemory, printStatus } = require("./print"); | ||
4 | +const parse = require("./parse"); | ||
5 | +const fs = require("fs"); | ||
6 | + | ||
7 | +function run(request, state) { | ||
8 | + const { type, payload } = request; | ||
9 | + const method = type == "allocate" ? allocate : free; | ||
10 | + const head = | ||
11 | + type == "allocate" | ||
12 | + ? `Request ${payload.id}: ${payload.size}K` | ||
13 | + : `Free Request ${payload}`; | ||
14 | + | ||
15 | + const nextState = method(state, payload); | ||
16 | + printMemory(nextState); | ||
17 | + printStatus(nextState); | ||
18 | + return nextState; | ||
19 | +} | ||
20 | + | ||
21 | +try { | ||
22 | + const raw = String(fs.readFileSync("test.txt")); | ||
23 | + const { MAX_CAPACITY, requests } = parse(raw); | ||
24 | + const init = { id: -1, size: MAX_CAPACITY }; | ||
25 | + let state = [init]; | ||
26 | + | ||
27 | + for (const request of requests) state = run(request, state); | ||
28 | +} catch (e) { | ||
29 | + console.error(e); | ||
30 | +} |
src/parse.js
0 → 100644
1 | +function buffer2(xs) { | ||
2 | + | ||
3 | + const ys = xs.filter((_, i) => !(i % 2)); | ||
4 | + const zs = xs.filter((_, i) => i % 2); | ||
5 | + let ws = []; | ||
6 | + | ||
7 | + for (let i = 0; i < ys.length; ++i) { | ||
8 | + ws.push([ys[i], zs[i]]); | ||
9 | + } | ||
10 | + return ws; | ||
11 | +} | ||
12 | + | ||
13 | +function parse(raw) { | ||
14 | + const [MAX_CAPACITY, rawRequests] = raw.split(/\r?\n/); | ||
15 | + const requests = buffer2(rawRequests.split(" ").map(v => parseInt(v))).map( | ||
16 | + ([id, size]) => | ||
17 | + size | ||
18 | + ? { type: "allocate", payload: { id, size } } | ||
19 | + : { type: "free", payload: id } | ||
20 | + ); | ||
21 | + return { MAX_CAPACITY, requests } | ||
22 | +} | ||
23 | + | ||
24 | +module.exports = parse; | ||
... | \ No newline at end of file | ... | \ No newline at end of file |
src/print.js
0 → 100644
1 | +function printMemory(state) { | ||
2 | + let addr = 0; | ||
3 | + console.log(`----------------`); | ||
4 | + for (const block of state) { | ||
5 | + if (block.id == -1) { | ||
6 | + console.log(`| free |`); | ||
7 | + } else { | ||
8 | + const pid = `${block.id}`.padStart(6, " "); | ||
9 | + console.log(`| pid: ${pid} |`); | ||
10 | + } | ||
11 | + const size = `${block.size}`.padStart(5, " "); | ||
12 | + const from = `${addr}`.padStart(5, " "); | ||
13 | + addr += block.size; | ||
14 | + const to = `${addr}`.padStart(5, " "); | ||
15 | + console.log(`| |`); | ||
16 | + console.log(`| size: ${size}K |`); | ||
17 | + console.log(`| from: ${from}K |`); | ||
18 | + console.log(`| to: ${to}K |`); | ||
19 | + console.log(`----------------`); | ||
20 | + } | ||
21 | +} | ||
22 | + | ||
23 | +function printStatus(state) { | ||
24 | + const freeBlocks = state.filter(block => block.id == -1); | ||
25 | + const count = freeBlocks.length; | ||
26 | + const totalFree = freeBlocks.reduce((z, block) => z + block.size, 0); | ||
27 | + console.log(`${totalFree}K free`); | ||
28 | + console.log(`${count} block(s)`); | ||
29 | + console.log(`Average: ${Math.round(totalFree / count)}\n`); | ||
30 | +} | ||
31 | + | ||
32 | +module.exports = { printMemory, printStatus }; |
src/tools.js
0 → 100644
test.txt
0 → 100644
yarn.lock
0 → 100644
1 | +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. | ||
2 | +# yarn lockfile v1 | ||
3 | + | ||
4 | + | ||
5 | +fs-extra@^6.0.1: | ||
6 | + version "6.0.1" | ||
7 | + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-6.0.1.tgz#8abc128f7946e310135ddc93b98bddb410e7a34b" | ||
8 | + dependencies: | ||
9 | + graceful-fs "^4.1.2" | ||
10 | + jsonfile "^4.0.0" | ||
11 | + universalify "^0.1.0" | ||
12 | + | ||
13 | +graceful-fs@^4.1.2, graceful-fs@^4.1.6: | ||
14 | + version "4.1.11" | ||
15 | + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" | ||
16 | + | ||
17 | +jsonfile@^4.0.0: | ||
18 | + version "4.0.0" | ||
19 | + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" | ||
20 | + optionalDependencies: | ||
21 | + graceful-fs "^4.1.6" | ||
22 | + | ||
23 | +universalify@^0.1.0: | ||
24 | + version "0.1.1" | ||
25 | + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" |
-
Please register or login to post a comment