How would you implement the following Bubble Sort algorithm in a functional (Java 8) way?
public static final <T extends Comparable<T>> List<T> imperativeBubbleSort(List<T> list) {
int len = list == null ? 0 : list.size();
for (int j = len - 1; j > 0; j--) {
for (int k = 0; k < j; k++) {
if (list.get(k + 1).compareTo(list.get(k)) < 0) {
list.add(k, list.remove(k + 1));
}
}
}
return list;
}
It would depend on what you mean by functional. If you mean just passing around functions as first class objects, then you should change your method signature to be:
public static final <T> List<T> imperativeBubbleSort(List<T> list, Comparator<T> comparisonFunction)
This way the comparison logic can be supplied as an argument.
If you mean going fully functional and not at all procedural, then I would call it an anti-pattern. Despite what you might hear, Java 8 does not fully support functional programming. A key feature that it is missing is tail-call optimization. Without it, the sort of loop-less programming that defines functional programming is likely to crash your JVM for relatively small values.
More information about tail call optimizations and the JVM can be found here: http://www.drdobbs.com/jvm/tail-call-optimization-and-java/240167044
Algorithm with two nested loops: Bubble sort with step-by-step output
Bubble sort with step-by-step output Java 8
You can replace two nested loops with two nested streams. The inner stream passes through the list, compares adjacent elements and returns the count of swaps. And the outer stream repeats passes until there is nothing left to swap in the inner stream.
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
Collections.addAll(list, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1);
bubbleSort8(list);
}
public static void bubbleSort8(List<Integer> list) {
// counters: 0-passes, 1-swaps
int[] counter = new int[2];
IntStream.iterate(0, i -> i + 1)
// output the beginning of the pass and increase the counter of passes
.peek(i -> System.out.print((i==0?"<pre>":"<br>")+"Pass: "+counter[0]++))
// repeat the passes through the list until
// all the elements are in the correct order
.anyMatch(i -> IntStream
// pass through the list and
// compare adjacent elements
.range(0, list.size() - 1)
// if this element is greater than the next one
.filter(j -> list.get(j) > list.get(j + 1))
// then swap them
.peek(j -> Collections.swap(list, j, j + 1))
// output the list and increase the counter of swaps
.peek(j -> System.out.print(outputSwapped8(list,j,j+1,counter[1]++)))
// if there are no swapped elements at the
// current pass, then this is the last pass
.count() == 0);
// output total
System.out.print("<br>Total: Passes=" + counter[0]);
System.out.println(", swaps=" + counter[1] + "</pre>");
}
static String outputSwapped8(List<Integer> list, int e1, int e2, int counter) {
return IntStream.range(0, list.size())
.mapToObj(i -> i == e1 || i == e2 ?
// swapped elements are in bold
"<b>" + list.get(i) + "</b>" :
// other elements
"" + list.get(i))
.collect(Collectors.joining(" ", "<br>", " | " + counter));
}
Output:
Pass: 09 10 8 7 6 5 4 3 2 1 | 09 8 10 7 6 5 4 3 2 1 | 19 8 7 10 6 5 4 3 2 1 | 29 8 7 6 10 5 4 3 2 1 | 39 8 7 6 5 10 4 3 2 1 | 49 8 7 6 5 4 10 3 2 1 | 59 8 7 6 5 4 3 10 2 1 | 69 8 7 6 5 4 3 2 10 1 | 79 8 7 6 5 4 3 2 1 10 | 8Pass: 18 9 7 6 5 4 3 2 1 10 | 98 7 9 6 5 4 3 2 1 10 | 108 7 6 9 5 4 3 2 1 10 | 118 7 6 5 9 4 3 2 1 10 | 128 7 6 5 4 9 3 2 1 10 | 138 7 6 5 4 3 9 2 1 10 | 148 7 6 5 4 3 2 9 1 10 | 158 7 6 5 4 3 2 1 9 10 | 16Pass: 27 8 6 5 4 3 2 1 9 10 | 177 6 8 5 4 3 2 1 9 10 | 187 6 5 8 4 3 2 1 9 10 | 197 6 5 4 8 3 2 1 9 10 | 207 6 5 4 3 8 2 1 9 10 | 217 6 5 4 3 2 8 1 9 10 | 227 6 5 4 3 2 1 8 9 10 | 23Pass: 36 7 5 4 3 2 1 8 9 10 | 246 5 7 4 3 2 1 8 9 10 | 256 5 4 7 3 2 1 8 9 10 | 266 5 4 3 7 2 1 8 9 10 | 276 5 4 3 2 7 1 8 9 10 | 286 5 4 3 2 1 7 8 9 10 | 29Pass: 45 6 4 3 2 1 7 8 9 10 | 305 4 6 3 2 1 7 8 9 10 | 315 4 3 6 2 1 7 8 9 10 | 325 4 3 2 6 1 7 8 9 10 | 335 4 3 2 1 6 7 8 9 10 | 34Pass: 54 5 3 2 1 6 7 8 9 10 | 354 3 5 2 1 6 7 8 9 10 | 364 3 2 5 1 6 7 8 9 10 | 374 3 2 1 5 6 7 8 9 10 | 38Pass: 63 4 2 1 5 6 7 8 9 10 | 393 2 4 1 5 6 7 8 9 10 | 403 2 1 4 5 6 7 8 9 10 | 41Pass: 72 3 1 4 5 6 7 8 9 10 | 422 1 3 4 5 6 7 8 9 10 | 43Pass: 81 2 3 4 5 6 7 8 9 10 | 44Pass: 9Total: Passes=10, swaps=45
See also: Bubble sort algorithm for a linked list
I don't think Java 8 will provide much help in this case to write bubble sort in a functional style.
For example this implementation implementation of Bubble sort in Haskell can be simulated in Java as follows. It's more functional as it uses recursion instead of iteration, but still Java 8 lacks
features such as pattern matching, list concatenation, etc to express the algorithms in a more functional style.
public static final <T extends Comparable<T>> List<T> functionalBubbleSort(List<T> list) {
for (int i = 0; i < list.size(); i++) {
list = onePassSort(list);
}
return list;
}
public static final <T extends Comparable<T>> List<T> onePassSort(List<T> list) {
if (list.size() == 0 || list.size() == 1) {
return list;
} else {
T first = list.get(0);
T second = list.get(1);
if (first.compareTo(second) < 0) {
return merge(first, onePassSort(list.subList(1, list.size())));
} else {
return merge(second, onePassSort(merge(first, list.subList(2, list.size()))));
}
}
}
public static <T> List<T> merge(T head, List<T> tail) {
List<T> result = new ArrayList<>();
result.add(head);
result.addAll(tail);
return result;
}
Shortest way I could think of is following. Where listForBubbleSort is input, and bubbleSorted is the output.
List<Integer> listForBubbleSort = Arrays.asList(5, 4, 3, 7, 6, 9, 11, 10, 21);
final List<Integer> copiedList = new ArrayList<>(listForBubbleSort);
copiedList.add(Integer.MAX_VALUE);
final List<Integer> bubbleSorted = new ArrayList<>();
copiedList.stream().reduce((c, e) -> {
if (c < e) {
bubbleSorted.add(c);
return e;
} else {
bubbleSorted.add(e);
return c;
}
});
System.out.println(bubbleSorted); // [4, 3, 5, 6, 7, 9, 10, 11, 21]
I still feel that, if we could create a custom collector and just pass the collector to the collect of stream that would be great. Like we pass collect(toList()) to the stream. But still learning Java 8, so need more time to create the same.
If anyone has already created a custom collector for the same please share.
Simplified version using Java 8 api:
public static int[] bubbleSort(int[] array) {
BiConsumer<int[], Integer> swapValueIf = (a, j) -> {
if (a[j] > a[j + 1]) {
int temp = a[j];
array[j] = a[j + 1];
array[j + 1] = temp;
}
};
IntStream.range(0, array.length - 1)
.forEach(i -> IntStream.range(0, array.length - 1)
.forEach(j -> swapValueIf.accept(array, j)));
return array;
}
I got a plausible approach:
#SuppressWarnings("unchecked")
public static final <T extends Comparable<T>> List<T> declarativeBubbleSort(final List<T> list) {
List<T> result = new ArrayList<>(list);
int len = result.size();
Function<Function<Object, Object>, IntConsumer> consumer =
recur -> length -> IntStream.range(0, length)
.filter(i -> IntStream.range(0, len - i - 1)
.filter(j -> result.get(j + 1).compareTo(result.get(j)) < 0)
.mapToObj(j -> {
T swap = result.remove(j + 1);
result.add(j, swap);
return swap;
}).count() > 0)
.max().ifPresent(IntConsumer.class.cast(recur.apply(Function.class.cast(recur))));
consumer.apply(Function.class.cast(consumer)).accept(len);
return result;
}
I know I'm still being a bit imperative, but for this kind of sort, I find it hard to do it completely declarative in Java and not to penalize performance.
If you want to be parallel, then:
#SuppressWarnings("unchecked")
public static final <T extends Comparable<T>> List<T> declarativeParallelBubbleSort(final List<T> list) {
List<T> result = new ArrayList<>(list);
int len = result.size();
Function<Function<Object, Object>, IntConsumer> consumer =
recur -> length -> IntStream.range(0, length)
.filter(i -> IntStream.range(0, len - i - 1)
.filter(j -> result.get(j + 1).compareTo(result.get(j)) < 0)
.parallel()
.mapToObj(j -> {
synchronized (result) {
T swap = result.remove(j + 1);
result.add(j, swap);
return swap;
}
}).count() > 0)
.max().ifPresent(IntConsumer.class.cast(recur.apply(Function.class.cast(recur))));
consumer.apply(Function.class.cast(consumer)).accept(len);
return result;
}
Related
So I have edited it some and am getting almost exactly what I want. The only problem I am having now is that I am getting a line of output that I don't want. I feel like the fix here is simple but my brain is fried right now.
static void bubbleSort(int[] myArray) {
int n = myArray.length;
int temp = 0;
int counter = 0;
for (int i = 0; i < n; i++) {
int k;
for (k = 0; k < n; k++) {
System.out.print(myArray[k] + "|");
}
System.out.println(" Num swaps: " + counter);
for (int j = 1; j < (n - i); j++) {
if (myArray[j - 1] > myArray[j]) {
//swap elements
temp = myArray[j - 1];
myArray[j - 1] = myArray[j];
myArray[j] = temp;
counter++;
}
}
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] myArray = new int[10];
for (int i = 0; i < 10; i++) {
System.out.print("Enter slot " + i + ": ");
myArray[i] = sc.nextInt();
}
bubbleSort(myArray);
}
Here is an example of what I get:
Enter slot 0: 10
Enter slot 1: 9
Enter slot 2: 8
Enter slot 3: 7
Enter slot 4: 6
Enter slot 5: 5
Enter slot 6: 4
Enter slot 7: 3
Enter slot 8: 2
Enter slot 9: 1
10|9|8|7|6|5|4|3|2|1| Num swaps: 0
9|8|7|6|5|4|3|2|1|10| Num swaps: 9
8|7|6|5|4|3|2|1|9|10| Num swaps: 17
7|6|5|4|3|2|1|8|9|10| Num swaps: 24
6|5|4|3|2|1|7|8|9|10| Num swaps: 30
5|4|3|2|1|6|7|8|9|10| Num swaps: 35
4|3|2|1|5|6|7|8|9|10| Num swaps: 39
3|2|1|4|5|6|7|8|9|10| Num swaps: 42
2|1|3|4|5|6|7|8|9|10| Num swaps: 44
1|2|3|4|5|6|7|8|9|10| Num swaps: 45
That first line of output where it just repeats what the user input and says 0 swaps. I don't want that.
Just changed the position of the for loops. Hope this is the output you actually want :).
static void bubbleSort(int[] myArray) {
int n = myArray.length;
int temp = 0;
int counter = 0;
for (int i = 0; i < n; i++) {
for (int j = 1; j < (n - i); j++) {
if (myArray[j - 1] > myArray[j]) {
// swap elements
temp = myArray[j - 1];
myArray[j - 1] = myArray[j];
myArray[j] = temp;
counter++;
}
}
int k;
for (k = 0; k < n; k++) {
System.out.print(myArray[k] + "|");
}
System.out.println(" Num swaps: " + counter);
}
}
Algorithm with two nested streams: Bubble sort with step-by-step output Java 8
Bubble sort with step-by-step output
The outer do-while-loop repeats until the array is sorted, and the inner for-loop passes through the array, swapping the unordered adjacent elements. The output is the swapped elements in the inner loop, grouped by passes in the outer loop.
public static void main(String[] args) {
int[] arr = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
bubbleSort(arr);
}
public static void bubbleSort(int[] arr) {
// counters
int passes = 0, swaps = 0;
// marker
boolean swapped;
// repeat the passes through the array until
// all the elements are in the correct order
do {
// output the beginning of the pass and increase the counter of passes
System.out.print((passes == 0 ? "<pre>" : "<br>") + "Pass: " + passes++);
swapped = false;
// pass through the array and
// compare adjacent elements
for (int i = 0; i < arr.length - 1; i++) {
// if this element is greater than
// the next one, then swap them
if (arr[i] > arr[i + 1]) {
int temp = arr[i];
arr[i] = arr[i + 1];
arr[i + 1] = temp;
swapped = true;
// output the array and increase the counter of swaps
System.out.print(outputSwapped(arr, i, i + 1, swaps++));
}
}
// if there are no swapped elements at the
// current pass, then this is the last pass
} while (swapped);
// output total
System.out.print("<br>Total: Passes=" + passes);
System.out.println(", swaps=" + swaps + "</pre>");
}
static String outputSwapped(int[] arr, int e1, int e2, int counter) {
StringBuilder sb = new StringBuilder("<br>");
for (int i = 0; i < arr.length; i++) {
if (i == e1 || i == e2) {
// swapped elements are in bold
sb.append("<b>").append(arr[i]).append("</b>");
} else {
// other elements
sb.append(arr[i]);
}
sb.append(" ");
}
return sb.append("| ").append(counter).toString();
}
Output:
Pass: 09 10 8 7 6 5 4 3 2 1 | 09 8 10 7 6 5 4 3 2 1 | 19 8 7 10 6 5 4 3 2 1 | 29 8 7 6 10 5 4 3 2 1 | 39 8 7 6 5 10 4 3 2 1 | 49 8 7 6 5 4 10 3 2 1 | 59 8 7 6 5 4 3 10 2 1 | 69 8 7 6 5 4 3 2 10 1 | 79 8 7 6 5 4 3 2 1 10 | 8Pass: 18 9 7 6 5 4 3 2 1 10 | 98 7 9 6 5 4 3 2 1 10 | 108 7 6 9 5 4 3 2 1 10 | 118 7 6 5 9 4 3 2 1 10 | 128 7 6 5 4 9 3 2 1 10 | 138 7 6 5 4 3 9 2 1 10 | 148 7 6 5 4 3 2 9 1 10 | 158 7 6 5 4 3 2 1 9 10 | 16Pass: 27 8 6 5 4 3 2 1 9 10 | 177 6 8 5 4 3 2 1 9 10 | 187 6 5 8 4 3 2 1 9 10 | 197 6 5 4 8 3 2 1 9 10 | 207 6 5 4 3 8 2 1 9 10 | 217 6 5 4 3 2 8 1 9 10 | 227 6 5 4 3 2 1 8 9 10 | 23Pass: 36 7 5 4 3 2 1 8 9 10 | 246 5 7 4 3 2 1 8 9 10 | 256 5 4 7 3 2 1 8 9 10 | 266 5 4 3 7 2 1 8 9 10 | 276 5 4 3 2 7 1 8 9 10 | 286 5 4 3 2 1 7 8 9 10 | 29Pass: 45 6 4 3 2 1 7 8 9 10 | 305 4 6 3 2 1 7 8 9 10 | 315 4 3 6 2 1 7 8 9 10 | 325 4 3 2 6 1 7 8 9 10 | 335 4 3 2 1 6 7 8 9 10 | 34Pass: 54 5 3 2 1 6 7 8 9 10 | 354 3 5 2 1 6 7 8 9 10 | 364 3 2 5 1 6 7 8 9 10 | 374 3 2 1 5 6 7 8 9 10 | 38Pass: 63 4 2 1 5 6 7 8 9 10 | 393 2 4 1 5 6 7 8 9 10 | 403 2 1 4 5 6 7 8 9 10 | 41Pass: 72 3 1 4 5 6 7 8 9 10 | 422 1 3 4 5 6 7 8 9 10 | 43Pass: 81 2 3 4 5 6 7 8 9 10 | 44Pass: 9Total: Passes=10, swaps=45
See also: Bubble sort output is incorrect
I am implementing a math table using two integers (a and tableSize). I have built a random operation named R. I am going to calculate a random number between the row and column range and print the random number. For those instances where the row value is larger than the column value, the output is a dash ("-").
Here is my code,
int a = 4;
int tableSize = 10;
System.out.print(" R ");
for(int i = a; i <= tableSize;i++ )
{
System.out.format("%4d",i);
}
System.out.println();
for(int i = a ;i <= tableSize;i++)
{
System.out.format("%4d ",i);
for(int j=a;j <= tableSize;j++)
{
int randomNum = rand.nextInt (j) + i;
if(!(i > j))
{
System.out.format("%4d", randomNum);
} else
{
System.out.format("%4s", "-");
}
}
System.out.println();
}
The output I need is like this,
R 4 5 6 7 8 9 10
4 4 4 5 5 4 9 8
5 - 5 5 6 5 9 8
6 - - 6 6 7 9 6
7 - - - 7 7 7 7
8 - - - - 8 9 9
9 - - - - - 9 10
10 - - - - - - 10
But the problem is I didn't get output like that. output I receive is,
R 4 5 6 7 8 9 10
4 5 7 6 8 8 10 13
5 - 5 9 8 8 10 12
6 - - 9 8 11 10 11
7 - - - 8 14 9 16
8 - - - - 14 12 11
9 - - - - - 13 18
10 - - - - - - 19
And the row value is larger than the column value, Please anyone can help me? Thanks in advance.
The problem is that you are computing the cell value as the sum of a random number between 1 and the column number plus the row number. The logic I think you want is that a given cell in the matrix can be no larger than the max of the row or column number. If so, then you need to change this line:
int randomNum = rand.nextInt(j) + i;
To this:
int randomNum = rand.nextInt((Math.max(i, j) - a) + 1) + a;
Demo
Change your random number like this.
int randomNum = rand.nextInt((tableSize - a) +1)+a;
Output:
R 4 5 6 7 8 9 10
4 4 6 7 6 6 7 7
5 - 6 5 4 6 8 8
6 - - 7 8 7 7 8
7 - - - 10 7 5 5
8 - - - - 9 5 8
9 - - - - - 8 8
10 - - - - - - 4
You want a number that can be up to the higher limit (inclusive), but Random.nextInt(int) excludes the higher limit, so you need to add 1 to the argument. To get a random number from zero to 10 (inclusive), you can use rand.nextInt(10+1).
But you also have a lower bound. It's correct that you need to add the lower bound to the result as you did, but you need to subtract it from the range first.
You need to change this line:
int randomNum = rand.nextInt (j) + i;
To this:
int randomNum = rand.nextInt(j + 1 - i) + i;
But you need to move this line within your check that i <= j, or else your range becomes negative:
if (i <= j) {
int randomNum = rand.nextInt(j + 1 - i) + i;
System.out.format("%4d", randomNum);
} else {
System.out.format("%4s", "-");
}
Output:
R 4 5 6 7 8 9 10
4 4 5 5 7 4 5 8
5 - 5 6 6 5 5 5
6 - - 6 6 8 8 9
7 - - - 7 7 9 9
8 - - - - 8 9 9
9 - - - - - 9 9
10 - - - - - - 10
First, you should know how to get random between two integers, and then code the rest (check code comments)
Here is an implementation using ternary operator ?:, which is good to know of
PrintR.java:
import java.util.Random;
public class PrintR {
public static void main(String[] args) {
int a = 4;
int end = 10;
printRTable(a, end);
}
public static void printRTable(int init, int end) {
Random rand = new Random();
// first print the top header row
System.out.format(" R ");
for(int i = init; i<=end;i++ ) {
System.out.format("%4d",i);
}
System.out.println();
System.out.println("------------------------------------------");
for(int i = init ;i<=end;i++) {
// print left most column first
System.out.format("%4d |",i);
for(int j=init;j<=end;j++) {
//Ternary operator
//r.nextInt(High-Low + 1) + Low; gives you a random number in between Low (inclusive) and High (inclusive)
System.out.format("%4s", i > j ? "-" : (rand.nextInt(j-i+1)) + i);
}
System.out.println();
}
}
}
Example output:
R 4 5 6 7 8 9 10
------------------------------------------
4 | 4 4 5 7 5 5 4
5 | - 5 6 6 5 8 10
6 | - - 6 7 7 6 8
7 | - - - 7 7 7 10
8 | - - - - 8 8 10
9 | - - - - - 9 10
10 | - - - - - - 10
I am currently working on converting an array of integers to a tree with a given order (could be 2, 3, 4, 5, ...). So far, I have only managed to get it to work for trees of order 2 and I am struggling to implement code for higher orders.
How it works is, we get a set of numbers (ex. 1 2 3 4 5 6 7 8 2) and the last one means the order of the tree. In this case, 2, resulting in this tree:
1
/ \
2 3
/ \ / \
4 5 6 7
/
8
We then have to pre- and post-order print the resulting built tree from the numbers provided. So, for the pre-order print I get 1 2 4 8 5 3 6 7 and for the post-order print I get 8 4 5 2 6 7 3 1, which are both the corrent answers.
The code I use for building the tree is:
public static Node arrayToTree(String[] input, int order) {
Node root = createNode(input, 1, order);
return root;
}
public static Node createNode(String[] input, int i, int order) {
if(i <= input.length) {
String val = input[i-1];
if(val != null){
Node t = new Node(val);
for(int j = 0; j < order; j++) {
t.children[j] = createNode(input, order * i + j, order);
}
return t;
}
}
return null;
}
class Node {
public Node[] children = new Node[64];
public String val;
public Node(String val) {
this.val = val;
}
}
The actual question would be how to get the correct indexes in the createNode function so that the Node t's children will actually be correct. So, for example if the input is 1 2 3 4 3.. means that the order of the tree is 3 so the root is 1 and has children 2, 3 and 4. Which are on indexes 1, 2 and 3.
public static void main(String[]args) {
String[] input = new String[]{"1", "2", "3", "4", "5", "6", "7", "8"};
int order = 2;
Node tree = arrayToTree(input, order);
System.out.print("Preorder: ");
preorder(tree);
System.out.println();
System.out.print("Postorder: ");
postorder(tree);
}
public static void preorder(Node node) {
System.out.print(node.val + " ");
for(Node n : node.children) {
if(n != null) preorder(n);
}
}
public static void postorder(Node node) {
for(Node n : node.children) {
if(n != null) postorder(n);
}
System.out.print(node.val + " ");
}
Here is the main function with postorder and preorder printing, to give you an idea how this should work later in the main program.
I assume that you have to do this with recursion, which does complicate it a bit; there are easier solutions otherwise.
It might be easiest to solve this visually first. Following are mappings of the index of the nodes in the array (not their values). The general reason to work with indices instead of values is that the values are meaningless, they are symbolic, while the index is the useful mathematical quantity in the calculation.
2
---
0 -> 1 2
1 -> 3 4
2 -> 5 6
3 -> 7
3
---
0 -> 1 2 3
1 -> 4 5 6
2 -> 7
4
---
0 -> 1 2 3 4
1 -> 5 6 7
Notice the pattern: the index of the first child of each parent at i is i * order + 1. Since we are working with indices, which happen to be 1 less than the value in them, shift your is by 1:
public static Node arrayToTree(String[] input, int order) {
Node root = createNode(input, 0, order); // 0 instead of 1
return root;
}
public static Node createNode(String[] input, int i, int order) {
if(i < input.length) { // < instead of <=
String val = input[i]; // i instead of i-1
if(val != null){
Node t = new Node(val);
for(int j = 0; j < order; j++) {
t.children[j] = createNode(input, ???, order);
}
return t;
}
}
return null;
}
and complete the recursion formula with the pattern found above. Here are the results I'm getting for input[16] and orders 2, 3 and 4 (excuse the not-well-formatted trees used as a visual aid):
2
---
1
2 3 |
4 5 | 6 7 |
8 9 | 10 11 | 12 13 | 14 15 |
16
Preorder: 1 2 4 8 16 9 5 10 11 3 6 12 13 7 14 15
Postorder: 16 8 9 4 10 11 5 2 12 13 6 14 15 7 3 1
3
---
1
2 3 4 |
5 6 7 | 8 9 10 | 11 12 13 |
14 15 16 |
Preorder: 1 2 5 14 15 16 6 7 3 8 9 10 4 11 12 13
Postorder: 14 15 16 5 6 7 2 8 9 10 3 11 12 13 4 1
4
---
1
2 3 4 5 |
6 7 8 9 | 10 11 12 13 | 14 15 16
Preorder: 1 2 6 7 8 9 3 10 11 12 13 4 14 15 16 5
Postorder: 6 7 8 9 2 10 11 12 13 3 14 15 16 4 5 1
I am trying to print out a Right Triangle that looks like this:
1
2 1
3 2 1
5 4 3 2 1
6 5 4 3 2 1
7 6 5 4 3 2 1
8 7 6 5 4 3 2 1
9 8 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2 1
11 10 9 8 7 6 5 4 3 2 1
The size of the triangle increases if the number in the method gets larger, which in this case is 11.
My code seems to only work up to 10 as after 10, my spacing is messed up.
1
2 1
3 2 1
4 3 2 1
5 4 3 2 1
6 5 4 3 2 1
7 6 5 4 3 2 1
8 7 6 5 4 3 2 1
9 8 7 6 5 4 3 2 1
10 9 8 7 6 5 4 3 2 1
11 10 9 8 7 6 5 4 3 2 1
12 11 10 9 8 7 6 5 4 3 2 1
13 12 11 10 9 8 7 6 5 4 3 2 1
I am trying to make it so that up to 99, the spacing is correct. What kind of edits should I do to my if statements or for loops in order to space it properly?
Code:
public class Patterns
{
public static void main(String[] args)
{
displayPattern(13);
//displayPattern(11,",");
}
public static void displayPattern(int n)
{
//print out n-1 spaces and the first number
//print n-2 spaces and the 2nd then first number
int counter = n;
for(int i = 1; i <= n; i++)
{
for(int j = 1; j <= counter; j++)
{
if (n > 10)
{
if (i == n)
{
System.out.print("");
}
else if (i <= 10)
{
System.out.print(" ");
}
else
{
System.out.print(" ");
}
}
else if (n <=10)
{
if (i>9)
{
System.out.print(" ");
}
else
{
System.out.print(" ");
}
}
}
System.out.print(i + " ");
int tempValue = i - 1;
while(tempValue>0)
{
System.out.print(tempValue);
if(tempValue>1)
{
System.out.print(" ");
}
tempValue--;
}
if(tempValue==0)
{
System.out.print("\n");
}
counter--;
}
}
}
This is currently what I have for my Palindrome program for my computer science class. I have it pretty much working, except whenever a word is a palindrome, it is an infinite loop. I know I have to insert a number base case, but I do not how to do that...I'm really having trouble understanding recursion. Help is appreciated.
public class PalindromeTester
{
public static void main(String[] args)
{
Scanner scan = new Scanner (System.in);
String str, another = "y";
int left, right;
while (another.equalsIgnoreCase("y"))
{
System.out.println("Enter a potential palindrome:");
str = scan.next();
left = 0;
right = str.length() - 1;
tester(str, left, right);
System.out.println();
System.out.println("Test another palindrome (y/n)?");
another = scan.next();
}
}
public static void tester (String str, int left, int right)
{
Scanner scan = new Scanner (System.in);
while (str.charAt(left) == str.charAt(right) && left < right)
{
System.out.println(str);
tester( str, left + 1, right -1);
}
if (left < right)
{
System.out.println("That string is NOT a palindrome.");
}
else
{
System.out.println("That string IS a palindrome.");
}
}
}
You are using a while loop. With recursion, this is done implicitly.
You have to split the algorithm in small parts.
[] represents left, {} represents right.
[1] 2 3 4 5 6 7 8 9 0 9 8 7 6 5 4 3 2 {1} -->Level 0
1 [2] 3 4 5 6 7 8 9 0 9 8 7 6 5 4 3 {2} 1 -->Level 1
1 2 [3] 4 5 6 7 8 9 0 9 8 7 6 5 4 {3} 2 1 -->Level 2
1 2 3 [4] 5 6 7 8 9 0 9 8 7 6 5 {4} 3 2 1 -->Level 3
1 2 3 4 [5] 6 7 8 9 0 9 8 7 6 {5} 4 3 2 1 -->Level 4
1 2 3 4 5 [6] 7 8 9 0 9 8 7 {6} 5 4 3 2 1 -->Level 5
1 2 3 4 5 6 [7] 8 9 0 9 8 {7} 6 5 4 3 2 1 -->Level 6
1 2 3 4 5 6 7 [8] 9 0 9 {8} 7 6 5 4 3 2 1 -->Level 7
1 2 3 4 5 6 7 8 [9] 0 {9} 8 7 6 5 4 3 2 1 -->Level 8
1 2 3 4 5 6 7 8 9 {[0]} 9 8 7 6 5 4 3 2 1 -->Level 9
So, tester will continue until:
We've reached the middle of the word.
The word is not a palindrome
Example of case 2:
[1] 2 3 A 5 6 7 8 9 0 9 8 7 6 5 4 3 2 {1}
1 [2] 3 A 5 6 7 8 9 0 9 8 7 6 5 4 3 {2} 1
1 2 [3] A 5 6 7 8 9 0 9 8 7 6 5 4 {3} 2 1
1 2 3 [A] 5 6 7 8 9 0 9 8 7 6 5 {4} 3 2 1 --> !!!
I thought this method would be very helpful for the understanding of how is this recursion working
public static String positions(String word, int l, int r) {
char[] a = word.toCharArray();
String s = "";
// [letter] if left, {} if right, [{}] if both
for (int i = 0; i < a.length; i++) {
if (l == i && r == i) {
s += "{[" + a[i] + "]}";
} else if (l == i) {
s += "[" + a[i] + "]";
} else if (r == i) {
s += "{" + a[i] + "}";
} else {
s += a[i];
}
s+=" ";
}
return s;
}
And finally, the tester method.
public static boolean tester(String str, int left, int right) {
System.out.println(positions(str, left, right) +" tester(str, "+left +", "+right+")");
if (left>=right) // case 1
return true; // that's ok, we've reached the middle
// the middle was not reached yet.
// is the condition satisfied?
if (str.charAt(left) == str.charAt(right)) {
// yes. So, lets do it again, with the parameters changed
return tester(str, left + 1, right - 1);
}
//the condition was not satisfied. Let's get out of here.
else {
return false;
}
}
Some outputs:
Enter a potential palindrome:
1234567890987654321
[1] 2 3 4 5 6 7 8 9 0 9 8 7 6 5 4 3 2 {1} tester(str, 0, 18)
1 [2] 3 4 5 6 7 8 9 0 9 8 7 6 5 4 3 {2} 1 tester(str, 1, 17)
1 2 [3] 4 5 6 7 8 9 0 9 8 7 6 5 4 {3} 2 1 tester(str, 2, 16)
1 2 3 [4] 5 6 7 8 9 0 9 8 7 6 5 {4} 3 2 1 tester(str, 3, 15)
1 2 3 4 [5] 6 7 8 9 0 9 8 7 6 {5} 4 3 2 1 tester(str, 4, 14)
1 2 3 4 5 [6] 7 8 9 0 9 8 7 {6} 5 4 3 2 1 tester(str, 5, 13)
1 2 3 4 5 6 [7] 8 9 0 9 8 {7} 6 5 4 3 2 1 tester(str, 6, 12)
1 2 3 4 5 6 7 [8] 9 0 9 {8} 7 6 5 4 3 2 1 tester(str, 7, 11)
1 2 3 4 5 6 7 8 [9] 0 {9} 8 7 6 5 4 3 2 1 tester(str, 8, 10)
1 2 3 4 5 6 7 8 9 {[0]} 9 8 7 6 5 4 3 2 1 tester(str, 9, 9)
true
Test another palindrome (y/n)?
y
Enter a potential palindrome:
12345A678654321
[1] 2 3 4 5 A 6 7 8 6 5 4 3 2 {1} tester(str, 0, 14)
1 [2] 3 4 5 A 6 7 8 6 5 4 3 {2} 1 tester(str, 1, 13)
1 2 [3] 4 5 A 6 7 8 6 5 4 {3} 2 1 tester(str, 2, 12)
1 2 3 [4] 5 A 6 7 8 6 5 {4} 3 2 1 tester(str, 3, 11)
1 2 3 4 [5] A 6 7 8 6 {5} 4 3 2 1 tester(str, 4, 10)
1 2 3 4 5 [A] 6 7 8 {6} 5 4 3 2 1 tester(str, 5, 9)
false
Test another palindrome (y/n)?
In the main method,
System.out.println(tester(str, left, right));
In order to see the true/false output
Since your are using recursion (in its basic purposes mostly used to eliminate loops), isn't your while loop inside the tester() method supposed to be an if?
public static void tester (String str, int left, int right)
{
Scanner scan = new Scanner (System.in);
if (str.charAt(left) == str.charAt(right) && left < right)
{
System.out.println(str);
tester( str, left + 1, right -1);
}
else if (left < right)
{
System.out.println("That string is NOT a palindrome.");
}
else
{
System.out.println("That string IS a palindrome.");
}
}
I modified your tester() method and replaced your while with an if and moved your second if clause.
public static void tester(String str, int left, int right) {
if (str.charAt(left) == str.charAt(right) && left < right) {
tester(str, left + 1, right - 1);
} else {
if (left < right) {
System.out.println("That string is NOT a palindrome.");
} else {
System.out.println("That string IS a palindrome.");
}
}
}