As the title says, I am looking for a sorting algorithm that can sort the numbers between 1 and 100 using the least amount of statements in only one method which is the main.
Here's an example to give you an idea on how I can check it(using a counter)
class Solution{
public static void main(String[] args) {
//declaration
int count = 0,inner, outer, temp, h = 1; count++;
int [] array = {100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1,}; count++;
System.out.println("Before: " + Arrays.toString(array)); count++;
//start of the sort
while (h <= array.length / 3) //start of while loop 1
{
h = h * 3 + 1; count++;
}count++; //end of while loop 1
while (h > 0) //start of while loop 2
{
for (outer = h; outer < array.length; outer++) //start of for loop
{
temp = array[outer]; count++;
inner = outer;count++;
while (inner > h - 1 && array[inner - h] >= temp) //start of while loop 3
{
array[inner] = array[inner - h]; count++;
inner -= h; count++;
}count++; //end of for loop 3
array[inner] = temp; count++;
}count++; //end of for loop
//equation to count for
count = count + array.length-h+1 + array.length - h +1 -1;
h = (h - 1) / 3; count++;
}count++; //end of while loop 2
System.out.println("After: " + Arrays.toString(array) + "\n" + "Counter = " + count);
}
}
The fastest algorithm with example would be quicksort, also as you are asking i believe this would also take the least amount of statments. Below you can find a link and also description of how it works.
https://www.geeksforgeeks.org/quick-sort/
I am trying to solve Project Euler problem 18. I have created an array for each row (starting from the bottom), and then an array of those arrays. I created a recursive method that starts from the bottom row, and looks ahead three rows to find the best path.
I created minimum and maximum methods to make sure that the index of my arrays could not go below zero, or above the length minus one.
/**
* A method that sets a minimum limit for an integer
* #param a The number
* #param b The lowest value it can go
* #return a
*/
public static int min(int a, int b) {
if (a<b) {
a=b;
}
return a;
}
/**
* Sets the maximum limit for an int
* #param a the number
* #param b The highest a number can go
* #return a
*/
public static int max(int a, int b) {
if(a>b) {
a=b;
}
return a;
}
Then I used these methods when calculating all possible paths in the next three rows.
I got the Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 11 error on this line of code:
eighthPoss = array[x+2][max(i, array[x].length-1)] + array[x+1][max(i, array[x].length-1)] + array[x][max(i, array[x].length-1)];
Where x is the current row, and i is the current position on the row.
I have if statements for when x+2 and x+1 are more than the amount of rows (When we are on the second to last, or last row of the triangle). I am genuinely confused how anything on this line of code is out of bounds as I have minimum and maximum values on each of them to make sure they don't go out of the range. I ran print statements and the last numbers the loops ran through before the error were x=1, i=10.
Below are my arrays. (I did not include the top row, since it is only one number.)
int[] row1 = {04, 62, 98, 27, 23, 9, 70, 98, 73, 93, 38, 53, 60, 04, 23};
int[] row2 = {63, 66, 04, 68, 89, 53, 67, 30, 73, 16, 69, 87, 40, 31};
int[] row3 = {91, 71, 52, 38, 17, 14, 91, 43, 58, 50, 27, 29, 48};
int[] row4 = {70, 11, 33 ,28, 77, 73, 17, 78, 39, 68, 17, 57};
int[] row5 = {53, 71, 44, 65, 25, 43, 91, 52, 97, 51, 14};
int[] row6 = {41, 48, 72, 33, 47, 32, 37, 16, 94, 29};
int[] row7 = {41, 41, 26, 56, 83, 40, 80, 70, 33};
int[] row8 = {99, 65, 4, 28, 6, 16, 70, 92};
int[] row9 = {88, 2, 77, 73, 7, 63, 67};
int[] row10 = {19, 1, 23, 75, 3, 34};
int[] row11 = {20, 4, 82, 47, 65};
int[] row12 = {18, 35, 87, 10};
int[] row13 = {17, 47, 82};
int[] row14 = {95, 64};
int[][] rows = {row1, row2, row3, row4, row5, row6, row7, row8, row9, row10, row11, row12,
row13, row14};
Any help you could give me would be greatly appreciated.
Make sure that your x+2 isn't going out of bounds as it seems you're only checking to see if i is going out of bounds. (You may be checking for it somewhere else but you didn't provide that code).
Bonus clamp method that I personally use instead of individual max and min methods (since they're built into Java).
public static int clamp(int a, int min, int max) {
return Math.max(min, Math.min(max, a));
}
I am trying to generate a random tour from the graph. I am using the adjacency-list method.
There is a problem with the vertices. When I add a vertex to a particular list, the vertex gets added to all the lists in the graph. I do not understand why! Here's the code:
public static void main(String[] args) {
defaultData(6);
}
public static void defaultData(int n) {
Integer costs[] = { 26, 95, 38, 74, 80, 73, 73, 92, 22, 97, 13, 81, 41,
17, 4, 2, 47, 54, 21, 68, 78, 4, 77, 3, 66, 55, 99, 42, 62, 39, 8, 36,
53, 74, 26, 8, 42, 66, 30, 58, 69, 14, 49, 39, 85, 98, 72, 3, 18, 99,
96, 66, 64, 36, 17, 44, 70, 0, 8, 14, 62, 41, 84, 59, 94, 27, 5, 27,
96, 10, 15, 52, 43, 20, 2, 86, 45, 43, 32, 17, 49, 92, 9, 15, 6, 49,
72, 7, 51, 21, 2, 26, 63, 82, 98, 48, 21, 96, 16 };
ArrayList<ArrayList<Integer>> costGraph = new ArrayList<>();
ArrayList<ArrayList<Integer>> completeGraph = new ArrayList<>();
Random rand = new Random(System.currentTimeMillis());
int costIndex = 0;
for (int i = 0; i <= n; i++) {
ArrayList<Integer> cost = new ArrayList<>();
ArrayList<Integer> edge = new ArrayList<>();
for (int j = 0; j <= n; j++) {
if (i == j) {
continue;
}
edge.add(j);
cost.add(costs[costIndex]);
costIndex++;
}
completeGraph.add(edge);
costGraph.add(cost);
}
System.out.println(completeGraph);
ArrayList<ArrayList<Integer>> dummyGraph =
(ArrayList<ArrayList<Integer>>)completeGraph.clone();
ArrayList<ArrayList<Integer>> randomTour = new ArrayList<>();
ArrayList<Integer> dummyList = new ArrayList<>();
for (int i = 0; i <= n; i++) {
randomTour.add(dummyList);
}
System.out.println(dummyGraph);
int edgeCount = 0;
Integer row = rand.nextInt(n);
Integer start = row;
while(edgeCount <= n-1){
//dummyList = dummyGraph.get(row);
// To keep the bounds of the random equal
// to the new reduced size of the lists in the graph
Integer col = dummyGraph.get(row).get(rand.nextInt(n-edgeCount));
randomTour.get(row).add(col);
System.out.println(row);
System.out.println(randomTour);
edgeCount++;
for(int k = 0; k < n; k++)
dummyGraph.get(k).remove(row);
row = col;
}
randomTour.get(row).add(start);
System.out.println(randomTour);
}
I would be very grateful for a timely response. Thanks in advance!
You don't want to do this:
for (int i = 0; i <= n; i++) {
randomTour.add(dummyList);
}
It keeps adding the same reference lots of times, so all the ArrayLists in the ArrayList are actually the same object.
Instead you want to do this:
for (int i = 0; i <= n; i++) {
randomTour.add(new ArrayList<Integer>());
}
That way the ArrayList instances in the ArrayList are all different.
I hope this answer was timely enough!
I need to split a deck of cards into two packets: the top half and the bottom half. This new array of cards is suppose to go: first card from from the top packet, first card from bottom packet, second card from top packet, second card from bottom packet, etc. If there are an odd number of cards then the top packet should have one more than the bottom packet. The top of the deck is the front of the array.
How would I go about doing this?
Here is the method I created to generate the deck of cards (I think it works):
private Card[] cards;
int value, suit;
private final int DECK_SIZE = 52;
public Deck()
{
int index = 0;
cards = new Card[DECK_SIZE];
//0 = spades, 1 = hearts, 2 = clovers, 3 =diamonds
int suits[] = {0, 1, 2, 3};
//1 = Ace, 11=jack, 12=queen, 13=king
int values[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
for (int suit : suits)
for (int value : values)
{
cards[index] = new Card(value, suit);
index++;
}
}
Before you go about doing what you say, note that a perfect shuffle is not a good idea if you are looking to randomize the order of a deck:
A perfect faro shuffle, where the cards are perfectly alternated, is considered one of the most difficult sleights of card manipulation, because it requires the shuffler to cut the deck into two equal stacks and apply just the right pressure when pushing the half decks into each other. If one manages to perform eight perfect faro out-shuffles in a row, then the deck of 52 cards will be restored to its original order. If one can do perfect in-shuffles, then 26 shuffles will reverse the order of the deck and 26 more will restore it to its original order.
If you want a random shuffle, on the other hand, the way to go is a Fisher-Yates shuffle. From the wikipedia page:
To shuffle an array a of n elements (indexes 0..n-1):
for i from n − 1 downto 1 do
j ← random integer with 0 ≤ j ≤ i
exchange a[j] and a[i]
Note, however, that depending on your randomness criteria, the standard Java random number generator may not be sufficient: (also from the Wikipedia page:)
For example, the built-in pseudorandom number generator provided by many programming languages and/or libraries may often have only 32 bits of internal state, which means it can only produce 232 different sequences of numbers. If such a generator is used to shuffle a deck of 52 playing cards, it can only ever produce a very small fraction of the 52! ≈ 2225.6 possible permutations. It's impossible for a generator with less than 226 bits of internal state to produce all the possible permutations of a 52-card deck. It has been suggested[citation needed] that confidence that the shuffle is unbiased can only be attained with a generator with more than about 250 bits of state.
Mersenne Twister is a well-known random number generator that would be adequate.
edit: for a literal answer to your original question, here's how I would probably do it (including a test method):
import java.util.Arrays;
public class Shuffle {
/* assumes input and output arrays are same length (N) */
static public <T> void perfectShuffle(T[] input, T[] output, int N)
{
int itop = 0;
int ibottom = N - (N/2);
/* bottom has (N/2) elements; for odd N this is rounded down,
* and the top part has 1 more element */
int k = 0;
while (ibottom < N)
{
output[k++] = input[itop++];
output[k++] = input[ibottom++];
}
// handle last element for N = odd
if (k < N)
output[k] = input[itop];
}
public static void main(String[] args) {
int N = 19;
String[] in = new String[N];
String[] out = new String[N];
for (int i = 0; i < N; ++i)
in[i] = Integer.toString(i);
perfectShuffle(in, out, N);
System.out.println(Arrays.asList(out));
}
}
output of main():
[0, 10, 1, 11, 2, 12, 3, 13, 4, 14, 5, 15, 6, 16, 7, 17, 8, 18, 9]
finally, the reason why you shouldn't use this for shuffling cards:
public static void main(String[] args) {
int N = 52;
String[] in = new String[N];
String[] out = new String[N];
for (int i = 0; i < N; ++i)
in[i] = Integer.toString(i);
for (int k = 0; k < 8; ++k)
{
perfectShuffle(in, out, N);
System.out.println(Arrays.asList(out));
String[] tmp = in;
in = out;
out = tmp;
}
}
output:
[0, 26, 1, 27, 2, 28, 3, 29, 4, 30, 5, 31, 6, 32, 7, 33, 8, 34, 9, 35, 10, 36, 11, 37, 12, 38, 13, 39, 14, 40, 15, 41, 16, 42, 17, 43, 18, 44, 19, 45, 20, 46, 21, 47, 22, 48, 23, 49, 24, 50, 25, 51]
[0, 13, 26, 39, 1, 14, 27, 40, 2, 15, 28, 41, 3, 16, 29, 42, 4, 17, 30, 43, 5, 18, 31, 44, 6, 19, 32, 45, 7, 20, 33, 46, 8, 21, 34, 47, 9, 22, 35, 48, 10, 23, 36, 49, 11, 24, 37, 50, 12, 25, 38, 51]
[0, 32, 13, 45, 26, 7, 39, 20, 1, 33, 14, 46, 27, 8, 40, 21, 2, 34, 15, 47, 28, 9, 41, 22, 3, 35, 16, 48, 29, 10, 42, 23, 4, 36, 17, 49, 30, 11, 43, 24, 5, 37, 18, 50, 31, 12, 44, 25, 6, 38, 19, 51]
[0, 16, 32, 48, 13, 29, 45, 10, 26, 42, 7, 23, 39, 4, 20, 36, 1, 17, 33, 49, 14, 30, 46, 11, 27, 43, 8, 24, 40, 5, 21, 37, 2, 18, 34, 50, 15, 31, 47, 12, 28, 44, 9, 25, 41, 6, 22, 38, 3, 19, 35, 51]
[0, 8, 16, 24, 32, 40, 48, 5, 13, 21, 29, 37, 45, 2, 10, 18, 26, 34, 42, 50, 7, 15, 23, 31, 39, 47, 4, 12, 20, 28, 36, 44, 1, 9, 17, 25, 33, 41, 49, 6, 14, 22, 30, 38, 46, 3, 11, 19, 27, 35, 43, 51]
[0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 1, 5, 9, 13, 17, 21, 25, 29, 33, 37, 41, 45, 49, 2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42, 46, 50, 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47, 51]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51]
[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, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51]
If you're able to substitute a non-perfect shuffle, try Collections.shuffle(). Your code would look something like this:
List card_list = Arrays.asList(cards);
Collections.shuffle(card_list);
or as #Mark Peters points out, the more concise:
Collections.shuffle(Arrays.asList(cards));
I was looking for something similar (shuffling a JSONArray) in this question: An efficient way to shuffle a JSON array in java?
I ended up making my own shuffle method implementing this algorithm. For your example, it would be something like:
public Card[] shuffle(Card[] cards) {
// Implementing Fisher–Yates shuffle
Random rnd = new Random();
for (int i = cards.length() - 1; i >= 0; i--)
{
int j = rnd.nextInt(i + 1);
// Simple swap
Card card = cards[j];
cards[j] = cards[i];
cards[i] = card;
}
return cards;
}