Current section
Files
Jump to
Current section
Files
src/glevenshtein.gleam
//// The module used to calculate the levenshtein distance
import gleam/int
import gleam/list
import gleam/result
import gleam/string
/// This function calculates the levenshtein distance.
/// It isn't case sensetive
///
/// ## Examples
///
/// ```gleam
/// glevenshtein.calculate("Gleam", "BEAM") // 2!
/// ```
///
/// ```gleam
/// glevenshtein.calculate("GLEAM", "Gleam") // 0!
/// ```
///
pub fn calculate(word1: String, word2: String) -> Int {
let word1 = word1 |> string.lowercase()
let word2 = word2 |> string.lowercase()
calculate_levenshtein_distance(
word1 |> string.to_graphemes(),
word2 |> string.to_graphemes(),
0,
)
}
fn calculate_levenshtein_distance(
word1: List(String),
word2: List(String),
distance: Int,
) -> Int {
use <- filter_requirement(list.is_empty(word1), fn() { list.length(word2) })
use <- filter_requirement(list.is_empty(word2), fn() { list.length(word1) })
use <- filter_requirement(
list.first(word1) |> result.unwrap("")
== list.first(word2) |> result.unwrap(""),
fn() {
calculate_levenshtein_distance(
list.drop(word1, 1),
list.drop(word2, 1),
distance,
)
},
)
get_operation_results(word1, word2, distance)
|> list.reduce(int.min)
|> result.unwrap(distance)
|> int.add(1)
}
fn get_operation_results(
word1: List(String),
word2: List(String),
distance: Int,
) -> List(Int) {
[
calculate_levenshtein_distance(list.drop(word1, 1), word2, distance),
calculate_levenshtein_distance(word1, list.drop(word2, 1), distance),
calculate_levenshtein_distance(
list.drop(word1, 1),
list.drop(word2, 1),
distance,
),
]
}
fn filter_requirement(
condition: Bool,
return: fn() -> Int,
apply: fn() -> Int,
) -> Int {
case condition {
True -> return()
False -> apply()
}
}