Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix tests #23

Merged
merged 1 commit into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/gleam_community/maths/conversion.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
//// * [`int_to_float`](#int_to_float)
//// * [`degrees_to_radians`](#degrees_to_radians)
//// * [`radians_to_degrees`](#radians_to_degrees)
////

import gleam/int

Expand Down
2 changes: 1 addition & 1 deletion src/gleam_community/maths/elementary.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -1000,7 +1000,7 @@ pub fn power(x: Float, y: Float) -> Result(Float, String) {
// 2. If the base (x) is 0 and the exponent (y) is negative then the
// expression is equivalent to the exponent (y) divided by 0 and an
// error should be returned
case x <. 0.0 && fractional || x == 0.0 && y <. 0.0 {
case { x <. 0.0 && fractional } || { x == 0.0 && y <. 0.0 } {
True ->
"Invalid input argument: x < 0 and y is fractional or x = 0 and y < 0."
|> Error
Expand Down
140 changes: 12 additions & 128 deletions src/gleam_community/maths/metrics.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,18 @@
////<style>
//// .katex { font-size: 1.1em; }
////</style>
////
////
//// ---
////
//// Metrics: A module offering functions for calculating distances and other
//// types of metrics.
////
//// Disclaimer: In this module, the terms "distance" and "metric" are used in
//// a broad and practical sense. That is, they are used to denote any difference
//// or discrepancy between two inputs. Consequently, they may not align with their
//// precise mathematical definitions (in particular, some "distance" functions in
//// this module do not satisfy the triangle inequality).
////
//// * **Distance measures**
//// * [`norm`](#norm)
//// * [`manhattan_distance`](#manhattan_distance)
Expand All @@ -40,26 +46,24 @@
//// * [`sorensen_dice_coefficient`](#sorensen_dice_coefficient)
//// * [`tversky_index`](#tversky_index)
//// * [`overlap_coefficient`](#overlap_coefficient)
//// * [`levenshtein_distance`](#levenshtein_distance)
//// * **Basic statistical measures**
//// * [`mean`](#mean)
//// * [`median`](#median)
//// * [`variance`](#variance)
//// * [`standard_deviation`](#standard_deviation)
////
////

import gleam/bool
import gleam/float
import gleam/int
import gleam/list
import gleam/option
import gleam/pair
import gleam/set
import gleam_community/maths/arithmetics
import gleam_community/maths/conversion
import gleam_community/maths/elementary
import gleam_community/maths/piecewise
import gleam/set
import gleam/float
import gleam/int
import gleam/string
import gleam/option

/// Utility function that checks all lists have the expected length and contents
/// The function is primarily used by all distance measures taking 'List(Float)'
Expand Down Expand Up @@ -1126,125 +1130,6 @@ pub fn cosine_similarity(
}
}

/// <div style="text-align: right;">
/// <a href="https://github.com/gleam-community/maths/issues">
/// <small>Spot a typo? Open an issue!</small>
/// </a>
/// </div>
///
/// Calculate the Levenshtein distance between two strings, i.e., measure the
/// difference between two strings (essentially sequences). It is defined as
/// the minimum number of single-character edits required to change one string
/// into the other, using operations:
/// - insertions
/// - deletions
/// - substitutions
///
/// Note: The implementation is primarily based on the Elixir implementation
/// [levenshtein](https://hex.pm/packages/levenshtein).
///
/// <details>
/// <summary>Example:</summary>
///
/// import gleeunit/should
/// import gleam_community/maths/metrics
///
/// pub fn example () {
/// metrics.levenshtein_distance("hello", "hello")
/// |> should.equal(0)
///
/// metrics.levenshtein_distance("cat", "cut")
/// |> should.equal(1)
///
/// metrics.levenshtein_distance("kitten", "sitting")
/// |> should.equal(3)
/// }
/// </details>
///
/// <div style="text-align: right;">
/// <a href="#">
/// <small>Back to top ↑</small>
/// </a>
/// </div>
///
///
pub fn levenshtein_distance(xstring: String, ystring: String) -> Int {
case xstring, ystring {
xstring, ystring if xstring == ystring -> {
0
}
xstring, ystring if xstring == "" -> {
string.length(ystring)
}
xstring, ystring if ystring == "" -> {
string.length(xstring)
}
_, _ -> {
let xstring_graphemes = string.to_graphemes(xstring)
let ystring_graphemes = string.to_graphemes(ystring)
let ystring_length = list.length(ystring_graphemes)
let distance_list = list.range(0, ystring_length)

do_edit_distance(xstring_graphemes, ystring_graphemes, distance_list, 1)
}
}
}

fn do_edit_distance(
xstring: List(String),
ystring: List(String),
distance_list: List(Int),
step: Int,
) -> Int {
case xstring {
// Safe as 'distance_list' is never empty
[] -> {
let assert Ok(last) = list.last(distance_list)
last
}
[xstring_head, ..xstring_tail] -> {
let new_distance_list =
distance_list_helper(ystring, distance_list, xstring_head, [step], step)
do_edit_distance(xstring_tail, ystring, new_distance_list, step + 1)
}
}
}

fn distance_list_helper(
ystring: List(String),
distance_list: List(Int),
grapheme: String,
new_distance_list: List(Int),
last_distance: Int,
) -> List(Int) {
case ystring {
[] -> list.reverse(new_distance_list)
[ystring_head, ..ystring_tail] -> {
let assert [distance_list_head, ..distance_list_tail] = distance_list
let difference = case ystring_head == grapheme {
True -> {
0
}
False -> {
1
}
}
let assert [first, ..] = distance_list_tail
let min =
last_distance + 1
|> piecewise.minimum(first + 1, int.compare)
|> piecewise.minimum(distance_list_head + difference, int.compare)
distance_list_helper(
ystring_tail,
distance_list_tail,
grapheme,
[min, ..new_distance_list],
min,
)
}
}
}

/// <div style="text-align: right;">
/// <a href="https://github.com/gleam-community/maths/issues">
/// <small>Spot a typo? Open an issue!</small>
Expand Down Expand Up @@ -1293,7 +1178,6 @@ fn distance_list_helper(
/// </a>
/// </div>
///
///
pub fn canberra_distance(
xarr: List(Float),
yarr: List(Float),
Expand Down
5 changes: 3 additions & 2 deletions src/gleam_community/maths/predicates.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@
//// * [`is_even`](#is_even)
//// * [`is_odd`](#is_odd)
//// * [`is_prime`](#is_prime)
////

import gleam/pair
import gleam/int
import gleam/list
import gleam/option
import gleam/pair
import gleam_community/maths/arithmetics
import gleam_community/maths/elementary
import gleam_community/maths/piecewise
import gleam_community/maths/arithmetics

/// <div style="text-align: right;">
/// <a href="https://github.com/gleam-community/maths/issues">
Expand Down
5 changes: 3 additions & 2 deletions src/gleam_community/maths/sequences.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@
//// * [`linear_space`](#linear_space)
//// * [`logarithmic_space`](#logarithmic_space)
//// * [`geometric_space`](#geometric_space)
////

import gleam/list
import gleam_community/maths/conversion
import gleam_community/maths/elementary
import gleam_community/maths/piecewise
import gleam_community/maths/conversion
import gleam/list

/// <div style="text-align: right;">
/// <a href="https://github.com/gleam-community/maths/issues">
Expand Down
2 changes: 1 addition & 1 deletion src/gleam_community/maths/special.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@
//// * [`incomplete_gamma`](#incomplete_gamma)
////

import gleam/list
import gleam_community/maths/conversion
import gleam_community/maths/elementary
import gleam_community/maths/piecewise
import gleam/list

/// <div style="text-align: right;">
/// <a href="https://github.com/gleam-community/maths/issues">
Expand Down
2 changes: 1 addition & 1 deletion test/gleam_community/maths/arithmetics_test.gleam
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import gleam/option
import gleam_community/maths/arithmetics
import gleeunit/should
import gleam/option

pub fn int_gcd_test() {
arithmetics.gcd(1, 1)
Expand Down
4 changes: 2 additions & 2 deletions test/gleam_community/maths/combinatorics_test.gleam
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import gleam_community/maths/combinatorics
import gleam/set
import gleam/list
import gleam/set
import gleam_community/maths/combinatorics
import gleeunit/should

pub fn int_factorial_test() {
Expand Down
6 changes: 3 additions & 3 deletions test/gleam_community/maths/conversion_test.gleam
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import gleam_community/maths/conversion
import gleam_community/maths/elementary
import gleam_community/maths/predicates
import gleam_community/maths/conversion
import gleeunit/should

pub fn float_to_degree_test() {
let assert Ok(tol) = elementary.power(-10.0, -6.0)
let assert Ok(tol) = elementary.power(10.0, -6.0)
conversion.radians_to_degrees(0.0)
|> predicates.is_close(0.0, 0.0, tol)
|> should.be_true()
Expand All @@ -15,7 +15,7 @@ pub fn float_to_degree_test() {
}

pub fn float_to_radian_test() {
let assert Ok(tol) = elementary.power(-10.0, -6.0)
let assert Ok(tol) = elementary.power(10.0, -6.0)
conversion.degrees_to_radians(0.0)
|> predicates.is_close(0.0, 0.0, tol)
|> should.be_true()
Expand Down
Loading
Loading