Skip to content

Instantly share code, notes, and snippets.

@lovasoa
Last active December 6, 2023 23:57
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lovasoa/55550cb561110300ad97398d2cf93214 to your computer and use it in GitHub Desktop.
Save lovasoa/55550cb561110300ad97398d2cf93214 to your computer and use it in GitHub Desktop.
Generic dichotomic search as a shell script
#!/usr/bin/env bash
# Dichotomic search in bash
# This is a bash-specific function that uses bash features.
# This is not guaranteed to work in other shells.
#
# Usage:
# source dichotomic-bash.sh
# result=$(dichotomic_search min max command)
#
# Returns the largest i for which `command i` succeeds (exits with a null exit code)
# This supposes that there is an i such that :
# forall min <= n <= i, `command n` succeeds,
# and forall i < n <= max, `command n` fails
#
# This script is public domain
function dichotomic_search {
min=$1
max=$2
command=$3
while (( $min < $max )); do
# Compute the mean between min and max, rounded up to the superior unit
current=$(( (min + max + 1 ) / 2 ))
if $command $current
then min=$current
else max=$((current - 1))
fi
done
echo $min
}
#!/bin/sh
# Dichotomic search in shell
# Usage: dichotomic.sh min max command
# Returns the largest i for which `command i` succeeds (exits with a null exit code)
# This supposes that there is an i such that :
# forall min <= n <= i, `command n` succeeds,
# and forall i < n <= max, `command n` fails
# This script works in any shell (not just bash) and is public domain
if [ "$#" -ne 3 ]; then
echo "$0: invalid number of parameters.
Usage: $0 min max command" >&2
exit 1
fi
min=$1
max=$2
command=$3
while [ $min -lt $max ]; do
# Compute the mean between min and max, rounded up to the superior unit
current=`expr '(' "$min" + "$max" + 1 ')' / 2`
if $command $current
then min=$current
else max=`expr $current - 1`
fi
done
echo $min
Copy link

ghost commented Apr 13, 2018

Yo this is super sexy. thanks

@William8915
Copy link

William8915 commented May 23, 2022

Thank you very much for the script, but [[ $min < $max ]] will not work correctly in bash, it should be changed to [[ $min -lt $max ]] just like in the POSIX version (Changing [ to [[ doesn't magically change < from string comparison to integer comparison). Or use (( $min < $max )) instead.

@lovasoa
Copy link
Author

lovasoa commented May 23, 2022

@William8915 : you are right, thanks ! I changed it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment