Bubble sort with output - java

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

Related

What is wrong with my Floyd Warshall algorithm?

Here is the problem link
Approach:
My approach is to simply give every other node the chance to be an in-between node for every 2 pairs of vertices i and j.
Below is my code for Floyd Warshall algorithm:
class Solution{
public void shortest_distance(int[][] mat){
int N = mat.length;
for(int i = 0; i < N; ++i){
for(int j = 0; j < N; ++ j){
for(int k = 0; k < N; ++k){
if(mat[i][k] != -1 && mat[k][j] != -1 && (mat[i][j] == -1 || mat[i][j] > mat[i][k] + mat[k][j])){
mat[i][j] = mat[i][k] + mat[k][j];
}
}
}
}
}
}
This gives wrong answer for the below case:
Input
12
0 4 2 1 2 9 4 8 -1 4 -1 -1
9 0 3 6 2 6 2 3 6 -1 -1 3
7 1 0 10 8 9 1 3 -1 7 -1 10
5 1 9 0 3 -1 1 10 7 1 -1 7
-1 5 1 4 0 2 10 4 10 6 4 5
7 8 3 7 5 0 5 1 3 5 7 2
6 -1 6 1 10 7 0 10 -1 -1 7 7
-1 3 2 7 4 -1 4 0 10 5 6 10
10 6 1 10 4 4 7 10 0 4 7 4
1 1 6 8 8 9 2 10 6 0 -1 3
5 9 3 -1 4 3 -1 -1 -1 3 0 1
2 2 8 6 2 4 4 3 -1 3 4 0
My output
0 2 2 1 2 4 2 5 7 2 6 5
5 0 3 3 2 4 2 3 6 4 6 3
6 1 0 2 3 5 1 3 7 3 7 4
2 1 4 0 3 5 1 4 7 1 7 4
6 2 1 3 0 2 2 3 5 4 4 4
4 4 3 5 4 0 4 1 3 5 6 2
3 2 5 1 4 6 0 5 8 2 7 5
6 3 2 4 4 6 3 0 9 5 6 6
5 2 1 3 4 4 2 4 0 4 7 4
1 1 3 2 3 5 2 4 6 0 7 3
3 3 3 4 3 3 4 4 6 3 0 1
2 2 3 3 2 4 4 3 7 3 4 0
Expected Output
0 2 2 1 2 4 2 5 7 2 6 5
5 0 3 3 2 4 2 3 6 4 6 3
4 1 0 2 3 5 1 3 7 3 7 4
2 1 4 0 3 5 1 4 7 1 7 4
5 2 1 3 0 2 2 3 5 4 4 4
4 4 3 5 4 0 4 1 3 5 6 2
3 2 5 1 4 6 0 5 8 2 7 5
6 3 2 4 4 6 3 0 9 5 6 6
5 2 1 3 4 4 2 4 0 4 7 4
1 1 3 2 3 5 2 4 6 0 7 3
3 3 3 4 3 3 4 4 6 3 0 1
2 2 3 3 2 4 4 3 7 3 4 0
Note: I have also observed that if I move the k loop out and make it the first loop, it works just fine. I am confused as to what is wrong with my current code.
It is all about states. This is more conceptual than any algorithmic implementation issue here.
As in your code,
for(i...)
for(j..)
for(k...)
mat[i][j] = mat[i][k] + mat[k][j];
The above states, for every pair of nodes i and j, check if any shortest path exists via every possible k. However, you are implicitly assuming that mat[i][k] and mat[k][j] are in already optimized states. This is incorrect as there is no real effort made in the code to bring them to that state.
Instead, you need to check for every pair of nodes i and j via only 1 value of k at a time. This is how you would be building the optimized states for every possible k one by one and the next one depending on the previous one. Hence, the below is correct version for this:
class Solution{
public void shortest_distance(int[][] mat){
int N = mat.length;
for(int k = 0; k < N; ++k){
for(int i = 0; i < N; ++i){
for(int j = 0; j < N; ++j){
if(mat[i][k] != -1 && mat[k][j] != -1 && (mat[i][j] == -1 || mat[i][j] > mat[i][k] + mat[k][j])){
mat[i][j] = mat[i][k] + mat[k][j];
}
}
}
}
}
}
Quoting from the Wiki.
The Floyd–Warshall algorithm compares all possible paths through the
graph between each pair of vertices. It is able to do this with
{\displaystyle \Theta (|V|^{3})}\Theta (|V|^{3}) comparisons in a
graph, even though there may be up to {\displaystyle \Omega
(|V|^{2})}{\displaystyle \Omega (|V|^{2})} edges in the graph, and
every combination of edges is tested. It does so by incrementally
improving an estimate on the shortest path between two vertices, until
the estimate is optimal.
Miscellaneous:
Although trivial, but I still think it is worth mentioning that the order of nodes used in the optimization process really doesn't matter. We simply need to shorten the distance(if exists and possible) node by node where every node is an intermediate candidate.
class Solution{
public void shortest_distance(int[][] mat){
int N = mat.length;
List<Integer> nodes = new ArrayList<>();
for(int i = 0; i < N; ++i) nodes.add(i);
Collections.shuffle(nodes);
for(int l = 0; l < nodes.size(); ++l){
int k = nodes.get(l);
for(int i = 0; i < N; ++i){
for(int j = 0; j < N; ++j){
if(mat[i][k] != -1 && mat[k][j] != -1 && (mat[i][j] == -1 || mat[i][j] > mat[i][k] + mat[k][j])){
mat[i][j] = mat[i][k] + mat[k][j];
}
}
}
}
}
}

How can I space my triangle correctly?

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--;
}
}
}

How can I print these numbers in correspoding location with array?

import java.util.*;
import java.io.*;
public class PracticeFinal {
public static void main (String[] args) throws FileNotFoundException{
Scanner input = new Scanner (new File("altitude.txt"));
int[] x = new int [400];
int[] y = new int [400];
float[] altitude = new float [400];
x[0] = 0;
y[0] = 0;
altitude[0] = 0;
int i = 0;
System.out.println("x\ty\taltitude");
while (input.hasNextFloat()) {
int line = input.nextInt();
x[i]=line;
int line2=input.nextInt();
y[i]=line2;
float line3 = input.nextFloat();
altitude[i]=line3;
System.out.println(x[i]+"\t" + y[i]+"\t"+ altitude[i]+"\t");
i+=1; }
printMax(altitude,x,y);
printMin(altitude,x,y);
printAverage(altitude);
printContour(altitude,x,y);
}
public static void printMax(float []altitude, int []x, int []y) {
float max=altitude[0];
int ind=0;
for(int i=0;i<100;i++)
{
if (altitude[i]>max)
{
max = altitude[i];
ind=i;
}
}
System.out.println("The maximum altitude is "+"("+x[ind]+","+y[ind]+","+max+")");
}
public static void printMin(float []altitude, int []x, int []y){
float min=altitude[0];
int ind=0;
for(int i=0;i<100;i++)
{
if (altitude[i] < min)
{
min = altitude[i];
ind=i;
}
}
System.out.println("The minimum altitude is "+"("+x[ind]+","+y[ind]+","+min+")");
}
public static void printAverage(float []altitude){
float total = 0;
for(int i=0;i<100;i++)
{
total += altitude[i];
}
float avg = total / 100;
System.out.printf("The aveage altitude of the region is " + "%.2f", avg);
System.out.println();
}
public static void printContour(float []altitude, int[]x, int[]y){
for (int i=0;i<100;i++) {
System.out.print (altitude[i] + " ");
}
}
}
I need help with the last part of this program there is an x and y chart with altitudes ex, 0,0 = 109.1 1,0= 200
So for the last method i need to print out the altitude in its corresponding location starting from 1,1 to 2,1 to 3,1 and so on
Dont know what to do next after the for loop
This is the file im reading first number is x second is y and third is the altitude.
1 1 101.0
2 2 97.2
3 3 112.3
4 4 114.2
5 5 100.2
6 6 97.5
7 7 97.8
8 8 81.3
9 9 105.4
10 10 108.7
3 1 107.8
3 2 115.4
3 4 118.3
3 5 120.3
3 6 122.3
3 7 90.3
3 8 81.7
3 9 87.4
3 10 113.2
1 2 102.3
1 3 104.5
1 4 109.8
1 5 99.8
1 6 88.9
1 7 89.3
1 8 100.1
1 9 110.8
1 10 98.3
2 1 98.8
2 3 80.5
2 4 85.1
2 5 83.2
2 6 92.3
2 7 94.3
2 8 199.3
2 9 104.3
2 10 105.2
4 1 120.5
4 2 87.3
4 3 82.3
5 1 83.2
5 2 84.5
5 3 96.9
5 4 86.7
4 5 115.3
4 6 101.3
4 7 102.6
4 8 106.9
4 9 109.8
4 10 93.4
6 7 93.2
6 8 92.4
6 9 80.9
6 10 81.2
5 6 102.3
5 7 101.1
5 8 106.7
5 9 105.3
5 10 88.9
6 1 80.8
6 2 81.3
6 3 84.5
6 4 90.8
6 5 99.8
8 1 98.6
8 2 101.1
8 3 103.5
8 4 104.6
8 5 105.8
8 6 80.9
8 7 80.1
7 1 98.3
7 2 96.4
7 3 95.1
7 4 83.4
7 5 95.1
7 6 96.3
7 8 99.9
7 9 100.0
7 10 102.3
10 3 99.9
10 4 98.3
10 5 91.3
10 6 94.3
10 7 95.3
10 8 103.2
8 9 90.2
8 10 91.3
9 1 93.2
9 2 81.5
9 3 91.0
9 4 95.3
9 5 122.3
9 6 119.8
9 7 118.7
9 8 117.3
9 10 107.8
10 1 108.8
10 2 109.9
10 9 104.2
public static void printContour(float []altitude, int[]x, int[]y){
for (int i = 0; i < 100; i++) {
for (int a = 0; a < 100; a++) {
if (x[i] < x[a]) {
int temp_for_x = x[i];
x[i] = x[a];
x[a] = temp_for_x;
int temp_for_y = y[i];
y[i] = y[a];
y[a] = temp_for_y;
float temp_for_alt = altitude[i];
altitude[i] = altitude[a];
altitude[a] = temp_for_alt;
}
if(y[i] < y[a]){
int temp_for_x = x[i];
x[i] = x[a];
x[a] = temp_for_x;
int temp_for_y = y[i];
y[i] = y[a];
y[a] = temp_for_y;
float temp_for_alt = altitude[i];
altitude[i] = altitude[a];
altitude[a] = temp_for_alt;
}
}
}
for (int incr=0;incr<100;incr++) {
System.out.print(x[incr]+ " " + y[incr] + " " + altitude[incr]+ " ");
if(incr%10 == 9)
System.out.println();
}
}
}
There are better sorting algorithms you can use Here

Bubble sort in functional style Java 8

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;
}

Palindrome Program using Recursion

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.");
}
}
}

Categories