AWK int比较语句不起作用

时间:2018-03-15 16:03:18

标签: bash awk

我正在使用Hacker Rank挑战自学BASH,我需要一些建议。

我正在努力解决这一挑战:Apple and Oranges by nabila_ahmed

我需要在多行上以空格分隔多行ints。我决定使用awk来执行此操作,因为它在内存存储方面似乎比使用read更有效。 (我使用read尝试了几个解决方案并且超时了,因为测试用例非常大。)

示例输入:

7 11
5 15
3 2
-2 2 1
5 -6

这是我第一次尝试使用bash并且超时:

row=0
while read line || [[ -n $line ]]; do
    if [ "$row" -eq 0 ]
    then
        column=0
        for n in $line; do
            if [ "$column" -eq 0 ]
            then
                housePos1=$n
            elif [ "$column" -eq 1 ]
            then
                housePos2=$n
            fi
            ((column++))
        done
        # Calculate house min and max
        if [ "$housePos1" -gt "$housePos2" ]
        then
            minHousePos=$housePos2
            maxHousePos=$housePos1
        else
            minHousePos=$housePos1
            maxHousePos=$housePos2
        fi
    elif [ "$row" -eq 1 ]
    then
        column=0
        for n in $line; do
            if [ "$column" -eq 0 ]
            then
                appleTreePos=$n    
            elif [ "$column" -eq 1 ]
            then
                orangeTreePos=$n
            fi
            ((column++))
        done
    elif [ "$row" -eq 3 ]
    then
        applesInHouse=0
        for n in $line; do
            # Calculate the apple's position
            let applePos=$((appleTreePos + n))
            # If the apple's position is within the houses position, count it
            if [ "$applePos" -ge "$minHousePos" ] && [ "$applePos" -le "$maxHousePos" ]
            then
                ((applesInHouse++))
            fi
        done
    elif [ "$row" -eq 4 ]
    then
        orangesInHouse=0
        for n in $line; do
            # Calculate the apple's position
            let orangePos=$((orangeTreePos + n))
            # If the apple's position is within the houses position, count it
            if [ "$orangePos" -ge "$minHousePos" ] && [ "$orangePos" -le "$maxHousePos" ]
            then
                ((orangesInHouse++))
            fi
        done
    fi
    ((row++))
done

echo "$applesInHouse"
echo "$orangesInHouse"

这是我在bash中的第二次尝试,更多的解决方案超时:

x=0;y=0;read -r s t;read -r a b;read -r m n;
for i in `seq 1 $m`; do
    if [ "$i" -lt "$m" ]
    then
        read -d\  z
    else
        read -r z
    fi
    if [ "$((a+z))" -ge "$s" ] && \
    [ "$((a+z))" -le "$t" ]
    then
        ((x++))
    fi
done
for i in `seq 1 $n`; do
    if [ "$i" -lt "$n" ]
    then
        read -d\  z
    else
        read -r z
    fi
    if [ "$((b+z))" -ge "$s" ] && \
    [ "$((b+z))" -le "$t" ]
    then
        ((y++))
    fi
done
echo $x; echo $y

以下是我使用awk ...

调试解决方案的地方
awk -v RS='[-]?[0-9]+' \
'{
    if(word==$1) { 
        counter++ 
        if(counter==1){
            s=RT
        }else if(counter==2){
            t=RT
        }else if(counter==3){
            a=RT
        }else if(counter==4){
            b=RT
        }else if(counter==5){
            m=RT
        }else if(counter==6){
            n=RT
        }else{
            counter2++
            if(counter2<=m){
                print "Apples:"
                print a+RT
                print a+RT>=s
                print a+RT<=t
                applecount++
            }
            if(counter2>m && counter2<=m+n){
                print "Oranges:"
                print b+RT
                print b+RT>=s
                print b+RT<=t
                orangecount++
            }
        }
    }else{
        counter=1
        word=$1
    }
}
END {
    print "Total Counts:"
    print applecount
    print orangecount
}
'

以下是使用示例输入时该脚本的输出

Apples:
3
0
0
Apples:
7
1
0 <-- This is the problem! (7 is less than or equal to 11)
Apples:
6
0
0
Oranges:
20
0
0
Oranges:
9
1
0 <-- This is also a problem! (9 is less than or equal to 11)
Total Counts:
3
2

正如你所看到的,我得到了一些错误的比较......

ANSWER

(主要由@ glenn-jackman提供)

apples_oranges() {
    local s t a b m n d
    local -a apples oranges
    local na=0 nb=0
    {
        read s t
        read a b
        read m n
        read -a apples
        read -a oranges
    } < "$1"
    for d in "${apples[@]}"; do 
        (( s <= a+d && a+d <= t )) && ((na++))
    done
    echo $na
    for d in "${oranges[@]}"; do
        (( s <= b+d && b+d <= t )) && ((nb++))
    done
    echo $nb
}

apples_oranges /dev/stdin

2 个答案:

答案 0 :(得分:1)

这可能会让你开始......

$ awk '
   NR==1{split($0,house)} 
   NR==2{split($0,trees)} 
   NR==3{split($0,counts)} 
   NR==4{split($0,apples)} 
   NR==5{split($0,oranges)}
   END{for(i in apples) 
     if(trees[1]+apples[i]>=house[1] && trees[1]+apples[i]<=house[2]) a++; print a}' file

答案 1 :(得分:1)

我用bash

做这件事
apples_oranges() {
    local s t a b m n d
    local -a apples oranges
    local na=0 nb=0
    {
        read s t
        read a b
        read m n        # unused
        read -a apples
        read -a oranges
    } < "$1"
    for d in "${apples[@]}"; do 
        (( a+d >= s )) && ((na++))
    done
    echo $na
    for d in "${oranges[@]}"; do
        (( b-d <= t )) && ((nb++))
    done
    echo $nb
}

apples_oranges input.txt