Skip to content

reduce is a dog (even in jq>1.4) #618

@pkoppstein

Description

@pkoppstein

The following function uses "reduce" to emit the "equilibrium indices" of the input array. An equivalent version written using recurse or foreach runs nicely in jq>1.4 (i.e. those versions that have TCO and foreach), but in both jq 1.4 and jq>1.4, the version using reduce has roughly exponentially worse performance in the length of the input array.

Here are some gross timings using jq>1.4 (i.e. based simply on "time jq ...") for the following query:

array(N;0) | equilibrium_indices | length
# N     (u+s in seconds)
#1000  0.19
# 1e4   0.43
# 2e4   1.54
# 3e4   3.43
# 4e4   6.2
# 5e4  10.4
# 6e4  16.5

Since the recurse and foreach versions of this program are fine in jq>1,4, the problem is evidently with the implementation of "reduce". Hopefully a skilled eye will be able to identify it; if not, then maybe "reduce" should be implemented using "foreach"!

def equilibrium_indices:
  def indices(a):
    reduce range(0;a|length) as $i 
      # state: [ headsum, tailsum, answers]
      ( [ 0, add, [] ];
        .[0] as $h
        | (.[1] - a[$i]) as $t
        | (if $h == $t then .[2] + [$i] else .[2] end) as $ans
        | [ $h + a[$i], $t, $ans ] )
    | .[2];

  . as $in | indices($in);

def array(n;init): reduce range(0;n) as $i ([]; . + [init]);

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions