Compare commits

...

5 Commits

Author SHA1 Message Date
e66b14d2a0 Add task description 2022-12-19 16:56:11 +02:00
951d68e8f7 Sector search task ready 2022-06-02 18:06:19 +03:00
2f296d5cf4 Lin Spec task ready 2022-06-02 16:32:01 +03:00
0eff9f6b46 Harvest per type task complete 2022-06-02 16:07:05 +03:00
e080a37e3f Data Table Model code refactor 2022-06-02 11:11:39 +03:00
10 changed files with 339 additions and 39 deletions

11
Copaci.in Normal file
View File

@@ -0,0 +1,11 @@
10 4
Яблоко Яблоко Яблоко Яблоко
Яблоко Груша Вишня Персик
Яблоко Абрикос Вишня Слива
Яблоко Айва Слива Слива
Яблоко Слива Слива Слива
Яблоко Слива Слива Слива
Яблоко Слива Слива Слива
Яблоко Слива Слива Слива
Яблоко Слива Слива Слива
Яблоко Слива Слива Слива

1
LinSpec.txt Normal file
View File

@@ -0,0 +1 @@
Яблоко Яблоко Яблоко Яблоко

BIN
Zadachi_po_praktike.docx Normal file

Binary file not shown.

View File

@@ -1,6 +1,8 @@
import javax.swing.*; import javax.swing.*;
import javax.swing.table.AbstractTableModel; import javax.swing.table.AbstractTableModel;
import java.awt.*; import java.awt.*;
import java.util.*;
import java.util.List;
public class DataTableModel extends AbstractTableModel { public class DataTableModel extends AbstractTableModel {
@@ -21,6 +23,53 @@ public class DataTableModel extends AbstractTableModel {
} }
} }
public String[] getColumnNames() {
return columnNames;
}
public Data[][] getRowData() {
return rowData;
}
public void setColumnNames(String[] columnNames) {
this.columnNames = columnNames;
}
@Override
public String getColumnName(int column) {
return columnNames[column];
}
@Override
public int getRowCount() {
return rowData.length;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int row, int col) {
return rowData[row][col];
}
@Override
public boolean isCellEditable(int row, int column) {
return true;
}
@Override
public void setValueAt(Object value, int row, int col) {
rowData[row][col] = new Data(value.toString());
fireTableCellUpdated(row, col);
}
/*
* Menu action functions:
*/
public void addRow(int newRowPos) { public void addRow(int newRowPos) {
int newRowCount = getRowCount() + 1; int newRowCount = getRowCount() + 1;
Data[][] newRowData = new Data[newRowCount][getColumnCount()]; Data[][] newRowData = new Data[newRowCount][getColumnCount()];
@@ -137,7 +186,7 @@ public class DataTableModel extends AbstractTableModel {
// Go through all cells in table // Go through all cells in table
for (int row = 0; row < getRowCount(); row++) { for (int row = 0; row < getRowCount(); row++) {
for (int col = 0; col < getColumnCount(); col++) { for (int col = 0; col < getColumnCount(); col++) {
Data cell = rowData[row][col]; Data cell = rowData[row][col];
// 1) Check if cell contains target tree // 1) Check if cell contains target tree
// 2) Compare tree output with max, save if higher // 2) Compare tree output with max, save if higher
if (cell.getTree().equals(treeName) && cell.getHarvest() > maxHarvest) { if (cell.getTree().equals(treeName) && cell.getHarvest() > maxHarvest) {
@@ -153,6 +202,7 @@ public class DataTableModel extends AbstractTableModel {
double harvest = 0; double harvest = 0;
int counter = 0; int counter = 0;
// Go through all cells in table
for (int row = 0; row < getRowCount(); row++) { for (int row = 0; row < getRowCount(); row++) {
for (int col = 0; col < getColumnCount(); col++) { for (int col = 0; col < getColumnCount(); col++) {
Data cell = rowData[row][col]; Data cell = rowData[row][col];
@@ -173,46 +223,99 @@ public class DataTableModel extends AbstractTableModel {
return harvest; return harvest;
} }
public String[] getColumnNames() { public List<Data> getTreeHarvestRating() {
return columnNames; // First, group trees by name
HashMap<String, Double> groupHarvests = new HashMap<>();
// Go through all cells in table
for (int row = 0; row < getRowCount(); row++) {
for (int col = 0; col < getColumnCount(); col++) {
Data cell = rowData[row][col];
// Skip cells without tree names
if (cell.getTree().equals("")) {
continue;
}
// Increase group harvest by harvest of this tree
if (!groupHarvests.containsKey(cell.getTree())) {
// If this is first time encountering this tree, create new group
groupHarvests.put(cell.getTree(), cell.getHarvest());
} else {
Double newValue = groupHarvests.get(cell.getTree()) + cell.getHarvest();
groupHarvests.put(cell.getTree(), newValue);
}
}
}
// Second, use Data class to store the results
List<Data> harvestData = new ArrayList<>();
for (Map.Entry<String, Double> entry : groupHarvests.entrySet()) {
Data newEntry = new Data(entry.getKey(), entry.getValue());
harvestData.add(newEntry);
}
// Third, sort the resulting list
harvestData.sort(new Comparator<Data>() {
@Override
public int compare(Data o1, Data o2) {
double h1 = o1.getHarvest();
double h2 = o2.getHarvest();
return Double.compare(h1, h2);
}
});
Collections.reverse(harvestData);
return harvestData;
} }
public Data[][] getRowData() { public RectangleArea findSmallestSectorWithVariety(int variety) {
return rowData; RectangleArea smallestArea = null;
for (int row = 0; row < getRowCount(); row++) {
for (int col = 0; col < getColumnCount(); col++) {
RectangleArea spotSmallestArea = getSmallestAreaWithVarietyForSpot(col, row, variety);
if (smallestArea == null || (spotSmallestArea != null && spotSmallestArea.area < smallestArea.area)) {
smallestArea = spotSmallestArea;
}
}
}
return smallestArea;
} }
public void setColumnNames(String[] columnNames) { private RectangleArea getSmallestAreaWithVarietyForSpot(int x, int y, int targetVariety) {
this.columnNames = columnNames; RectangleArea smallestArea = null;
int maxHeight = getRowCount() - y;
int maxWidth = getColumnCount() - x;
for (int height = 1; height <= maxHeight; height++) {
for (int width = 1; width <= maxWidth; width++) {
RectangleArea rectangle = new RectangleArea(x, y, width, height);
int uniqueTreesAmount = getRectangleUniqueTreesAmount(rectangle);
if (uniqueTreesAmount != targetVariety) {
continue;
}
if (smallestArea == null || rectangle.area < smallestArea.area) {
smallestArea = rectangle;
}
}
}
return smallestArea;
} }
@Override private int getRectangleUniqueTreesAmount(RectangleArea rectangle) {
public String getColumnName(int column) { Set<String> uniqueTrees = new HashSet<>();
return columnNames[column]; for (int row = rectangle.y; row < rectangle.y + rectangle.height; row++) {
} for (int col = rectangle.x; col < rectangle.x + rectangle.width; col++) {
uniqueTrees.add(rowData[row][col].getTree());
}
}
@Override return uniqueTrees.size();
public int getRowCount() {
return rowData.length;
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public Object getValueAt(int row, int col) {
return rowData[row][col];
}
@Override
public boolean isCellEditable(int row, int column) {
return true;
}
@Override
public void setValueAt(Object value, int row, int col) {
rowData[row][col] = new Data(value.toString());
fireTableCellUpdated(row, col);
} }
} }

View File

@@ -29,7 +29,7 @@ public class IndexValidator {
// Error: resulting index is negative // Error: resulting index is negative
if (inputRow <= 0) { if (inputRow <= 0) {
String message = String.format("Невозможно нийти строчку %d: номер должен быть больше 0", inputRow); String message = String.format("Невозможно найти строчку %d: номер должен быть больше 0", inputRow);
JOptionPane.showMessageDialog(null, message, "Неправильный индекс строчки", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(null, message, "Неправильный индекс строчки", JOptionPane.ERROR_MESSAGE);
return -1; return -1;
} }

View File

@@ -0,0 +1,80 @@
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MenuActionFindSmallestSector implements ActionListener {
private DataTableModel tableModel;
public MenuActionFindSmallestSector(DataTableModel tableModel) {
this.tableModel = tableModel;
}
public void actionPerformed(ActionEvent e) {
System.out.println("Find smallest sector");
Object[] options = {"Поиск", "Отмена"};
JPanel panel = new JPanel();
panel.add(new JLabel("Введите число k"));
JTextField textField = new JTextField(10);
panel.add(textField);
int variety = -1;
while (variety == -1) {
int result = JOptionPane.showOptionDialog(
null,
panel,
"Введите число k",
JOptionPane.YES_NO_OPTION,
JOptionPane.PLAIN_MESSAGE,
null,
options,
null
);
// Canceled by user
if (result == JOptionPane.CLOSED_OPTION || result == 1) {
return;
}
int inputVariety;
// Check for validity of input data (should be a number)
try {
inputVariety = Integer.parseInt(textField.getText());
} catch (NumberFormatException error) {
// Error: empty input field / input not a number
String message = "Пожалуйста введите правильное число";
JOptionPane.showMessageDialog(null, message, "Неправильное число", JOptionPane.ERROR_MESSAGE);
continue;
}
// Error: resulting number is negative
if (inputVariety <= 0) {
String message = String.format("Невозможно найти сектор с k=%d: номер должен быть больше 0", inputVariety);
JOptionPane.showMessageDialog(null, message, "Неправильное число", JOptionPane.ERROR_MESSAGE);
continue;
}
variety = inputVariety;
}
RectangleArea smallestSector = tableModel.findSmallestSectorWithVariety(variety);
// Check if operation is successful
if (smallestSector != null) {
String message = String.format(
"Площадь: %d\евая верхняя область: x=%d, y=%d\равая нижняя область: x=%d, y=%d",
smallestSector.area,
smallestSector.x + 1,
smallestSector.y + 1,
smallestSector.x + smallestSector.width,
smallestSector.y + smallestSector.height
);
JOptionPane.showMessageDialog(null, message);
} else {
String message = String.format("Не удалось найти сектор с k=%d", variety);
JOptionPane.showMessageDialog(null, message, "Неудача", JOptionPane.ERROR_MESSAGE);
}
}
}

View File

@@ -0,0 +1,28 @@
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
public class MenuActionGetHarvestPerType implements ActionListener {
private DataTableModel tableModel;
public MenuActionGetHarvestPerType(DataTableModel tableModel) {
this.tableModel = tableModel;
}
public void actionPerformed(ActionEvent e) {
System.out.println("Get harvest per type");
// Get sorted list of harvest per tree type
List<Data> harvestData = tableModel.getTreeHarvestRating();
// Create a string where each element is at a separate line
StringBuilder result = new StringBuilder();
for (Data entry : harvestData) {
result.append(String.format("%s - %.3f", entry.getTree(), entry.getHarvest()));
result.append("\n");
}
JOptionPane.showMessageDialog(null, result);
}
}

View File

@@ -0,0 +1,53 @@
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;
public class MenuActionLinSpec implements ActionListener {
public void actionPerformed(ActionEvent e) {
DataReader dataReader = new DataReader();
String[][] treesGrid = dataReader.readTrees("Copaci.in");
int rowCount = treesGrid.length;
int colCount = treesGrid[0].length;
// Go through each row of the grid
StringBuilder outputGrid = new StringBuilder();
for (int row = 0; row < rowCount; row++) {
// Get first tree in the row. It will be compared to other elements to define if row is homogenous
String treeName = treesGrid[row][0];
boolean isHomogenous = true;
StringBuilder outputRow = new StringBuilder();
for (int col = 0; col < colCount; col++) {
// Stop execution if a tree of different type was discovered
if (!treesGrid[row][col].equals(treeName)) {
isHomogenous = false;
break;
}
// Add tree to output row
outputRow.append(treesGrid[row][col]);
outputRow.append(" ");
}
if (isHomogenous) {
outputGrid.append(outputRow);
outputGrid.append("\n");
}
}
try {
BufferedWriter writer = new BufferedWriter(new FileWriter("LinSpec.txt"));
writer.write(outputGrid.toString());
writer.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
JOptionPane.showMessageDialog(null, "Копирование успешно");
}
}

View File

@@ -58,9 +58,18 @@ public class MenuBar extends JMenuBar {
plumHarvestAvgItem.addActionListener(new MenuActionGetPlumHarvestAvg(tableModel)); plumHarvestAvgItem.addActionListener(new MenuActionGetPlumHarvestAvg(tableModel));
menu.add(plumHarvestAvgItem); menu.add(plumHarvestAvgItem);
menu.add(createMockMenuItem("Общий урожай")); JMenuItem harvestPerTypeItem = new JMenuItem("Общий урожай");
menu.add(createMockMenuItem("Lin Spec")); harvestPerTypeItem.addActionListener(new MenuActionGetHarvestPerType(tableModel));
menu.add(createMockMenuItem("Сектор К деревьев")); menu.add(harvestPerTypeItem);
JMenuItem linSpecItem = new JMenuItem("Lin Spec");
linSpecItem.addActionListener(new MenuActionLinSpec());
menu.add(linSpecItem);
JMenuItem sectorItem = new JMenuItem("Сектор K деревьев");
sectorItem.addActionListener(new MenuActionFindSmallestSector(tableModel));
menu.add(sectorItem);
this.add(menu); this.add(menu);
} }

15
src/RectangleArea.java Normal file
View File

@@ -0,0 +1,15 @@
public class RectangleArea {
public int x;
public int y;
public int width;
public int height;
public int area;
public RectangleArea(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.area = width * height;
}
}