You are not logged in.

#1 2013-06-12 17:12:10

Thme
Member
From: Raleigh NC
Registered: 2012-01-22
Posts: 105

[Solved]Bash:Subtract a set of numbers from each other in pairs?

Solution: see my reply.
I know the description isn't exact, there really isn't an easy way to describe it with the limits of the title so the circumstances are these:

say I have arrays which contain small numbers like so:
ex. 12, 7 and 13
I which is greater than the other when comparing the following number in sequence and need to subtract the lower one from it. the 3 numbers above in that order will end up producing two simple problems:
(12 - 7) and (13 - 7). The results will be stored in an array in the order they were performed (left to right)
Currently I'm trying to accomplish this with a while loop and some if statements
Note: the array "Tree" is named such so I can print the results somewhat like so after performing this operation until only one result is left:

12   7   13
     5   6
        1

#!/usr/bin/env bash
Num_Set=( 12 7 13 ) 
A=0 ; B=1
while ((  ${#Num_Set[B]} >= 1 )) ; do
	if (( ${Num_Set[A]} >= ${Num_Set[B]} )) ; then
		Tree[A]=$(( ${Num_Set[A]} - ${Num_Set[B]} ))	
	elif  (( ${Num_Set[A]} < ${Num_Set[B]} )) ; then 
		Tree[A]=$(( ${Num_Set[B]} - ${Num_Set[A]} ))	
	fi
       A=$(( A++ )) ; B=$(( B++ ))
done

echo "${Num_Set[@]}"
echo "${Tree[@]}"

I believe i'm on the right track but this becomes an endless loop for reasons unknown for to me.
Any bash hackers out there know whats happening here?

Last edited by Thme (2013-06-12 18:57:40)


"Hidden are the ways for those who pass by, for light is perished and darkness comes into being." Nephthys:
Ancient Egyptian Coffin Texts

Offline

#2 2013-06-12 17:59:10

Procyon
Member
Registered: 2008-05-07
Posts: 1,819

Re: [Solved]Bash:Subtract a set of numbers from each other in pairs?

You cannot increase A and B like that. ++A and ++B would work, or just ((A++)) ; ((B++))

Offline

#3 2013-06-12 18:04:16

Mr Green
Forum Fellow
From: U.K.
Registered: 2003-12-21
Posts: 5,896
Website

Re: [Solved]Bash:Subtract a set of numbers from each other in pairs?

Only a quick search but http://www.unix.com/shell-programming-s … array.html not sure it will help..


Mr Green

Offline

#4 2013-06-12 18:53:36

Thme
Member
From: Raleigh NC
Registered: 2012-01-22
Posts: 105

Re: [Solved]Bash:Subtract a set of numbers from each other in pairs?

Ok So I solved it:
there were a couple problems with it and a few minor corrections..
I indeed switched to (( A++ )) and (( B++ )) right before I went back to seeif there were any replies here... I was more focused on getting it working but yes that is the way to do increments...
One issue to note was more so for any potential readers.
this syntax was wrong:

(( ${Num_Set[A]} - ${Num_Set[B]} ))

So far as I Learned you cannot reference array elements directly inside arithmetic operations "(( ))" so I had to store them as variables like so:

X=${Num_Set[A]} ; Y=${Num_Set[B]}
Tree+=( $(( X - Y ))  )

The here is the working script (actually its a function for a larger script)

#!/usr/bin/env bash
Num_Set=( $@ ) 
A=0 ; B=1
N=${#Num_Set[B]}  
while (( N != 0 )) ; do
	X=${Num_Set[A]} ; Y=${Num_Set[B]}
	if (( X >= Y )) ; then
		Tree+=( $(( X - Y )) )
	elif  (( X < Y )) ; then 
		Tree+=( $(( Y - X )) )
	fi
	(( A++ )) ; (( B++ ))
	N=${#Num_Set[B]}
done
echo "${Num_Set[@]}"
echo "${Tree[@]}"

Last edited by Thme (2013-06-12 18:55:19)


"Hidden are the ways for those who pass by, for light is perished and darkness comes into being." Nephthys:
Ancient Egyptian Coffin Texts

Offline

#5 2013-06-12 19:39:47

Procyon
Member
Registered: 2008-05-07
Posts: 1,819

Re: [Solved]Bash:Subtract a set of numbers from each other in pairs?

Thme wrote:

So far as I Learned you cannot reference array elements directly inside arithmetic operations "(( ))" so I had to store them as variables like so:

You can:

aa=( 1 0 )
echo $((${aa[${aa[0]}]} + ${aa[${aa[1]}]}))
1
echo $((${aa[${aa[1]}]} + ${aa[${aa[1]}]}))
2

Offline

#6 2013-06-12 20:49:20

progandy
Member
Registered: 2012-05-17
Posts: 5,190

Re: [Solved]Bash:Subtract a set of numbers from each other in pairs?

Procyon wrote:
Thme wrote:

So far as I Learned you cannot reference array elements directly inside arithmetic operations "(( ))" so I had to store them as variables like so:

You can:

My bash allows this, too:

a=(1 2 3)
b=1
echo $(( a[b] ))
echo $(( a[b] + a[2] ))

| alias CUTF='LANG=en_XX.UTF-8@POSIX ' |

Offline

#7 2013-06-13 02:50:15

Thme
Member
From: Raleigh NC
Registered: 2012-01-22
Posts: 105

Re: [Solved]Bash:Subtract a set of numbers from each other in pairs?

@ progandy. Completely forgot that... So my previous post and this one currently works:
I will mention this though you can't use this:

a=( 12 7 345 )
if (( #a[1] < #a[0] )) ; then echo "${a[1]}" ; fi

Note: It is actually the full function. The part which was the focus of my post is the inner/second while loop here.

Num_Set=( $@ ) 
Set=( ${Num_Set[@]} )
Count=${#Set[@]}
while (( Count > 1  )) ; do
	A=0 ; B=1
	N=${#Num_Set[B]} 
	while (( N != 0 )) ; do
		if (( Num_Set[A] >= Num_Set[B] )) ; then
			Tree+=( $(( Num_Set[A] - Num_Set[B] )) )
			Tmp+=( $(( Num_Set[A] - Num_Set[B]   )) )
		elif  (( Num_Set[A] < Num_Set[B] )) ; then 
			Tree+=( $(( Num_Set[B] - Num_Set[A] )) )
			Tmp+=( $(( Num_Set[B] - Num_Set[A] )) )
		fi
		(( A++ )) ; (( B++ ))
		N=${#Num_Set[B]}
	done ; wait
	(( Count-- ))
	Num_Set=( ${Tmp[@]} )
	unset Tmp[@]
done
echo "${Num_Set[@]}"
echo "${Tree[@]}"

@ Procyon I've recently read that although you can still use $ inside (( )) it isn't necessary/recommended as progangy demonstrates. Anyhow, I appreciate the corrections and help here. It's all working the way I wanted it to now.

Last edited by Thme (2013-06-13 02:56:10)


"Hidden are the ways for those who pass by, for light is perished and darkness comes into being." Nephthys:
Ancient Egyptian Coffin Texts

Offline

#8 2013-06-13 08:06:41

Procyon
Member
Registered: 2008-05-07
Posts: 1,819

Re: [Solved]Bash:Subtract a set of numbers from each other in pairs?

Thme wrote:

I will mention this though you can't use this:

a=( 12 7 345 )
if (( #a[1] < #a[0] )) ; then echo "${a[1]}" ; fi

@ Procyon I've recently read that although you can still use $ inside (( )) it isn't necessary/recommended as progangy demonstrates. Anyhow, I appreciate the corrections and help here. It's all working the way I wanted it to now.

You're checking the length of the string with #. (so 12 7 345 -> 2 1 3)
You can change this:

	N=${#Num_Set[B]} 
	while (( N != 0 )) ; do

With just while [[ ${Num_Set[$B]} ]]; do

And bash has associative arrays as well. Your claim that the $ is not recommended is not valid at all:

declare -A aa
aa[bb]=100
aa[0]=1
bb=0
echo $(( aa[bb] + 1 ))
101
echo $(( aa[$bb] + 1 ))
2

Offline

#9 2013-06-13 11:06:37

Trent
Member
From: Baltimore, MD (US)
Registered: 2009-04-16
Posts: 990

Re: [Solved]Bash:Subtract a set of numbers from each other in pairs?

(this is not the post you're looking for, move along)

Last edited by Trent (2013-06-13 22:11:22)

Offline

#10 2013-06-15 00:46:31

Thme
Member
From: Raleigh NC
Registered: 2012-01-22
Posts: 105

Re: [Solved]Bash:Subtract a set of numbers from each other in pairs?

And bash has associative arrays as well. Your claim that the $ is not recommended is not valid at all:

declare -A aa
aa[bb]=100
aa[0]=1
bb=0
echo $(( aa[bb] + 1 ))
101
echo $(( aa[$bb] + 1 ))
2

My apologies however I tested my original post with http://www.shellcheck.net/ upon finding the site through an unrelated thread. This was an example test to illustrate what was commented on and what was not. This works in the shell:

A=( 2 1 10 )
B=2
echo $(( A[0] + A[B] - ${A[${A[$B]}]} - A[$B] + ${A[A[1]]} + A[0] - ${#A[2]} ))
23

However ${A[${A[$B]}]} and ${A[A[1]]} were commented on by shellcheck with "don't use $ on variables in (( ))". Aside from that it does still work. Also I tested this as well:

echo $(( A[${A[0]}] + 1 ))

And although it works in my bash it gets "This $((..)) expression is malformed." and "Unexpected "}". Fix any mentioned problems and try again." when tested in shellcheck. I suspect that maybe a fault on shellcheck but either way it looks less readable than just A[A[0]]. So what I've gathered from all this is that, although the above examples all work, the following ones below are probably the best practice here for use in (( )).

#!/usr/bin/env bash
declare -A AA
AA[BB]=3
AA[0]=1
BB=0
A=( 2 1 10 )
B=1
echo $(( A[0] + 1 ))
echo $(( B + 1 ))
echo $(( A[0] + 1 ))
echo $(( A[B] + 1 ))
echo $(( A[A[0]] + 1 ))
echo $(( ${#A[2]} + 1 ))
echo $(( ${A[2]/0/1} + 1 ))
echo $(( A[BB] + 1 ))
echo $(( AA[$BB] + 1 ))
echo $(( AA[BB]++ ))

So in the cases of using arrays in manners like ${#A[2]}, ${A[2]/0/1} and AA[$BB] ( AA[BB] being different. ) using $ would be necessary inside of (( )). If I missed any or there are any needed corrections please note them as I'm concerned with good practices here. I'll leave it at that. Again thanks for the help everyone.

Last edited by Thme (2013-06-15 00:49:54)


"Hidden are the ways for those who pass by, for light is perished and darkness comes into being." Nephthys:
Ancient Egyptian Coffin Texts

Offline

Board footer

Powered by FluxBB