201902-sort.sh (5208B)
1 #!/usr/bin/env bash 2 3 if [[ ! ${BLE_VERSION-} ]]; then 4 source ../../src/benchmark.sh 5 fi 6 7 declare RANDSUP=32768 8 9 function fill-rand { 10 data=() 11 local i n=${1:-10000} 12 for ((i=0;i<n;i++)); do 13 data[i]=$RANDOM 14 done 15 } 16 17 function sort.command { 18 data=($(printf '%s\n' "${data[@]}"|sort -n)) 19 } 20 21 function sort.qsort1.1 { 22 local L=$1 U=$2 23 local p=${data[L+RANDOM*(U-L)/RANDSUP]} 24 25 local i=$L j=$((U-1)) t 26 while :; do 27 while ((data[i]<p)); do ((i++)); done 28 while ((i<j&&p<=data[j])); do ((j--)); done 29 30 ((i<j)) || break 31 32 ((t=data[i],data[i++]=data[j],data[j--]=t)) 33 done 34 while ((data[j]==p)); do ((j++)); done 35 #((j++)) 36 ((L+1<i)) && sort.qsort1.1 "$L" "$i" 37 ((j+1<U)) && sort.qsort1.1 "$j" "$U" 38 } 39 function sort.qsort1 { 40 local L=0 U=${#data[@]} 41 ((L+1<U)) && sort.qsort1.1 "$L" "$U" 42 } 43 44 #------------------------------------------------------------------------------ 45 46 function sort.qsort3.1 { 47 local L=$1 U=$2 48 49 local length=$((U-L)) 50 if ((length<=1)); then 51 return 0 52 53 elif ((length==2)); then 54 local a=${data[L]} b=${data[L+1]} 55 if ((a>b)); then 56 data[L]=$b 57 data[L+1]=$a 58 fi 59 return 0 60 61 elif ((length==3)); then 62 local a=${data[L]} b=${data[L+1]} c=${data[L+2]} 63 if ((b<a)); then 64 if ((a<c)); then # bac 65 data[L]=$b data[L+1]=$a 66 elif ((b<c)); then # bca 67 data[L]=$b data[L+1]=$c data[L+2]=$a 68 else # cba 69 data[L]=$c data[L+2]=$a 70 fi 71 else # ab 72 if ((c<a)); then # cab 73 data[L]=$c data[L+1]=$a data[L+2]=$b 74 elif ((c<b)); then # acb 75 data[L+1]=$c data[L+2]=$b 76 fi 77 fi 78 79 elif ((length==4)); then 80 local a=${data[L]} b=${data[L+1]} c=${data[L+2]} d=${data[L+3]} 81 ((b<a)) && local a=$b b=$a 82 ((d<c)) && local c=$d d=$c 83 84 if ((a<c)); then 85 #a|b,cd 86 if ((b<c)); then # abcd 87 data[L]=$a data[L+1]=$b data[L+2]=$c data[L+3]=$d 88 elif ((b<d)); then # acbd 89 data[L]=$a data[L+1]=$c data[L+2]=$b data[L+3]=$d 90 else # acdb 91 data[L]=$a data[L+1]=$c data[L+2]=$d data[L+3]=$b 92 fi 93 else 94 #c|ab,d 95 if ((d<a)); then # cdab 96 data[L]=$c data[L+1]=$d data[L+2]=$a data[L+3]=$b 97 elif ((d<b)); then # cadb 98 data[L]=$c data[L+1]=$a data[L+2]=$d data[L+3]=$b 99 else # cabd 100 data[L]=$c data[L+1]=$a data[L+2]=$b data[L+3]=$d 101 fi 102 fi 103 104 elif ((length<=64)); then 105 local M=$((L+length/2)) 106 sort.qsort3.1 "$L" "$M" 107 sort.qsort3.1 "$M" "$U" 108 109 # merge 110 local index=$L lhs rhs out= 111 for rhs in "${data[@]:M:U-M}"; do 112 while ((index<M&&(lhs=data[index])<rhs)); do 113 out="$out $lhs" 114 ((index++)) 115 done 116 out="$out $rhs" 117 done 118 out="$out ${data[*]:index:M-index}" 119 120 data=("${data[@]::L}" $out "${data[@]:U}") 121 122 else #elif ((length<10)); then 123 # quick sort 124 local L=$1 U=$2 125 local p=${data[L+RANDOM*(U-L)/RANDSUP]} 126 127 local i=$L j=$((U-1)) t 128 while :; do 129 while ((data[i]<p)); do ((i++)); done 130 while ((i<j&&p<=data[j])); do ((j--)); done 131 ((i<j)) || break 132 ((t=data[i],data[i++]=data[j],data[j--]=t)) 133 done 134 while ((data[j]==p)); do ((j++)); done 135 #((j++)) 136 ((L+1<i)) && sort.qsort3.1 "$L" "$i" 137 ((j+1<U)) && sort.qsort3.1 "$j" "$U" 138 fi 139 } 140 141 function sort.qsort3 { 142 local L=0 U=${#data[@]} 143 ((L+1<U)) && sort.qsort3.1 "$L" "$U" 144 } 145 146 #------------------------------------------------------------------------------ 147 148 function sort.array { 149 local -a dict 150 local a dup=0 151 for a in "${data[@]}"; do ((dict[a]++&&dup++)); done 152 if ((dup)); then 153 # 重複があると駄目… 154 data=() 155 for a in "${!dict[@]}"; do 156 for ((i=0;i<dict[a];i++)); do 157 data+=("$a") 158 done 159 done 160 else 161 data=("${!dict[@]}") 162 fi 163 } 164 165 #------------------------------------------------------------------------------ 166 167 function sort._insert { 168 local L=${1:-0} U=${2:-${#data[@]}} 169 for ((i=L+1;i<U;i++)); do 170 for ((j=i;j>L;j--)); do 171 ((data[j-1]<=data[j])) && break 172 # ■ 173 done 174 done 175 } 176 177 # fill-rand 178 # declare -p data 179 # sort.command 180 # declare -p data 181 182 ble-measure 'fill-rand' 183 ble-measure 'fill-rand && sort.qsort1' 184 ble-measure 'fill-rand && sort.qsort3' 185 ble-measure 'fill-rand && sort.command' 186 ble-measure 'fill-rand && sort.array' 187 188 function check-sort-algorithm { 189 local algorithm=$1 190 local i 191 for ((i=0;i<100;i++)); do 192 fill-rand 193 eval "$algorithm" 194 prev=${data[0]} 195 for v in "${data[@]}"; do 196 ((prev<=v)) || return 1 197 prev=$v 198 done 199 done 200 } 201 202 #check-sort-algorithm sort.qsort1 || echo failed 203 #check-sort-algorithm sort.qsort3 || echo failed 204 205 #------------------------------------------------------------------------------ 206 # swap の速度 207 # 208 # 長さ2の配列の swap は data=(...) の方が速い 209 # 長さ2の配列の swap は t=${data[0]} data[0]=${data[1]} data[1]=$t の方が速い 210 # 211 212 # data=(4321 1324) 213 # ble-measure 'local t=${data[0]}; data[0]=${data[1]}; data[1]=$t' # 5.88u(chat) 214 # ble-measure 'data=("${data[1]}" "${data[0]}")' # 4.88u(chat) 215 216 # data=(4321 123 1324) 217 # ble-measure 'local t=${data[0]}; data[0]=${data[2]}; data[2]=$t' # 5.88u(chat) 218 # ble-measure 'data=("${data[2]}" "${data[1]}" "${data[0]}")' # 4.88u(chat)