Last active
February 18, 2026 13:12
-
-
Save coderodde/bc718d5d2b7c421177d25a5cae26ce6f to your computer and use it in GitHub Desktop.
Ohejlma Todennököisyyslaskenta I 2026 kurssia varten: viikko 5 tehtävä 5.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package viikko5; | |
| import java.util.Objects; | |
| public final class Fraction implements Comparable<Fraction> { | |
| public static final Fraction ZERO = new Fraction(0); | |
| private final long numerator; | |
| private final long denominator; | |
| public Fraction(long numerator, long denominator) { | |
| if (denominator == 0) { | |
| throw new ArithmeticException("Denominator cannot be zero."); | |
| } | |
| // Normalize sign (denominator always positive) | |
| if (denominator < 0) { | |
| numerator = -numerator; | |
| denominator = -denominator; | |
| } | |
| long gcd = gcd(Math.abs(numerator), denominator); | |
| this.numerator = numerator / gcd; | |
| this.denominator = denominator / gcd; | |
| } | |
| public Fraction(long number) { | |
| this(number, 1L); | |
| } | |
| public static Fraction of(long numerator, long denominator) { | |
| return new Fraction(numerator, denominator); | |
| } | |
| public static Fraction of(long number) { | |
| return of(number, 1L); | |
| } | |
| public long getNumerator() { | |
| return numerator; | |
| } | |
| public long getDenominator() { | |
| return denominator; | |
| } | |
| /* ================= Arithmetic ================= */ | |
| public Fraction add(Fraction other) { | |
| long num = this.numerator * other.denominator | |
| + other.numerator * this.denominator; | |
| long den = this.denominator * other.denominator; | |
| return new Fraction(num, den); | |
| } | |
| public Fraction subtract(Fraction other) { | |
| long num = this.numerator * other.denominator | |
| - other.numerator * this.denominator; | |
| long den = this.denominator * other.denominator; | |
| return new Fraction(num, den); | |
| } | |
| public Fraction multiply(Fraction other) { | |
| return new Fraction( | |
| this.numerator * other.numerator, | |
| this.denominator * other.denominator | |
| ); | |
| } | |
| public Fraction divide(Fraction other) { | |
| if (other.numerator == 0) { | |
| throw new ArithmeticException("Division by zero fraction."); | |
| } | |
| return new Fraction( | |
| this.numerator * other.denominator, | |
| this.denominator * other.numerator | |
| ); | |
| } | |
| public Fraction negate() { | |
| return new Fraction(-numerator, denominator); | |
| } | |
| public Fraction reciprocal() { | |
| if (numerator == 0) { | |
| throw new ArithmeticException("Zero has no reciprocal."); | |
| } | |
| return new Fraction(denominator, numerator); | |
| } | |
| public double asDouble() { | |
| return (double) numerator / (double) denominator; | |
| } | |
| /* ================= Comparison ================= */ | |
| @Override | |
| public int compareTo(Fraction other) { | |
| // Avoid floating-point comparison | |
| return Long.compare( | |
| this.numerator * other.denominator, | |
| other.numerator * this.denominator | |
| ); | |
| } | |
| @Override | |
| public boolean equals(Object obj) { | |
| if (this == obj) return true; | |
| if (!(obj instanceof Fraction)) return false; | |
| Fraction other = (Fraction) obj; | |
| return numerator == other.numerator && | |
| denominator == other.denominator; | |
| } | |
| @Override | |
| public int hashCode() { | |
| return Objects.hash(numerator, denominator); | |
| } | |
| @Override | |
| public String toString() { | |
| if (denominator == 1) { | |
| return Long.toString(numerator); | |
| } | |
| return numerator + "/" + denominator; | |
| } | |
| public String toTexDollar() { | |
| return "$\\frac{" + numerator + "}{" + denominator + "}$"; | |
| } | |
| public String toTex() { | |
| return "\\frac{" + numerator + "}{" + denominator + "}"; | |
| } | |
| /* ================= Utilities ================= */ | |
| private static long gcd(long a, long b) { | |
| while (b != 0) { | |
| long tmp = b; | |
| b = a % b; | |
| a = tmp; | |
| } | |
| return a; | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package viikko5; | |
| import java.util.HashMap; | |
| import java.util.Map; | |
| public class Tehtavat5 { | |
| public static void tehtava5() { | |
| Map<Integer, Map<Integer, Fraction>> m = new HashMap<>(); | |
| for (int s = 2; s <= 12; ++s) { | |
| m.put(s, new HashMap<>()); | |
| for (int x = 1; x <= 6; ++x) { | |
| m.get(s).put(x, Fraction.ZERO); | |
| } | |
| } | |
| // Table initialized! | |
| for (int s = 2; s <= 12; ++s) { | |
| for (int b = 1; b <= 6; ++b) { | |
| int a = s - b; | |
| Fraction p = | |
| (1 <= a && a <= 6 | |
| ? Fraction.of(1, 36) | |
| : Fraction.ZERO); | |
| m.get(s).put(b, p); | |
| } | |
| } | |
| for (int j = 2; j <= 12; ++j) { | |
| System.out.printf("%2d & ", j); | |
| for (int i = 1; i <= 6; ++i) { | |
| if (i > 1) { | |
| System.out.print("& "); | |
| } | |
| Fraction p = m.get(j).get(i); | |
| System.out.print(p); | |
| } | |
| Fraction rs = rowSum(m, j); | |
| System.out.printf(" & %s \\\\%n", rs); | |
| } | |
| printColumnSums(m); | |
| printRowWiseTotal(m); | |
| System.out.println("Poikkeavat todennäköisyydet:"); | |
| printDifferentEtnries(m); | |
| printSubtaskCProbability(m); | |
| } | |
| private static void printRowWiseTotal( | |
| Map<Integer, Map<Integer, Fraction>> m) { | |
| System.out.println(); | |
| Fraction total = Fraction.ZERO; | |
| for (int s = 2; s <= 12; ++s) { | |
| total = total.add(rowSum(m, s)); | |
| } | |
| System.out.println(total); | |
| } | |
| private static void printColumnSums( | |
| Map<Integer, Map<Integer, Fraction>> m) { | |
| System.out.print(" "); | |
| Fraction total = Fraction.ZERO; | |
| for (int b = 1; b <= 6; ++b) { | |
| Fraction s = columnSum(m, b); | |
| total = total.add(s); | |
| System.out.printf(" & %s", s); | |
| } | |
| System.out.printf(" & %s \\\\", total); | |
| } | |
| private static Fraction columnSum(Map<Integer, Map<Integer, Fraction>> m, | |
| int b) { | |
| Fraction sum = Fraction.ZERO; | |
| for (int y = 2; y <= 12; ++y) { | |
| Map<Integer, Fraction> mm = m.get(y); | |
| sum = sum.add(mm.get(b)); | |
| } | |
| return sum; | |
| } | |
| private static Fraction rowSum(Map<Integer, Map<Integer, Fraction>> m, | |
| int row) { | |
| Fraction sum = Fraction.ZERO; | |
| for (Fraction f : m.get(row).values()) { | |
| sum = sum.add(f); | |
| } | |
| return sum; | |
| } | |
| private static Fraction fx(int x, Map<Integer, Map<Integer, Fraction>> m) { | |
| Fraction s = Fraction.ZERO; | |
| for (Map<Integer, Fraction> row : m.values()) { | |
| s = s.add(row.get(x)); | |
| } | |
| return s; | |
| } | |
| private static Fraction fy(int y, Map<Integer, Map<Integer, Fraction>> m) { | |
| Fraction s = Fraction.ZERO; | |
| Map<Integer, Fraction> mm = m.get(y); | |
| for (Fraction d : mm.values()) { | |
| s = s.add(d); | |
| } | |
| return s; | |
| } | |
| private static void printDifferentEtnries( | |
| Map<Integer, Map<Integer, Fraction>> m) { | |
| int rowNumber = 1; | |
| for (int y = 2; y <= 12; ++y) { | |
| for (int x = 1; x <= 6; ++x) { | |
| Fraction fxy = m.get(y).get(x); | |
| Fraction fx = fx(x, m); | |
| Fraction fy = fy(y, m); | |
| Fraction fxfy = fx.multiply(fy); | |
| if (!fxfy.equals(fxy)) { | |
| System.out.printf( | |
| "Rivi %2d: x = %d, y = %d: %s vs %s\n", | |
| rowNumber++, | |
| x, | |
| y, | |
| fxfy, | |
| fxy); | |
| } | |
| } | |
| } | |
| } | |
| private static void | |
| printSubtaskCProbability(Map<Integer, Map<Integer, Fraction>> m) { | |
| Fraction ex = ex(m); | |
| Fraction ey = ey(m); | |
| Fraction varx = varx(m, ex); | |
| Fraction vary = vary(m, ey); | |
| Fraction cov = cov(m, ex, ey); | |
| double corr = cov.asDouble() / | |
| (Math.sqrt(varx.asDouble() * vary.asDouble())); | |
| System.out.println("Corr(X, Y) = " + corr); | |
| } | |
| private static Fraction ex(Map<Integer, Map<Integer, Fraction>> m) { | |
| Fraction fp = Fraction.ZERO; | |
| for (int x = 1; x <= 6; ++x) { | |
| fp = fp.add(Fraction.of(x).multiply(fx(x, m))); | |
| } | |
| System.out.println(); | |
| return fp; | |
| } | |
| private static Fraction ey(Map<Integer, Map<Integer, Fraction>> m) { | |
| Fraction fp = Fraction.ZERO; | |
| for (int y = 2; y <= 12; ++y) { | |
| fp = fp.add(Fraction.of(y).multiply(fy(y, m))); | |
| } | |
| System.out.println(); | |
| return fp; | |
| } | |
| private static Fraction varx(Map<Integer, Map<Integer, Fraction>> m, | |
| Fraction ex) { | |
| Fraction fp = Fraction.ZERO; | |
| for (int x = 1; x <= 6; ++x) { | |
| Fraction t = Fraction.of(x).subtract(ex); | |
| Fraction pow = t.multiply(t); | |
| fp = fp.add(pow.multiply(fx(x, m))); | |
| } | |
| return fp; | |
| } | |
| private static Fraction vary(Map<Integer, Map<Integer, Fraction>> m, | |
| Fraction ey) { | |
| Fraction fp = Fraction.ZERO; | |
| for (int y = 2; y <= 12; ++y) { | |
| Fraction t = Fraction.of(y).subtract(ey); | |
| Fraction pow = t.multiply(t); | |
| fp = fp.add(pow.multiply(fy(y, m))); | |
| } | |
| return fp; | |
| } | |
| private static Fraction cov(Map<Integer, Map<Integer, Fraction>> m, | |
| Fraction ex, | |
| Fraction ey) { | |
| Fraction fp = Fraction.ZERO; | |
| for (int x = 1; x <= 6; ++x) { | |
| for (int y = 2; y <= 12; ++y) { | |
| Fraction term1 = Fraction.of(x).subtract(ex); | |
| Fraction term2 = Fraction.of(y).subtract(ey); | |
| fp = fp.add(term1.multiply(term2).multiply(m.get(y).get(x))); | |
| } | |
| } | |
| return fp; | |
| } | |
| public static void main(String[] args) { | |
| tehtava5(); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment