Skip to content

Commit b9c1881

Browse files
committed
chapter 20 Exercise 22 + 23
1 parent 36e96e3 commit b9c1881

File tree

2 files changed

+377
-0
lines changed

2 files changed

+377
-0
lines changed

ch_20/Exercise20_21.java

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
package ch_20;
2+
3+
import java.util.Arrays;
4+
import java.util.Comparator;
5+
6+
/**
7+
* 20.21 (Use Comparator) Write the following generic method using selection sort
8+
* and a comparator.
9+
* public static <E> void selectionSort(E[] list, Comparator<? super E> comparator)
10+
* <p>
11+
* Write a test program that creates an array of 10 GeometricObjects and
12+
* invokes this method using the GeometricObjectComparator introduced in
13+
* Listing 20.4 to sort the elements. Display the sorted elements. Use the following statement to create the array.
14+
* GeometricObject[] list = {new Circle(5), new Rectangle(4, 5),
15+
* new Circle(5.5), new Rectangle(2.4, 5), new Circle(0.5),
16+
* new Rectangle(4, 65), new Circle(4.5), new Rectangle(4.4, 1),
17+
* new Circle(6.5), new Rectangle(4, 5)};
18+
*/
19+
public class Exercise20_21 {
20+
public static void main(String[] args) {
21+
GeometricObject[] list = {new Circle(5), new Rectangle(4, 5),
22+
new Circle(5.5), new Rectangle(2.4, 5), new Circle(0.5),
23+
new Rectangle(4, 65), new Circle(4.5), new Rectangle(4.4, 1),
24+
new Circle(6.5), new Rectangle(4, 5)};
25+
26+
selectionSort(list, new GeometricObjectComparator());
27+
for (int i = 0; i < list.length; i++) {
28+
System.out.println("Area of GeometricObject: list[" + i + "] = " + list[i].getArea());
29+
}
30+
}
31+
32+
public static <E> void selectionSort(E[] list,
33+
Comparator<? super E> comparator) {
34+
for (int i = 0; i < list.length - 1; i++) {
35+
E currentMin = list[i];
36+
int currentMinIndex = i;
37+
38+
for (int j = i + 1; j < list.length; j++) {
39+
if (comparator.compare(currentMin, list[j]) > 0) { // currentMin is greater than list at j
40+
currentMin = list[j];
41+
currentMinIndex = j;
42+
}
43+
}
44+
if (currentMinIndex != i) {
45+
list[currentMinIndex] = list[i];
46+
list[i] = currentMin;
47+
}
48+
}
49+
}
50+
}
51+
52+
53+
class GeometricObjectComparator
54+
implements Comparator<GeometricObject>, java.io.Serializable {
55+
public int compare(GeometricObject o1, GeometricObject o2) {
56+
double area1 = o1.getArea();
57+
double area2 = o2.getArea();
58+
if (area1 < area2)
59+
return -1;
60+
else if (area1 == area2)
61+
return 0;
62+
else
63+
return 1;
64+
}
65+
}
66+
67+
68+
class Circle extends GeometricObject {
69+
70+
private double radius;
71+
72+
public Circle() {
73+
74+
}
75+
76+
public Circle(double radius) {
77+
78+
this.radius = radius;
79+
80+
}
81+
82+
public Circle(double radius, String color,
83+
boolean filled) {
84+
85+
this.radius = radius;
86+
setColor(color);
87+
setFilled(filled);
88+
89+
}
90+
91+
public double getRadius() {
92+
return radius;
93+
}
94+
95+
public void setRadius(double radius) {
96+
this.radius = radius;
97+
}
98+
99+
@Override
100+
public double getArea() {
101+
return radius * radius * Math.PI;
102+
}
103+
104+
@Override
105+
public double getPerimeter() {
106+
return 2 * radius * Math.PI;
107+
}
108+
109+
@Override
110+
public String toString() {
111+
return super.toString() + "\nRadius: " + getRadius() + "\nArea: "
112+
+ getArea() + "\nPerimeter: " + getPerimeter();
113+
}
114+
115+
}
116+
117+
class Rectangle extends GeometricObject {
118+
119+
private double width;
120+
private double height;
121+
122+
public Rectangle() {
123+
width = 1;
124+
height = 1;
125+
}
126+
127+
public Rectangle(double newWidth, double newHeight) {
128+
129+
width = newWidth;
130+
height = newHeight;
131+
}
132+
133+
public double getWidth() {
134+
return width;
135+
}
136+
137+
public void setWidth(double width) {
138+
this.width = width;
139+
}
140+
141+
public double getHeight() {
142+
return height;
143+
}
144+
145+
public void setHeight(double height) {
146+
this.height = height;
147+
}
148+
149+
@Override
150+
public double getArea() {
151+
double area = width * height;
152+
return area;
153+
}
154+
155+
@Override
156+
public double getPerimeter() {
157+
158+
return (2 * width) + (2 * height);
159+
}
160+
161+
@Override
162+
public String toString() {
163+
return super.toString() + "\nWidth: " + width + "\nHeight: " + height
164+
+ "\nArea: " + getArea() + "\nPerimeter: " + getPerimeter();
165+
}
166+
167+
168+
}
169+
170+
abstract class GeometricObject {
171+
private String color = "white";
172+
private boolean filled;
173+
private java.util.Date dateCreated;
174+
175+
/**
176+
* Construct a default geometric object
177+
*/
178+
protected GeometricObject() {
179+
dateCreated = new java.util.Date();
180+
}
181+
182+
/**
183+
* Construct a geometric object with color and filled value
184+
*/
185+
protected GeometricObject(String color, boolean filled) {
186+
dateCreated = new java.util.Date();
187+
this.color = color;
188+
this.filled = filled;
189+
}
190+
191+
/**
192+
* Return color
193+
*/
194+
public String getColor() {
195+
return color;
196+
}
197+
198+
/**
199+
* Set a new color
200+
*/
201+
public void setColor(String color) {
202+
this.color = color;
203+
}
204+
205+
/**
206+
* Return filled. Since filled is boolean,
207+
* the get method is named isFilled
208+
*/
209+
public boolean isFilled() {
210+
return filled;
211+
}
212+
213+
/**
214+
* Set a new filled
215+
*/
216+
public void setFilled(boolean filled) {
217+
this.filled = filled;
218+
}
219+
220+
/**
221+
* Get dateCreated
222+
*/
223+
public java.util.Date getDateCreated() {
224+
return dateCreated;
225+
}
226+
227+
@Override
228+
public String toString() {
229+
return "created on " + dateCreated + "\ncolor: " + color +
230+
" and filled: " + filled;
231+
}
232+
233+
/**
234+
* Abstract method getArea
235+
*/
236+
public abstract double getArea();
237+
238+
/**
239+
* Abstract method getPerimeter
240+
*/
241+
public abstract double getPerimeter();
242+
}

ch_20/Exercise20_23.java

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
package ch_20;
2+
3+
import java.util.Scanner;
4+
import java.util.Stack;
5+
6+
/**
7+
* *20.23 (Evaluate expression) Modify Listing 20.9 EvaluateExpression.java to add
8+
* operators ^ for exponent and % for modulus. For example, 3 ^ 2 is 9 and 3 % 2
9+
* is 1. The ^ operator has the highest precedence and the % operator has the same
10+
* precedence as the * and / operators. Your program should prompt the user to
11+
* enter an expression. Here is a sample run of the program:
12+
* Enter an expression: (5 * 2 ^ 3 + 2 * 3 % 2) * 4
13+
* (5 * 2 ^ 3 + 2 * 3 % 2) * 4 = 160
14+
*/
15+
public class Exercise20_23 {
16+
public static void main(String[] args) {
17+
Scanner input = new Scanner(System.in);
18+
System.out.print("Enter an expression: ");
19+
String expression = input.nextLine();
20+
try {
21+
System.out.print(expression + " = ");
22+
System.out.print(evaluateExpression(expression));
23+
} catch (Exception ex) {
24+
System.out.println("Wrong expression: " + expression);
25+
}
26+
}
27+
28+
/**
29+
* Evaluate an expression
30+
*/
31+
public static int evaluateExpression(String expression) {
32+
// Create operandStack to store operands
33+
Stack<Integer> operandStack = new Stack<>();
34+
// Create operatorStack to store operators
35+
Stack<Character> operatorStack = new Stack<>();
36+
// Pad following characters with space: (, ), +, -, /, *, ^ and %
37+
expression = insertBlanks(expression);
38+
// Extract operands and operators
39+
String[] tokens = expression.split(" ");
40+
// Phase 1: Scan tokens
41+
for (String token : tokens) {
42+
if (token.length() == 0) {
43+
continue;
44+
}
45+
if (token.charAt(0) == '^') {
46+
operatorStack.push(token.charAt(0));
47+
} else if (token.charAt(0) == '+' || token.charAt(0) == '-') {
48+
// Process all ^ in the top of the operator stack (has the highest precedence)
49+
while (!operatorStack.isEmpty() && operatorStack.peek() == '^') {
50+
processAnOperator(operandStack, operatorStack);
51+
}
52+
53+
while (!operatorStack.isEmpty() &&
54+
token.charAt(0) == '*' ||
55+
token.charAt(0) == '/' ||
56+
token.charAt(0) == '%') {
57+
processAnOperator(operandStack, operatorStack);
58+
}
59+
60+
// Push the + or - operator into the operator stack
61+
operatorStack.push(token.charAt(0));
62+
} else if (token.charAt(0) == '*' || token.charAt(0) == '/' || token.charAt(0) == '%') {
63+
while (!operatorStack.isEmpty() && operatorStack.peek() == '^') {
64+
processAnOperator(operandStack, operatorStack);
65+
}
66+
67+
// Process all *, / , % in the top of the operator stack (same precedence)
68+
while (!operatorStack.isEmpty() &&
69+
(operatorStack.peek() == '*' ||
70+
operatorStack.peek() == '^' ||
71+
operatorStack.peek() == '/' ||
72+
operatorStack.peek() == '%')) {
73+
processAnOperator(operandStack, operatorStack);
74+
}
75+
// Push the *, /, or % operator into the operator stack
76+
operatorStack.push(token.charAt(0));
77+
} else if (token.trim().charAt(0) == '(') {
78+
operatorStack.push('('); // Push '(' to stack
79+
} else if (token.trim().charAt(0) == ')') {
80+
// Process all the operators in the stack until seeing '(
81+
while (operatorStack.peek() != '(') {
82+
processAnOperator(operandStack, operatorStack);
83+
}
84+
operatorStack.pop(); // Pop the '(' symbol from the stack
85+
} else { // An operand scanned
86+
// Push an operand to the stack
87+
operandStack.push(new Integer(token));
88+
}
89+
}
90+
91+
// Phase 2: Process all the remaining operators in the stack
92+
while (!operatorStack.isEmpty()) {
93+
processAnOperator(operandStack, operatorStack);
94+
}
95+
// Return the result
96+
return operandStack.pop();
97+
}
98+
99+
/**
100+
* Process one operator: Take an operator from operatorStack a
101+
* apply it on the operands in the operandStack
102+
*/
103+
public static void processAnOperator(
104+
Stack<Integer> operandStack, Stack<Character> operatorStack) {
105+
char op = operatorStack.pop();
106+
int op1 = operandStack.pop();
107+
int op2 = operandStack.pop();
108+
if (op == '+')
109+
operandStack.push(op2 + op1);
110+
else if (op == '-')
111+
operandStack.push(op2 - op1);
112+
else if (op == '*')
113+
operandStack.push(op2 * op1);
114+
else if (op == '/')
115+
operandStack.push(op2 / op1);
116+
else if (op == '^')
117+
operandStack.push((int) Math.pow(op2, op1)); // Exponent operation
118+
else if (op == '%')
119+
operandStack.push(op2 % op1);// Modulus operation
120+
}
121+
122+
public static String insertBlanks(String s) {
123+
String result = "";
124+
for (int i = 0; i < s.length(); i++) {
125+
if (s.charAt(i) == '(' || s.charAt(i) == ')' ||
126+
s.charAt(i) == '+' || s.charAt(i) == '-' ||
127+
s.charAt(i) == '*' || s.charAt(i) == '/' ||
128+
s.charAt(i) == '^' || s.charAt(i) == '%') // Check for exponent and modulus operands.
129+
result += " " + s.charAt(i) + " ";
130+
else
131+
result += s.charAt(i);
132+
}
133+
return result;
134+
}
135+
}

0 commit comments

Comments
 (0)