package UE09_191124_Rekursion2;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

public class UE09_Rekursion2 {
    public static void main(String[] args) {
        int[][] file1 = readFile("src/UE09_191124_Rekursion2/UE09_triangle1.txt");
        int[][] file2 = readFile("src/UE09_191124_Rekursion2/UE09_triangle2.txt");
        int[][] file3 = readFile("src/UE09_191124_Rekursion2/UE09_triangle.txt");
        System.out.println("\n" + maxTotalRekursion(file1, 0, 0)); //23
        System.out.println("\n" + maxTotalRekursion(file2, 0, 0)); //1074
////        System.out.println("\n" + maxTotalRekursion(file3, 0, 0)); //Braucht ewig lange, da File sehr groß
        System.out.println("\n" + maxTotal(file1)); //23
        System.out.println("\n" + maxTotal(file2)); //1074
        System.out.println("\n" + maxTotal(file3)); //7273
        System.out.println(longestCollatzSequence(999999)); //837799
        System.out.println(longestCollatzSequence(13)); //9
        System.out.println(collatzSequenceLength(13)); //10
        int[] coins = new int[]{200, 100, 50, 20, 10, 5, 2, 1}; //73682
        System.out.println(coinSums(200, coins, 0)); //11
        System.out.println(coinSums(10, new int[]{200, 100, 50, 20, 10, 5, 2, 1}, 0)); //11
        System.out.println(coinSums(2, new int[]{200, 100, 50, 20, 10, 5, 2, 1}, 0)); //2
    }

    public static int[][] readFile(String file) {
        try {
            List<String> lines = Files.readAllLines(Path.of(file));
            int[][] output = new int[lines.size()][];
            for (int i = 0; i < output.length; i++) {
                String[] line = lines.get(i).trim().split(" ");
                output[i] = new int[line.length];
                for (int j = 0; j < line.length; j++) output[i][j] = Integer.parseInt(line[j]);
            }
            return output;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static long maxTotalRekursion(int[][] input, int y, int x) {
        return (y >= input.length - 1) ? input[y][x] : Long.max(maxTotalRekursion(input, y + 1, x), maxTotalRekursion(input, y + 1, x + 1)) + input[y][x];
    }

    public static long maxTotal(int[][] input) {
        for (int y = input.length - 1; y >= 0; y--)
            for (int x = 0; x < input[y].length - 1; x++) input[y - 1][x] += Math.max(input[y][x], input[y][x + 1]);
        return input[0][0];
    }

    public static long longestCollatzSequence(int limit) {
        long startingNumber = 0, maxLength = 0;
        for (int i = 1; i <= limit; i++) {
            long length = collatzSequenceLength(i);
            if (length > maxLength) {
                maxLength = length;
                startingNumber = i;
            }
        }
        return startingNumber;
    }

    public static long collatzSequenceLength(long n) {
        return n == 1 ? 1 : collatzSequenceLength((n & 1) == 0 ? n / 2 : 3 * n + 1) + 1;
    }

    public static int coinSums(int value, int[] coins, int index) {
        if (value == 0) return 1;
        if (value < 0 || index >= coins.length) return 0;
        return coinSums(value - coins[index], coins, index) + coinSums(value, coins, index + 1);
    }
}
