Return empty string if out of bounds - java

How would I get my program to return an empty set if a number out of bounds is entered? The class at the bottom is only a tester, so if someone were to change Jezebel to row 7, how would I keep it from crashing? Being that there are only six rows.
import java.util.Arrays;
public class Classroom {
private String[][] desks;
private String[] students = {"Todd", "Harry", "James", "Bob", "Michael",
"Fred", "Andy", "Jessica", "Kara", "Ed", "Jane", "", "Dennis", "Dwight",
"Sandy", "", "Toby", "", "Sara", "", "Randy", "", "", "", "", "John", "",
"", "", "Lindsay", "", "", "", "", "", "Marie", "", "", "", "",
"David", "", "",};
// the number of row is desks.length
// the number of column is desks[0].length
public Classroom(int row, int column) {
int i = 0;
desks = new String[row][column];
for (int r = 0; r < row; r++) {
for (int c = 0; c < column; c++) {
desks[r][c] = students[i++];
//Arrays.fill(desks[r][c], students[i++]);
}
}
}
public void setDesks(String[][] desks) {
this.desks = desks;
}
public boolean isDeskTaken(int row, int column) {
boolean taken = false;
if (desks[row][column] == "") {
taken = true;
}
if (desks[row][column].isEmpty()) {
taken = false;
}
return taken;
}
public String getRow(int row) {
String name = Arrays.toString(desks[row]);
return name;
}
public String getStudent(int row, int column) {
return desks[row][column];
}
public boolean placeStudent(int row, int column, String name) {
boolean placed = false;
// call isDeskTaken(row, column) if not
if (desks[row][column].isEmpty()) {
desks[row][column] = name;
return true;
}
return placed;
} // places student if the seat is empty
public static void main(String[] args) {
Classroom classroom = new Classroom(6, 5);
System.out.println("getRow(2)" + classroom.getRow(2));
System.out.println("placeStudent(7,1) " + classroom.placeStudent(7, 1, "Jezebel"));
System.out.println("placeStudent(4,0) " + classroom.placeStudent(4, 0, "John"));
System.out.println("Student " + classroom.getStudent(4, 1) + " has been placed in the 4th row and 1st column");
}
}

You can check the length of an array before you try and index it, like this:
String[] myArray = new String[5]; // an array with indexes [0] to [4]
// ...
// at some point we might try to access the element at index [5]
// remembering that we only have indexes [0] -> [4] in a 5 element array
// so we first check that the array is of sufficient length
if(myArray.length >= 6) {
return myArray[5]; // 6th element
} else {
return "";
}
Just to re-iterate, the length of the array is 5 elements, but the indexes of those elements are 0, 1, 2, 3, 4.

Related

Java to Excel: How to get value from main class to excel class in column B?

Excel: I want to take the variable value from "name", "number" and "country" from main class to excel class? Instead of column B: "Johan Svenson" 250 and "SWE"
Main class
Take value from "Name, "Number" and "country" from main class to excel class
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class MainProgramPA {
private static Scanner scan = new Scanner(System.in);
private static List<Contestant> scoreboard = new ArrayList<>();
private static String[] heptathlon = { "100 m hurdles", "High jump", "Shot put", "200 m", "Long jump",
"Javelin throw", "800 m" };
private static ScoreCalculator calc = new ScoreCalculator();
private static String mainEvent = "Heptathlon";
//private static Excel excel = new Excel();
public static void main(String[] args) {
contestantInput();
resultInput();
}
private static void contestantInput() {
int contestants = 0;
while (true) {
if (contestants < 40) {
System.out.println("Input the contestants name. Or input Exit to stop inputting contestants.");
String name = scan.nextLine();
if (name.equalsIgnoreCase("Exit")) {
break;
}
System.out.println("Input the contestants countrys alpha-3 code.");
String country = scan.nextLine();
System.out.println("Input the contestants number.");
int number = Integer.valueOf(scan.nextLine());
Contestant competitor = new Contestant(name, number, country);
scoreboard.add(competitor);
} else {
break;
}
contestants++;
}
}
private static void resultInput() {
System.out.println(
"The result should be measured in seconds (running), metres (throwing) or centimetres (jumping). \n");
if (mainEvent.equalsIgnoreCase("Decathlon")) {
for (int i = 0; i < decathlon.length; i++) {
for (int j = 0; j < scoreboard.size(); j++) {
System.out.println("Input the result " + scoreboard.get(j).getName() + " got on the " + decathlon[i]
+ " event. Or write exit to stop the program.");
String input = scan.nextLine();
if (input.equalsIgnoreCase("Exit")) {
i = 15;
break;
} else {
double result = Double.valueOf(input);
int score = calc.eventScoreCalculation("Decathlon", decathlon[i], result);
scoreboard.get(j).addSportEvent(decathlon[i], score, result);
System.out.println(score);
}
}
System.out.println("Input scoreboard if you want to see the scores. Input anything else to continue.");
String choice = scan.nextLine();
if (choice.equalsIgnoreCase("Scoreboard")) {
ConsoleOutput.printResultTable(scoreboard);
}
}
} else if (mainEvent.equalsIgnoreCase("Heptathlon")) {
for (int i = 0; i < heptathlon.length; i++) {
for (int j = 0; j < scoreboard.size(); j++) {
System.out.println("Input the result " + scoreboard.get(j).getName() + " got on the "
+ heptathlon[i] + " event. Or write exit to stop the program.");
String input = scan.nextLine();
if (input.equalsIgnoreCase("Exit")) {
i = 15;
break;
} else {
double result = Double.valueOf(input);
int score = calc.eventScoreCalculation("Heptathlon", heptathlon[i], result);
scoreboard.get(j).addSportEvent(heptathlon[i], score, result);
System.out.println(score);
}
}
System.out.println("Input scoreboard if you want to see the scores. Input anything else to continue.");
String choice = scan.nextLine();
if (choice.equalsIgnoreCase("Scoreboard")) {
ConsoleOutput.printResultTable(scoreboard);
}
}
}
}
}
Excel class
Replace value "Johan Svenson", 250 and "SWE"
import java.io.*;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.*;
public class Excel extends MainProgramPA {
MainProgramPA mains = new MainProgramPA();
public static void main(String[] args) {
// Create workbook in .xls format
Workbook workbook = new HSSFWorkbook();
// For .xslx workbooks use XSSFWoorkbok();
// Create Sheets
Sheet sh = workbook.createSheet("Decathlon");
Sheet sh2 = workbook.createSheet("Heptathlon");
Cell cell, cell1;
Row row, row1;
CellStyle cellStyle, cellStyle1;
Font font;
//-----------------------------------------------------------------------------------------
// Values for Column A for Heptathlon
Object columnA1[][] = { { "Name" },
{ "Number" },
{ "Country" },
{ "" },
{ "1. 100 metres hurdles" },
{ "2. High jump" },
{ "3. Shot put" },
{ "4. 200 metres" },
{ "DAY 1 TOTAL" },
{ "DAY 1 PLACE" } };
// Create Cells and Column A for Heptathlon
int rowCount0 = 0;
for (Object emp[] : columnA1) {
row = sh2.createRow(rowCount0++);
int columnCount = 0;
for (Object value : emp) {
cell = row.createCell(columnCount++);
if (value instanceof String)
cell.setCellValue((String) value);
if (value instanceof Integer)
cell.setCellValue((Integer) value);
if (value instanceof Boolean)
cell.setCellValue((Boolean) value);
// Make the column A "bold text"
cellStyle = workbook.createCellStyle();
font = workbook.createFont();
font.setBold(true);
cellStyle.setFont(font);
cell.setCellStyle(cellStyle);
}
}
// Values for Column B for Heptathlon
Object columnB1[][] = { { "Johan Svensson" },
{ 250 },
{ "SWE" },
{ "RESULT", "SCORE", "PLACE" },
{ "E1 Result", "E1 Score", "E1 Place" },
{ "E2 Result", "E2 Score", "E2 Place" },
{ "E3 Result", "E3 Score", "E3 Place" },
{ "E4 Result", "E4 Score", "E4 Place" },
{ "D1 TOTAL" },
{ "D1 PLACE" } };
// Create Row and Column B for Heptathlon
int rowCount01 = 0;
for (Object emp1[] : columnB1) {
row1 = sh2.getRow(rowCount01++);
int columnCount1 = 1;
for (Object value1 : emp1) {
cell1 = row1.createCell(columnCount1++);
if (value1 instanceof String)
cell1.setCellValue((String) value1);
if (value1 instanceof Integer)
cell1.setCellValue((Integer) value1);
if (value1 instanceof Boolean)
cell1.setCellValue((Boolean) value1);
CellUtil.setAlignment(cell1, HorizontalAlignment.CENTER);
}
}
// Make the row 4 to "bold text" in Heptathlon
cellStyle1 = workbook.createCellStyle();
font = workbook.createFont();
font.setBold(true);
cellStyle1.setFont(font);
row1 = sh2.getRow(3);
cell1 = row1.getCell(0);
cell1.setCellStyle(cellStyle1);
for (int j = 0; j <= 3; j++)
row1.getCell(j).setCellStyle(cellStyle1);
// Merge cells on row 1,2,3,9,10 Column B, C and D in Heptathlon
sh2.addMergedRegion(new CellRangeAddress(0, 0, 1, 3));
sh2.addMergedRegion(new CellRangeAddress(1, 1, 1, 3));
sh2.addMergedRegion(new CellRangeAddress(2, 2, 1, 3));
sh2.addMergedRegion(new CellRangeAddress(8, 8, 1, 3));
sh2.addMergedRegion(new CellRangeAddress(9, 9, 1, 3));
// Autosize Heptathlon-columns
for (int i = 0; i < 16; i++) {
sh2.autoSizeColumn(i);
}
try {
// Write the output to file
FileOutputStream output = new FileOutputStream("src//main//java//Deca-HeptathlonScoreboard.xls");
workbook.write(output);
output.close();
workbook.close();
System.out.println("Excel-file is Completed");
} catch (Exception e) {
e.printStackTrace();
}
}
}
I think the easiest way would be to examine your access modifiers. Remember, private classes, methods, and variables can only be referenced within the context of the class they belong to.
Additionally, a static method or variable is only initialized once, at the beginning of the code execution.
I would start by examining this section here:
private static List<Contestant> scoreboard = new ArrayList<>();
Additionally, I'm not sure how your Contestant class is built, but you should have some getters and setters there to allow you to pull contestant information. So, you could so something like this in your excel class:
for (Contestant contestant : mains.scoreboard){
if (contestant.getName.equals('Johan Svensson')){
...do action here...
}
Finally, remember that declaring a variable within a loop means that variable is discarded each iteration of the loop and collected in garbage collection. So, there is no way to access those variables themselves outside of that loop.

C# DataTable XML Equivalent in java

public Dictionary<string, SomeObject> DictionaryVar= new Dictionary<string, SomeObject>();
foreach (SomeObject ojv in DictionaryVar.Values)
{
if (dt.Rows.Find(obj.FirstName()) == null)
{
dt.Rows.Add(new object[] { false, obj.FirstName(), "", "", 0 });
}
}
I have tried this but its not working.. I am trying to populate jtable by looping through some objects by checking whether the field exists if it doesn't , then i add it to the table.
for (SomeObject bs : DictionaryVar.values()) {
System.out.println("not getting inside");
for (int i = 0; i < jTable1.getRowCount(); i++) {
if (!jTable1.getValueAt(i, 1).equals(bs.FirstName())) {
((DefaultTableModel) jTable1.getModel()).addRow(new Object[]{false, bs.FirstName(), "", "", 0, ""});
} else {
}
}
}
System.out.println("the program is outputing this");
if (ListBookMark.size() > 0) {
for (SomeObject bs : DictionaryVar.values()) {
System.out.println("working now");
if (jTable1.getModel().getColumnName(1).equalsIgnoreCase(bs.GetName()) == false) {
((DefaultTableModel) jTable1.getModel()).addRow(new Object[]{false, bs.GetName(), "", "", 0, ""});
}
}
}else {
System.out.println("bs size = " + (ListBookMark.size() ));
}

Get ranks to iterating ArrayList value

I have five values in an ArrayList like {50,25,50,30,10} . I want to set ranks in every value, So please tell me how I could do this. The output is like
50->1st rank
50->1st rank
30->2nd rank
20->3rd rank
10->4th rank
you should check this and this.
It is easy to do with lambda expression which is available from java 1.8.
Here is code i have got from above reference link
List<Player> players = new ArrayList<Player>() {{
add(new Player(1L, "a", 5));
add(new Player(2L, "b", 7));
add(new Player(3L, "c", 8));
add(new Player(4L, "d", 9));
add(new Player(5L, "e", 3));
add(new Player(6L, "f", 8));
}};
int[] score = {Integer.MIN_VALUE};
int[] no = {0};
int[] rank = {0};
List<Ranking> ranking = players.stream()
.sorted((a, b) -> b.getScores() - a.getScores())
.map(p -> {
++no[0];
if (score[0] != p.getScores()) rank[0] = no[0];
return new Ranking(rank[0], score[0] = p.getScores());
})
// .distinct() // if you want to remove duplicate rankings.
.collect(Collectors.toList());
System.out.println(ranking);
// result:
// rank=1, score=9
// rank=2, score=8
// rank=2, score=8
// rank=4, score=7
// rank=5, score=5
// rank=6, score=3
Please try this code.
package snakePack;
import java.util.ArrayList;
public class MainSnake {
public static void main(String[] args) {
Snake blackMambo = new Snake("blackMambo",2,0);
Snake rattle = new Snake("rattle",9,0);
Snake green = new Snake("green",6,0);
Snake cobra = new Snake("cobra",78,0);
Snake kingCobra = new Snake("kingCobra",5,0);
Snake whiteCobra = new Snake("whiteCobra",5,0);
Snake python = new Snake("python",5,0);
Snake yellow = new Snake("yellow",5,0);
Snake blackCobra = new Snake("blackCobra",1000,0);
Snake desertCobra = new Snake("desertCobra",5,0);
ArrayList<Snake> list = new ArrayList<Snake>();
list.add(blackMambo);list.add(rattle);list.add(green);list.add(cobra);list.add(kingCobra);
list.add(whiteCobra);list.add(python);list.add(yellow);list.add(blackCobra);list.add(desertCobra);
ArrayList<Integer> mongoosebigSnakes = new ArrayList<Integer>();
Integer tempHelperFrog = 0;
Integer rankMe = 0;
for (int grossHopper = 0; grossHopper < list.size(); grossHopper++) {
Integer strongSnake = 0;
for (int spider = 0; spider < list.size(); spider++) {
if (list.get(spider).getSnakePoisionRate() > strongSnake) {
boolean bool = false;
if (mongoosebigSnakes.size() != 0) {
for (int dragonFly = 0; dragonFly < mongoosebigSnakes.size(); dragonFly++) {
if (mongoosebigSnakes.get(dragonFly).intValue() == list.get(spider).getSnakePoisionRate().intValue()) {
bool = true;
}
}
if (bool != true) {
bool = false;
strongSnake = list.get(spider).getSnakePoisionRate();
}
} else {
if (tempHelperFrog != list.get(spider).getSnakePoisionRate()) {
strongSnake = list.get(spider).getSnakePoisionRate();
}
}
}
}
tempHelperFrog = strongSnake;
mongoosebigSnakes.add(strongSnake);
++rankMe;
for (int x = 0; x < list.size(); x++) {
if (strongSnake == list.get(x).getSnakePoisionRate()) {
list.get(x).setSnakeRank(rankMe);
}
}
}
System.out.println(" Hey guys get ready to see who has strong poison >>>");
Integer ratHelperCounter = 0;
for (Snake snake : list) {
System.out.println(++ratHelperCounter + " :" + snake.toString());
}
System.out.println("it's awesome" + " huge me !!!! ");
}
}
Bean class:
package snakePack;
public class Snake {
String snakeName;
Integer snakePoisionRate;
Integer snakeRank;
public Snake(String string, int i, int j) {
this.snakeName = "";
this.snakePoisionRate = i;
this.snakeRank = j;
}
public String getSnakeName() {
return snakeName;
}
public void setSnakeName(String snakeName) {
this.snakeName = snakeName;
}
public Integer getSnakePoisionRate() {
return snakePoisionRate;
}
public void setSnakePoisionRate(Integer snakePoisionRate) {
this.snakePoisionRate = snakePoisionRate;
}
public Integer getSnakeRank() {
return snakeRank;
}
public void setSnakeRank(Integer snakeRank) {
this.snakeRank = snakeRank;
}
#Override
public String toString() {
return "Snake [snakeName=" + snakeName + ", snakePoisionRate="
+ snakePoisionRate + ", snakeRank=" + snakeRank + "]";
}
}

JTable object [][] data

I am trying to create a table based on my trial class. When I try to run my table class the table prints with the proper heading, but it does not print anything in the body of the table. How should I fix my for loop so the data enters the table? Do I need to add a parameter to the constructor?
I understand there are more getters and setters than necessary. I was just trying to go about the for loop in different ways.
public class Trial extends JFrame{
static int counter = 0;
int laps = 0;
String lapTime;
double currentTime = 0;
String difference;
int lapsCount = 0;
String[] array1;
double[] array2;
double[] array3;
public int getLapsCount() {
return lapsCount;
}
public void setLapsCount(int lapsCount) {
this.lapsCount = lapsCount;
}
public static int getCounter() {
return counter;
}
public static void setCounter(int counter) {
Trial.counter = counter;
}
public int getLaps() {
return laps;
}
public void setLaps(int laps) {
this.laps = laps;
}
public String getLapTime() {
return lapTime;
}
public void setLapTime(String lapTime) {
this.lapTime = lapTime;
}
public double getCurrentTime() {
return currentTime;
}
public void setCurrentTime(double currentTime) {
this.currentTime = currentTime;
}
public String getDifference() {
return difference;
}
public void setDifference(String difference) {
this.difference = difference;
}
public String[] getArray1() {
return array1;
}
public void setArray1(String[] array1) {
this.array1 = array1;
}
public double[] getArray2() {
return array2;
}
public void setArray2(double[] array2) {
this.array2 = array2;
}
public double[] getArray3() {
return array3;
}
public void setArray3(double[] array3) {
this.array3 = array3;
}
public static void main(String[] args) {
//drop down for number of laps
String lapsString;
String[] selections = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
lapsString = (String) JOptionPane.showInputDialog(null,
"Choose a number of laps:",
"Lap Counter",
JOptionPane.INFORMATION_MESSAGE,
null, /* icon */
selections,
"0");
System.out.printf("Number of laps = \"%s\"\n", lapsString);
int lapsCount = Integer.parseInt(lapsString);
String[] array1 = new String[lapsCount+1];
double[] array2 = new double[lapsCount+1];
double[] array3 = new double[lapsCount+1];
// showInputDialog with for lap time
for (int i = 1; i <= lapsCount; i++){
String lapTime;
lapTime =
JOptionPane.showInputDialog("Enter lap " + i + " total time.");
System.out.printf("Lap " + i + " = \"%s\"\n", lapTime);
array1[i] = lapTime;
double currentTime = inputConvert(array1[i]);
array2[i] = currentTime;
array3[i] = (array2[i] - array2[i-1]);
counter++;
//confirm each time
int result;
String[] results = { "Yes", "No", "Cancel" };
result = JOptionPane.showConfirmDialog(null,
"Please confirm lap " + i + " is " + lapTime);
if (result == -1)
System.out.printf("user closed window\n");
else if (result == 0)
System.out.printf("result = %d, user pressed \"%s\"\n", result, results[result]);
else {
lapTime =
JOptionPane.showInputDialog("Please re-enter lap " + i);
System.out.printf("Lap " + i + " = \"%s\"\n", lapTime);
counter++;
}
}
}
public static double inputConvert(String s) {
double convert = 0.0;
int minutes = Integer.parseInt(s.substring(0, 1));
double seconds = Double.parseDouble(s.substring(2, s.length()));
minutes = minutes * 60;
convert = minutes + seconds;
return convert;
}
private static String getDifference(int j, double sign) {
String difference = "";
if(j == 0) {
difference = "---";
}
else if(sign > 0.0) {
difference = "+";
}
return difference;
}
public static String displayTime(double time) {
String result = null;
int minutes = (int) (time/60);
double seconds = (time % 60);
seconds = Math.round(seconds*100.0)/100.0;
if(seconds < 10){
result = minutes + ":0" + seconds;
}
else{
result = minutes + ":" + seconds;
}
return result;
}
}
This is my table class where the problem arises.
public class table {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new table();
}
});
}
public table() {
JFrame guiFrame = new JFrame();
guiFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
guiFrame.setTitle("Table to record lap times");
guiFrame.setSize(700,200);
guiFrame.setLocationRelativeTo(null);
JTable table = new JTable(new ExampleTableModel());
table.setAutoCreateRowSorter(true);
table.setGridColor(Color.YELLOW);
table.setBackground(Color.CYAN);
JScrollPane tableScrollPane = new JScrollPane(table);
guiFrame.add(tableScrollPane);
guiFrame.setVisible(true);
}
class ExampleTableModel extends AbstractTableModel{
int laps = 0;
String lapTime;
double currentTime = 0;
String difference;
Trial t = new Trial();
//Two arrays used for the table data
private String[] columnNames = {"Lap #", "Total Time", "Lap Time" , "Difference" };
private Object[][] data;
public ExampleTableModel(){
data = new Object[laps][4];
for(int i = 0; i < laps; i++){
data[i][0] = "Lap " + i;
data[i][1] = t.getArray1() [i];
data[i][2] = t.getArray2()[i];
data[i][3] = t.getArray3()[i];
}
}
#Override public int getRowCount() {
return data.length;
}
#Override public int getColumnCount() {
return columnNames.length;
}
#Override public Object getValueAt(int row, int column) {
return data[row][column];
}
#Override public String getColumnName(int column) {
return columnNames[column];
}
#Override public Class getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
#Override public boolean isCellEditable(int row, int column) {
if (column == 0 || column == 1) {
return false;
}
else {
return true;
}
}
}
}
I made those changes but I need my output to look like this
Lap #: Total time Lap time Difference
Lap1: 2:10 2:10 ---
I fixed the lap number so it starts at 1. I made these changes in the hopes that it would fix the lap time and difference cells but it is giving me an error.
public ExampleTableModel(Trial trial){
int laps = trial.getLapsCount();
data = new Object[laps][4];
for(int i = 0; i < laps; i++){
if (i == 0){
data[i][0] = "Lap " + (i + 1);
data[i][1] = trial.getArray1() [i + 1];
data[i][2] = trial.getArray2() [i + 1];
data[i][3] = trial.getDifference(i, (trial.getArray3()[i + 1] - trial.getArray3()[i]));
}
else {
data[i][0] = "Lap " + (i + 1);
data[i][1] = trial.getArray1() [i + 1];
data[i][2] = trial.displayTime(trial.getArray2() [i + 1] - trial.getArray2() [i]);
data[i][3] = trial.getDifference(i, (trial.getArray3()[i + 1] - trial.getArray3()[i])) + (trial.getArray3()[i + 1] - trial.getArray3()[i]);
}
}
}
Edit: combining the code from the Trial.main and the Table.main methods
To make the code from your Trial class easier to use from the Table class, you can make the following changes. This way you can create a Trial object and call the getUserInput to let the user initialize it:
public static void main(String[] args) {
new Trial().getUserInput();
}
public void getUserInput() {
// [Code from the old main method...]
// Use the fields of the class instead of local variables:
lapsCount = Integer.parseInt(lapsString);
array1 = new String[lapsCount+1];
array2 = new double[lapsCount+1];
array3 = new double[lapsCount+1];
// [Code from the old main method...]
}
Now you can modify the Table model like this:
public Table() {
// [...]
Trial trial = new Trial();
trial.getUserInput();
JTable table = new JTable(new ExampleTableModel(trial));
// [...]
}
And let the ExampleTableModel constructor use a trail parameter (the laps and t fields are no longer used):
public ExampleTableModel(Trial trial){
int laps = trial.getLapsCount();
data = new Object[laps][4];
for(int i = 0; i < laps; i++){
data[i][0] = "Lap " + i;
data[i][1] = trial.getArray1()[i];
data[i][2] = trial.getArray2()[i];
data[i][3] = trial.getArray3()[i];
}
}
There was also an issue with the getColumnClass method:
#Override public Class getColumnClass(int column) {
//return getValueAt(0, column).getClass();
return (column <= 1) ? String.class : Double.class;
}
Now the table looks like this:
The output was:
Number of laps = "2"
Lap 1 = "2:10"
result = 0, user pressed "Yes"
Lap 2 = "2:20"
result = 0, user pressed "Yes"
Old answer
There seem to be a few issues that prevent the table from being filled:
In the ExampleTableModel class the laps field should be something higher than zero (for the constructor to fill the data array):
class ExampleTableModel extends AbstractTableModel {
//int laps = 0;
int laps = 6;
In the constructor of the ExampleTableModel class:
public ExampleTableModel(){
data = new Object[laps][4];
for(int i = 0; i < laps; i++){
data[i][0] = "Lap " + i;
data[i][1] = t.getArray1()[i];
data[i][2] = t.getArray2()[i];
data[i][3] = t.getArray3()[i];
}
}
the calls to the t.getArray1, t.getArray2, and t.getArray3 methods return null. The Trial object appears to have no data yet.
Do you want your program to execute both the code of the Trial.main method and the Table.main method?

Bin Packing Algorithm In Need of Speeding-Up

I'm looking for an intelligent way to approach a version of the common bin-packing problem. Given a number of bags (as I'm calling them) with a certain capacity, and list of items that take up a certain amount of space, the task is to determine if all of the items can fit in the bags; and if so, how. I've got an exhaustive DFS working right now, but it takes... forever. My DFS is iterative and requires copying entire states at every step, which is very expensive. Here's my code for a specific problem with 4 bags with 10 capacity (the truly relevant portions of this code are just the pack() method and the State class if you don't want to look at it all):
import java.util.ArrayList;
import java.util.Stack;
public class BagProblem {
int numBags;
int bagCapacity;
ArrayList<Item> items = new ArrayList<Item>();
public static void main(String[] args) {
BagProblem bp = new BagProblem(4, 10);
bp.pack();
}
public BagProblem(int numBags, int bagCapacity) {
this.numBags = numBags;
this.bagCapacity = bagCapacity;
items = new ArrayList<Item>();
items.add(new Item("item0", 6));
items.add(new Item("item1", 6));
items.add(new Item("item2", 6));
items.add(new Item("item5", 3));
items.add(new Item("item6", 3));
items.add(new Item("item7", 3));
items.add(new Item("item8", 2));
items.add(new Item("item9", 2));
items.add(new Item("item10", 2));
items.add(new Item("item11", 2));
items.add(new Item("item12", 2));
items.add(new Item("item13", 2));
items.add(new Item("item14", 1));
}
// find a valid way to pack and print the items in each Bag, or
// print failure
public void pack() {
Stack <State> s = new Stack<State>();
Bag[] currBags = new Bag[numBags];
for (int i = 0; i < numBags; i++) {
currBags[i] = new Bag(bagCapacity);
}
s.push(new State(currBags));
while(!s.isEmpty()) {
State currState = s.pop();
for (Item i : items) {
if (!currState.containsItem(i)) {
State newState = new State(currState.bags);
newState.numItems = currState.numItems;
if (newState.addItem(i)) {
s.push(newState);
if (newState.numItems == items.size()) {
System.out.println("success");
System.out.println(newState);
return;
}
}
}
}
}
System.out.println("failure");
}
private class State {
Bag[] bags;
int numItems;
public State(Bag[] currBags) {
bags = new Bag[numBags];
for (int i = 0; i < numBags; i++) {
bags[i] = new Bag(bagCapacity);
}
// figure out how to actually copy this
for (int j = 0; j < numBags; j++) {
Bag bagToCopy = currBags[j];
for (Item item : bagToCopy.contents) {
Item newItem = new Item(item.name, item.size);
bags[j].size = bagToCopy.size;
bags[j].contents.add(newItem);
}
}
}
public boolean addItem(Item i) {
for (Bag b : bags) {
if (b.addItem(i)) {
numItems++;
return true;
}
}
return false;
}
public boolean containsItem(Item i) {
for (Bag b : bags) {
for (Item item : b.contents) {
if (item.name.equals(i.name))
return true;
}
}
return false;
}
public String toString() {
String output = "";
for (Bag b : bags) {
for (Item j : b.contents) {
output += j.name + " ";
}
output += "\n";
}
return output;
}
}
private class Bag {
int capacity;
int size;
ArrayList<Item> contents;
public Bag(int capacity) {
this.capacity = capacity;
this.size = 0;
contents = new ArrayList<Item>();
}
public boolean addItem(Item i) {
if(size + i.size > capacity)
return false;
contents.add(i);
size += i.size;
return true;
}
public String toString() {
String output = "";
for (Item i : contents) {
output += i.name + " ";
}
return output + "\n";
}
}
private class Item {
String name;
int size;
public Item(String name, int size) {
this.name = name;
this.size = size;
}
public String toString() {
return name;
}
}
}
After approximately one million years, this does spit out a correct answer (you probably won't want to actually wait that long if you try to run this):
success
item14 item7 item6 item5
item13 item12 item2
item11 item10 item1
item9 item8 item0
Each line indicates a separate bag. How can I speed this up? I know there are heuristics about trying to place the largest item first, etc., but what I'm really interested in is getting the basic DFS (or maybe I should try backtracking?) to have less overhead; I'll try to get fancier later.
Any help would be greatly appreciated.
I don't use Java but your implementation seems quite inefficient (as you've mentioned yourself) due to overcomplicating it. The algorithm itself is also very strange, I did not attempt to replicate it and just used the obvious O(bags^items) brute force algorithm that tries to put the first item into each bag, for each of those cases tries to put the second item into each bag, etc...
Instead of replicating the entire state repeatedly on the stack, you can put an item in a bag, explore the branch of the tree with this change, then take the item out of the bag.
Here is an example that completes instantly for your test case in C#.
static int[] itemSize;
static int[] bagFreeSpace;
static bool[,] doesBagContainItem; // in case this looks weird, [,] is a matrix, in java it would be [][]
static bool pack(int item)
{
// output the solution if we're done
if (item == itemSize.Length)
{
for (int i = 0; i < bagFreeSpace.Length; i++)
{
Console.WriteLine("bag" + i);
for (int j = 0; j < itemSize.Length; j++)
if (doesBagContainItem[i, j])
Console.Write("item" + j + "(" + itemSize[j] + ") ");
Console.WriteLine();
}
return true;
}
// otherwise, keep traversing the state tree
for (int i = 0; i < bagFreeSpace.Length; i++)
{
if (bagFreeSpace[i] >= itemSize[item])
{
doesBagContainItem[i,item] = true; // put item into bag
bagFreeSpace[i] -= itemSize[item];
if (pack(item + 1)) // explore subtree
return true;
bagFreeSpace[i] += itemSize[item]; // take item out of the bag
doesBagContainItem[i,item] = false;
}
}
return false;
}
static void Main(string[] args)
{
itemSize = new int[] { 6, 6, 6, 3, 3, 3, 2, 2, 2, 2, 2, 2, 1 };
bagFreeSpace = new int[] { 10, 10, 10, 10 };
doesBagContainItem = new bool[bagFreeSpace.Length, itemSize.Length];
if (!pack(0))
Console.WriteLine("No solution");
}
Note: if you want to parallelize execution, you need to give each worker its own copy of the state (or 1 copy per job), but only at the point of branching, they can still then proceed as above, without replicating the state.

Categories