-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathrain_drops_fill_sidewalk.js
119 lines (99 loc) · 3.22 KB
/
rain_drops_fill_sidewalk.js
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
/**
* The sidewalk is 1m long, rain drop is 1cm each
* find out how many rain drops will fill the sidewalk
* Time Complexity: O(N) --- N is the number of raindrops
*
* Idea:
* 1. Divide the sidewalk into 100 slots
* 2. Each slot has a dryStartPos and a dryEndPos
* 3. When a rain drop falls, update the current slot dryEndPos and the possible next slot's dryStartPos
* 4. If the current slot's dryEndPos - dryStartPos <= a delta (for example: 0.05), increment the number of filled slots
* 5. If the next slot's dryEndPos - dryStartPos <= a delta (for example: 0.05), increment the number of filled slots
* 6. The slidewalk is considered filled when the number of filled slots is 100
*/
class RainDrop {
constructor(startPos) {
this.startPos = startPos;
}
getStartPos() {
return this.startPos;
}
getEndPos() {
return this.startPos + 1;
}
}
class SideWalk {
constructor() {
//we just want the difference of the delta is small enough to consider "filled"
this.delta = 0.01;
this.numOfRainDrops = 0;
this.numOfFilledSlots = 0;
this.slots = [];
for (let i = 0; i < 100; i = i + 1) {
this.slots[i] = {};
this.slots[i].dryStartPos = i;
this.slots[i].dryEndPos = i + 1;
this.slots[i].isFilled = false;
}
}
addRainDrop(rainDrop) {
const startPos = rainDrop.getStartPos();
const endPos = rainDrop.getEndPos();
const slotIndex = Math.floor(startPos);
const curSlot = this.slots[slotIndex];
this.numOfRainDrops = this.numOfRainDrops + 1;
if (!curSlot.isFilled) {
//examine the current slot, update the dryEndPos
if (startPos < curSlot.dryEndPos) {
curSlot.dryEndPos = startPos;
}
curSlot.dryLength = curSlot.dryEndPos - curSlot.dryStartPos;
if ( curSlot.dryLength <= this.delta) {
//this means the current slot is filled already
curSlot.isFilled = true;
this.numOfFilledSlots = this.numOfFilledSlots + 1;
}
}
//examine the next slot, update the dryStartPos
const nextSlotIndex = slotIndex + 1;
if (nextSlotIndex < 100) {
const nextSlot = this.slots[slotIndex];
if (!nextSlot.isFilled) {
if (endPos > nextSlot.dryStartPos) {
nextSlot.dryStartPos = endPos;
nextSlot.dryLength = nextSlot.dryEndPos - nextSlot.dryStartPos;
if ( nextSlot.dryLength <= this.delta) {
//this means the next slot is filled already
nextSlot.isFilled = true;
this.numOfFilledSlots = this.numOfFilledSlots + 1;
}
}
}
}
}
getSlots() {
return this.slots;
}
isFilled() {
return this.numOfFilledSlots == 100;
}
getNumOfRainDrops() {
return this.numOfRainDrops;
}
}
function getRandomIntegerWithin(min, max) { //min inclusive, max exclusive
return Math.random() * (max - min) + min;
}
function getTotalNumberOfRainDropsUntilFilled(sidewalk) {
const rainDrops = [];
for(;;) {
const rdStartPos = getRandomIntegerWithin(0,100);
sidewalk.addRainDrop( new RainDrop(rdStartPos) );
if (sidewalk.isFilled()) {
break;
}
}
return sidewalk.getNumOfRainDrops();
}
const sidewalk = new SideWalk();
console.log(getTotalNumberOfRainDropsUntilFilled(sidewalk));