Skip to content

Commit

Permalink
Merge pull request #24 from Ramy-Badr-Ahmed/feature/ternary_search_im…
Browse files Browse the repository at this point in the history
…plementation
  • Loading branch information
SatinWukerORIG authored Sep 29, 2024
2 parents ea1245e + e127b6e commit ec8fe1c
Show file tree
Hide file tree
Showing 10 changed files with 256 additions and 6 deletions.
1 change: 1 addition & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
## Searches
* [linear_search](/modules/searches/linear_search.f90)
* [recursive_linear_search](/modules/searches/recursive_linear_search.f90)
* [ternary_search](/modules/searches/ternary_search_module.f90)
## Sorts
* [bubble_sort](/modules/sorts/bubble_sort.f90)
* [recursive_bubble_sort](/modules/sorts/recursive_bubble_sort.f90)
Expand Down
20 changes: 20 additions & 0 deletions examples/searches/example_ternary_search_array_based.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
! Example Program: Array-based Ternary Search
! This program demonstrates how to use the array-based ternary search algorithm
! implemented in the `ternary_search` module to find a target element in a sorted array.

program example_ternary_search_array
use ternary_search
implicit none
integer :: result ! Holds the index of the found target
integer, dimension(10) :: arr = [1, 3, 5, 7, 9, 11, 13, 15, 17, 19] ! Sorted Test Array
integer :: target ! Target value to search for

target = 17
result = ternary_search_array(arr, target, 1, size(arr))

if (result /= -1) then
print *, "Target found at index:", result
else
print *, "Target not found."
end if
end program example_ternary_search_array
74 changes: 74 additions & 0 deletions examples/searches/example_ternary_search_function_based.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
!> Example Program: Function-based Ternary Search for Minimum and Maximum
!!
!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
!! in Pull Request: #24
!! https://github.com/TheAlgorithms/Fortran/pull/24
!!
!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
!! addressing bugs/corrections to this file. Thank you!
!!
!! This program demonstrates how to use the function-based ternary search algorithm
!! from the `ternary_search` module to find the minimum and maximum of unimodal functions.

program ternary_search_function_based
use ternary_search
implicit none

! Define the variables
integer, parameter :: dp = kind(0.0d0) ! Define double precision kind
real(8) :: result_min, result_max ! Results for minimum and maximum values
real(8) :: min_point, max_point ! Points where minimum and maximum occur
real(8) :: left, right, tol ! Left and right bounds, and tolerance

interface
! Function with a minimum (example function - defined externally)
real(8) function f_min(x)
real(8), intent(in) :: x
end function f_min

! Function with a maximum (example function - defined externally)
real(8) function f_max(x)
real(8), intent(in) :: x
end function f_max
end interface

! The boundary values can vary depending on the problem context.
! In this example, they are chosen arbitrarily.
left = 0.0d0
right = 10.0d0

! The tolerance value defines how close the left and right bounds must be for the search to terminate.
tol = 1.0e-6_dp

! Call the ternary search to find the minimum point of f_min
min_point = ternary_search_minimum(f_min, left, right, tol)
result_min = f_min(min_point)

! Call the ternary search to find the maximum point of f_max
max_point = ternary_search_maximum(f_max, left, right, tol)
result_max = f_max(max_point)

print *, "Minimum of the function f_min is at x =", min_point, "with value =", result_min
print *, "Maximum of the function f_max is at x =", max_point, "with value =", result_max

end program ternary_search_function_based

! Define the unimodal function f_min with a minimum near x = 5.0
! The quadratic term (x - 5.0)**2 defines a parabola that is concave upward with a minimum at x = 5.0
! and values increasing as x moves away from 5.
! The cosine term introduces oscillations, affecting the exact location of the minimum slightly away from 5.0.

real(8) function f_min(x)
real(8), intent(in) :: x
f_min = (x - 5.0d0)**2 + cos(x) ! Example of a quadratic function with a cosine oscillation
end function f_min

! Define the unimodal function f_max with a maximum near x = 5.0
! The quadratic term -(x - 5.0)**2 defines a parabola that is concave downward with a maximum at x = 5.0
! and values decreasing as x moves away from 5.
! The cosine term introduces oscillations, affecting the exact location of the maximum slightly away from 5.0.

real(8) function f_max(x)
real(8), intent(in) :: x
f_max = -(x - 5.0d0)**2 + cos(x) ! Example of a quadratic function with a cosine oscillation
end function f_max
160 changes: 160 additions & 0 deletions modules/searches/ternary_search_module.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
!> Ternary Search Algorithm Module
!!
!! This module implements two types of ternary search algorithm: array-based and function-based.
!!
!! Created by: Ramy-Badr-Ahmed (https://github.com/Ramy-Badr-Ahmed)
!! in Pull Request: #24
!! https://github.com/TheAlgorithms/Fortran/pull/24
!!
!! Please mention me (@Ramy-Badr-Ahmed) in any issue or pull request
!! addressing bugs/corrections to this file. Thank you!
!!
!! The array-based ternary search is used to find a target element within a sorted array, while the function-based
!! approach is used to find the minimum or maximum of a unimodal function.
!!
!! Array-based ternary search:
!! - Given a sorted array and a target, it splits the array into three parts and recursively searches for the target.
!!
!! Function-based ternary search:
!! - Used for unimodal functions, which have a single peak (maximum) or valley (minimum).
!! This method divides the function’s search space into thirds to converge on the minimum or maximum.
!!

module ternary_search
implicit none
contains

!> Array-based ternary search algorithm
!! This recursive function searches for the target value in a sorted array.
!!
!! Input:
!! - arr: The sorted array to search within.
!! - target: The value to search for.
!! - left, right: The range of indices within which to search.
!!
!! Output:
!! - The index of the target element if found, otherwise -1.
recursive integer function ternary_search_array(arr, target, left, right) result(result_index)
implicit none
integer, intent(in) :: arr(:) ! Array to search within
integer, intent(in) :: target ! Target value to search for
integer, intent(in) :: left, right ! Left and right indices
integer :: mid1, mid2 ! Midpoints
integer :: new_left, new_right ! Temporary indices

! Base case: if the range is invalid, return -1 (not found)
if (right < left) then
result_index = -1
return
end if

! Divide array into three parts
mid1 = left + (right - left)/3
mid2 = right - (right - left)/3

! Check if the target is at mid1 or mid2
if (arr(mid1) == target) then
result_index = mid1
return
else if (arr(mid2) == target) then
result_index = mid2
return
end if

! Recursive search in the appropriate third of the array
if (target < arr(mid1)) then
new_right = mid1 - 1
result_index = ternary_search_array(arr, target, left, new_right)
else if (target > arr(mid2)) then
new_left = mid2 + 1
result_index = ternary_search_array(arr, target, new_left, right)
else
new_left = mid1 + 1
new_right = mid2 - 1
result_index = ternary_search_array(arr, target, new_left, new_right)
end if
end function ternary_search_array

!> Function-based ternary search to find the minimum of a unimodal function
!! This function finds the minimum point of a unimodal function using the ternary search algorithm.
!!
!! Input:
!! - f: The unimodal function to search.
!! - left, right: The range within which to search for the minimum.
!! - tol: The tolerance to determine convergence.
!!
!! Output:
!! - The point at which the function achieves its minimum value.
recursive real(8) function ternary_search_minimum(f, left, right, tol) result(minimum)
implicit none
interface
real(8) function f(x)
real(8), intent(in) :: x
end function f
end interface
real(8), intent(in) :: left, right, tol
real(8) :: mid1, mid2
real(8) :: l, r

l = left
r = right

! Termination condition based on tolerance
do while (r - l > tol)
mid1 = l + (r - l)/3.0d0
mid2 = r - (r - l)/3.0d0

! Compare function values at midpoints
if (f(mid1) < f(mid2)) then
r = mid2
else
l = mid1
end if
end do

! The minimum point is approximately at the midpoint
minimum = (l + r)/2.0d0
end function ternary_search_minimum

!> Function-based ternary search to find the maximum of a unimodal function
!! This function finds the maximum point of a unimodal function using the ternary search algorithm.
!!
!! Input:
!! - f: The unimodal function to search.
!! - left, right: The range within which to search for the maximum.
!! - tol: The tolerance to determine convergence.
!!
!! Output:
!! - The point at which the function achieves its maximum value.
recursive real(8) function ternary_search_maximum(f, left, right, tol) result(maximum)
implicit none
interface
real(8) function f(x)
real(8), intent(in) :: x
end function f
end interface
real(8), intent(in) :: left, right, tol
real(8) :: mid1, mid2
real(8) :: l, r

l = left
r = right

! Termination condition based on tolerance
do while (r - l > tol)
mid1 = l + (r - l)/3.0d0
mid2 = r - (r - l)/3.0d0

! Compare function values at midpoints
if (f(mid1) > f(mid2)) then
r = mid2
else
l = mid1
end if
end do

! The maximum point is approximately at the midpoint
maximum = (l + r)/2.0d0
end function ternary_search_maximum

end module ternary_search
2 changes: 1 addition & 1 deletion modules/sorts/merge_sort.f90
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ recursive subroutine merge_sort(array, n)
implicit none
integer, dimension(:), intent(inout) :: array ! Input/output array to be sorted
integer, intent(in) :: n ! Size of the array
integer :: middle, i
integer :: middle
integer, dimension(:), allocatable :: left_half, right_half, sorted_array

! Base case: return if the array has 1 or fewer elements
Expand Down
1 change: 0 additions & 1 deletion tests/sorts/tests_gnome_sort.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ program tests_gnome_sort

use gnome_sort_module
implicit none
integer :: i
integer, dimension(:), allocatable :: array

! Test 1: Repeated elements
Expand Down
1 change: 0 additions & 1 deletion tests/sorts/tests_heap_sort.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ program tests_heap_sort

use heap_sort_module
implicit none
integer :: i
integer, dimension(:), allocatable :: array

! Test 1: Repeated elements
Expand Down
1 change: 0 additions & 1 deletion tests/sorts/tests_merge_sort.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ program tests_merge_sort

use merge_sort_module
implicit none
integer :: i
integer, dimension(:), allocatable :: array

! Test 1: Repeated elements
Expand Down
1 change: 0 additions & 1 deletion tests/sorts/tests_quick_sort.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ program tests_quick_sort

use quick_sort_module
implicit none
integer :: i
integer, dimension(:), allocatable :: array

! Test 1: Repeated elements
Expand Down
1 change: 0 additions & 1 deletion tests/sorts/tests_radix_sort.f90
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
program tests_radix_sort
use radix_sort_module
implicit none
integer :: i
integer, dimension(:), allocatable :: array
integer, parameter :: base10 = 10, base2 = 2, base16 = 16

Expand Down

0 comments on commit ec8fe1c

Please sign in to comment.