Sort a 2d array by two separate columns - java

Right now I've got a method that can get data from a 2D array, throw it into a Arraylist and then lets me retrieve only the particular parts from that Arraylist that I want.
The code below loops through the races Arraylist and places the racers, the total times and how many events they take part in into an array, as of yet unordered in any way.
if (!Found && selected.equals(race.GetCat()))
{
ranking[j][0] = race.GetComp();
ranking[j][1] = race.GetCat();
ranking[j][2] = (GetSecs(race.GetRace1()))
+ (GetSecs(race.GetRace2()))
+ (GetSecs(race.GetRace3())) + "";
n++;
};
Found= false;
for (int i = 0; i < locations.size(); i++)
{
for (Race race: races)
{
if (race.GetComp().equals(array[i][0]) && option.equals(array[i][1]))
{
seconds += (GetSes(race.GetRace1()))
+ (GetSes(race.GetRace2()))
+ (GetSes(race.GetRace3()));
total= GetMin(seconds);
counter++;
}
ranking[i][2] = total2 + "";
ranking[i][3] = counter + "";
}
}
So ranking prints out like
RACER TOTAL TIME EVENTS TAKING PART IN
name 230.44 2
name 142.51 4
name 523.01 7
name 444.55 2
name 432.18 4
And ordering the rankings (String) array so that it is sorted via perhaps the number of events or the total time of the races would not be too difficult.
However, more than one racer will take part in the same number of events, so I was wondering what process or code I would have to go through in order to order the array based on the number of events, and then check to see which rankings share the number of events, and then switch them around based on which total time is lowest
So rankings sorted like
george 500 5
john 400 5
george 500 4
david 300 3
carl 200 3
is sorted like
john 400 5
george 500 5
george 500 4
carl 200 3
david 300 3
If something like that is possible. I can put them into an array, and even sort them by one particular column, but sorting them by one, and then by another if the first column has numbers are are the same is totally beyond me, if any of this post makes sense.

Check out:
Column Comparator. It allows you to sort on any column in an ArrayList.
Group Comparator. It allows you to sort on multiple columns at the same time.

Related

Replicating the sleight of hand Trick Oil and Water

Note: I haven't found an answer to this particular question.
Backstory:
I recently learned the Oil and Water routine that magician's use in sleight of hand (this doesn't mean I can actually do it, but I have the mechanics done). For those that are unfamiliar with this routine, it takes three red cards and three black cards. These cards are initially put together red, black, red, black, red, black. By the end of the trick, all the reds are back together and all the blacks are back together.
I have successfully coded this in Java, but I am at a loss as to explain why it is doing it correctly. I think there is a problem with my logic I am sure, but I need some verification.
Here is the code I currently have:
int[] mixed = {1,2,1,2,1,2};
System.out.println("Before Sort: ");
for (int element : mixed){
System.out.println("Element: " + element);
}
for (int element : mixed){//this for loop moves all but the first and last element.
// for (int element=0;element < mixed.length-1;element++){// this for loop reverses order
int temp = mixed[element];
mixed[element]=mixed[element+1];
mixed[element+1]=temp;
}
if ((mixed[0]==1) && (mixed[5]==2)){//this swaps the first and last elements after using an enhanced for loop
int temp = mixed[0];
mixed[0] = mixed[5];
mixed[5] = temp;
}
System.out.println("After sort: ");
for (int element : mixed){
System.out.println("Element: " + element);
}
Make sure to read the comments I have in the code, as this is where my wtf moment is. My goal is to be able to have my high school students do this when it comes time to hit arrays. I would like to be able to introduce this as I introduce arrays. Any help would be greatly appreciated.
You are iterating over the array using elements of the array as an index for the switches that you make.
You are only ever doing two of the same switches.
When the current element is 1, it switches values at index 1 and index 2 of the array.
When the current element is 2, it switches values at index 2 and index 3 of the array.
This doesn't work; you have to do a manual switch at the end. And this manual switch will not work in other cases.
The right way to do this is to:
array 1 2 1 2 1 2
index 0 1 2 3 4 5
Switch:
0 with 1
1 with 3
2 with 5
The are only 3 switches so the loop should start at 0 and end at array length / 2.

Counting all permutations of a string (Cracking the Coding Interview, Chapter VI - Example 12)

In Gayle Laakman's book "Cracking the Coding Interview", chapter VI (Big O), example 12, the problem states that given the following Java code for computing a string's permutations, it is required to compute the code's complexity
public static void permutation(String str) {
permutation(str, "");
}
public static void permutation(String str, String prefix) {
if (str.length() == 0) {
System.out.println(prefix);
} else {
for (int i = 0; i < str.length(); i++) {
String rem = str.substring(0, i) + str.substring(i + 1);
permutation(rem, prefix + str.charAt(i));
}
}
}
The book assumes that since there will be n! permutations, if we consider each of the permutations to be a leaf in the call tree, where each of the leaves is attached to a path of length n, then there will be no more that n*n! nodes in the tree (i.e.: the number of calls is no more than n*n!).
But shouldn't the number of nodes be:
since the number of calls is equivalent to the number of nodes (take a look at the figure in the video Permutations Of String | Code Tutorial by Quinston Pimenta).
If we follow this method, the number of nodes will be 1 (for the first level/root of the tree) + 3 (for the second level) + 3*2 (for the third level) + 3*2*1 (for the fourth/bottom level)
i.e.: the number of nodes = 3!/3! + 3!/2! + 3!/1! + 3!/0! = 16
However, according to the aforementioned method, the number of nodes will be 3*3! = 18
Shouldn't we count shared nodes in the tree as one node, since they express one function call?
You're right about the number of nodes. That formula gives the exact number, but the method in the book counts some multiple times.
Your sum also seems to be approach e * n! for large n, so can be simplified to O(n!).
It's still technically correct to say the number of calls is no more than n * n!, as this is a valid upper bound. Depending on how this is used, this can be fine, and may be easier prove.
For the time complexity, we need to multiply by the average work done for each node.
First, check the String concatenation. Each iteration creates 2 new Strings to pass to the next node. The length of one String increases by 1, and the length of the other decreases by 1, but the total length is always n, giving a time complexity of O(n) for each iteration.
The number of iterations varies for each level, so we can't just multiply by n. Instead look at the total number of iterations for the whole tree, and get the average for each node. With n = 3:
The 1 node in the first level iterates 3 times: 1 * 3 = 3
The 3 nodes in the second level iterate 2 times: 3 * 2 = 6
The 6 nodes in the third level iterate 1 time: 6 * 1 = 6
The total number of iterations is: 3 + 6 + 6 = 15. This is about the same as number of nodes in the tree. So the average number of iterations for each node is constant.
In total, we have O(n!) iterations that each do O(n) work giving a total time complexity of O(n * n!).
According to your video where we have string with 3 characters (ABC), the number of permutations is 6 = 3!, and 6 happens to be equal to 1 + 2 + 3. However, if we have a string with 4 characters (ABCD), the number of permutations should be 4 * 3! as D could be in any position from 1 to 4. With each position of D you can generate 3! permutations for the rest. If you re-draw the tree and count the number of permutations you will see the difference.
According to your code, we have n! = str.length()! permutations, but in each call of the permutations, you also run a loop from 0 to n-1. Therefore, you have O(n * n!).
Update in response to the edited question
Firstly, in programming, we often have either 0->n-1 or 1->n not 0->n.
Secondly, we don't count the number of nodes in this case as if you take a look at the recursion tree in the clip again, you will see nodes duplicated. The permutations in this case should be the number of leaves which are unique among each other.
For instance, if you have a string with 4 characters, the number of leaves should be 4 * 3! = 24 and it would be the number of permutations. However, in your code snippet, you also have a 0->n-1 = 0->3 loop in each permutation, so you need to count the loops in. Thus, your code complexity in this case is O(n *n!) = O(4 * 4!).

Calculate total bill and Subtotals

Write a program that reads the total number of pieces of oranges, eggs, apples, watermelons, and bagels they purchased. Calculate the total bill and subtotals for each item using the following prices:
a.Oranges: 10 for 2.99/0.50 each
b.Eggs: 12 for 1.69/0.25 each
c.Apples: 3 for 1.00/0.75 each
d.Watermelons: 4.39 each
e.Bagels: 6 for 3.50/0.95 each
I'm a little bit confused for on what method should I use to program/solve this problem? I'm thinking to use a If statement but I think it's not a good idea. How should i start my coding? This is my first time encountering a price system with (I think discount?) fix amount of price on each item. It's bothering me to think that how can i do a "2.99 for 10 apples" while one apple is 0.50?" should I use discount? My mind is bleeding right now -_-
Here is an algorithm for solving the problem. Go step by step and implement the logic. I am sure you will get the final result.
Take the count for one fruit and display it.
From the count, calculate the sub-total price by taking the rate as per piece. Display the sub-total.
Store the sub-total you got in 2nd step in a separate variable and display it.
Follow the steps 1 to 3 for other fruits now, storing the sub-total of each fruit in a separate variable.
Calculate the final total by adding the values of all sub-total variables.
For applying the discounts, you can use a simple if...else logic along with some arithmetic operators.
6.1 Divide the count by 10 (for oranges) and store it in a variable called tmp.
6.2 If tmp is greater than 0,
subTotal = tmp * price_of_10
count = count - (tmp * 10)
subTotal = subTotal + (count * price_of_1)
6.3 If tmp is equal to zero
subTotal = count * price_of_1
I can help you get started. I don't want to give you all the code because I still want you to learn from it.
//Read number of Oranges here
//Some code
if(number = 10) price = 2.99
else price = number*0.50
total += price
Repeat for other products, don't forget to change the price value
EDIT: if you want to buy more than 10 and still get the discount, you will need to do something like this
int ten = 0;
Double rest =0;
if(number/10 >= 1){
ten = number/10;
rest = number%10;
price = ten*2.99 + rest*0.50;
}else{
price = number*0.50
}
total += price

For loop stopping prematurely

I'm trying to solve problem #299 - Train Swapping in website UVa Online judge. The code I have works fine for independent test cases. However, when I use the sample input they provide, my program omits one of the test cases, the last one to be more specific:
Here is my code:
import java.util.Scanner;
public class Tester {
void problem(){
Scanner imput = new Scanner(System.in);
int numT =imput.nextInt();
int numL, aux, swaps=0;
int [] train = new int [50];
for (int i =0; i<numT; i++) {
numL = imput.nextInt();
for (int m =0; m< numL; m++) {
train[m]=imput.nextInt();
}
for (int j=0; j<numL; j++) {
if (train[j]>train[j+1]) {
for (int k =j; k<numL-1;k++) {
aux = train[k];
train[k]=train[k+1];
train[k+1]=aux;
swaps++;
}
}
}
System.out.println("Optimal train swapping takes "+swaps+" swaps.");
swaps = 0;
}
}
}
Example Input:
3
3
1 3 2
4
4 3 2 1
2
2 1
Example Output:
Optimal train swapping takes 1 swaps.
Optimal train swapping takes 6 swaps.
Optimal train swapping takes 1 swaps.
My code prints until the second solution, then for some reason stops. I've tried to debug it and check what's going on step by step but it has driven me to a migraine point. Any insight is highly appreciated.
...
To be more precise it stops at the second for loop the third time around without taking anything into the array...and I don't know why!
Another thing I found out is that to solve this problem the number of swaps for the case of the middle is 6, therefore the bubble sort wont be useful here, since it makes over 10 swaps thus yielding a wrong output, this is a separate issue to the original one I presented however. I still haven't figure out why it stops the third time around the loop where I assign values to the array for the third time.
The input consists of:
first line is number of cases.
this line enters the length of a train ex: 4
this line enters the number of the wagons ex: 2 4 3 1
the next following lines correspond to the following test cases whose structure is the same as the example.
They ask you to arrange the train and tell the number of swaps made to make the train in order.

Tennis tournament algorithm

After a tennis tournament each player was asked how many matches he had.
An athlete can't play more than one match with another athlete.
As an input the only thing you have is the number of athletes and the matches each athlete had. As an output you will have 1 if the tournament was possible to be done according to the athletes answers or 0 if not. For example:
Input: 4 3 3 3 3 Output: 1
Input: 6 2 4 5 5 2 1 Output: 0
Input: 2 1 1 Output: 1
Input: 1 0 Output: 0
Input: 3 1 1 1 Output: 0
Input: 3 2 2 0 Output: 0
Input: 3 4 3 2 Output: 0
the first number of the input is not part of the athletes answer it's the number of athletes that took part in the tournament for example in 6 2 4 5 5 2 1 we have 6 athletes that took part and their answers were 2 4 5 5 2 1.
So far this is what we wrote but didn't work that great:
import java.util.Scanner;
import java.util.Arrays;
public class Tennis {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String N;
int count;
int sum = 0;
int max;
int activeAthletes;
int flag;
System.out.printf("Give: ");
N = input.nextLine();
String[] arr = N.split(" ");
int[] array = new int[arr.length];
for (count = 0; count < arr.length; count++) {
array[count] = Integer.parseInt(arr[count]);
//System.out.print(arr[count] + " ");
}
for (count = 1; count < arr.length; count++) {
sum += array[count];
}
//System.out.println("\n" + sum);
activeAthletes = array[0];
for (count = 1; count < array.length; count++) {
if (array[count] == 0) {
activeAthletes--;
}
}
max = array[1];
for (count = 2; count < array.length; count++) {
if (array[count] > max) {
max = array[count];
}
}
// System.out.println(max);
if ((sum % 2 == 0) && (max < activeAthletes)) {
flag = 1;
} else{
flag = 0;
}
System.out.println(flag);
}
}
I do not want a straight solution just maybe some tips and hints because we really have no idea what else to do and I repeat even though I'll tag it as a homework (because I feel the moderators will close it again) it is not, it's just something my brother found and we are trying to solve.
Well many of you have answered and I'm really grateful but as I have work tomorrow I need to go to sleep, so I'll probably read the rest of the answers tomorrow and see what works
Not sure if it works 100%, i would go like:
Sort input
for each element going from right to left in array (bigger to smaller)
based on value n of element at index i decrease n left elements by 1
return fail if cant decrease because you reached end of list or value 0
return success.
This logic (if correct) can lead whit some modifications to O(N*log(N)) solution, but I currently think that that would be just too much for novice programmer.
EDIT:
This does not work correct on input
2 2 1 1
All steps are then (whitout sorting):
while any element in list L not 0:
find largest element N in list L
decrease N other values in list L by 1 if value >= 1 (do not decrease this largest element)
return fail if failure at this step
set this element N on 0
return OK
Here's a hint. Answer these questions
Given N athletes, what is the maximum number of matches?
Given athlete X, what is the maximum number of matches he could do?
Is this sufficient to check just these? If you're not sure, try writing a program to generate every possible matching of players and check if at least one satisfies the input. This will only work for small #s of atheletes, but it's a good exercise. Or just do it by hand
Another way of asking this question, can we create a symmetric matrix of 1s and 0s whose rows are equal the values. This would be the table of 'who played who'. Think of this like an N by N grid where grid[i][j] = grid[j][i] (if you play someone they play you) and grid[i][i] = 0 (no one plays themselves)
For example
Input: 4 3 3 3 3 Output: 1
Looks like
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
We can't do this with this one, though:
Input: 3 2 2 0 Output: 0
EDIT
This is equivalent to this (from Degree (graph theory))
Hakimi (1962) proved that (d1, d2, ..., dn) is a degree sequence of a
simple graph if and only if (d2 − 1, d3 − 1, ..., dd1+1 − 1, dd1+2,
dd1+3, ..., dn) is. This fact leads to a simple algorithm for finding
a simple graph that has a given realizable degree sequence:
Begin with a graph with no edges.
Maintain a list of vertices whose degree requirement has not yet been met in non-increasing order of residual degree requirement.
Connect the first vertex to the next d1 vertices in this list, and then remove it from the list. Re-sort the list and repeat until all
degree requirements are met.
The problem of finding or estimating the number of graphs with a given
degree sequence is a problem from the field of graph enumeration.
Maybe you can take the array of athletes' match qties, and determine the largest number in there.
Then see if you can split that number into 1's and subtract those 1's from a few other members of the array.
Zero out that largest number array member, and remove it from the array, and update the other members with reduced values.
Now, repeat the process - determine the new largest number, and subtract it from other members of the array.
If at any point there are not enough array members to subtract the 1's from, then have the app return 0. otherwise continue doing it until there are no more members in the array, at which point you can have the app return 1.
Also, remember to remove array members that were reduced down to zero.
Your examples can all trivially be solved by counting the matches and looking whether they divide by 2.
A problem not covered by your examples would be a player, who has more games than the sum of the other players:
Input: 4 5 1 1 1 Output: 0
This can be complicated if we add more players:
Input: 6 5 5 5 1 1 1 Output: 0
How to solve this question? Well, remove one game pairwise from the maximum and the minimum player, and see what happens:
Input: 6 5 5 5 1 1 1
Input: 5 5 5 4 1 1 -
Input: 4 5 4 4 1 - -
Input: 3 4 4 4 - - -
It violates the rule:
An athlete can't play more than one match with another athlete.
If 3 players are left, they can't have had more than 2 games each.
Edit: Below solution passes some invalid inputs as valid. It's a fast way to check for definite negatives, but it allows false positives.
Here's what a mathematician would suggest:
The sum of the number of matches must be even. 3 3 4 2 1 sums to 13, which would imply someone played a match against themselves.
For n players, if every match eliminates one player at least n-1 distinct matches must be played. (A knockout tournament.) To see this, draw a tree of matches for 2, 4, 8, 16, 32... players, requiring 1, 3, 7, 31... matches to decide a winner.
For n players, the maximum number of matches if everyone plays everyone once, assuming no repeat matches, is n choose 2, or (n!)/(2!)(n-2)! (Round robin tournament). n! is the factorial function, n! = n * n-1 * n-2 * ... * 3 * 2 * 1..
So the criteria are:
Sum of the number of matches must be even.
Sum of the number of matches must be at least 2n-2. (Note the multiplication by 2 - each match results in both players increasing their count by one.)
Sum of the number of matches must be at most 2 * n choose 2.
[Edit] Each player must participate in at least one match.
If your tournament is a cross between a knockout tournament and a round robin tournament, you could have somewhere between n-1 and n choose 2 matches.
Edit:
If any player plays more than n-1 matches, they played someone at least twice.
If your tournament is a knockout tournament ordered so that each player participates in as few matches as possible, then each player can participate in at most log_2(n) matches or so (Take log base 2 and round up.) In a tournament with 16 players, at most 4 matches. In a tournament of 1024 players, at most 10 matches.

Categories