Skip to content

Commit a2bf581

Browse files
committed
adding chapter 4 Stacks
1 parent 014d37b commit a2bf581

File tree

1 file changed

+239
-0
lines changed

1 file changed

+239
-0
lines changed

04-chapter-Stacks.js

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
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('### Excercise 1');
74+
console.log(`Expression example: ${exp}`);
75+
(balanced) ? console.log('The expression is balanced') : console.log('The expression is no balanced');
76+
77+
console.log(`\nExpression example: ${exp2}`);
78+
(balanced2) ? console.log('The expression is balanced') : console.log('The expression is no balanced');
79+
80+
// ###########################################
81+
/*
82+
2. A postfix expression evaluator works on arithmetic expressions taking the following form:
83+
op1 op2 operator
84+
Using two stacks—one for the operands and one for the operators—design and implement
85+
a JavaScript function that converts infix expressions to postfix expres‐ sions, and
86+
then use the stacks to evaluate the expression.
87+
*/
88+
89+
function checkOperator(op) {
90+
switch (op) {
91+
case ')':
92+
return 4;
93+
case '(':
94+
return 3;
95+
case '/':
96+
return 2;
97+
case '*':
98+
return 2;
99+
case '+':
100+
return 1;
101+
case '-':
102+
return 1;
103+
}
104+
}
105+
106+
function infixToPostfix(exp) {
107+
let value = '';
108+
const stack = new Stack();
109+
const postfix = new Stack();
110+
111+
for (const key in exp) {
112+
if(exp[key] === '(' || exp[key] === ')' || exp[key] === '+' ||
113+
exp[key] === '-' || exp[key] === '*' || exp[key] === '/' ) {
114+
if(value !== '') {
115+
postfix.push(value);
116+
}
117+
if(stack.length() === 0 && exp[key] !== '(') {
118+
stack.push(exp[key]);
119+
} else {
120+
if(checkOperator(exp[key]) !== 3) {
121+
innerLoop:
122+
while(stack.length() > 0) {
123+
if(checkOperator(exp[key]) < checkOperator(stack.peek())) {
124+
postfix.push(stack.peek());
125+
stack.pop();
126+
} else if (checkOperator(exp[key]) === checkOperator(stack.peek())) {
127+
postfix.push(stack.peek());
128+
stack.pop();
129+
stack.push(exp[key]);
130+
break innerLoop;
131+
} else {
132+
if(checkOperator(exp[key]) !== 4) {
133+
stack.push(exp[key]);
134+
}
135+
break innerLoop;
136+
}
137+
}
138+
}
139+
}
140+
value = '';
141+
} else {
142+
value += exp[key];
143+
}
144+
}
145+
146+
while(stack.length() > 0) {
147+
postfix.push(stack.peek());
148+
stack.pop();
149+
}
150+
return postfix;
151+
}
152+
153+
function evalPostFix(exp) {
154+
const resultStack = new Stack();
155+
const postfix = exp.dataStore;
156+
157+
for(const key in postfix) {
158+
if(!isNaN(postfix[key])) {
159+
resultStack.push(postfix[key]);
160+
} else {
161+
162+
const a = resultStack.peek();
163+
resultStack.pop();
164+
const b = resultStack.peek();
165+
resultStack.pop();
166+
167+
if(postfix[key] === "+") {
168+
resultStack.push((parseFloat(a, 10) + parseFloat(b, 10)).toFixed(2));
169+
} else if(postfix[key] === "-") {
170+
resultStack.push((parseFloat(b, 10) - parseFloat(a, 10)).toFixed(2));
171+
} else if(postfix[key] === "*") {
172+
resultStack.push((parseFloat(a, 10) * parseFloat(b, 10)).toFixed(2));
173+
} else if(postfix[key] === "/") {
174+
resultStack.push((parseFloat(b, 10) / parseFloat(a, 10)).toFixed(2));
175+
}
176+
}
177+
}
178+
return resultStack.dataStore[0];
179+
}
180+
181+
console.log('\n\n### Excercise 2');
182+
console.log(`Infix => ${exp2}`);
183+
const postfix = infixToPostfix(e2);
184+
console.log(`Postfix => ${postfix.dataStore.reduce((total, value) => total + ' ' + value )}`);
185+
evalPostFix(postfix);
186+
console.log(`Evaluation => ${evalPostFix(postfix)}`);
187+
188+
// ###########################################
189+
/*
190+
3. An example of a real-world stack is a Pez dispenser. Imagine that your virtual Pez dispenser
191+
is filled with red, yellow, and white colors and you don’t like the yellow ones. Write a program
192+
that uses a stack (and maybe more than one) to replace the yellow ones for another color without
193+
changing the order of the other candies in the dispenser.
194+
*/
195+
function getCandy() {
196+
switch (parseInt(Math.random() * (4 - 1) + 1, 10)) {
197+
case 1:
198+
return 'red';
199+
case 2:
200+
return 'yellow';
201+
case 3:
202+
return 'white';
203+
}
204+
}
205+
function replaceStackElements(pezDispender) {
206+
const replace = new Stack();
207+
const temporal = new Stack();
208+
209+
while (pezDispender.length() > 0) {
210+
if(pezDispender.peek() !== 'yellow') {
211+
temporal.push(pezDispender.peek());
212+
} else {
213+
let candy = getCandy();
214+
while (candy === 'yellow') {
215+
candy = getCandy();
216+
}
217+
temporal.push(candy);
218+
}
219+
pezDispender.pop();
220+
}
221+
while (temporal.length() > 0) {
222+
replace.push(temporal.peek());
223+
temporal.pop();
224+
}
225+
return replace;
226+
}
227+
228+
console.log('\n\n### Excercise 3');
229+
let dispenderStack = [];
230+
const numCandies = 20;
231+
for(var i = 0; i < numCandies; i++) {
232+
dispenderStack.push(getCandy());
233+
}
234+
235+
let pezDispender = new Stack(dispenderStack, numCandies);
236+
console.log('Original pezDispender: ');
237+
console.log(pezDispender);
238+
console.log('Replaced pezDispender: ');
239+
console.log(replaceStackElements(pezDispender));

0 commit comments

Comments
 (0)