急勾配の列の判定

急勾配の判定 - みずぴー日記からですが、元は急勾配の判定 DouKaku? からです。

有限の長さの数列で,各要素の値が,その要素の後ろにある残りの列に含まれる
すべての要素の和よりも大きい列を「急勾配の列」ということにします(空列の
和は0とします).

任意の長さ(ただし有限の長さの)数列を与えられたとき,それが「急勾配の列」
であるかどうかを判定する述語関数を定義してください.

解き方ですが、この問題は配列の最初から計算するのではなく、最後から計算していく方が効率良く解くことができます。

#! /usr/bin/gawk -f
# super_inc.awk

BEGIN {

    arr[1] = 5; arr[2] = 4; arr[3] = 1;
    print is_super_inc(arr);

    arr[1] = 5; arr[2] = 2; arr[3] = 1;
    print is_super_inc(arr);

}

# is_super_inc():   急勾配かどうかを判定する
#   in:     配列 arr
#   out:    急勾配の場合 1、そうでない場合 0 を返す
function is_super_inc(arr,     i, num_arr, sum_left) {
    for (i in arr) {
        num_arr++;
    }

    for (i = num_arr; i >= 1; i--) {
        if (arr[i] <= sum_left) {
            return 0;
        }
        sum_left += arr[i];
    }
    return 1;
}

BEGIN ブロックにある最初のものは 0 を返し、後のものは 1 を返します。 実際に実行してみましょう。

$ nawk -f super_inc.awk
0
1

ここでは nawk などでも動作するように配列の数を for 〜 in で数えていますが、もちろん gawk であれば length(arr) で計数することができます。 特に効率は考えていませんが、この場合の O-記法での表記は O(n) になります。

tag_nawk.pngtag_nawk.pngtag_nawk.pngtag_nawk.png