139 lines
3.4 KiB
Bash
139 lines
3.4 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
array.min2() {
|
|
(( $1 < $2 )) && echo "$1" && return
|
|
echo "$2"
|
|
}
|
|
|
|
|
|
_int.insertion_sort() {
|
|
local -n _int_isort_arr="$1"
|
|
local _int_isort_left="$2" _int_isort_right="$3"
|
|
local i=0 j=0
|
|
|
|
for (( i=_int_isort_left+1; i<=_int_isort_right; i+=1 )) do
|
|
local value="${_int_isort_arr["$i"]}" j=$((i-1))
|
|
while (( j>=_int_isort_left && _int_isort_arr[j] > value )); do
|
|
_int_isort_arr[j+1]="${_int_isort_arr["$j"]}"
|
|
((j-=1))
|
|
done
|
|
_int_isort_arr[j+1]="$value"
|
|
done
|
|
}
|
|
|
|
_int.merge() {
|
|
local -n _int_merge_arr="$1"
|
|
local l="$2" m="$3" r="$4" _int_merge_left=() _int_merge_right=()
|
|
local _int_merge_left_len=$((m-l+1)) _int_merge_right_len=$((r-m))
|
|
|
|
for (( i=0; i < _int_merge_left_len; i+=1 )); do
|
|
_int_merge_left[i]="${_int_merge_arr[$((l+i))]}"
|
|
done
|
|
|
|
for (( i=0; i < _int_merge_right_len; i+=1 )); do
|
|
_int_merge_right[i]="${_int_merge_arr[$((m+1+i))]}"
|
|
done
|
|
|
|
local i=0 j=0 k="$l"
|
|
|
|
while (( i < _int_merge_left_len && j < _int_merge_right_len )); do
|
|
if (( _int_merge_left[i] <= _int_merge_right[j] )); then
|
|
_int_merge_arr[k]="${_int_merge_left[$i]}"
|
|
((i+=1))
|
|
else
|
|
_int_merge_arr[k]="${_int_merge_right[$j]}"
|
|
((j+=1))
|
|
fi
|
|
((k+=1))
|
|
done
|
|
|
|
while (( i < _int_merge_left_len )); do
|
|
_int_merge_arr[k]="${_int_merge_left[$i]}"
|
|
((k+=1))
|
|
((i+=1))
|
|
done
|
|
|
|
while (( j < _int_merge_right_len )); do
|
|
_int_merge_arr[k]="${_int_merge_right[$j]}"
|
|
((k+=1))
|
|
((j+=1))
|
|
done
|
|
}
|
|
_int.min_run() {
|
|
local len="$1" r=0
|
|
|
|
while (( len >= 32 )); do
|
|
r=$((r | (len & 1)))
|
|
len=$((len >> 1))
|
|
done
|
|
echo $((len + r))
|
|
}
|
|
|
|
array.timsort() {
|
|
local -n _array_timsort_arr="$1"
|
|
local len="${#_array_timsort_arr[@]}"
|
|
local min_run; min_run="$(_int.min_run "$len")"
|
|
local i=0 j=0 size=0 _array_timsort_left=0 _int_timsort_mid=0 _array_timsort_right=0
|
|
|
|
for (( i=0; i < len; i+=min_run )); do
|
|
_int.insertion_sort _array_timsort_arr "$i" "$(array.min2 "$((i+min_run-1))" "$((len-1))")"
|
|
done
|
|
|
|
for (( size=min_run; size < len; size*=2 )); do
|
|
for (( _array_timsort_left=0; _array_timsort_left < len; _array_timsort_left+=2*size )); do
|
|
_int_timsort_mid=$((_array_timsort_left+size-1))
|
|
_array_timsort_right=$(array.min2 "$((_array_timsort_left+2*size-1))" "$((len-1))")
|
|
if (( _int_timsort_mid < _array_timsort_right )); then
|
|
_int.merge _array_timsort_arr "$_array_timsort_left" "$_int_timsort_mid" "$_array_timsort_right"
|
|
fi
|
|
done
|
|
done
|
|
}
|
|
|
|
array.insertion_sort() {
|
|
local -n _array_isort_arr="$1"
|
|
_int.insertion_sort _array_isort_arr 0 "$((${#_array_isort_arr[@]}-1))"
|
|
}
|
|
|
|
array.qsort() {
|
|
read -ra arr <<< "$@"
|
|
((${#arr[@]} == 0)) && echo && return
|
|
local smaller=() bigger=() pivot="${arr[0]}" res=()
|
|
|
|
for i in "${arr[@]}"; do
|
|
if ((i < pivot)); then
|
|
smaller+=("$i")
|
|
elif ((i > pivot)); then
|
|
bigger+=("$i")
|
|
fi
|
|
done
|
|
|
|
read -ra smaller_sorted <<< "$(array.qsort "${smaller[@]}")"
|
|
read -ra bigger_sorted <<< "$(array.qsort "${bigger[@]}")"
|
|
|
|
res=("${smaller_sorted[@]}" "$pivot" "${bigger_sorted[@]}")
|
|
|
|
echo "${res[@]}"
|
|
}
|
|
|
|
array.sum() {
|
|
local -n _array_sum_input="$1"
|
|
local result=0
|
|
|
|
for i in "${_array_sum_input[@]}"; do
|
|
((result+=i))
|
|
done
|
|
|
|
echo "$result"
|
|
}
|
|
|
|
array.from_bytes() {
|
|
local input="$1" output=()
|
|
|
|
while IFS= read -rd '' -n1 byte; do
|
|
output+=("$byte")
|
|
done <<< "$input"
|
|
|
|
echo "${output[@]}"
|
|
}
|