Bash Century From Year
century_from_year() {
    local _year=$1
    echo $(( (_year + 99) / 100 ))
}

This converts a year into its century. Years 1-100 are century 1, 101-200 are century 2, and so on.

Bash Check Palindrome
check_palindrome() {
    local _s=$1
    local _rev=""
    local _i
    for ((_i = ${#_s} - 1; _i >= 0; _i--)); do
        _rev="${_rev}${_s:_i:1}"
    done
    if [[ "$_rev" == "$_s" ]]; then echo true; else echo false; fi
}

This compares the string with its reverse. If they match, it is a palindrome.

Bash Chocolates By Numbers
gcd() {
    local _n=$1 _m=$2
    if (( _n % _m == 0 )); then
        echo "$_m"
        return
    fi
    gcd "$_m" $(( _n % _m ))
}

chocolates_by_numbers() {
    local _n=$1 _m=$2
    local _g
    _g=$(gcd "$_n" "$_m")
    echo $(( (_n * _m / _g) / _m ))
}

This uses the greatest common divisor to figure out how many chocolates get eaten before the pattern repeats.

Bash Common Prime Divisors
gcd() {
    local _n=$1 _m=$2
    if (( _n % _m == 0 )); then
        echo "$_m"
        return
    fi
    gcd "$_m" $(( _n % _m ))
}

remove_common_prime_divisors() {
    local _n=$1 _m=$2 _d
    while (( _n != 1 )); do
        _d=$(gcd "$_n" "$_m")
        if (( _d == 1 )); then
            break
        fi
        _n=$(( _n / _d ))
    done
    echo "$_n"
}

common_prime_divisors() {
    local -n _arrA="$1"
    local -n _arrB="$2"
    local _counter=0 _i _x _y _d _rx _ry
    for _i in "${!_arrA[@]}"; do
        _x=${_arrA[$_i]}
        _y=${_arrB[$_i]}
        _d=$(gcd "$_x" "$_y")
        _rx=$(remove_common_prime_divisors "$_x" "$_d")
        if (( _rx != 1 )); then
            continue
        fi
        _ry=$(remove_common_prime_divisors "$_y" "$_d")
        if (( _ry == 1 )); then
            ((_counter++))
        fi
    done
    echo "$_counter"
}

This checks whether two numbers are built from the same prime factors by repeatedly dividing out their shared parts.

Bash Count Div
count_div() {
    local _a=$1 _b=$2 _k=$3
    local _firstDiv
    if (( _a % _k == 0 )); then _firstDiv=$_a; else _firstDiv=$(( _a + (_k - _a % _k) )); fi
    local _lastDiv=$(( _b - _b % _k ))
    echo $(( (_lastDiv - _firstDiv) / _k + 1 ))
}

This counts how many numbers in a range are divisible by K without looping through every value.

Bash Count Factors
count_factors() {
    local _n=$1
    local _count=0 _i=1
    while (( _i * _i < _n )); do
        if (( _n % _i == 0 )); then
            _count=$(( _count + 2 ))
        fi
        ((_i++))
    done
    if (( _i * _i == _n )); then
        ((_count++))
    fi
    echo "$_count"
}

This checks divisors in pairs up to the square root, which keeps the work much smaller than testing every number.

Bash Count Non Divisible
count_non_divisible() {
    local -n _a="$1"
    local -n _out="$2"
    local _size=${#_a[@]}
    local _maxv=${_a[0]} _v
    for _v in "${_a[@]}"; do (( _v > _maxv )) && _maxv=$_v; done
    local -a _occ
    for ((_v = 0; _v <= _maxv; _v++)); do _occ[_v]=0; done
    for _v in "${_a[@]}"; do _occ[_v]=$(( _occ[_v] + 1 )); done
    _out=()
    local _k
    for _k in "${!_a[@]}"; do
        _v=${_a[$_k]}
        local _count=0 _i=1
        while (( _i * _i <= _v )); do
            if (( _v % _i == 0 )); then
                _count=$(( _count + _occ[_i] ))
                if (( _v / _i != _i )); then
                    _count=$(( _count + _occ[_v/_i] ))
                fi
            fi
            ((_i++))
        done
        _out[_k]=$(( _size - _count ))
    done
}

This counts how often each value appears, then subtracts the divisor matches so you get the non-divisible count for each item.

Bash Count Semi Primes
count_semi_primes() {
    local _n=$1
    local -n _pArr="$2"
    local -n _qArr="$3"
    local -n _outArr="$4"
    local -a _is_prime _semi _cum
    local _i _k _idx
    for ((_i = 0; _i <= _n; _i++)); do _is_prime[_i]=1; _semi[_i]=0; done
    for ((_i = 2; _i * _i <= _n; _i++)); do
        if (( _is_prime[_i] )); then
            for ((_k = _i * _i; _k <= _n; _k += _i)); do
                _is_prime[_k]=0
            done
        fi
    done
    for ((_k = 2; _k * _k <= _n; _k++)); do
        if (( _is_prime[_k] )); then
            for ((_i = 2; _i * _k <= _n; _i++)); do
                if (( _is_prime[_i] )); then
                    _semi[_k * _i]=1
                fi
            done
        fi
    done
    _cum[0]=${_semi[0]}
    for ((_i = 1; _i <= _n; _i++)); do
        _cum[_i]=$(( _cum[_i-1] + _semi[_i] ))
    done
    _outArr=()
    for _idx in "${!_pArr[@]}"; do
        local _lo=${_pArr[$_idx]}
        local _hi=${_qArr[$_idx]}
        _outArr[_idx]=$(( _cum[_hi] - _cum[_lo-1] ))
    done
}

This precomputes semiprimes and prefix sums so each range query becomes a quick subtraction.

Bash Cyclic Rotation
cyclic_rotation() {
    local -n _a="$1"
    local -n _out="$2"
    local _k=$3
    local _size=${#_a[@]}
    if (( _size == 0 )); then
        _out=()
        return
    fi
    _k=$(( _k % _size ))
    _out=()
    local _i
    for ((_i = 0; _i < _size; _i++)); do
        _out[(_i + _k) % _size]=${_a[_i]}
    done
}

This rotates the array to the right by K steps and keeps the wrap-around values in the correct order.

Bash Distinct
distinct() {
    local -n _a="$1"
    local -A _seen
    local _v
    for _v in "${_a[@]}"; do _seen[$_v]=1; done
    echo "${#_seen[@]}"
}

This counts unique values by tracking what has already been seen.