I am attempting to make a QuickSort program and while I feel like it should be outputting as desired, it is not. I feel the problems lies in how I have constructed my loops but that may not be the case. As you can see, the first test with the runner prints out as I want and everything eventually gets sorted right. Any help would be greatly appreciated.
My main program:
import static java.lang.System.*;
import java.util.Arrays;
//use Arrays.toString() to help print out the array
public class QuickSort
{
private static int passCount;
public static void quickSort(Comparable[] list)
{
passCount=0;
quickSort(list, 0, list.length-1);
}
private static void quickSort(Comparable[] list, int low, int high)
{
if(low >= high)
return;
int a = partition(list, low, high);
quickSort(list, low, a-1);
quickSort(list, a+1, high);
}
private static int partition(Comparable[] list, int low, int high)
{
int x = low + 1;
int y = high;
while(x <= y)
{
if(list[x].compareTo(list[low]) <= 0)
{x++;}
else if(list[y].compareTo(list[low]) > 0)
{y--;}
else if(y < x)
{break;}
else
exchange(list, x, y);
}
exchange(list, low, y);
out.println("pass " + passCount++ + " " + Arrays.toString(list) + "\n");
return y;
}
private static void exchange(Object[] list, int x, int y) {
Object temporary = list[x];
list[x] = list[y];
list[y] = temporary;
}
}
My runner:
public class QuickSortRunner
{
public static void main(String args[])
{
QuickSort.quickSort(new Comparable[]{9,5,3,2});
System.out.println("\n");
QuickSort.quickSort(new Comparable[]{19,52,3,2,7,21});
System.out.println("\n");
QuickSort.quickSort(new Comparable[]{68,66,11,2,42,31});
System.out.println("\n");
}
}
My output:
pass 0 [2, 5, 3, 9]
pass 1 [2, 5, 3, 9]
pass 2 [2, 3, 5, 9]
pass 0 [2, 7, 3, 19, 52, 21]
pass 1 [2, 7, 3, 19, 52, 21]
pass 2 [2, 3, 7, 19, 52, 21]
pass 3 [2, 3, 7, 19, 21, 52]
pass 0 [31, 66, 11, 2, 42, 68]
pass 1 [11, 2, 31, 66, 42, 68]
pass 2 [2, 11, 31, 66, 42, 68]
pass 3 [2, 11, 31, 42, 66, 68]
Desired output:
pass 0 [2, 5, 3, 9]
pass 1 [2, 5, 3, 9]
pass 2 [2, 3, 5, 9]
pass 0 [7, 2, 3, 52, 19, 21]
pass 1 [3, 2, 7, 52, 19, 21]
pass 2 [2, 3, 7, 52, 19, 21]
pass 3 [2, 3, 7, 21, 19, 52]
pass 4 [2, 3, 7, 19, 21, 52]
pass 0 [31, 66, 11, 2, 42, 68]
pass 1 [2, 11, 66, 31, 42, 68]
pass 2 [2, 11, 66, 31, 42, 68]
pass 3 [2, 11, 42, 31, 66, 68]
pass 4 [2, 11, 31, 42, 66, 68]
The x++ and y-- to skip exchanges need to be in while loops so that exchange happens only when it is called for.
Related
I have a troubles with an application.
I would like to move my String into this ArrayList.
My String contains numbers like 15 17 18 110 113 (numbers from 1 do 200).
I have about 80 numbers in one String, eg.:
I/System.out: 15 13 13 12 12 11 11 21 21 39 39 38 38 40 40 41 41 42 42 43 43 74 74 75 75 76 76 77 77 78 78 80 80 99 99 100 100 102 102 103 103 105 105 104
While I have List<String> tmpPath = new ArrayList<>(); and I have tried two different methods:
1.
public void transferStringToArray(string s1){
for(int i = 0; i < s1.length(); i++){
int extra = 0;
if(s1.charAt(i) != ' '){
String x = Character.toString(s1.charAt(i));
tmpPath.add(extra, x);
else extra++;
}
}
where the output is:
I/System.out: [4, 0, 1, 5, 0, 1, 5, 0, 1, 3, 0, 1, 3, 0, 1, 2, 0, 1, 2, 0, 1, 0, 0, 1, 0, 0, 1, 9, 9, 9, 9, 0, 8, 0, 8, 8, 7, 8, 7, 7, 7, 7, 7, 6, 7, 6, 7, 5, 7, 5, 7, 4, 7, 4, 7, 3, 4, 3, 4, 2, 4, 2, 4, 1, 4, 1, 4, 0, 4, 0, 4, 8, 3, 8, 3, 9, 3, 9, 3, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 5, 1]
(numbers are printed from last to first number which is wrong with my assumptions)
2.
public void transferStringToArray(string s1){
for(int i = 0; i < s1.length(); i++)
if(s1.charAt(i) != ' '){
String x = Character.toString(s1.charAt(i));
tmpPath.add(x);
}
where the output is in good order, but one number means one index of an array.
I/System.out: [1, 5, 1, 3, 1, 3, 1, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 1, 3, 9, 3, 9, 3, 8, 3, 8, 4, 0, 4, 0, 4, 1, 4, 1, 4, 2, 4, 2, 4, 3, 4, 3, 7, 4, 7, 4, 7, 5, 7, 5, 7, 6, 7, 6, 7, 7, 7, 7, 7, 8, 7, 8, 8, 0, 8, 0, 9, 9, 9, 9, 1, 0, 0, 1, 0, 0, 1, 0, 2, 1, 0, 2, 1, 0, 3, 1, 0, 3, 1, 0, 5, 1, 0, 5, 1, 0, 4]
Do you have any ideas how to move full number as one index separated by a space?
Also I have one more question:
How could I delete all repeated numbers? I know, that numbers are printed once or twice but in the result I have to have unique numbers.
All you need to do is a split with space s.split("\\s+"), and then put the result in a Set like this:
Set<String> set = new HashSet<>(Arrays.asList(s.split("\\s+")));
Or if you want to maintain the order, you can use :
Set<String> set = new LinkedHashSet<>(Arrays.asList(s.split("\\s+")));
If you are looking to use List and nothing else, then you can use, distinct like so :
List<String> set = Arrays.stream(s.split("\\s+"))
.distinct()
.collect(Collectors.toList());
Outputs
[15, 13, 12, 11, 21, 39, 38, 40, 41, 42, 43, 74, 75, 76, 77, 78, 80, 99, 100, 102, 103, 105, 104]
To convert space separated string into an array list :
You first need to split your string into an string array and then convert it into array list
public void convertStringToList() {
String stringToSplit = "15 13 13 12";
String[] splittedString = stringToSplit.split(" "); // Will split string based upon the space into an string array
List<String> listOfStrings = Arrays.asList(splittedString);
}
To remove the duplicates, you can insert all the array lists value into a Set. A set is a data structure in java which stores only unique values.
Set<String> uniqueValuesSet = new HashSet<>(listOfStrings);
for(String str : uniqueValuesSet) {
System.out.println(str);
}
In 2nd point, you might see your output is in random order. That is because HashSet doesn't maintain order of elements. If you need to maintain order as well. Use LinkedHashSet.
Set<String> uniqueValuesSet = new LinkedHashSet<>(listOfStrings);
for(String str : uniqueValuesSet) {
System.out.println(str);
}
Note: This solution assumes number in the original string are single space separated. If you want solution irrespective of number of spaces between 2 numbers, replace this line in point 1
String[] splittedString = stringToSplit.split(" ");
To
String[] splittedString = stringToSplit.split("\\s+");
I'm sticking with Set, as MaciejB wanted to eliminate duplicates and that's the contract of Set.
And, as MaciejB mentioned order too, I parsed them as Integer & put 'em in a TreeSet.
That looks like this:
Set<Integer> set = Stream.of(s.split("\\s+")).map(Integer::parseInt).collect(Collectors.toCollection(TreeSet::new));
Or if you prefer multiple lines:
Set<Integer> set = Stream // Result is ordered, parsed Set
.of(s.split("\\s+")) // -> String[]
.map(Integer::parseInt) // -> Integer[] for order in TreeSet
.collect(Collectors.toCollection(TreeSet::new)); // no duplicates
Outputs:
[11, 12, 13, 15, 21, 38, 39, 40, 41, 42, 43, 74, 75, 76, 77, 78, 80, 99, 100, 102, 103, 104, 105]
While looping through a for loop which is randomly 1-10 long. I also go through a while loop. I am trying to find 6 random numbers between 1-42. I then do that again (1-10) times. Currently, these 6 random numbers stay the same. I suspect it has something to do with the seed but I could not solve it.
I tried to use both SecureRandom, Random, and via Math.random()
Nothing has worked.
The model:
public static final int MAX_TIPS = 10;
public static final int MIN_TIPS = 1;
public static final int REQUIRED_NUMBERS = 6;
public static final int RANGE_NUMBER_MIN = 1;
public static final int RANGE_NUMBER_MAX = 42;
public static final int RANGE_LUCKY_NUMBER_MIN = 1;
public static final int RANGE_LUCKY_NUMBER_MAX = 6;
private Random random = new Random();
private int getRandomInt(int min, int max) {
return random.nextInt((max - min) + 1) + min;
}
public ArrayList<LottoTip> createOpponentTips() {
ArrayList<Integer> opponentChosenNumbers = new ArrayList<>();
ArrayList<LottoTip> lottoTips = new ArrayList<>();
//1-10
int amountOfTips = getRandomInt(MIN_TIPS, MAX_TIPS);
for (int i = 0; i < amountOfTips; i++) {
int[] arrayOpponentChosenNumbers = new int[REQUIRED_NUMBERS];
while (opponentChosenNumbers.size() < REQUIRED_NUMBERS) {
//1-42 This here is the problem zone
int randomNumber = getRandomInt(RANGE_NUMBER_MIN, RANGE_NUMBER_MAX);
if (!opponentChosenNumbers.contains(randomNumber)) {
opponentChosenNumbers.add(randomNumber);
}
}
//1-6 ---This here works
int opponentLuckyNumber = getRandomInt(RANGE_LUCKY_NUMBER_MIN, RANGE_LUCKY_NUMBER_MAX);
for (int j = 0; j < opponentChosenNumbers.size(); j++) {
arrayOpponentChosenNumbers[j] = opponentChosenNumbers.get(j);
}
lottoTips.add(new LottoTip(arrayOpponentChosenNumbers, opponentLuckyNumber));
}
return lottoTips;
}
LottoTip:
public class LottoTip {
private int[] numbers;
private int luckyNumber;
public LottoTip(int[] numbers, int luckyNumber) {
this.numbers = numbers;
this.luckyNumber = luckyNumber;
}
public String getNumbers() {
return numbers[0] + ", " + numbers[1] + ", " + numbers[2] + ", " + numbers[3] + ", " + numbers[4] + ", " + numbers[5];
}
public void setNumbers(int[] numbers) {
this.numbers = numbers;
}
public int[] getNumbersArray() {
return numbers;
}
public int getLuckyNumber() {
return luckyNumber;
}
public void setLuckyNumber(int luckyNumber) {
this.luckyNumber = luckyNumber;
}
#Override
public String toString() {
return "\nNumbers: " + getNumbers() + " Lucky Number: " + luckyNumber;
}
}
Here is a System.out.println as you can see the Numbers are staying the same. Could you help me find a way to create a getRandomInt method which works all the time?
Thank you very much for your help.
Kerry York [
Numbers: 6, 4, 30, 15, 25, 5 Lucky Number: 2,
Numbers: 6, 4, 30, 15, 25, 5 Lucky Number: 4,
Numbers: 6, 4, 30, 15, 25, 5 Lucky Number: 5,
Numbers: 6, 4, 30, 15, 25, 5 Lucky Number: 1,
Numbers: 6, 4, 30, 15, 25, 5 Lucky Number: 3,
Numbers: 6, 4, 30, 15, 25, 5 Lucky Number: 6]
Don Dickinson [
Numbers: 23, 29, 34, 18, 16, 19 Lucky Number: 6,
Numbers: 23, 29, 34, 18, 16, 19 Lucky Number: 5,
Numbers: 23, 29, 34, 18, 16, 19 Lucky Number: 3,
Numbers: 23, 29, 34, 18, 16, 19 Lucky Number: 2,
Numbers: 23, 29, 34, 18, 16, 19 Lucky Number: 4,
Numbers: 23, 29, 34, 18, 16, 19 Lucky Number: 1,
Numbers: 23, 29, 34, 18, 16, 19 Lucky Number: 1,
Numbers: 23, 29, 34, 18, 16, 19 Lucky Number: 4,
Numbers: 23, 29, 34, 18, 16, 19 Lucky Number: 3]
Clifford Weinstein [
Numbers: 6, 33, 13, 2, 37, 38 Lucky Number: 6,
Numbers: 6, 33, 13, 2, 37, 38 Lucky Number: 3,
Numbers: 6, 33, 13, 2, 37, 38 Lucky Number: 2,
Numbers: 6, 33, 13, 2, 37, 38 Lucky Number: 1,
Numbers: 6, 33, 13, 2, 37, 38 Lucky Number: 4,
Numbers: 6, 33, 13, 2, 37, 38 Lucky Number: 3,
Numbers: 6, 33, 13, 2, 37, 38 Lucky Number: 5,
Numbers: 6, 33, 13, 2, 37, 38 Lucky Number: 6,
Numbers: 6, 33, 13, 2, 37, 38 Lucky Number: 3,
Numbers: 6, 33, 13, 2, 37, 38 Lucky Number: 3]
Angela Spencer [
Numbers: 12, 39, 8, 25, 40, 15 Lucky Number: 6,
Numbers: 12, 39, 8, 25, 40, 15 Lucky Number: 3,
Numbers: 12, 39, 8, 25, 40, 15 Lucky Number: 2,
Numbers: 12, 39, 8, 25, 40, 15 Lucky Number: 4,
Numbers: 12, 39, 8, 25, 40, 15 Lucky Number: 5,
Numbers: 12, 39, 8, 25, 40, 15 Lucky Number: 4,
Numbers: 12, 39, 8, 25, 40, 15 Lucky Number: 2,
Numbers: 12, 39, 8, 25, 40, 15 Lucky Number: 2,
Numbers: 12, 39, 8, 25, 40, 15 Lucky Number: 3]
Leroy McIntosh [
Numbers: 5, 23, 2, 24, 28, 3 Lucky Number: 1]
You reuse the opponentChosenNumbers list between iterations of the outer for loop.
As such, on the second iteration, the while loop guard
while (opponentChosenNumbers.size() < REQUIRED_NUMBERS) {
is immediately false, so you don't pick new random numbers.
Move the declaration of opponentChosenNumbers into the for loop (or ensure it is empty before the while loop, e.g. by invoking opponentChosenNumbers.clear()).
having this issue with a decryption program I am writing in Java. Here is the code in question
public static int int_to_int(int input)
{
int[] value_array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26};
int[]bin_array= {00000, 00001, 00010, 00011,
00100, 00101, 00110, 00111,
01000, 01001, 01010, 01011, 01100,
01101, 01110, 01111, 10000, 10001,
10010, 10011, 10100, 10101, 10110,
10111, 11000,11001, 11010, 11011};
for(int i=0; i <27; i++)
{
System.out.println("hello");
if(input==value_array[i])
{
System.out.println("returning: " + bin_array[i] + "at: " + i);
return bin_array[i];
}
}
return -1;
}
And here is the issue highlighted in a line
double temp = 00010;
System.out.println("returning: " + temp);
This will output
returning: 8
but I want to see
returning: 00010
thoughts?
The 00010 is octal number, i.e., 8. Remove all the leading zeroes.
Integers prefixed with 0 are treated as octal, not binary. Prefix with 0b or 0B to indicate binary, like 0B00010. To print as binary, use
System.out.println("returning: " + Integer.toBinaryString(temp));
or,
System.out.println("returning: " + Integer.toString(temp, 2));
That is, assuming temp is an integer, like in your bin_array.
public static int int_to_int(int input)
{
int[] value_array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26};
int[]bin_array= {00000, 00001, 00010, 00011,
00100, 00101, 00110, 00111,
01000, 01001, 01010, 01011, 01100,
01101, 01110, 01111, 10000, 10001,
10010, 10011, 10100, 10101, 10110,
10111, 11000,11001, 11010, 11011};
for(int i=0; i <27; i++)
{
System.out.println("hello");
if(input==value_array[i])
{
System.out.println("returning: " + Integer.toOctalString(bin_array[i]) + "at: " + i);
return bin_array[i];
}
}
return -1;
}
I use Integer.toOctalString
I have a 2d array called interval[g][2] where g is some number.
Currently, I'm trying to sort the array first by increasing order in the first element, and if they are equal, sort by decreasing order in the second element.
I've attempted this in two ways:
1) Using Java 8's Comparator.comparing method:
Arrays.sort(interval, Comparator.comparing((int[] arr) -> arr[0]));
2) Using Arrays.sort:
Arrays.sort(interval, new Comparator<int[]>() {
#Override
public int compare(int[] s1, int[] s2) {
if (s1[0] > s2[0])
return 1;
else if (s1[0] < s2[0])
return -1;
else {
if(s1[1] < s2[1])
return 1;
else if (s1[1] > s2[1])
return -1;
else
return 0;
}
}
});
The first method returns a partially sorted list.
[[0, 10], [10, 30], [30, 50]]
[[0, 10], [3, 19], [35, 45]]
[[10, 30], [27, 33], [30, 50]]
[[-10, 10], [0, 20], [35, 45]]
[[10, 30], [20, 40], [30, 50]]
[[0, 20], [8, 28], [37, 43]]
[[0, 20], [15, 35], [37, 43]]
[[0, 0], [8, 28], [10, 40]]
As you can see, it's sorting things in a set of three tuples.
The second method doesn't sort the array at all. Can I not sort using primitive data types? Can anyone advise?
I think you're looking for this:
Arrays.sort(interval, Comparator.comparingInt((int[] arr) -> arr[0]).thenComparing(Comparator.comparingInt((int[] arr) -> arr[1]).reversed()));
Or if you want to go with the custom Comparator:
Arrays.sort(interval, new Comparator<int[]>() {
#Override
public int compare(int[] o1, int[] o2) {
int result = Integer.compare(o1[0], o2[0]);
if (result == 0) {
result = Integer.compare(o2[1], o1[1]);
}
return result;
}
});
int[][] interval = new int[][] { {0, 10}, {10, 30}, {30, 50}, {0, 10}, {3, 19}, {35, 45}, {10, 30}, {27, 33}, {30, 50}, {-10, 10}, {0, 20}, {35, 45}, {10, 30}, {20, 40}, {30, 50}, {0, 20}, {8, 28}, {37, 43}, {0, 20}, {15, 35}, {37, 43}, {0, 0}, {8, 28}, {10, 40} };
Arrays.sort(interval, Comparator.<int[]>comparingInt(arr -> arr[0]).thenComparing(arr -> arr[1], Comparator.<Integer>naturalOrder().reversed()));
Stream.of(interval).forEachOrdered(ints -> System.out.println(Arrays.toString(ints)));
This is a brute force attempt to solve the problem, but it is not giving the right answer. The program runs, but its not producing desired output. I believe the logic and program is correct.
This is problem of a famous site (don't want to a spoiler)
It asks for the number that produces the longest Collatz chain under one million.
class Euler
{
public static void main (String args[])
{
long len,longLength=0;
for(long i =3;i<=1000000;i++)
{
len = Euler14.numFucs(i);
System.out.println("Ans"+len+"\t"+i);
if(len>longLength)
longLength=len;
}
System.out.println(longLength);
}
public static long numFucs(long num)
{
long count=1,$test=0;
while(num>1)
{
if(num%2==0)
{
num=num/2;
}
else
{
num=3*num+1;
}
count++;
}
//System.out.println("\tEnd");
return count;
}
}
Well, I feel like it'd be cheating to give you the code for the right answer, as a fellow Project Euler fan. You're outputting the length of the longest chain, not the number that obtains it. If you really want, I can show you the one line that needs to change, but, honestly, this is a simple fix, and I challenge you to do it yourself.
If the program is suppose to compute the number of steps in the Collatz Conjecture the implementation looks fine to me.
The sequence of numbers in described by OEIS Sequence A008908.
Here's is your program together with some debug output.
class Test {
public static void main(String args[]) {
long len, longLength = 0;
System.out.println(Test.numFucs(13));
String[] correct = ("1, 1, 2, 8, 3, 6, 9, 17, 4, 20, 7, 15, 10, 10, 18,"
+ " 18, 5, 13, 21, 21, 8, 8, 16, 16, 11, 24, 11, 112, "
+ "19, 19, 19, 107, 6, 27, 14, 14, 22, 22, 22, 35, 9, "
+ "110, 9, 30, 17, 17, 17, 105, 12, 25, 25, 25, 12, "
+ "12, 113, 113, 20, 33, 20, 33, 20, 20, 108, 108, 7,"
+ " 28, 28, 28, 15, 15, 15, 103").split(", ");
for (int i = 0; i <= 70; i++) {
len = Test.numFucs(i);
System.out.printf("i = %2d, Correct %3s, Computed: %3d%n", i,
correct[i], len);
if (len > longLength)
longLength = len;
}
System.out.println(longLength);
}
public static long numFucs(long num) {
long count = 1;
while (num > 1) {
if (num % 2 == 0) {
num = num / 2;
} else {
num = 3 * num + 1;
}
count++;
}
// System.out.println(count);
return count;
}
}
Output:
i = 0, Correct 1, Computed: 1
i = 1, Correct 1, Computed: 1
i = 2, Correct 2, Computed: 2
i = 3, Correct 8, Computed: 8
i = 4, Correct 3, Computed: 3
i = 5, Correct 6, Computed: 6
i = 6, Correct 9, Computed: 9
i = 7, Correct 17, Computed: 17
i = 8, Correct 4, Computed: 4
i = 9, Correct 20, Computed: 20
i = 10, Correct 7, Computed: 7
i = 11, Correct 15, Computed: 15
i = 12, Correct 10, Computed: 10
i = 13, Correct 10, Computed: 10
i = 14, Correct 18, Computed: 18
i = 15, Correct 18, Computed: 18
i = 16, Correct 5, Computed: 5
...
As you can see it follows the OEIS sequence.
The error must be some where else.