Untitled

mail@pastecode.io avatar
unknown
java
a year ago
13 kB
5
Indexable
Never
package pack;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.IntStream;

import static java.lang.Math.PI;
import static java.lang.Math.abs;
import static java.lang.Math.cos;
import static java.lang.Math.sin;

record Dot(double x, double y) {
    public String toString() {
        return "(x: %.5f, y: %.5f)".formatted(x, y);
    }
}

record Constant(double a, double b) {
    public String toString() {
        return "(leftBound: %.5f, rightBound: %.5f)".formatted(a, b);
    }
}

record BoundedFunPart(
        Function<Double, Double> func,
        Double leftBound,
        Double rightBound,
        boolean isLeftClosed,
        boolean isRightClosed
) {

    public Double getFuncValue(Double x) {
        return func.apply(x);
    }

    public boolean isInBounds(Double x) {
        if (abs(this.leftBound - x) < 0.000001 && !isLeftClosed) {
            return true;
        } else if (abs(this.rightBound - x) < 0.000001 && !isRightClosed) {
            return true;
        } else {
            return this.leftBound < x && x < this.rightBound;
        }
    }

}

class TableGenerator {

    private int PADDING_SIZE = 2;
    private String NEW_LINE = "\n";
    private String TABLE_JOINT_SYMBOL = "+";
    private String TABLE_V_SPLIT_SYMBOL = "|";
    private String TABLE_H_SPLIT_SYMBOL = "-";

    public String generateTable(List<String> headersList, List<List<String>> rowsList, int... overRiddenHeaderHeight) {
        StringBuilder stringBuilder = new StringBuilder();

        int rowHeight = overRiddenHeaderHeight.length > 0 ? overRiddenHeaderHeight[0] : 1;

        Map<Integer, Integer> columnMaxWidthMapping = getMaximumWidhtofTable(headersList, rowsList);

        stringBuilder.append(NEW_LINE);
        stringBuilder.append(NEW_LINE);
        createRowLine(stringBuilder, headersList.size(), columnMaxWidthMapping);
        stringBuilder.append(NEW_LINE);


        for (int headerIndex = 0; headerIndex < headersList.size(); headerIndex++) {
            fillCell(stringBuilder, headersList.get(headerIndex), headerIndex, columnMaxWidthMapping);
        }

        stringBuilder.append(NEW_LINE);

        createRowLine(stringBuilder, headersList.size(), columnMaxWidthMapping);


        for (List<String> row : rowsList) {

            for (int i = 0; i < rowHeight; i++) {
                stringBuilder.append(NEW_LINE);
            }

            for (int cellIndex = 0; cellIndex < row.size(); cellIndex++) {
                fillCell(stringBuilder, row.get(cellIndex), cellIndex, columnMaxWidthMapping);
            }

        }

        stringBuilder.append(NEW_LINE);
        createRowLine(stringBuilder, headersList.size(), columnMaxWidthMapping);
        stringBuilder.append(NEW_LINE);
        stringBuilder.append(NEW_LINE);

        return stringBuilder.toString();
    }

    private void fillSpace(StringBuilder stringBuilder, int length) {
        for (int i = 0; i < length; i++) {
            stringBuilder.append(" ");
        }
    }

    private void createRowLine(StringBuilder stringBuilder, int headersListSize, Map<Integer, Integer> columnMaxWidthMapping) {
        for (int i = 0; i < headersListSize; i++) {
            if (i == 0) {
                stringBuilder.append(TABLE_JOINT_SYMBOL);
            }

            for (int j = 0; j < columnMaxWidthMapping.get(i) + PADDING_SIZE * 2; j++) {
                stringBuilder.append(TABLE_H_SPLIT_SYMBOL);
            }
            stringBuilder.append(TABLE_JOINT_SYMBOL);
        }
    }


    private Map<Integer, Integer> getMaximumWidhtofTable(List<String> headersList, List<List<String>> rowsList) {
        Map<Integer, Integer> columnMaxWidthMapping = new HashMap<>();

        for (int columnIndex = 0; columnIndex < headersList.size(); columnIndex++) {
            columnMaxWidthMapping.put(columnIndex, 0);
        }

        for (int columnIndex = 0; columnIndex < headersList.size(); columnIndex++) {

            if (headersList.get(columnIndex).length() > columnMaxWidthMapping.get(columnIndex)) {
                columnMaxWidthMapping.put(columnIndex, headersList.get(columnIndex).length());
            }
        }


        for (List<String> row : rowsList) {

            for (int columnIndex = 0; columnIndex < row.size(); columnIndex++) {

                if (row.get(columnIndex).length() > columnMaxWidthMapping.get(columnIndex)) {
                    columnMaxWidthMapping.put(columnIndex, row.get(columnIndex).length());
                }
            }
        }

        for (int columnIndex = 0; columnIndex < headersList.size(); columnIndex++) {

            if (columnMaxWidthMapping.get(columnIndex) % 2 != 0) {
                columnMaxWidthMapping.put(columnIndex, columnMaxWidthMapping.get(columnIndex) + 1);
            }
        }


        return columnMaxWidthMapping;
    }

    private int getOptimumCellPadding(int cellIndex, int datalength, Map<Integer, Integer> columnMaxWidthMapping, int cellPaddingSize) {
        if (datalength % 2 != 0) {
            datalength++;
        }

        if (datalength < columnMaxWidthMapping.get(cellIndex)) {
            cellPaddingSize = cellPaddingSize + (columnMaxWidthMapping.get(cellIndex) - datalength) / 2;
        }

        return cellPaddingSize;
    }

    private void fillCell(StringBuilder stringBuilder, String cell, int cellIndex, Map<Integer, Integer> columnMaxWidthMapping) {

        int cellPaddingSize = getOptimumCellPadding(cellIndex, cell.length(), columnMaxWidthMapping, PADDING_SIZE);
        if (cellIndex == 0) {
            stringBuilder.append(TABLE_V_SPLIT_SYMBOL);
        }

        fillSpace(stringBuilder, cellPaddingSize);
        stringBuilder.append(cell);
        if (cell.length() % 2 != 0) {
            stringBuilder.append(" ");
        }
        fillSpace(stringBuilder, cellPaddingSize);
        stringBuilder.append(TABLE_V_SPLIT_SYMBOL);
    }
}


public class Computations {

    private static final int NUMBER_OF_NODES = 50;

    private final List<BoundedFunPart> functions;
    private final List<Integer> nodesNumber;
    private final Map<String, List<Dot>> pointsGrid;
    private final Map<String, List<Constant>> abCoefficientsGrid;
    private final Map<String, Double> steps;
    private final Map<String, List<Double>> approximatedValuesGrid;
    private final Double T;

    public Computations(List<BoundedFunPart> functions, Double T, List<Integer> nodesNumber) {
        this.functions = functions;
        this.nodesNumber = nodesNumber;
        this.T = T;
        this.pointsGrid = new HashMap<>();
        this.steps = new HashMap<>();
        this.abCoefficientsGrid = new HashMap<>();
        this.approximatedValuesGrid = new HashMap<>();
        solve();
    }

    public void solve() {
        setPointsGrid();
        findABCoefficients();
        setApproximatedValuesGrid();

        System.out.println("Узлы интерполирования");
        nodesNumber.forEach(this::printPointsTable);

        System.out.println("Коэффициенты");
        nodesNumber.forEach(this::printCoefficientsTable);

        System.out.println("Таблица результатов");
        printApproximatedValuesTable();
    }

    private void setPointsGrid() {
        for (Integer n : nodesNumber) {
            ArrayList<Dot> dots = new ArrayList<>();
            double step = T / (2 * n);
            double currX = -T / 2;

            for (int i = 1; i <= 2 * n; i++) {
                for (var func : functions) {
                    if (func.isInBounds(currX + step * i)) {
                        dots.add(new Dot(currX + step * i, func.getFuncValue(currX + step * i)));
                    }
                }
            }

            pointsGrid.put(n.toString(), dots);
            steps.put(n.toString(), step);
        }
    }

    private void findABCoefficients() {
        for (var n : nodesNumber) {
            ArrayList<Constant> coefficients = new ArrayList<>();
            coefficients.add(new Constant(getAWithParams(n, 0)/2,getBWithParams(n, 0)/2));
            for (int l = 1; l < n; l++) {
                coefficients.add(new Constant(getAWithParams(n, l),getBWithParams(n, l)));
            }
            coefficients.add(new Constant(getAWithParams(n, n)/2,getBWithParams(n, n)/2));
            abCoefficientsGrid.put(n.toString(), coefficients);
        }
    }

    private Double getAWithParams(Integer n, int l) {
        List<Dot> dots = pointsGrid.get(n.toString());
        Double sum = 0.0;
        for (var point : dots){
            sum += point.y()* cos(2 * PI * l * point.x() / T);
        }
        return 2 * steps.get(n.toString()) * sum / T;
    }

    private Double getBWithParams(Integer n, int l) {
        List<Dot> dots = pointsGrid.get(n.toString());
        Double sum = 0.0;
        for (var point : dots){
            sum += point.y() * sin(2 * PI * l * point.x() / T);
        }
        return 2 * steps.get(n.toString()) * sum / T;
    }

    private Double evaluateApproximation(Double x, Integer n) {
        List<Constant> coefficients = abCoefficientsGrid.get(n.toString());
        double sum = 0.0;
        int l = 0;
        for (var coef : coefficients) {
            sum += coef.a() * cos(l * 2 * PI * x / T) + coef.b()* sin(l * 2 * PI * x / T);
            l++;
        }
        return sum;
    }

    private void setApproximatedValuesGrid() {
        double step = T / NUMBER_OF_NODES;
        ArrayList<Double> xs = new ArrayList<>();
        ArrayList<Double> ys = new ArrayList<>();
        for (int i = 0; i < NUMBER_OF_NODES - 1; i++) {
            xs.add(-T/2 + i*step);
            for (var func : functions) {
                if (func.isInBounds(-T/2 + i*step)) {
                    ys.add(func.getFuncValue(-T/2 + i*step));
                }
            }
        }

        xs.add(T/2);
        ys.add(functions.get(functions.size() - 1).getFuncValue(T/2));

        approximatedValuesGrid.put("X", xs);
        approximatedValuesGrid.put("Y", ys);

        for (var n : nodesNumber) {
            ArrayList<Double> approximated = new ArrayList<>();
            for (int i = 0; i < NUMBER_OF_NODES; i++) {
                approximated.add(evaluateApproximation(xs.get(i), n));
            }
            approximatedValuesGrid.put("n = " + n, approximated);
        }
    }

    private List<List<String>> mergeArrays(String[] left, String[] right) {
        return IntStream.range(0, left.length).mapToObj(i -> List.of(left[i], right[i])).toList();
    }

    private void printPointsTable(Integer n) {
        List<Dot> dots = pointsGrid.get(n.toString());

        String[] pointsX = new String[2 * n + 1];
        String[] pointsY = new String[2 * n + 1];

        pointsX[0] = "X";
        pointsY[0] = "Y";

        for (int i = 0; i < dots.size(); i++) {
            pointsX[i + 1] = String.format("%.5f", dots.get(i).x());
            pointsY[i + 1] = String.format("%.5f", dots.get(i).y());
        }
        var str = new TableGenerator().generateTable(
                List.of("X", "Y"),
                mergeArrays(pointsX, pointsY)
        );
        System.out.println(str);
    }

    private void printCoefficientsTable(Integer n) {
        List<Constant> abCoefficients = abCoefficientsGrid.get(n.toString());

        String[] coefficientsA = new String[n + 1];
        String[] coefficientsB = new String[n + 1];

        coefficientsA[0] = "al";
        coefficientsB[0] = "bl";

        for (int i = 1; i < abCoefficients.size(); i++) {
            coefficientsA[i] = String.format("%.5f", abCoefficients.get(i).a());
            coefficientsB[i] = String.format("%.5f", abCoefficients.get(i).b());
        }

        System.out.println("n = " + n + "; a0 = " + abCoefficients.get(0).a());
        var str = new TableGenerator().generateTable(
                List.of("al", "bl"),
                mergeArrays(coefficientsA, coefficientsB)
        );
        System.out.println(str);

    }

    private void printApproximatedValuesTable() {
        String[] headers = new String[2 + nodesNumber.size()];
        String[][] data = new String[50][2 + nodesNumber.size()];

        for (int i = 0; i < NUMBER_OF_NODES; i++) {
            String[] buffer = new String[2 + nodesNumber.size()];
            buffer[0] = String.format("%.5f", approximatedValuesGrid.get("X").get(i));
            headers[0] = "X";
            buffer[1] = String.format("%.5f", approximatedValuesGrid.get("Y").get(i));
            headers[1] = "Y";

            for (int j = 1; j <= nodesNumber.size(); j++) {
                buffer[1 + j] = String.format("%.5f", approximatedValuesGrid.get("n = " + nodesNumber.get(j - 1)).get(i));
                headers[1 + j] = "n = " + nodesNumber.get(j - 1);
            }
            data[i] = buffer;
        }


        var str = new TableGenerator().generateTable(
                List.of(headers),
                Arrays.stream(data).map(List::of).toList()
        );
        System.out.println(str);
    }

    public static void main(String[] args) {
        var func = List.of(
                new BoundedFunPart(x -> -x, -PI / 2, 0.0, false, false),
                new BoundedFunPart(x -> x, 0.0, PI / 2, true, false)
        );
        new Computations(func, PI, List.of(4, 8, 16));
    }

}