I want to book one seat in a cinema hall according to input but when I am trying to do that it changes all the rows.
Booked seat is denoted by 'B'.
Method that changes the state of cinema hall:
public void bookSeat(int row, int seat) {
this.seatsArrangement.get(row - 1).set(seat - 1, 'B');
}
Input and output:
Enter the number of rows:
> 7
Enter the number of seats in each row:
> 8
Cinema:
1 2 3 4 5 6 7 8
1 S S S S S S S S
2 S S S S S S S S
3 S S S S S S S S
4 S S S S S S S S
5 S S S S S S S S
6 S S S S S S S S
7 S S S S S S S S
Enter a row number:
> 2
Enter a seat number in that row:
> 4
Cinema:
1 2 3 4 5 6 7 8
1 S S S B S S S S
2 S S S B S S S S
3 S S S B S S S S
4 S S S B S S S S
5 S S S B S S S S
6 S S S B S S S S
7 S S S B S S S S
whole code:
package cinema;
import java.util.*;
public class Cinema {
private final int rows;
private final int seats;
private final List<List<Character>> seatsArrangement = new ArrayList<>();
public Cinema (int rows, int seats) {
this.rows = rows;
this.seats = seats;
List<Character> rowArrangement = new ArrayList<>();
while (seats-- != 0) {
rowArrangement.add('S');
}
while (rows-- != 0) {
seatsArrangement.add(rowArrangement);
}
}
public int calculateProfit() {
if (this.rows * this.seats <= 60) {
return this.rows * this.seats * 10;
} else {
return (int) ((Math.floor(this.rows / 2.0) * 10 + (this.rows - Math.floor(this.rows / 2.0)) * 8) * this.seats);
}
}
public void showSeatsArrangement() {
System.out.print("Cinema:\n ");
int i = 1;
while (i <= this.seats) {
System.out.printf("%d ", i++);
}
i = 1;
for (var row : this.seatsArrangement) {
System.out.print("\n" + i + " ");
for (var seat : row) {
System.out.printf("%c ", seat);
}
++i;
}
}
public void bookSeat(int row, int seat) {
this.seatsArrangement.get(row - 1).set(seat - 1, 'B');
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter the number of rows:");
int rows = sc.nextInt();
System.out.println("Enter the number of seats in each row:");
int seats = sc.nextInt();
Cinema cinema = new Cinema(rows, seats);
cinema.showSeatsArrangement();
System.out.println("\nEnter a row number:");
int row = sc.nextInt();
System.out.println("Enter a seat number in that row:");
int seat = sc.nextInt();
cinema.bookSeat(row, seat);
cinema.showSeatsArrangement();
}
}
Each element of your seatsArrangement array is the same ArrayList. You're adding the same ArrayList, rowArrangement, to seatsArrangement.
To fix this create a copies of rowArrangement in the second while loop.
e.g.
while (rows-- != 0) {
List<Integer> tmp = new ArrayList<>(rowArrangement);
seatsArrangement.add(tmp);
}
Thanks #MCI for your help it was a silly mistake.
made few changes in constructor:
original version:
public Cinema (int rows, int seats) {
this.rows = rows;
this.seats = seats;
List<Character> rowArrangement = new ArrayList<>();
while (seats-- != 0) {
rowArrangement.add('S');
}
while (rows-- != 0) {
seatsArrangement.add(rowArrangement);
}
}
Working version:
public Cinema(int rows, int seats) {
this.rows = rows;
this.seats = seats;
List<Character> rowArrangement = new ArrayList<>();
while (seats-- != 0) {
rowArrangement.add('S');
}
while (rows-- != 0) {
seatsArrangement.add(new ArrayList<>(rowArrangement));
}
}
But for some reason rowArrangment.clone() is not working, getting this error
'clone()' has protected access in 'java.lang.Object'
This solved the issue but I have no idea why?
((ArrayList) rowArrangement).clone();
EDIT: Reason why we need to explicitly cast rowArrangment is because clone() method is integral property of ArrayList and since I used List to refer rowArrangement so I can not call clone() method directly on it because upcasting does not support to access methods of subclass.
Ok so I'm kind of in the loss here but here goes. So I need to sort the array medalList when they get printed out. First I need to sort by gold medals which are added to the index [0], second after silvers in index [1], third after bronze in index [2] and last if a team is tied they get sorted by team name. Do I need to call a sorting method in another class, keep track of one and sort through and compare to the rest of the teams and if they're the best print them out first?
How do I compare Integers in an array of one classes to another?
When a user enters a certain command a list of teams with their results will get printed out.
As of now it looks like this:
1st 2nd 3rd Team Name
0 0 0 North Korea
3 1 1 America
5 0 2 France
2 1 3 Germany
I want it to say:
1st 2nd 3rd Team Name
5 0 2 France
3 1 1 America
2 1 3 Germany
0 0 0 North Korea
import java.util.ArrayList;
import java.util.Arrays;
public class Team {
private String teamName;
private ArrayList<Participant> participantList = new ArrayList<Participant>();
private int[] medalList = new int[3];
public Team(String teamName) {
this.teamName = teamName;
}
public String getTeamName() {
return teamName;
}
public void addParticipant(Participant participant) {
participantList.add(participant);
}
public void removeFromTeam(int participantNr){
for(int i = 0; i < participantList.size(); i++){
if(participantList.get(i).getParticipantNr() == participantNr){
participantList.remove(i);
}
}
}
public void printOutParticipant() {
for(int i = 0; i < participantList.size(); i++){
System.out.println(participantList.get(i).getName() + " " + participantList.get(i).getLastName());
}
}
public boolean isEmpty() {
boolean empty = false;
if (participantList.size() == 0) {
empty = true;
return empty;
}
return empty;
}
public void emptyMedalList(){
Arrays.fill(medalList, 0);
}
public void recieveMedals(int medal) {
if(medal == 1){
int gold = 0;
gold = medalList[0];
medalList[0] = ++gold;
} else if (medal == 2){
int silver = 0;
silver = medalList[1];
medalList[1] = ++silver;
} else if (medal == 3){
int bronze = 0;
bronze = medalList[2];
medalList[2] = ++bronze;
}
}
public void printMedals(){
System.out.println(medalList[0] + " " + medalList[1] + " " + medalList[2] + " " + teamName);
}
public int compareTo(Team team) {
int goldDif = Integer.compare(team.medalList[0], this.medalList[0]);
if (goldDif != 0)
return goldDif;
int silverDif = Integer.compare(team.medalList[1], this.medalList[1]);
if (silverDif != 0)
return silverDif;
int bronzeDif = Integer.compare(team.medalList[2], this.medalList[2]);
if (bronzeDif != 0)
return bronzeDif;
return this.getTeamName().compareTo(team.getTeamName());
}
public String toString() {
return teamName;
}
}
Make your Team class comparable
public class Team implements Comparable<Team> {
and add a comparison method
#Override
public int compareTo(final Team other) {
for (int i = 0; i < 3; i++) {
final int compareMedals = Integer.compare(medalList[i], other.medalList[i])
if (compareMedals != 0) {
return compareMedals;
}
}
return teamName.compareTo(other.teamName);
}
This will check gold medals first, then silver medals if the amount of gold medals is equal and so on and use the team name comparison as a last resort. You can then sort a collection of Teams with
final List<Team> teams = new ArrayList<>();
...
Collections.sort(teams);
EDIT:
Or if you like it in Java 8 style you could also write your comparison method like
#Override
public int compareTo(final Team other) {
return Stream.of(0, 1, 2)
.map(i -> Integer.compare(medalList[i], other.medalList[i]))
.filter(i -> i != 0)
.findFirst()
.orElse(teamName.compareTo(other.teamName));
}
I try running a map reduce on some data on a cluster and get the following output.
0000000000 44137 0 2
1 1
902996760100000 44137 2 6
2 2
9029967602 44137 2 8
2 2
90299676030000 44137 2 1
9029967604 44137 2 5
2 2
905000 38704 2 1
9050000001 38702 2 24
2 2
9050000001 38704 2 14
2 2
9050000001 38705 2 12
2 2
9050000001 38706 2 13
2 2
9050000001 38714 2 24
2 2
9050000002 38704 2 12
2 2
9050000002 38706 2 12
2 2
9050000011 38704 2 6
2 2
9050000011 38706 2 12
2 2
9050000021 38702 2 12
2 2
9050000031 38704 2 6
2 2
9050000031 38705 2 6
2 2
9050000031 38714 2 12
2 2
This is my reducer
public class RTopLoc extends Reducer<CompositeKey, IntWritable, Text, Text> {
private static int number = 0;
private static CompositeKey lastCK;
private static Text lastLac = new Text();
#Override
public void reduce(CompositeKey key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int sum = sumValues(values);
String str = Integer.toString(sum);
String str2 = Integer.toString(number);
String str3 = key.getSecond().toString();
context.write(key.getFirst(), new Text(str3 + " " + str2 + " " + str));
context.write(lastCK.getFirst(), lastCK.getSecond());
if(number == 0){
number = sum;
lastCK = new CompositeKey(key.getFirst().toString(), key.getSecond().toString());
context.write(new Text("1"), new Text("1"));
}
else if(lastCK.getFirst().equals(key.getFirst()) && sum > number){
lastCK = new CompositeKey(key.getFirst().toString(), key.getSecond().toString());
context.write(new Text("2"), new Text("2"));
}
else if(!lastCK.getFirst().equals(key.getFirst())){
// context.write(lastCK.getFirst(), lastCK.getSecond());
context.write(new Text("3"), new Text("3"));
number = sum;
lastCK = new CompositeKey(key.getFirst().toString(), key.getSecond().toString());
}
}
From what I understand the problem is that hadoop treats lastCK and key as the same object and this condition
if(lastCK.getFirst().equals(key.getFirst())
will always be true
This is my CompositeKey class
public class CompositeKey implements WritableComparable {
private Text first = null;
private Text second = null;
public CompositeKey() {
}
public CompositeKey(Text first, Text second) {
this.first = first;
this.second = second;
}
//...getters and setters
public Text getFirst() {
return first;
}
public void setFirst(Text first) {
this.first = first;
}
public void setFirst(String first) {
setFirst(new Text(first));
}
public Text getSecond() {
return second;
}
public void setSecond(Text second) {
this.second = second;
}
public void setSecond(String second) {
setSecond(new Text(second));
}
public void write(DataOutput d) throws IOException {
first.write(d);
second.write(d);
}
public void readFields(DataInput di) throws IOException {
if (first == null) {
first = new Text();
}
if (second == null) {
second = new Text();
}
first.readFields(di);
second.readFields(di);
}
public int compareTo(Object obj) {
CompositeKey other = (CompositeKey) obj;
int cmp = first.compareTo(other.getFirst());
if (cmp != 0) {
return cmp;
}
return second.compareTo(other.getSecond());
}
#Override
public boolean equals(Object obj) {
CompositeKey other = (CompositeKey)obj;
return first.equals(other.getFirst());
}
#Override
public int hashCode() {
return first.hashCode();
}
}
I tried changing setters to something along this lines
public void setFirst(Text first) {
this.first.set(first);
}
public void setFirst(String first) {
setFirst(new Text(first));
}
where set is Hadoop Text Documentation
but got
Error: java.lang.NullPointerException
at task.SecondarySort.CompositeKey.setFirst(CompositeKey.java:29)
at task.SecondarySort.CompositeKey.setFirst(CompositeKey.java:33)
How do I make hadoop treat lastCK and key as different objects?
If you change these lines:
private Text first = null;
private Text second = null;
to
private Text first = new Text();
private Text second = new Text();
And then use:
public void setFirst(Text first) {
this.first.set(first);
}
It should work. You could also create first and second in the constructors.
This question already has answers here:
Sorting two arrays simultaneously
(9 answers)
Closed 8 years ago.
Warnings: These examples are just examples. Not same my code, so don't think it's duplicate or it's bad question and vote down!
This title may be a little confusing sorry for that. Here's my problem;
I have two Arraylist. One of them takes a string and onether one takes integer. Let me illustrate it
arrList1 = {"apple", "strawberry", "banana", "watermelon"};
arrList2 = { 60, 90, 77 , 160};
arrList2 store how much fruits in arrList1 in same index number. For example there are 60 apples, 90 strawberry, 77 banana, 160 watermelon.
Also I have two more Arraylist like above;
arrList3 = { "strawberry", "watermelon", "apple", "banana" };
arrList4 = { 45, 40 , 10 , 11 };
arrList1 and arrList3 have same string but different index number. Now I want to print like by divide arrList2's number by arrList1 number and print objects by amount order. Let me illustrate it;
apple = 60/10 = 6
strawberry = 90/45 = 2
banana = 77/11 = 7
watermelon = 160/40 = 4
We divided and get some numbers and print to console ordered by amounts;
Banana // first because we got 7
Apple // second because we got 6 and etc
Watermelon
Strawberry
So, how I do it effectively?
To be clear, there are two questions here:
How do I efficiently do the lookup for each fruit in each pair of arrays?
How do I efficiently sort the results of dividing the corresponding entries' values?
You appear to have arrays, and not ArrayList(s). Next, you should create a Fruit class that implements Comparable<Fruit>. It should have two fields, an amount and a name. You could then use a Map<String, Integer> to perform your division, and finally build and sort a List of Fruit(s). Something like this,
public class Fruit implements Comparable<Fruit> {
private final String name;
private int amount;
public Fruit(String name, int amount) {
super();
this.name = (name != null) ? name.trim() : "";
setAmount(amount);
}
public void setAmount(int amount) {
this.amount = amount;
}
public int getAmount() {
return amount;
}
public String getName() {
return name;
}
#Override
public boolean equals(Object o) {
if (o instanceof Fruit) {
Fruit that = (Fruit) o;
return this.name.equals(that.name);
}
return false;
}
#Override
public String toString() {
return String.format("%s = %d", name, amount);
}
#Override
public int compareTo(Fruit o) {
return Integer.valueOf(o.amount).compareTo(amount);
}
#Override
public int hashCode() {
return this.name.hashCode();
}
public static void main(String[] args) {
String[] arrList1 = { "apple", "strawberry", "banana", "watermelon" };
int[] arrList2 = { 60, 90, 77, 160 };
String[] arrList3 = { "strawberry", "watermelon", "apple", "banana" };
int[] arrList4 = { 45, 40, 10, 11 };
Map<String, Integer> map = new TreeMap<>();
for (int i = 0; i < arrList1.length; i++) {
map.put(arrList1[i], arrList2[i]);
}
List<Fruit> al = new ArrayList<>();
for (int i = 0; i < arrList3.length; i++) {
String key = arrList3[i];
int val = map.get(key) / arrList4[i];
al.add(new Fruit(key, val));
}
Collections.sort(al);
System.out.println(al);
}
}
Which (when I run it here) outputs,
[banana = 7, apple = 6, watermelon = 4, strawberry = 2]
public class Main {
public static void main(String[] args) {
String[] arrList1 = { "apple", "strawberry", "banana", "watermelon" };
Integer[] arrList2 = { 60, 90, 77, 160 };
String[] arrList3 = { "strawberry", "watermelon", "apple", "banana" };
Integer[] arrList4 = { 45, 40, 10, 11 };
HashMap<String, Integer> result = new HashMap<>();
for (int i = 0; i < arrList1.length; i++) {
for (int j = 0; j < arrList3.length; j++) {
if (arrList1[i].contains(arrList3[j])) {
result.put(arrList1[i], arrList2[i] + arrList4[j]);
}
}
}
LinkedHashMap sorted = sortHashMap(result);
Set<String> keys = sorted.keySet();
for(String k:keys){
System.out.println(k+" -- "+sorted.get(k));
}
System.out.println("End");
}
public static LinkedHashMap sortHashMap(HashMap passedMap) {
List mapKeys = new ArrayList(passedMap.keySet());
List mapValues = new ArrayList(passedMap.values());
Collections.sort(mapValues);
Collections.sort(mapKeys);
LinkedHashMap sortedMap = new LinkedHashMap();
Iterator valueIt = mapValues.iterator();
while (valueIt.hasNext()) {
Object val = valueIt.next();
Iterator keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Object key = keyIt.next();
String comp1 = passedMap.get(key).toString();
String comp2 = val.toString();
if (comp1.equals(comp2)) {
passedMap.remove(key);
mapKeys.remove(key);
sortedMap.put((String) key, (Integer) val);
break;
}
}
}
return sortedMap;
}
}
That is it, of course is doesn't have the best programming practices. I recommend using generics on it.
So, how I do it effectively?
Don't use seperate arrays. Encapsulate the data you need within POJOs (Plain Old Java Objects) and make use of the Collections API
But, without using List or Map, you need to build, at least, two more arrays (or at least I did ;))...
The first will hold the results of the calcaultions. To do this, you need some way to find the matching indexes from arrList1 in arrList3, for example...
This will find the index of the given value in the given array or return -1 if it was not found...
public static int find(String value, String[] list) {
int matchIndex = -1;
for (int index = 0; index < list.length; index++) {
if (list[index].equals(value)) {
matchIndex = index;
break;
}
}
return matchIndex;
}
Next, we need to calculate the results ...
int[] results = new int[arrList1.length];
for (int index = 0; index < arrList1.length; index++) {
String v1 = arrList1[index];
int v2 = arrList2[index];
int subIndex = find(v1, arrList3);
if (subIndex != -1) {
int v4 = arrList4[subIndex];
results[index] = (v2 / v4);
System.out.println(v1 + " = " + v2 + " / " + v4 + " = " + results[index]);
}
}
This will generate the output of...
apple = 60 / 10 = 6
strawberry = 90 / 45 = 2
banana = 77 / 11 = 7
watermelon = 160 / 40 = 4
And store the results of the calculations in the results array...
Now comes the fun part...We could sort ALL the arrays, but that just seems messy to me, or we could create a "proxy" array whose individual elements pointed to the index in the other arrays. This would represent a "virtual" sorted view of all the arrays...
int[] proxy = new int[arrList1.length];
for (int index = 0; index < proxy.length; index++) {
proxy[index] = index;
}
for (int n = 0; n < results.length; n++) {
for (int m = 0; m < results.length - 1 - n; m++) {
if ((results[proxy[m + 1]] - (results[proxy[m]])) > 0) {
int index = proxy[m];
proxy[m] = proxy[m + 1];
proxy[m + 1] = index;
}
}
}
This means that proxy[0] will hold the index of the first item, when sorted.
And if we use this to print the results...
for (int index : proxy) {
System.out.println(arrList1[index] + " = " + results[index]);
}
We get something like...
banana = 7
apple = 6
watermelon = 4
strawberry = 2
I know, it might sound confusing to start with, but this means that all the original arrays remain unaffected and you reduce the risk of the arrays becoming out of sequence.
If you needed the list in sorted order, you could easily create new arrays and apply the values accordingly (like we did when printing the results)
Having said all that. POJOs, which could hold the various properties and List and/or a sorted Map would be significantly easier :P
You can use maps:
Map<String, Integer> fruit1 = new HashMap<String, Integer>();
Map<String, Integer> fruit2 = new HashMap<String, Integer>();
then:
fruit1.put("apple", 60);
fruit2.put("apple", 10);
And lastly:
System.out.println(fruit1.get("apple")/fruit2.get("apple"));
EDIT: To have it sorted use another map - this time TreeMap which maintains sorted order (be key):
Map<Integer, String> results = new TreeMap<Integer, String>();
results.add(fruit1.get("apple")/fruit2.get("apple"), "apple");
// add more...
Then to print them so they look like you specified in your question:
for(Map.Entry<Integer,String> entry : results.entrySet()) {
System.out.println(entry.getValue() + ": " + entry.getKey());
}
This will print:
apple: 6
//and so on...
I can't see where I'm going wrong with this one, I want it to display the frequencies of the survey's result but all I get is zeros, for example if I enter 1,1,2,2,5 I want it to output:
Displaying response frequencies...
1 2
2 2
3 0
4 0
5 1
but instead I get this:
Displaying response frequencies...
1 0
2 0
3 0
4 0
5 0
here is my main method:
import java.util.Scanner;
public class SurveyTester {
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
System.out.println("How many people took the survey?");
int numPeople = input.nextInt();
Survey s = new Survey(numPeople);
int nextResponse;
for (int i = 0; i < numPeople; i++)
{
System.out.print("Input the next survey response (values 1-5):");
nextResponse = input.nextInt();
s.addResponse(nextResponse);
}
System.out.println("Displaying all responses...");
s.displayAllResponses();
System.out.println("Displaying response frequencies...");
s.displayResponseFrequencies();
}
}
here is my class:
public class Survey
{
private int numResponses;
private int maxResponses;
private int[] responses;
private int[] frequencies;
private final int NUM_RESPONSES = 5;
public Survey(int nResponses)
{
maxResponses = nResponses;
numResponses = 0;
responses = new int[nResponses];
frequencies = new int[NUM_RESPONSES]; // There are 5 possible responses to the survey
}
public void addResponse(int response)
{
// This method stores the response
// passed in the parameter 'response'
// to the next free space in the array
{
responses[numResponses]= response;
}
numResponses++;
}
public void displayAllResponses()
{
// This method displays on the screen
// all the responses to the survey
for (int i=0; i<maxResponses; i++)
{
System.out.print(responses[i] + " ");
}
System.out.println("");
}
public void calculateResponseFrequencies()
{
// This method calculates the number of
// responses for each possible answer
// to the survey, 1, 2, 3, 4 or 5
// It stores the frequencies in the
// array 'frequencies'
for (int i=1; i<=maxResponses; i++)
{
if (responses[i] == 1)
{
frequencies[1]++;
}
else if (responses[i] == 2)
{
frequencies[2]++;
}
else if (responses[i] == 3)
{
frequencies[3]++;
}
else if (responses[i] == 4)
{
frequencies[4]++;
}
else if (responses[i] == 5)
{
frequencies[5]++;
}
}
}
public void displayResponseFrequencies()
{
// This method displays the response
// frequences for each of the possible
// response, 1, 2, 3, 4 or 5
for (int i=0; i<frequencies.length; i++)
{
System.out.println((i+1) + "\t" + frequencies[i]);
}
}
}
You are not doing anything with your frequencies array. In you your addResponse method, you need to get the appropriate value and increment it. Add a statement like
frequencies[response-1] = frequencies[response-1] + 1;
Note you can do this with 2 arrays, as you are, especially for learning, but a lot of Java developers would use a Map implementation for this sort of thing, where the keys are the entered values and the values are the frequencies. Keeps all the data in one data structure.
public class DuplicatesInArray {
public static void main(String[] args) {
int count = 0;
int[] arr = new int[6];
int[] frequencyArr = new int[6];
arr[0] = 4;
arr[1] = 1;
arr[2] = 1;
arr[3] = 1;
arr[4] = 5;
arr[5] = 4;
for(int i = 0;i < arr.length;i++){
frequencyArr[arr[i]] = frequencyArr[arr[i]] + 1;
}
for(int x = 0;x<frequencyArr.length;x++){
if(frequencyArr[x] > 0){
System.out.println(x + " " + frequencyArr[x] + " times." );
}
}
}
}
Default value in an integer array will be zero. We increment it by one for every occurrence.
Example:If integer 4 occurs 2 times,4th index at the frequencyArr is incremented twice.