Skip to content

Commit 5634c1f

Browse files
committed
Added relative numbers to copy cmd
Added additional unit tests to check this Useful for UDFs or when the number of items on the stack is unknown
1 parent 510bbbf commit 5634c1f

File tree

6 files changed

+97
-55
lines changed

6 files changed

+97
-55
lines changed

.idea/jarRepositories.xml

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mdbook/src/Chapters/CalculatorCommands.md

Lines changed: 33 additions & 30 deletions
Large diffs are not rendered by default.

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
<groupId>org.fross</groupId>
55
<artifactId>rpncalc</artifactId>
6-
<version>5.4.1</version>
6+
<version>5.5.0</version>
77
<packaging>jar</packaging>
88

99
<name>rpncalc</name>
@@ -279,15 +279,15 @@
279279
<dependency>
280280
<groupId>org.junit.jupiter</groupId>
281281
<artifactId>junit-jupiter</artifactId>
282-
<version>5.11.4</version>
282+
<version>5.12.0-RC1</version>
283283
<scope>test</scope>
284284
</dependency>
285285

286286
<!-- https://mvnrepository.com/artifact/org.jline/jline-reader -->
287287
<dependency>
288288
<groupId>org.jline</groupId>
289289
<artifactId>jline</artifactId>
290-
<version>3.28.0</version>
290+
<version>3.29.0</version>
291291
</dependency>
292292

293293
</dependencies>

snap/snapcraft.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: rpncalc
2-
version: '5.4.1'
2+
version: '5.5.0'
33
summary: The command line Reverse Polish Notation (RPN) calculator
44
description: |
55
RPNCalc is an easy to use command line based Reverse Polish

src/main/java/org/fross/rpncalc/StackCommands.java

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,7 @@ public static void cmdAverage(StackObj calcStack, String arg) {
135135
BigDecimal mean = Math.mean(calcStack);
136136

137137
// If we are not going to keep the stack (the default) clear it
138-
if (!keepFlag)
139-
calcStack.clear();
138+
if (!keepFlag) calcStack.clear();
140139

141140
// Add the average to the stack
142141
calcStack.push(mean);
@@ -182,14 +181,26 @@ public static void cmdCopy(StackObj calcStack, String arg) {
182181
return;
183182
}
184183

185-
// Determine line number to copy
184+
// If Arg is blank, set arg to the top of the stack number so we copy the last value
185+
if (arg.isBlank()) arg = "1";
186+
187+
// Determine if the provided argument is not a number
188+
if (!Math.isNumeric(arg)) {
189+
Output.printColorln(Ansi.Color.RED, "ERROR: '" + arg + "' is not a valid line number");
190+
return;
191+
}
192+
186193
try {
194+
// Grab the value from the argument
187195
lineNumToCopy = Integer.parseInt(arg);
188-
} catch (NumberFormatException ex) {
189-
if (!arg.isBlank()) {
190-
Output.printColorln(Ansi.Color.RED, "ERROR: '" + arg + "' is not a valid line number");
191-
return;
196+
197+
// If a relative number is provided (i.e. `-1`) then set the value to copy back from the top of the stack
198+
if (lineNumToCopy <= -1) {
199+
lineNumToCopy = java.lang.Math.abs(lineNumToCopy); // Remove the negative sign
200+
lineNumToCopy = 1 + lineNumToCopy;
192201
}
202+
} catch (Exception ex) {
203+
Output.printColorln(Ansi.Color.RED, "ERROR: '" + arg + "' is not a valid relative value");
193204
}
194205

195206
// Save current calcStack to the undoStack
@@ -200,14 +211,14 @@ public static void cmdCopy(StackObj calcStack, String arg) {
200211
// Copy the provided number if it's valid
201212
try {
202213
// Ensure the number entered is valid
203-
if (lineNumToCopy < 1 || lineNumToCopy > calcStack.size()) {
204-
Output.printColorln(Ansi.Color.RED, "Invalid line number entered: " + lineNumToCopy);
214+
if (lineNumToCopy > calcStack.size()) {
215+
Output.printColorln(Ansi.Color.RED, "Invalid line number entered");
205216
} else {
206217
// Perform the copy
207218
calcStack.push(calcStack.get(calcStack.size() - lineNumToCopy));
208219
}
209220
} catch (Exception e) {
210-
Output.printColorln(Ansi.Color.RED, "Error parsing line number for element copy: '" + lineNumToCopy + "'");
221+
Output.printColorln(Ansi.Color.RED, "Error parsing line number for copy: '" + lineNumToCopy + "'");
211222
Output.debugPrintln(e.getMessage());
212223
}
213224
}
@@ -479,13 +490,12 @@ public static void cmdLinearRegression(StackObj calcStack, String args) {
479490
sumY2 = sumY2.add(new BigDecimal(String.valueOf(y)).pow(2));
480491

481492
// Line by line debug output
482-
Output.debugPrintln(
483-
"#" + i + ":\tx:" + x + "\ty:" + y + "\tXY:" + y.multiply(new BigDecimal(String.valueOf(x))) + "\tX2:" + (x * x) + "\tY2:" + y.pow(2));
493+
Output.debugPrintln("#" + i + ":\tx:" + x + "\ty:" + y + "\tXY:" + y.multiply(new BigDecimal(String.valueOf(x))) + "\tX2:" + (x * x) + "\tY2:" + y.pow(2));
484494
}
485495

486-
// Calculate the remaining values
487-
// Reference Formula: a = ((sumY * sumX2) - (sumX * sumXY)) / ((n * sumX2) - (sumX * sumX));
488-
// Reference Formula: b = ((n * sumXY) - (sumX * sumY)) / ((n * sumX2) - (sumX * sumX));
496+
// Calculate the remaining values
497+
// Reference Formula: a = ((sumY * sumX2) - (sumX * sumXY)) / ((n * sumX2) - (sumX * sumX));
498+
// Reference Formula: b = ((n * sumXY) - (sumX * sumY)) / ((n * sumX2) - (sumX * sumX));
489499

490500
BigDecimal a_top = sumY.multiply(sumX2).subtract(sumX.multiply(sumXY));
491501
BigDecimal a_bottom = n.multiply(sumX2).subtract(sumX.pow(2));
@@ -583,8 +593,7 @@ public static boolean cmdMaximum(StackObj calcStack) {
583593

584594
// Loop through the stack and look for the largest value
585595
for (int i = 0; i < calcStack.size(); i++) {
586-
if (calcStack.get(i).compareTo(largestValue) > 0)
587-
largestValue = calcStack.get(i);
596+
if (calcStack.get(i).compareTo(largestValue) > 0) largestValue = calcStack.get(i);
588597
}
589598

590599
// Add the lowest value to the stack
@@ -626,8 +635,7 @@ public static void cmdMedian(StackObj calcStack, String arg) {
626635
BigDecimal median = Math.median(calcStack);
627636

628637
// If we are not going to keep the stack (the default) clear it
629-
if (!keepFlag)
630-
calcStack.clear();
638+
if (!keepFlag) calcStack.clear();
631639

632640
// Add the average to the stack
633641
calcStack.push(median);
@@ -654,8 +662,7 @@ public static boolean cmdMinimum(StackObj calcStack) {
654662

655663
// Loop through the stack and look for the lowest value
656664
for (int i = 0; i < calcStack.size(); i++) {
657-
if (calcStack.get(i).compareTo(lowestValue) < 1)
658-
lowestValue = calcStack.get(i);
665+
if (calcStack.get(i).compareTo(lowestValue) < 1) lowestValue = calcStack.get(i);
659666
}
660667

661668
// Add the lowest value to the stack

src/test/java/org/fross/rpncalc/StackCommandsTest.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,33 @@ void testCmdCopy() {
232232
assertEquals("123E+42", stk.peek().toEngineeringString());
233233
assertEquals("123E+42", stk.get(stk.size() - 1).toEngineeringString());
234234
assertEquals(1.23, stk.get(0).doubleValue());
235+
236+
// Test relative copy
237+
stk.clear();
238+
stk.push(1);
239+
stk.push(2);
240+
stk.push(3);
241+
stk.push(4);
242+
stk.push(5);
243+
StackCommands.cmdCopy(stk, "-3");
244+
assertEquals(6, stk.size());
245+
assertEquals("2", stk.pop().toString());
246+
247+
StackCommands.cmdCopy(stk, "-1");
248+
assertEquals(6, stk.size());
249+
assertEquals("4", stk.pop().toString());
250+
251+
StackCommands.cmdCopy(stk, "-4");
252+
assertEquals(6, stk.size());
253+
assertEquals("1", stk.pop().toString());
254+
255+
StackCommands.cmdCopy(stk, "-5");
256+
assertEquals(5, stk.size());
257+
assertEquals("4", stk.get(stk.size() - 2).toString());
258+
259+
StackCommands.cmdCopy(stk, "err");
260+
assertEquals(5, stk.size());
261+
assertEquals("4", stk.get(stk.size() - 2).toString());
235262
}
236263

237264
/**

0 commit comments

Comments
 (0)