Issue
I attempted to eliminate the middle element of an array using the following function. Here is the code:
#!/bin/bash
shift_array_to_left () {
local n=$1
local idx=$2
for ((i=idx; i < n-1; i++)); do
arr[$i]=${arr[i + 1]}
done
arr[n - 1]=0
echo $((n - 1))
}
return_mid_index () {
local n=$1
if [ $n -le 0 ]; then
echo $n
elif [ $((n&1)) -eq 1 ]; then
echo $((n - (n-1)/2 - 1))
else
echo $((n/2 - 1))
fi
}
main() {
local n=0
read -p "Enter size of array: " n
echo "Enter your array"
declare -a arr
for ((i=0; i < n; i++)); do
read arr[$i]
done
idx=$(return_mid_index $n)
n=$(shift_array_to_left $n $idx)
for ((i=0; i < n; i++)); do
echo -n "${arr[i]} "
done
return 0
}
main
Output
Enter size of array: 3
Enter your array
1
2
3
1 2
Expected
Enter size of array: 3
Enter your array
1
2
3
1 3
Kindly recommend modifications that I can make.
below is the algorithm of above code
Shift Array to Left Function:
- Input: Size of the array
n
, Index of the element to be removedidx
- Iterate from
idx
ton-1
and shift each element to the left. - Set the last element to 0 (or any default value).
- Return the updated size of the array (
n - 1
).
- Input: Size of the array
Return Mid Index Function:
- Input: Size of the array
n
- If
n
is less than or equal to 0, returnn
. - If
n
is odd, return the middle index (n / 2
). - If
n
is even, return the index before the middle element (n / 2 - 1
).
- Input: Size of the array
Main Function:
- Read the size of the array
n
. - Read the array elements from the user.
- Calculate the index of the middle element using
return_mid_index
. - Remove the middle element using
shift_array_to_left
. - Print the updated array.
- Read the size of the array
Solution
@choroba fixed the bug in your shell script but regarding "Kindly recommend modifications...." - your script is manipulating text which is not something shells are designed to do so don't use a shell for that, use a tool designed for the purpose.
A shell is an environment from which to manipulate (create/destroy) files and processes and sequence calls to tools, not a tool to manipulate text. The mandatory POSIX tool for general purpose text manipulation is awk. So, the shell part of your solution should be just a call to awk and everything else should be an awk script for simplicity, clarity, efficiency, portability, etc.
For example, using any awk and keeping to your original code style as much as possible:
$ cat tst.sh
#!/usr/bin/env bash
main() {
awk '
function shift_array_to_left (n,idx, i) {
for ( i=idx; i < n-1; i++ ) {
arr[i]=arr[i + 1]
}
delete arr[n]
return n - 1
}
function return_mid_index (n) {
if ( n <= 0 )
return n
else if ( n % 2 )
return n - (n-1)/2 - 1
else
return n/2 - 1
}
BEGIN {
printf "Enter size of array: "
getline n
print "Enter your array"
for ( i=0; i < n; i++ ) {
getline arr[i]
}
idx = return_mid_index(n)
n = shift_array_to_left(n, idx)
for ( i=0; i < n; i++ ) {
printf "%s ", arr[i]
}
exit 0
}
'
}
main
$ ./tst.sh
Enter size of array: 3
Enter your array
1
2
3
1 3
You could call that awk script from any shell in any Unix box and it'd run orders of magnitude faster than your existing shell script plus it wouldn't fail (potentially cryptically and/or dangerously) given various input values, environment settings, and contents of the directory you run it from, unlike your shell script (copy/paste your shell script into http://shellcheck.net and it'll tell you about some of the issues).
There are various ways the awk script could be improved, I'd at least make sure to print a terminating newline on the output (and no trailing blank) and use arrays that start at index 1
instead of 0
to make the math and loops simpler:
$ cat tst.sh
#!/usr/bin/env bash
main() {
awk '
function shift_array_to_left (n,idx, i) {
for ( i=idx; i < n; i++ ) {
arr[i] = arr[i + 1]
}
delete arr[n--]
return n
}
function return_mid_index (n) {
return int( (n + 1) / 2)
}
BEGIN {
printf "Enter size of array: "
getline n
print "Enter your array"
for ( i=1; i <= n; i++ ) {
getline arr[i]
}
idx = return_mid_index(n)
n = shift_array_to_left(n, idx)
for ( i=1; i <= n; i++ ) {
printf "%s%s", arr[i], (i<n ? OFS : ORS)
}
}
'
}
main
Answered By - Ed Morton Answer Checked By - Cary Denson (WPSolving Admin)