Skip to content

Commit dc07ba6

Browse files
committed
refacoring stack class to module
1 parent 93b86c5 commit dc07ba6

File tree

3 files changed

+271
-0
lines changed

3 files changed

+271
-0
lines changed

04-chapter-Stack/04-chapter-Stacks.js

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
// Stack data structure class example
2+
class Stack {
3+
constructor(dataStore = [], top = 0) {
4+
this.dataStore = dataStore;
5+
this.top = top;
6+
}
7+
8+
push(element) {
9+
this.dataStore[this.top++] = element;
10+
}
11+
12+
pop() {
13+
this.dataStore.splice(--this.top,1);
14+
}
15+
16+
peek() {
17+
return this.dataStore[this.top - 1];
18+
}
19+
20+
length() {
21+
return this.top;
22+
}
23+
24+
clear() {
25+
this.top = 0;
26+
}
27+
}
28+
29+
function checkBalancedExpression(e) {
30+
const s = new Stack();
31+
let balanced = false;
32+
33+
for(const key in e) {
34+
if(e[key] === '(') {
35+
s.push(e[key]);
36+
} else if(e[key] === ')') {
37+
if (s.length() === 0) {
38+
balanced = false;
39+
}
40+
s.pop();
41+
}
42+
if (s.length() > 0) {
43+
balanced = false;
44+
} else {
45+
balanced = true;
46+
}
47+
}
48+
return balanced;
49+
}
50+
51+
// Implementation
52+
// ###########################################
53+
/*
54+
1. A stack can be used to ensure that an arithmetic expression has balanced
55+
parentheses. Write a function that takes an arithmetic expression as an argument
56+
and returns the postion in the expression where a parenthesis is missing.
57+
An example of an arithmetic expression with unbalanced parentheses
58+
is 2.3 + 23 / 12 + (3.14159 * .24.
59+
*/
60+
61+
let exp = '2.3 + 23 / 12 + (3.14159 * .24';
62+
let e = exp.split('');
63+
64+
e = e.filter(item => item !== ' ');
65+
let balanced = checkBalancedExpression(e)
66+
67+
let exp2 = '2.3 + (23 / 12) + (3.14159 * .24)';
68+
let e2 = exp2.split('');
69+
70+
e2 = e2.filter(item => item !== ' ');
71+
let balanced2 = checkBalancedExpression(e2)
72+
73+
console.log('CHAPTER 4');
74+
console.log('### Excercise 1');
75+
console.log(`Expression example: ${exp}`);
76+
(balanced) ? console.log('The expression is balanced') : console.log('The expression is no balanced');
77+
78+
console.log(`\nExpression example: ${exp2}`);
79+
(balanced2) ? console.log('The expression is balanced') : console.log('The expression is no balanced');
80+
81+
// ###########################################
82+
/*
83+
2. A postfix expression evaluator works on arithmetic expressions taking the following form:
84+
op1 op2 operator
85+
Using two stacks—one for the operands and one for the operators—design and implement
86+
a JavaScript function that converts infix expressions to postfix expres‐ sions, and
87+
then use the stacks to evaluate the expression.
88+
*/
89+
90+
function checkOperator(op) {
91+
switch (op) {
92+
case ')':
93+
return 4;
94+
case '(':
95+
return 3;
96+
case '/':
97+
return 2;
98+
case '*':
99+
return 2;
100+
case '+':
101+
return 1;
102+
case '-':
103+
return 1;
104+
}
105+
}
106+
107+
function infixToPostfix(exp) {
108+
let value = '';
109+
const stack = new Stack();
110+
const postfix = new Stack();
111+
112+
for (const key in exp) {
113+
if(exp[key] === '(' || exp[key] === ')' || exp[key] === '+' ||
114+
exp[key] === '-' || exp[key] === '*' || exp[key] === '/' ) {
115+
if(value !== '') {
116+
postfix.push(value);
117+
}
118+
if(stack.length() === 0 && exp[key] !== '(') {
119+
stack.push(exp[key]);
120+
} else {
121+
if(checkOperator(exp[key]) !== 3) {
122+
innerLoop:
123+
while(stack.length() > 0) {
124+
if(checkOperator(exp[key]) < checkOperator(stack.peek())) {
125+
postfix.push(stack.peek());
126+
stack.pop();
127+
} else if (checkOperator(exp[key]) === checkOperator(stack.peek())) {
128+
postfix.push(stack.peek());
129+
stack.pop();
130+
stack.push(exp[key]);
131+
break innerLoop;
132+
} else {
133+
if(checkOperator(exp[key]) !== 4) {
134+
stack.push(exp[key]);
135+
}
136+
break innerLoop;
137+
}
138+
}
139+
}
140+
}
141+
value = '';
142+
} else {
143+
value += exp[key];
144+
}
145+
}
146+
147+
while(stack.length() > 0) {
148+
postfix.push(stack.peek());
149+
stack.pop();
150+
}
151+
return postfix;
152+
}
153+
154+
function evalPostFix(exp) {
155+
const resultStack = new Stack();
156+
const postfix = exp.dataStore;
157+
158+
for(const key in postfix) {
159+
if(!isNaN(postfix[key])) {
160+
resultStack.push(postfix[key]);
161+
} else {
162+
163+
const a = resultStack.peek();
164+
resultStack.pop();
165+
const b = resultStack.peek();
166+
resultStack.pop();
167+
168+
if(postfix[key] === "+") {
169+
resultStack.push((parseFloat(a, 10) + parseFloat(b, 10)).toFixed(2));
170+
} else if(postfix[key] === "-") {
171+
resultStack.push((parseFloat(b, 10) - parseFloat(a, 10)).toFixed(2));
172+
} else if(postfix[key] === "*") {
173+
resultStack.push((parseFloat(a, 10) * parseFloat(b, 10)).toFixed(2));
174+
} else if(postfix[key] === "/") {
175+
resultStack.push((parseFloat(b, 10) / parseFloat(a, 10)).toFixed(2));
176+
}
177+
}
178+
}
179+
return resultStack.dataStore[0];
180+
}
181+
182+
console.log('\n\n### Excercise 2');
183+
console.log(`Infix => ${exp2}`);
184+
const postfix = infixToPostfix(e2);
185+
console.log(`Postfix => ${postfix.dataStore.reduce((total, value) => total + ' ' + value )}`);
186+
evalPostFix(postfix);
187+
console.log(`Evaluation => ${evalPostFix(postfix)}`);
188+
189+
// ###########################################
190+
/*
191+
3. An example of a real-world stack is a Pez dispenser. Imagine that your virtual Pez dispenser
192+
is filled with red, yellow, and white colors and you don’t like the yellow ones. Write a program
193+
that uses a stack (and maybe more than one) to replace the yellow ones for another color without
194+
changing the order of the other candies in the dispenser.
195+
*/
196+
function getCandy() {
197+
switch (parseInt(Math.random() * (4 - 1) + 1, 10)) {
198+
case 1:
199+
return 'red';
200+
case 2:
201+
return 'yellow';
202+
case 3:
203+
return 'white';
204+
}
205+
}
206+
function replaceStackElements(pezDispender) {
207+
const replace = new Stack();
208+
const temporal = new Stack();
209+
210+
while (pezDispender.length() > 0) {
211+
if(pezDispender.peek() !== 'yellow') {
212+
temporal.push(pezDispender.peek());
213+
} else {
214+
let candy = getCandy();
215+
while (candy === 'yellow') {
216+
candy = getCandy();
217+
}
218+
temporal.push(candy);
219+
}
220+
pezDispender.pop();
221+
}
222+
while (temporal.length() > 0) {
223+
replace.push(temporal.peek());
224+
temporal.pop();
225+
}
226+
return replace;
227+
}
228+
229+
console.log('\n\n### Excercise 3');
230+
let dispenderStack = [];
231+
const numCandies = 20;
232+
for(var i = 0; i < numCandies; i++) {
233+
dispenderStack.push(getCandy());
234+
}
235+
236+
let pezDispender = new Stack(dispenderStack, numCandies);
237+
console.log('Original pezDispender: ');
238+
console.log(pezDispender);
239+
console.log('Replaced pezDispender: ');
240+
console.log(replaceStackElements(pezDispender));

04-chapter-Stack/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(function (exports) {
2+
const stack = require('./stack.module')
3+
4+
Object.assign(exports, stack)
5+
}((typeof module.exports !== undefined) ? module.exports : window))

04-chapter-Stack/stack.module.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
(function (exports) {
2+
let dataStore
3+
let top
4+
5+
const stackFactory = (data = [], t = -1) => {
6+
let stackProto = {}
7+
dataStore = data
8+
top = t
9+
10+
stackProto.push = (element) => {
11+
dataStore[top++] = element
12+
}
13+
14+
stackProto.pop = () => {
15+
dataStore.splice(--top, 1)
16+
}
17+
18+
stackProto.peek = () => dataStore[top - 1]
19+
20+
stackProto.length = () => top
21+
22+
stackProto.isEmpty = () => top === -1
23+
}
24+
25+
Object.assign(exports, {stack: stackFactory})
26+
}((typeof module.exports !== undefined) ? module.exports : window))

0 commit comments

Comments
 (0)