From 6e0f79d39d2c5c3a6ecff0cec78fe619d240be1c Mon Sep 17 00:00:00 2001 From: depial <91621102+depial@users.noreply.github.com> Date: Sun, 22 Jun 2025 05:29:46 -0400 Subject: [PATCH 1/2] add concept exercise problematic-probabilities --- config.json | 12 +++ .../problematic-probabilities/.docs/hints.md | 25 +++++++ .../.docs/instructions.md | 73 +++++++++++++++++++ .../.docs/introduction.md | 67 +++++++++++++++++ .../.meta/config.json | 17 +++++ .../problematic-probabilities/.meta/design.md | 27 +++++++ .../.meta/exemplar.jl | 12 +++ .../problematic-probabilities.jl | 15 ++++ .../problematic-probabilities/runtests.jl | 43 +++++++++++ 9 files changed, 291 insertions(+) create mode 100644 exercises/concept/problematic-probabilities/.docs/hints.md create mode 100644 exercises/concept/problematic-probabilities/.docs/instructions.md create mode 100644 exercises/concept/problematic-probabilities/.docs/introduction.md create mode 100644 exercises/concept/problematic-probabilities/.meta/config.json create mode 100644 exercises/concept/problematic-probabilities/.meta/design.md create mode 100644 exercises/concept/problematic-probabilities/.meta/exemplar.jl create mode 100644 exercises/concept/problematic-probabilities/problematic-probabilities.jl create mode 100644 exercises/concept/problematic-probabilities/runtests.jl diff --git a/config.json b/config.json index 9adc8365..3d2c3a38 100644 --- a/config.json +++ b/config.json @@ -343,6 +343,18 @@ ], "status": "beta" }, + { + "slug": "problematic-probabilities", + "name": "Problematic Probabilities", + "uuid": "f3fe4029-03fd-4dde-aeeb-a05f4873f377", + "concepts": [ + "rational-numbers" + ], + "prerequisites": [ + "loops" + ], + "status": "beta" + }, { "slug": "old-elyses-enchantments", "name": "Old Elyse's Enchantments", diff --git a/exercises/concept/problematic-probabilities/.docs/hints.md b/exercises/concept/problematic-probabilities/.docs/hints.md new file mode 100644 index 00000000..feb5bfc6 --- /dev/null +++ b/exercises/concept/problematic-probabilities/.docs/hints.md @@ -0,0 +1,25 @@ +# Hints + +## 1. Give the ratio of successes to trials + +- Create `Rational` numbers using the successes as the numerator and the trials as the denominator. +- Loops, comprehensions or vector operations can be employed to create the new array. + +## 2. Find the real probabilities associated with successes to trials + +- Create `Float` numbers using the successes as the numerator and the trials as the denominator. +- Loops, comprehensions or vector operations can be employed to create the new array. + +## 3. Check the mean of the probabilities + +- The mean is found by summing the data and dividing by the number of events. +- Use your `rationalize` and `probabilities` functions. +- If a discrepancy is found between using floats and rationals, return the rational number. +- Loops or vector operations can be employed. + +## 4. Check the independent probability + +- Probabilities of independent events can be multiplied together to find the total probability of those events happening together. +- Use your `rationalize` and `probabilities` functions. +- If a discrepancy is found between using floats and rationals, return the rational number. +- Loops or vector operations can be employed. diff --git a/exercises/concept/problematic-probabilities/.docs/instructions.md b/exercises/concept/problematic-probabilities/.docs/instructions.md new file mode 100644 index 00000000..f1f863d4 --- /dev/null +++ b/exercises/concept/problematic-probabilities/.docs/instructions.md @@ -0,0 +1,73 @@ +# Instructions + +A research organization has noticed that some of its junior researchers have been using less-than-optimal methods in their analysis. +One of these methods is to immediately convert discrete probabilites into floats (i.e. real numbers) before doing further calculations. + +Senior researchers prefer to use rational numbers in the calculations, which may provide higher precision, and would like to know if the poor practices of the junior researchers have affected the studies' outcomes. + +There were two types of studies done: +- Many tests were run, each returning a discrete probability for success, and then the mean of these probabilities was calculated. +- Many independent events were tested, and the total probability for all events to occur was calculated by multiplying them together. + +The senior researchers are asking you to write functions which can help them determine if there are rounding errors in the analyses from using floats, and asking you provide a precise rational number for the outcome if there are errors. + +## 1. Give the ratio of successes to trials + +The `rationalize(successes, trials)` function takes two arrays, `successes` and `trials`. +For an index `i`, `successes[i]` corresponds to the number of successes which occurred in `trials[i]` number of trials. +The function returns an array of rational numbers of the successes over the number of trials, in the same order as the input arrays. + +```julia-repl +julia> rationalize([1, 2, 3], [4, 5, 6]) +3-element Vector{Rational{Int64}}: + 1//4 + 2//5 + 1//2 +``` + +## 2. Find the real probabilities associated with successes to trials + +Similarly, the `probabilities(successes, trials)` function takes two arrays, `successes` and `trials`. +It returns an array of floats of the successes over the number of trials, in the same order as the input arrays. + +```julia-repl +julia> prababilities(([1, 2, 3], [4, 5, 6])) +3-element Vector{Float64}: + 0.25 + 0.4 + 0.5 +``` + +## 3. Check the mean of the probabilities + +The `checkmean(successes, trials)` takes the two arrays, `successes` and `trials`. +It checks the mean of the real probabilities against the mean of the rational probabilities. +- If the two probabilities are equal, `checkmean` returns `true` +- If the two probabilites are different, `checkmean` returns the rational probability. + +```julia-repl +julia> successes, trials = [9, 4, 7, 8, 6], [22, 22, 11, 17, 12]; +julia> checkmean(successes, trials) +true + +julia> successes, trials = [6, 5, 9, 8, 9], [21, 19, 13, 25, 22]; +julia> checkmean(sucesses, trials) +1873629//4754750 +``` + +## 4. Check the independent probability + +The `checkprob(successes, trials)` takes the two arrays, `successes` and `trials`. +It checks the total probability of the float probabilities against the total probability of the rational probabilities. +- If the two probabilities are equal, `checkprob` returns `true` +- If the two probabilites are different, `checkprob` returns the rational probability. + +```julia-repl +julia> successes, trials = [2, 9, 4, 4, 5], [15, 11, 17, 19, 15]; +julia> checkprob(successes, trials) +true + +julia> successes, trials = [9, 8, 5, 4, 3], [22, 14, 19, 25, 18]; +julia> checkprob(sucesses, trials) +12//7315 +``` diff --git a/exercises/concept/problematic-probabilities/.docs/introduction.md b/exercises/concept/problematic-probabilities/.docs/introduction.md new file mode 100644 index 00000000..d1a30d8d --- /dev/null +++ b/exercises/concept/problematic-probabilities/.docs/introduction.md @@ -0,0 +1,67 @@ +# Introduction + +`Rational numbers` are fractions with an integer numerator divided by an integer denominator. + +For example, we can store `2//3` as an exact fraction instead of the approximate `Float64` value `0.6666...` + +The advantage is that (except in the extreme case of *integer overflow*) a rational number will remain exact, avoiding the rounding errors that are often inevitable with floating-point numbers. + +Rational numbers are quite a simple numeric type and aim to work much as you would expect. +Because they have been a standard type in Julia since the early versions, most functions will accept them as input in the same way as integers and floats. + +## Creating rational numbers + +Creation is as simple as using `//` between two integers. + +```julia-repl +julia> 3//4 +3//4 + +julia> a = 3; b = 4; + +julia> a//b +3//4 +``` + +Common factors are automatically removed, converting the fraction to its "lowest terms": the smallest integers that accurately represent the fraction, and with a non-negative denominator. + +```julia-repl +julia> 5//15 +1//3 + +julia> 5//-15 +-1//3 +``` + +## Arithmetic with rational numbers + +The usual `arithmetic operators` `+ - * / ^ %` work with rationals, essentially the same as with other numeric types. + +Integers and other `Rational`s can be included and give a `Rational` result. +Including a `float` in the expression results in `float` output, with a consequent (possible) loss in precision. + +If a `float` is desired, simply use the `float()` function to convert a rational. +It is quite normal to use rational numbers to preserve precision through a long calculation, then convert to a float at the end. + +```julia-repl +julia> 3//4 + 1//3 # addition +13//12 + +julia> 3//4 * 1//3 # multiplication +1//4 + +julia> 3//4 / 1//3 # division +9//4 + +julia> 3//4 ^ 2 # exponentiation +3//16 + +julia> 3//4 + 5 # rational and int => rational +23//4 + +julia> 3//4 + 5.3 # rational and float => float +6.05 + +julia> float(3//4) # casting +0.75 +``` diff --git a/exercises/concept/problematic-probabilities/.meta/config.json b/exercises/concept/problematic-probabilities/.meta/config.json new file mode 100644 index 00000000..3b7fc826 --- /dev/null +++ b/exercises/concept/problematic-probabilities/.meta/config.json @@ -0,0 +1,17 @@ +{ + "authors": [ + "depial" + ], + "files": { + "solution": [ + "problematic-probabilities.jl" + ], + "test": [ + "runtests.jl" + ], + "exemplar": [ + ".meta/exemplar.jl" + ] + }, + "blurb": "Help make statistics more accurate with rational numbers" +} diff --git a/exercises/concept/problematic-probabilities/.meta/design.md b/exercises/concept/problematic-probabilities/.meta/design.md new file mode 100644 index 00000000..01b08f66 --- /dev/null +++ b/exercises/concept/problematic-probabilities/.meta/design.md @@ -0,0 +1,27 @@ +# Design + +## Goal + +The goal of this exercise is to introduce the student to rational numbers. + +## Learning objectives + +- Understand the use of rational numbers +- Understand basic construction and arithmetic operations +- Become more familiar with the key use case of rational numbers: mitigation of rounding errors + +## Out of scope + +- Subtlties of conversion from rational to floating-point numbers +- Infinite rationals +- `NaN`s + +## Concepts + +The Concepts this exercise unlocks are: + +- + +## Prerequisites + +- `loops` diff --git a/exercises/concept/problematic-probabilities/.meta/exemplar.jl b/exercises/concept/problematic-probabilities/.meta/exemplar.jl new file mode 100644 index 00000000..f8d364cd --- /dev/null +++ b/exercises/concept/problematic-probabilities/.meta/exemplar.jl @@ -0,0 +1,12 @@ +rationalize = .// +probabilities = ./ + +function checkmean(successes, trials) + r, p = sum(rationalize(successes, trials)) // length(trials), sum(probabilities(successes, trials)) / length(trials) + float(r) == p || r +end + +function checkprob(successes, trials) + r, p = prod(rationalize(successes, trials)), prod(probabilities(successes, trials)) + float(r) == p || r +end diff --git a/exercises/concept/problematic-probabilities/problematic-probabilities.jl b/exercises/concept/problematic-probabilities/problematic-probabilities.jl new file mode 100644 index 00000000..54f15fa1 --- /dev/null +++ b/exercises/concept/problematic-probabilities/problematic-probabilities.jl @@ -0,0 +1,15 @@ +function rationalize(successes, trials) + +end + +function probabilities(successes, trials) + +end + +function checkmean(successes, trials) + +end + +function checkprob(successes, trials) + +end diff --git a/exercises/concept/problematic-probabilities/runtests.jl b/exercises/concept/problematic-probabilities/runtests.jl new file mode 100644 index 00000000..23c7c17b --- /dev/null +++ b/exercises/concept/problematic-probabilities/runtests.jl @@ -0,0 +1,43 @@ +using Test + +include("problematic-probabilities.jl") + +@testset verbose = true "tests" begin + @testset "rationalize" begin + @test rationalize([2], [4]) == [1//2] + @test rationalize([1, 2, 3, 4], [2, 3, 4, 5]) == [1//2, 2//3, 3//4, 4//5] + end + + @testset "probabilities" begin + @test probabilities([2], [4]) == [2/4] + @test probabilities([1, 2, 3, 4], [2, 3, 4, 5]) == [1/2, 2/3, 3/4, 4/5] + end + + @testset "average check" begin + successes, trials = [8, 1, 4, 4, 4], [13, 24, 16, 23, 18] + @test checkmean(successes, trials) + + successes, trials = [9, 8, 6, 8, 3], [18, 15, 23, 19, 14] + @test checkmean(successes, trials) + + successes, trials = [1, 9, 7, 7, 8], [13, 16, 13, 12, 21] + @test checkmean(successes, trials) == 3119//7280 + + successes, trials = [1, 6, 8, 6, 5], [20, 15, 18, 11, 25] + @test checkmean(successes, trials) == 3247//9900 + end + + @testset "probability check" begin + successes, trials = [4, 2, 4, 3, 2], [18, 20, 18, 25, 22] + @test checkprob(successes, trials) + + successes, trials = [9, 1, 8, 4, 3], [14, 22, 15, 15, 20] + @test checkprob(successes, trials) + + successes, trials = [6, 2, 2, 9, 8], [18, 23, 12, 18, 16] + @test checkprob(successes, trials) == 1//828 + + successes, trials = [9, 3, 7, 6, 7], [11, 17, 13, 13, 17] + @test checkprob(successes, trials) == 7938//537251 + end +end From 8b299f0558e01c05b614e20ff10ffaceb215be51 Mon Sep 17 00:00:00 2001 From: Colin Leach Date: Sun, 22 Jun 2025 15:08:36 -0700 Subject: [PATCH 2/2] Update instructions.md It's hard to even guess which time zone you are in currently, so I went ahead and fixed the typo. I'll merge. --- .../concept/problematic-probabilities/.docs/instructions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/exercises/concept/problematic-probabilities/.docs/instructions.md b/exercises/concept/problematic-probabilities/.docs/instructions.md index f1f863d4..eb13f0fa 100644 --- a/exercises/concept/problematic-probabilities/.docs/instructions.md +++ b/exercises/concept/problematic-probabilities/.docs/instructions.md @@ -31,7 +31,7 @@ Similarly, the `probabilities(successes, trials)` function takes two arrays, `su It returns an array of floats of the successes over the number of trials, in the same order as the input arrays. ```julia-repl -julia> prababilities(([1, 2, 3], [4, 5, 6])) +julia> probabilities(([1, 2, 3], [4, 5, 6])) 3-element Vector{Float64}: 0.25 0.4