Decreasing contiguous subsequences

From Rosetta Code
Decreasing contiguous subsequences is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Given a List (abstract data type) of integer values, find all its maximal-length non-increasing subsequences. Categorize each of these subsequences by its percentage change using the following groups:

  • Greater than 0% and less than 4%
  • Greater than or equal to 4% and less than 8%
  • Greater than or equal to 8% and less than 12%
  • Greater than or equal to 12% and less than 16%
  • Greater than or equal to 16% and less than 25%
  • Greater than or equal to 25%

If we were to plot these values, we'd be looking for peaks and troughs, categorized by the difference between the local maximum and the local minimum, as a percentage of the local maximum.

A plot highlighting decreasing contiguous subsequences
A plot highlighting decreasing contiguous subsequences

Using the following example sequence, display the count of subsequences per group.

90, 90, 90, 91, 91, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 89, 88, 87, 87, 87, 86, 86, 86, 85, 85,
86, 86, 87, 87, 88, 89, 89, 89, 90, 90, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 91, 90,
90, 90, 90, 90, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89,
89, 90, 90, 90, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 87, 88, 88, 88, 88, 88, 88, 88, 88,
88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 89,
89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88,
88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 87, 87, 87, 87, 86, 86, 86, 86,
86, 86, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89,
88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 89, 89, 91,
94, 94, 95, 96, 96, 96, 97, 97, 96, 96, 96, 96, 95, 95, 94, 93, 93, 92, 92, 91, 91, 90, 89, 89, 88,
86, 86, 85, 83, 83, 81, 80, 80, 80, 79, 79, 79, 78, 78, 79, 81, 82, 82, 85, 89, 89, 91, 93, 93, 94,
95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 93, 93, 93, 92, 92, 91, 91, 91, 90, 90, 90, 88,
87, 87, 86, 85, 85, 84, 84, 84, 83, 84, 84, 84, 85, 86, 86, 87, 87, 87, 88, 88, 88, 89, 90, 90, 90,
91, 91, 92, 92, 92, 93, 94, 94, 94, 95, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 90,
89, 89, 87, 86, 85, 85, 84, 83, 83, 82, 82, 82, 81, 81, 81, 81, 81, 81, 82, 85, 85, 86, 89, 89, 91,
92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 89, 89,
88, 88, 88, 87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 86, 87, 87, 87, 88, 88, 88, 88, 88, 88,
89, 89, 89, 89, 89, 89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 95, 95, 96, 96, 96, 95, 95,
95, 94, 94, 93, 93, 93, 92, 90, 90, 89, 87, 87, 87, 85, 83, 83, 82, 81, 81, 81, 80, 80, 81, 81, 81,
81, 81, 81, 81, 81, 81, 81, 81, 81, 83, 86, 88, 88, 90, 91, 91, 91, 92, 92, 93, 93, 93, 94, 95, 95,
95, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 94, 93, 93, 92, 92, 92, 91, 90, 90, 90, 90, 90,
91, 93, 93, 94, 94, 94, 94, 95, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 92, 92,
91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95,
95, 95, 95, 95, 94, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 91, 90, 90, 90, 89, 89, 89, 88, 88,
88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91,
91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 92,
92, 93, 93, 93, 93, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 88,
88, 87, 87, 87, 86, 86, 85, 85, 85, 86, 86, 86, 87, 87, 88, 88, 88, 89, 90, 90, 90, 91, 91, 91, 91,
91, 91, 91, 91, 91, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 90, 90, 90, 89, 88,
87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, 86, 87, 88, 88, 88,
89, 89, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91,
90, 90, 90, 89, 89, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88,
90, 90, 91, 93, 93, 93, 93, 93, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89,
89, 89, 88, 87, 87, 87, 87, 87, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88,
89

It's OK to hard code the example sequence or read it from a file. Plotting decreasing subsequences is optional.

ALGOL 68

BEGIN # find non-ascending subsequences in a list of integer values and      #
      # count those with the percentage change in various ranges             #

    # mode to hold the details of a non-ascending sequence                   #
    MODE SEQUENCE = STRUCT( INT start index, end index );

    # returns the next non-ascending SEQUENCE from data starting at prev,    #
    #         or a SEQUENCE with start index > end index if there isn't one  #
    PRIO NEXTSEQUENCE = 1;
    OP   NEXTSEQUENCE = ( []INT data, SEQUENCE prev )SEQUENCE:
         IF  INT s pos = end index OF prev + 1;
             s pos > UPB data
         THEN SEQUENCE( s pos, UPB data )      # reached the end of the data #
         ELSE INT value := data[ s pos ];            # still some data left #
              INT e pos := s pos + 1;
              WHILE IF e pos > UPB data THEN FALSE ELSE data[ e pos ] <= value FI
              DO
                  value  := data[ e pos ];
                  e pos +:= 1
              OD;
              SEQUENCE( s pos, e pos - 1 )
         FI # NEXTSEQUENCE # ;

    # returns the first non-ascending SEQUENCE from data                     #
    #         or a SEQUENCE with start index > end index if there isn't one  #
    OP   FIRSTSEQUENCE = ( []INT data )SEQUENCE:
         IF  LWB data > UPB data
         THEN SEQUENCE( LWB data, UPB data )          # data has no elements #
         ELSE                                            # data is not empty #
              data NEXTSEQUENCE SEQUENCE( -1, LWB data - 1 )
         FI # FIRSTSEQUENCE # ;

    # count the non-ascending SEQUENCEs in data, grouping by the percentage  #
    # changes in the specified ranges                                        #
    # ranges must be the upper bound of the required range and must be       #
    # specified in order, the first range will start at 0, there will be a   #
    # final element for percentages >= the final range                       #
    # SEQUENCEs with a single element or 0 percentage change are ignored     #
    # returns the counts                                                     #
    PRIO COUNTCHANGESBYPERCENTAGE = 1;
    OP   COUNTCHANGESBYPERCENTAGE = ( []INT data, ranges )[]INT:
         BEGIN
            [ LWB ranges : UPB ranges + 1 ]INT counts;
            FOR i FROM LWB counts TO UPB counts DO counts[ i ] := 0 OD;
            SEQUENCE prev := FIRSTSEQUENCE data;
            WHILE INT start pos = start index OF prev;
                  INT end pos   = end index OF prev;
                  end pos >= start pos
            DO
                IF end pos > start pos THEN          # more than one element #
                    INT  s value = data[ start pos ], e value = data[ end pos ];
                    REAL change = ( ( s value - e value ) / s value ) * 100;
                    IF change > 0 THEN               # there was a decrease #
                        BOOL found := FALSE;
                        FOR i FROM LWB counts TO UPB counts - 1 WHILE NOT found DO
                            IF found := ranges[ i ] > change THEN counts[ i ] +:= 1 FI
                        OD;
                        IF NOT found THEN counts[ UPB counts ] +:= 1 FI
                    FI
                FI;
                prev := data NEXTSEQUENCE prev
            OD;
            counts
         END # COUNTCHANGESBYPERCEBTAGE # ;

    BEGIN # task test case                                                   #
        []INT ranges = ( 4, 8, 12, 16, 25 );
        []INT data = (
90, 90, 90, 91, 91, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 89, 88, 87, 87, 87, 86, 86, 86, 85, 85,
86, 86, 87, 87, 88, 89, 89, 89, 90, 90, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 91, 90,
90, 90, 90, 90, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89,
89, 90, 90, 90, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 87, 88, 88, 88, 88, 88, 88, 88, 88,
88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 89,
89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88,
88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 87, 87, 87, 87, 86, 86, 86, 86,
86, 86, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89,
88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 89, 89, 91,
94, 94, 95, 96, 96, 96, 97, 97, 96, 96, 96, 96, 95, 95, 94, 93, 93, 92, 92, 91, 91, 90, 89, 89, 88,
86, 86, 85, 83, 83, 81, 80, 80, 80, 79, 79, 79, 78, 78, 79, 81, 82, 82, 85, 89, 89, 91, 93, 93, 94,
95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 93, 93, 93, 92, 92, 91, 91, 91, 90, 90, 90, 88,
87, 87, 86, 85, 85, 84, 84, 84, 83, 84, 84, 84, 85, 86, 86, 87, 87, 87, 88, 88, 88, 89, 90, 90, 90,
91, 91, 92, 92, 92, 93, 94, 94, 94, 95, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 90,
89, 89, 87, 86, 85, 85, 84, 83, 83, 82, 82, 82, 81, 81, 81, 81, 81, 81, 82, 85, 85, 86, 89, 89, 91,
92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 89, 89,
88, 88, 88, 87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 86, 87, 87, 87, 88, 88, 88, 88, 88, 88,
89, 89, 89, 89, 89, 89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 95, 95, 96, 96, 96, 95, 95,
95, 94, 94, 93, 93, 93, 92, 90, 90, 89, 87, 87, 87, 85, 83, 83, 82, 81, 81, 81, 80, 80, 81, 81, 81,
81, 81, 81, 81, 81, 81, 81, 81, 81, 83, 86, 88, 88, 90, 91, 91, 91, 92, 92, 93, 93, 93, 94, 95, 95,
95, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 94, 93, 93, 92, 92, 92, 91, 90, 90, 90, 90, 90,
91, 93, 93, 94, 94, 94, 94, 95, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 92, 92,
91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95,
95, 95, 95, 95, 94, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 91, 90, 90, 90, 89, 89, 89, 88, 88,
88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91,
91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 92,
92, 93, 93, 93, 93, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 88,
88, 87, 87, 87, 86, 86, 85, 85, 85, 86, 86, 86, 87, 87, 88, 88, 88, 89, 90, 90, 90, 91, 91, 91, 91,
91, 91, 91, 91, 91, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 90, 90, 90, 89, 88,
87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, 86, 87, 88, 88, 88,
89, 89, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91,
90, 90, 90, 89, 89, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88,
90, 90, 91, 93, 93, 93, 93, 93, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89,
89, 89, 88, 87, 87, 87, 87, 87, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88,
89               );

        # shows start percentage, end percentage and count                   #
        PROC show range count = ( INT p start, p end, count )VOID:
             print( ( IF p start = 0 THEN "(" ELSE "[" FI
                    , whole( p start, -3 ), "% .. ", whole( p end, -3 ), "% "
                    , IF p end = 100 THEN "]" ELSE ")" FI, ": ", whole( count, 0 )
                    , newline ) );

        []INT counts = data COUNTCHANGESBYPERCENTAGE ranges;
        INT r start := 0;
        FOR i FROM LWB counts TO UPB counts - 1 DO
            show range count( r start, ranges[ i ], counts[ i ] );
            r start := ranges[ i ]
        OD;
        IF r start < 100 THEN show range count( r start, 100, counts[ UPB counts ] ) FI
    END
END
Output:
(  0% ..   4% ): 7
[  4% ..   8% ): 6
[  8% ..  12% ): 4
[ 12% ..  16% ): 2
[ 16% ..  25% ): 2
[ 25% .. 100% ]: 0

DuckDB

Works with: DuckDB version V1.1
Works with: DuckDB version V1.0

Some possible points of interest:

  • the use of regexp_extract_all() for parsing and of unnest() for creating a column vector
  • the use of lag() and sum() for identifying the subsequences

Note also that intermediate tables are retained to facilitate understanding and reuse but are inessential.

The input as shown in the problem description is assumed to be in a text file named `input.txt`. The program will actually parse the input for all non-negative integers quite flexibly.

# The data
create or replace table sequence as (
 select row_number() over () as id, c::INTEGER as c 
 from (select unnest(regexp_extract_all(content, '[0-9]+') ) as c
       from read_text('input.txt') )
);

# The buckets
create or replace function bucketize(value) as (
  case
    when value <= 0 then NULL
    when value <= 4 then   4
    when value < 8  then   8
    when value < 12 then  12
    when value < 16 then  16
    when value < 25 then  25
    else 100
  end
);

# Add a flag to signal the start of a new subsequence, and then form partitions
create or replace table partitions as (
  select *, sum(flag) over (order by id) as partition_number
  from (select *, if(id=1 or (c > (lag(c) over ())), 1, 0) as flag
        from sequence)
);

# The classification
select histogram(decline) as buckets
from (select partition_number,
            bucketize( 100 * (max(c) - min(c)) / max(c)) as decline
      from partitions
      group by partition_number);
Output:
┌──────────────────────────────┐
│           buckets            │
│    map(integer, ubigint)     │
├──────────────────────────────┤
│ {4=7, 8=6, 12=4, 16=2, 25=2} │
└──────────────────────────────┘

EasyLang

Translation of: Julia
global seq[] .
proc read . .
   repeat
      s$ = input
      until s$ = ""
      for e in number strsplit s$ ","
         seq[] &= e
      .
   .
.
read
func[] percdesc a[] .
   init = a[1]
   prev = init
   for i = 2 to len a[]
      if a[i] > prev
         if prev <> init
            percents[] &= 100 * (init - prev) / init
         .
         prev = a[i]
         init = a[i]
      else
         prev = a[i - 1]
      .
   .
   return percents[]
.
bin[] = [ 4 8 12 16 25 101 ]
func[] countbins percents[] .
   len cnts[] len bin[]
   for p in percents[]
      i = 1
      while p >= bin[i]
         i += 1
      .
      cnts[i] += 1
   .
   return cnts[]
.
print countbins percdesc seq[]
# 
input_data
90, 90, 90, 91, 91, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 89, 88, 87, 87, 87, 86, 86, 86, 85, 85,
86, 86, 87, 87, 88, 89, 89, 89, 90, 90, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 91, 90,
90, 90, 90, 90, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89,
89, 90, 90, 90, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 87, 88, 88, 88, 88, 88, 88, 88, 88,
88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 89,
89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88,
88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 87, 87, 87, 87, 86, 86, 86, 86,
86, 86, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89,
88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 89, 89, 91,
94, 94, 95, 96, 96, 96, 97, 97, 96, 96, 96, 96, 95, 95, 94, 93, 93, 92, 92, 91, 91, 90, 89, 89, 88,
86, 86, 85, 83, 83, 81, 80, 80, 80, 79, 79, 79, 78, 78, 79, 81, 82, 82, 85, 89, 89, 91, 93, 93, 94,
95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 93, 93, 93, 92, 92, 91, 91, 91, 90, 90, 90, 88,
87, 87, 86, 85, 85, 84, 84, 84, 83, 84, 84, 84, 85, 86, 86, 87, 87, 87, 88, 88, 88, 89, 90, 90, 90,
91, 91, 92, 92, 92, 93, 94, 94, 94, 95, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 90,
89, 89, 87, 86, 85, 85, 84, 83, 83, 82, 82, 82, 81, 81, 81, 81, 81, 81, 82, 85, 85, 86, 89, 89, 91,
92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 89, 89,
88, 88, 88, 87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 86, 87, 87, 87, 88, 88, 88, 88, 88, 88,
89, 89, 89, 89, 89, 89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 95, 95, 96, 96, 96, 95, 95,
95, 94, 94, 93, 93, 93, 92, 90, 90, 89, 87, 87, 87, 85, 83, 83, 82, 81, 81, 81, 80, 80, 81, 81, 81,
81, 81, 81, 81, 81, 81, 81, 81, 81, 83, 86, 88, 88, 90, 91, 91, 91, 92, 92, 93, 93, 93, 94, 95, 95,
95, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 94, 93, 93, 92, 92, 92, 91, 90, 90, 90, 90, 90,
91, 93, 93, 94, 94, 94, 94, 95, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 92, 92,
91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95,
95, 95, 95, 95, 94, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 91, 90, 90, 90, 89, 89, 89, 88, 88,
88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91,
91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 92,
92, 93, 93, 93, 93, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 88,
88, 87, 87, 87, 86, 86, 85, 85, 85, 86, 86, 86, 87, 87, 88, 88, 88, 89, 90, 90, 90, 91, 91, 91, 91,
91, 91, 91, 91, 91, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 90, 90, 90, 89, 88,
87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, 86, 87, 88, 88, 88,
89, 89, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91,
90, 90, 90, 89, 89, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88,
90, 90, 91, 93, 93, 93, 93, 93, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89,
89, 89, 88, 87, 87, 87, 87, 87, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88,
89
Output:
[ 7 6 4 2 2 0 ]

F#

// Decreasing contiguous subsequences. Nigel Galloway: September 6th., 2024
let data=[90; 90; 90; 91; 91; 92; 92; 92; 91; 91; 91; 90; 90; 90; 89; 89; 88; 87; 87; 87; 86; 86; 86; 85; 85;86; 86; 87; 87; 88; 89; 89; 89; 90; 90; 91; 91; 91; 92; 92; 92; 92; 92; 92; 92; 92; 92; 91; 91; 90;90; 90; 90; 90; 89; 89; 89; 89; 88; 88; 88; 88; 88; 88; 88; 88; 88; 88; 88; 88; 89; 89; 89; 89; 89;89; 90; 90; 90; 89; 89; 89; 89; 89; 89; 88; 88; 88; 88; 88; 88; 87; 88; 88; 88; 88; 88; 88; 88; 88;88; 88; 88; 88; 88; 88; 88; 88; 88; 88; 88; 88; 88; 89; 89; 89; 89; 89; 88; 88; 88; 88; 88; 88; 89;89; 89; 89; 89; 89; 89; 89; 88; 88; 88; 88; 88; 88; 88; 88; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87;87; 87; 88; 88; 88; 88; 88; 88; 88; 88; 88; 89; 89; 89; 89; 89; 89; 89; 88; 88; 88; 88; 88; 88; 88;88; 88; 88; 88; 89; 89; 89; 89; 89; 89; 89; 89; 89; 89; 88; 88; 88; 87; 87; 87; 87; 86; 86; 86; 86;86; 86; 87; 87; 87; 87; 87; 87; 87; 88; 88; 88; 88; 88; 88; 88; 88; 88; 89; 89; 89; 89; 89; 89; 89;88; 88; 88; 88; 88; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 89; 89; 91;94; 94; 95; 96; 96; 96; 97; 97; 96; 96; 96; 96; 95; 95; 94; 93; 93; 92; 92; 91; 91; 90; 89; 89; 88;86; 86; 85; 83; 83; 81; 80; 80; 80; 79; 79; 79; 78; 78; 79; 81; 82; 82; 85; 89; 89; 91; 93; 93; 94;95; 95; 95; 95; 95; 95; 95; 95; 95; 94; 94; 94; 94; 93; 93; 93; 92; 92; 91; 91; 91; 90; 90; 90; 88;87; 87; 86; 85; 85; 84; 84; 84; 83; 84; 84; 84; 85; 86; 86; 87; 87; 87; 88; 88; 88; 89; 90; 90; 90;91; 91; 92; 92; 92; 93; 94; 94; 94; 95; 95; 95; 95; 94; 94; 94; 93; 93; 93; 92; 92; 92; 91; 91; 90;89; 89; 87; 86; 85; 85; 84; 83; 83; 82; 82; 82; 81; 81; 81; 81; 81; 81; 82; 85; 85; 86; 89; 89; 91;92; 93; 93; 93; 94; 94; 94; 94; 94; 94; 94; 94; 94; 93; 93; 93; 92; 92; 92; 91; 91; 91; 90; 89; 89;88; 88; 88; 87; 87; 87; 86; 86; 86; 85; 85; 85; 85; 85; 85; 86; 87; 87; 87; 88; 88; 88; 88; 88; 88;89; 89; 89; 89; 89; 89; 90; 90; 90; 90; 91; 91; 92; 93; 93; 94; 94; 95; 95; 95; 96; 96; 96; 95; 95;95; 94; 94; 93; 93; 93; 92; 90; 90; 89; 87; 87; 87; 85; 83; 83; 82; 81; 81; 81; 80; 80; 81; 81; 81;81; 81; 81; 81; 81; 81; 81; 81; 81; 83; 86; 88; 88; 90; 91; 91; 91; 92; 92; 93; 93; 93; 94; 95; 95;95; 96; 96; 96; 96; 96; 96; 96; 95; 95; 95; 95; 95; 94; 93; 93; 92; 92; 92; 91; 90; 90; 90; 90; 90;91; 93; 93; 94; 94; 94; 94; 95; 94; 94; 94; 94; 94; 94; 93; 93; 93; 93; 93; 93; 92; 92; 92; 92; 92;91; 91; 91; 91; 91; 91; 91; 91; 90; 90; 90; 90; 90; 90; 90; 90; 89; 89; 89; 89; 89; 89; 89; 89; 89;89; 90; 90; 90; 90; 91; 91; 92; 93; 93; 93; 94; 94; 94; 94; 94; 94; 94; 94; 94; 95; 95; 95; 95; 95;95; 95; 95; 95; 94; 93; 93; 93; 93; 93; 92; 92; 92; 91; 91; 91; 91; 90; 90; 90; 89; 89; 89; 88; 88;88; 88; 88; 88; 88; 88; 88; 89; 89; 89; 89; 90; 90; 90; 90; 90; 90; 90; 90; 90; 90; 91; 91; 91; 91;91; 91; 91; 91; 91; 91; 91; 91; 91; 91; 90; 90; 90; 90; 90; 90; 90; 90; 90; 90; 90; 90; 90; 91; 92;92; 93; 93; 93; 93; 94; 94; 94; 93; 93; 93; 93; 93; 93; 92; 92; 92; 91; 91; 91; 90; 90; 90; 89; 88;88; 87; 87; 87; 86; 86; 85; 85; 85; 86; 86; 86; 87; 87; 88; 88; 88; 89; 90; 90; 90; 91; 91; 91; 91;91; 91; 91; 91; 91; 92; 92; 92; 93; 93; 93; 93; 93; 93; 93; 92; 92; 92; 91; 91; 90; 90; 90; 89; 88;87; 87; 87; 86; 86; 86; 85; 85; 85; 85; 85; 85; 85; 85; 85; 85; 85; 86; 86; 86; 86; 87; 88; 88; 88;89; 89; 90; 91; 91; 92; 93; 93; 93; 94; 94; 94; 94; 94; 94; 94; 94; 94; 93; 93; 93; 92; 92; 92; 91;90; 90; 90; 89; 89; 88; 88; 88; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 87; 88; 88; 88;90; 90; 91; 93; 93; 93; 93; 93; 94; 93; 93; 93; 93; 93; 93; 92; 92; 92; 91; 91; 91; 90; 90; 90; 89;89; 89; 88; 87; 87; 87; 87; 87; 86; 87; 87; 87; 87; 87; 87; 87; 87; 87; 88; 88; 88; 88; 88; 88; 88;89]
type cat=LT4 |LT8 |LT12 |LT16 |LT25 |GT25 
let cat=function n when n<4.0->LT4 |n when n<8.0->LT8 |n when n<12.0->LT12 |n when n<16.0->LT16 |n when n<25.0->LT25 |_->GT25
let t1=data|>List.pairwise|>List.filter(fun(n,g)->g<>n)|>List.filter(fun(n,g)->(n>g))
let n,g=t1|>List.pairwise |>List.filter(fun((_,n),(g,_))->n<g)|>List.unzip
let res=List.map2(fun(n,_)(_,g)->100.0-(((float g)/(float n))*100.0)) (t1.Head::g) (n@[t1|>List.last])|>List.countBy cat|>List.sortBy fst
printfn "%A" res
Output:
[(LT4, 7); (LT8, 6); (LT12, 4); (LT16, 2); (LT25, 2)]

FreeBASIC

Translation of: ALGOL 68
' Define the Sequence structure
Type Sequence
    startIndex As Integer
    endIndex As Integer
End Type

Dim As Integer datos(900) = { _
90, 90, 90, 91, 91, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 89, 88, 87, 87, 87, _
86, 86, 86, 85, 85, 86, 86, 87, 87, 88, 89, 89, 89, 90, 90, 91, 91, 91, 92, 92, _
92, 92, 92, 92, 92, 92, 92, 91, 91, 90, 90, 90, 90, 90, 89, 89, 89, 89, 88, 88, _
88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 90, 90, 90, 89, _
89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 87, 88, 88, 88, 88, 88, 88, 88, 88, _
88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 88, 88, _
88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, _
87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, _
88, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, _
89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 87, 87, 87, 87, 86, 86, 86, 86, _
86, 86, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, _
89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, _
87, 87, 87, 87, 87, 87, 87, 89, 89, 91, 94, 94, 95, 96, 96, 96, 97, 97, 96, 96, _
96, 96, 95, 95, 94, 93, 93, 92, 92, 91, 91, 90, 89, 89, 88, 86, 86, 85, 83, 83, _
81, 80, 80, 80, 79, 79, 79, 78, 78, 79, 81, 82, 82, 85, 89, 89, 91, 93, 93, 94, _
95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 93, 93, 93, 92, 92, 91, 91, _
91, 90, 90, 90, 88, 87, 87, 86, 85, 85, 84, 84, 84, 83, 84, 84, 84, 85, 86, 86, _
87, 87, 87, 88, 88, 88, 89, 90, 90, 90, 91, 91, 92, 92, 92, 93, 94, 94, 94, 95, _
95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 90, 89, 89, 87, 86, 85, _
85, 84, 83, 83, 82, 82, 82, 81, 81, 81, 81, 81, 81, 82, 85, 85, 86, 89, 89, 91, _
92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, _
91, 91, 90, 89, 89, 88, 88, 88, 87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, _
86, 87, 87, 87, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 90, 90, 90, 90, _
91, 91, 92, 93, 93, 94, 94, 95, 95, 95, 96, 96, 96, 95, 95, 95, 94, 94, 93, 93, _
93, 92, 90, 90, 89, 87, 87, 87, 85, 83, 83, 82, 81, 81, 81, 80, 80, 81, 81, 81, _
81, 81, 81, 81, 81, 81, 81, 81, 81, 83, 86, 88, 88, 90, 91, 91, 91, 92, 92, 93, _
93, 93, 94, 95, 95, 95, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 94, 93, _
93, 92, 92, 92, 91, 90, 90, 90, 90, 90, 91, 93, 93, 94, 94, 94, 94, 95, 94, 94, _
94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 92, 92, 91, 91, 91, 91, 91, _
91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 89, 89, 89, 89, 89, 89, 89, 89, 89, _
89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, _
95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, _
91, 91, 90, 90, 90, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, _
89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, _
91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 92, _
92, 93, 93, 93, 93, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, _
90, 90, 90, 89, 88, 88, 87, 87, 87, 86, 86, 85, 85, 85, 86, 86, 86, 87, 87, 88, _
88, 88, 89, 90, 90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 92, 92, 92, 93, 93, _
93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 90, 90, 90, 89, 88, 87, 87, 87, 86, 86, _
86, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, 86, 87, 88, 88, 88, _
89, 89, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, _
93, 92, 92, 92, 91, 90, 90, 90, 89, 89, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, _
87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 90, 90, 91, 93, 93, 93, 93, 93, 94, 93, _
93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 89, 89, 88, 87, 87, _
87, 87, 87, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, _
89 }
Dim ranges(4) As Integer = {4, 8, 12, 16, 25}
Dim counts(Lbound(ranges) To Ubound(ranges) + 1) As Integer

' Function to get the next non-ascending Sequence
Function nextSequence(datos() As Integer, prev As Sequence) As Sequence
    Dim As Integer sPos, ePos, value
    sPos = prev.endIndex + 1
    If sPos > Ubound(datos) Then
        Return Type<Sequence>(sPos, Ubound(datos))
    Else
        value = datos(sPos)
        ePos = sPos + 1
        While ePos <= Ubound(datos) Andalso datos(ePos) <= value
            value = datos(ePos)
            ePos += 1
        Wend
        Return Type<Sequence>(sPos, ePos - 1)
    End If
End Function

' Function to get the first non-ascending Sequence
Function firstSequence(datos() As Integer) As Sequence
    If Lbound(datos) > Ubound(datos) Then
        Return Type<Sequence>(Lbound(datos), Ubound(datos))
    Else
        Return nextSequence(datos(), Type<Sequence>(-1, Lbound(datos) - 1))
    End If
End Function

' Subroutine to count the non-ascending Sequence by percentage change
Sub countChangesByPercentage(datos() As Integer, ranges() As Integer, counts() As Integer)
    Dim prev As Sequence = firstSequence(datos())
    While prev.endIndex >= prev.startIndex
        If prev.endIndex > prev.startIndex Then
            Dim As Double change = ((datos(prev.startIndex) - datos(prev.endIndex)) / datos(prev.startIndex)) * 100
            If change > 0 Then
                For i As Integer = Lbound(counts) To Ubound(counts)
                    If ranges(i) > change Then
                        counts(i) += 1
                        Exit For
                    End If
                Next
                If change > ranges(Ubound(ranges)) Then counts(Ubound(counts)) += 1
            End If
        End If
        prev = nextSequence(datos(), prev)
    Wend
End Sub

' Procedure to show the range count
Sub showRangeCount(pStart As Integer, pEnd As Integer, cnt As Integer)
    Print Using "! ##_% .. ###_% ! : &"; (Iif(pStart = 0, "(", "[")); pStart; pEnd; Iif(pEnd = 100, "]", ")"); cnt
End Sub

' Main program
countChangesByPercentage(datos(), ranges(), counts())
Dim As Integer i, start
start = 0
For i = Lbound(counts) To Ubound(counts) - 1
    showRangeCount(start, ranges(i), counts(i))
    start = ranges(i)
Next
If start < 100 Then showRangeCount(start, 100, counts(Ubound(counts)))

Sleep
Output:
Same as ALGOL 68 entry.

jq

Works with jq, the C implementation of jq

Works with jaq, the Rust implementation of jq

Works with gojq, the Go implementation of jq

To save space, this entry supposes that the list of values is provided as input to the program as a JSON array -- see the Wren entry, for example, for its presentation as such.

Also to save space, the output is shown as a JSON object corresponding in the obvious way to the categorization specified in the task description.

### Generic functions
# bag of words
def bow(stream): 
  reduce stream as $word ({}; .[($word|tostring)] += 1);

# Input: a nonempty array of non-increasing non-negative integers 
# Output: the overall percentage decrease
def percentageDecrease:
  if .[0] == 0
  then 0
  else 100 - ((.[-1] / .[0]) * 100)
  end;

# Input: an array
# Emit a stream of maximal non-increasing subsequences, include singletons
def maximal_nonincreasing_subsequences:
  foreach (.[], null) as $x ({subsequence: []};
     .emit = null
     | if $x == null
       then if (.subsequence|length) > 0 then .emit = .subsequence
            else empty
            end
       elif (.subsequence | length) == 0 or  $x <= .subsequence[-1]
       then .subsequence += [$x]
       else if (.subsequence | length) > 0
            then .emit = .subsequence
            end
       | .subsequence = [$x]
       end )
   | select(.emit).emit;

# Classify the input numbers as per the implementation
def bucketize:
  if . <= 0 then empty
  elif . < 4 then "  4"
  elif . < 8 then "  8"
  elif . < 12 then " 12"
  elif . < 16 then " 16"
  elif . < 25 then " 25"
  else "100"
  end;

# Input: an array of non-negative numbers.
# Output: a JSON object that gives the classification of the maximal
# non-decreasing subsequences as per the task description
def classify:
  def zero: {"  4":0, "  8":0, " 12":0, " 16":0, " 25":0, "100": 0};
 
  bow(maximal_nonincreasing_subsequences
      | percentageDecrease
      | bucketize)
  | to_entries
  | zero + from_entries;

# The example:
classify

Invocation: jq -cf classify-decreasing-contiguous-subsequences.jq < input.json

Output:
{"  4":7,"  8":6," 12":4," 16":2," 25":2,"100":0}

Julia

const seq = [90, 90, 90, 91, 91, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 89, 88, 87, 87, 87, 86, 86, 86, 85, 85,
	86, 86, 87, 87, 88, 89, 89, 89, 90, 90, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 91, 90,
	90, 90, 90, 90, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89,
	89, 90, 90, 90, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 87, 88, 88, 88, 88, 88, 88, 88, 88,
	88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 89,
	89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
	87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88,
	88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 87, 87, 87, 87, 86, 86, 86, 86,
	86, 86, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89,
	88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 89, 89, 91,
	94, 94, 95, 96, 96, 96, 97, 97, 96, 96, 96, 96, 95, 95, 94, 93, 93, 92, 92, 91, 91, 90, 89, 89, 88,
	86, 86, 85, 83, 83, 81, 80, 80, 80, 79, 79, 79, 78, 78, 79, 81, 82, 82, 85, 89, 89, 91, 93, 93, 94,
	95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 93, 93, 93, 92, 92, 91, 91, 91, 90, 90, 90, 88,
	87, 87, 86, 85, 85, 84, 84, 84, 83, 84, 84, 84, 85, 86, 86, 87, 87, 87, 88, 88, 88, 89, 90, 90, 90,
	91, 91, 92, 92, 92, 93, 94, 94, 94, 95, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 90,
	89, 89, 87, 86, 85, 85, 84, 83, 83, 82, 82, 82, 81, 81, 81, 81, 81, 81, 82, 85, 85, 86, 89, 89, 91,
	92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 89, 89,
	88, 88, 88, 87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 86, 87, 87, 87, 88, 88, 88, 88, 88, 88,
	89, 89, 89, 89, 89, 89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 95, 95, 96, 96, 96, 95, 95,
	95, 94, 94, 93, 93, 93, 92, 90, 90, 89, 87, 87, 87, 85, 83, 83, 82, 81, 81, 81, 80, 80, 81, 81, 81,
	81, 81, 81, 81, 81, 81, 81, 81, 81, 83, 86, 88, 88, 90, 91, 91, 91, 92, 92, 93, 93, 93, 94, 95, 95,
	95, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 94, 93, 93, 92, 92, 92, 91, 90, 90, 90, 90, 90,
	91, 93, 93, 94, 94, 94, 94, 95, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 92, 92,
	91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 89, 89, 89, 89, 89, 89, 89, 89, 89,
	89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95,
	95, 95, 95, 95, 94, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 91, 90, 90, 90, 89, 89, 89, 88, 88,
	88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91,
	91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 92,
	92, 93, 93, 93, 93, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 88,
	88, 87, 87, 87, 86, 86, 85, 85, 85, 86, 86, 86, 87, 87, 88, 88, 88, 89, 90, 90, 90, 91, 91, 91, 91,
	91, 91, 91, 91, 91, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 90, 90, 90, 89, 88,
	87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, 86, 87, 88, 88, 88,
	89, 89, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91,
	90, 90, 90, 89, 89, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88,
	90, 90, 91, 93, 93, 93, 93, 93, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89,
	89, 89, 88, 87, 87, 87, 87, 87, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88,
	89]

function percentdescent(arr)
	percents = Float64[]
	initial = arr[begin]
	previous = initial
	for i in firstindex(arr)+1:lastindex(arr)
		if arr[i] > previous
			previous != initial && push!(percents, 100 * (initial - previous) / initial)
			previous = arr[i]
			initial = arr[i]
		else
			previous = arr[i-1]
		end
	end
	return percents
end

function countbins(percents, bins)
	counts = zeros(Int, length(bins)-1)
	for p in percents
		bin = findfirst(x -> p < x, bins)
		counts[bin-1] += 1
	end
	return counts
end

function test_decreasing(arr = seq, bins = [0, 4, 8, 12, 16, 25, 100])
	counts = countbins(percentdescent(arr), bins)
	println("  Bin         Count\n===================")
	for i in eachindex(counts)
		println("($(lpad(bins[i], 2))% - $(rpad(bins[i+1], 3))%]    ", counts[i])
	end
end

test_decreasing()
Output:
  Bin         Count
===================
( 0% - 4  %]    7
( 4% - 8  %]    6
( 8% - 12 %]    4
(12% - 16 %]    2
(16% - 25 %]    2
(25% - 100%]    0

PascalABC.NET

// Decreasing contiguous subsequences. Nigel Galloway: September 11th., 2024
var f: file of integer;
type Tcat=(LT4,LT8,LT12,LT25,GT25);
function cat(n:integer;g:integer):Tcat;
begin
  var t:=100-(g/n)*100;
  Result:=if t<4.0 then LT4 else if t<8.0 then LT8 else if t<12.0 then LT12 else if t<25.0 then LT25 else GT25;
end;
function fN(f:file of integer;n:integer;g:integer):sequence of Tcat;
begin
  if not eof(f) then begin
    var t:= f.read;
    if t<=g then begin yield sequence fN(f,n,t); exit; end;
    if n>g then yield cat(n,g);
    yield sequence fN(f,t,t);
    exit;
  end;
  if n>g then yield cat(n,g);
end;
begin
  assign(f,'test.dat');
  reset(f);
  var t:=f.read;
  print(fN(f,t,t).eachCount);
  close(f);
end.
Output:
{(LT8,6),(LT4,7),(LT25,4),(LT12,4)}

Phix

Translation of: Julia
with javascript_semantics
function percentdescent(sequence data)
    sequence percents = {}
    integer initial = data[1],
            previous = initial
    for d in data from 2 do
        if d > previous then
            if previous != initial then
                percents &= 100 * (initial - previous) / initial
            end if
            initial = d
        end if
        previous = d
    end for
    return percents
end function

function countbins(sequence percents, bins)
    sequence counts = repeat(0,length(bins)-1)
    for p in percents do
        integer bin = 1
        while p>=bins[bin+1] do bin += 1 end while
        counts[bin] += 1
    end for
    return counts
end function

procedure test_decreasing(sequence data, bins)
    sequence counts = countbins(percentdescent(data), bins)
    printf(1,"  Bin         Count\n===================\n")
    for i,c in counts do
        printf(1,"(%2d%% - %-3d%%]    %d\n",{bins[i], bins[i+1],c})
    end for
end procedure

constant data = {90, 90, 90, 91, 91, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 89, 88, 87, 87, 87, 86, 86, 86, 85, 85,
                 86, 86, 87, 87, 88, 89, 89, 89, 90, 90, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 91, 90,
                 90, 90, 90, 90, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89,
                 89, 90, 90, 90, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 87, 88, 88, 88, 88, 88, 88, 88, 88,
                 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 89,
                 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
                 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88,
                 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 87, 87, 87, 87, 86, 86, 86, 86,
                 86, 86, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89,
                 88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 89, 89, 91,
                 94, 94, 95, 96, 96, 96, 97, 97, 96, 96, 96, 96, 95, 95, 94, 93, 93, 92, 92, 91, 91, 90, 89, 89, 88,
                 86, 86, 85, 83, 83, 81, 80, 80, 80, 79, 79, 79, 78, 78, 79, 81, 82, 82, 85, 89, 89, 91, 93, 93, 94,
                 95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 93, 93, 93, 92, 92, 91, 91, 91, 90, 90, 90, 88,
                 87, 87, 86, 85, 85, 84, 84, 84, 83, 84, 84, 84, 85, 86, 86, 87, 87, 87, 88, 88, 88, 89, 90, 90, 90,
                 91, 91, 92, 92, 92, 93, 94, 94, 94, 95, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 90,
                 89, 89, 87, 86, 85, 85, 84, 83, 83, 82, 82, 82, 81, 81, 81, 81, 81, 81, 82, 85, 85, 86, 89, 89, 91,
                 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 89, 89,
                 88, 88, 88, 87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 86, 87, 87, 87, 88, 88, 88, 88, 88, 88,
                 89, 89, 89, 89, 89, 89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 95, 95, 96, 96, 96, 95, 95,
                 95, 94, 94, 93, 93, 93, 92, 90, 90, 89, 87, 87, 87, 85, 83, 83, 82, 81, 81, 81, 80, 80, 81, 81, 81,
                 81, 81, 81, 81, 81, 81, 81, 81, 81, 83, 86, 88, 88, 90, 91, 91, 91, 92, 92, 93, 93, 93, 94, 95, 95,
                 95, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 94, 93, 93, 92, 92, 92, 91, 90, 90, 90, 90, 90,
                 91, 93, 93, 94, 94, 94, 94, 95, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 92, 92,
                 91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 89, 89, 89, 89, 89, 89, 89, 89, 89,
                 89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95,
                 95, 95, 95, 95, 94, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 91, 90, 90, 90, 89, 89, 89, 88, 88,
                 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91,
                 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 92,
                 92, 93, 93, 93, 93, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 88,
                 88, 87, 87, 87, 86, 86, 85, 85, 85, 86, 86, 86, 87, 87, 88, 88, 88, 89, 90, 90, 90, 91, 91, 91, 91,
                 91, 91, 91, 91, 91, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 90, 90, 90, 89, 88,
                 87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, 86, 87, 88, 88, 88,
                 89, 89, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91,
                 90, 90, 90, 89, 89, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88,
                 90, 90, 91, 93, 93, 93, 93, 93, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89,
                 89, 89, 88, 87, 87, 87, 87, 87, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88,
                 89},
        bins = {0, 4, 8, 12, 16, 25, 100}

test_decreasing(data,bins)
Output:
  Bin         Count
===================
( 0% - 4  %]    7
( 4% - 8  %]    6
( 8% - 12 %]    4
(12% - 16 %]    2
(16% - 25 %]    2
(25% - 100%]    0

Python

"""Requires Python >= 3.10"""
import operator
from collections import Counter
from itertools import chain
from itertools import groupby
from itertools import pairwise
from typing import Iterable

# Example sequences is saved to data.py
from data import data

GROUPS = [
    (0, 4),
    (4, 8),
    (8, 12),
    (12, 16),
    (16, 25),
    (25, 100),
]


def decreasing_contiguous_subsequences(s: Iterable[int]) -> list[list[int]]:
    subsequences = [t for t in contiguous_subsequences(s) if not is_flat(t)]
    return [trim_plateaus(t) for t in subsequences]


def contiguous_subsequences(s: Iterable[int], op=operator.le) -> Iterable[list[int]]:
    it = iter(s)

    try:
        subsequence = [next(it)]
    except StopIteration:
        return

    for a, b in pairwise(it):
        if op(b, a):
            subsequence.append(b)
        else:
            yield subsequence
            subsequence = [b]


def is_flat(s: list[int]) -> bool:
    return len(s) < 2 or s[0] == s[-1]


def trim_plateaus(s: Iterable[int]) -> list[int]:
    groups = [(k, list(g)) for k, g in groupby(s)]

    if len(groups) < 2:
        return list(s)

    return (
        [groups[0][0]]
        + list(chain.from_iterable(g[1] for g in groups[1:-1]))
        + [groups[-1][0]]
    )


def percentage_change(s: list[int]) -> float:
    return 100 - ((s[-1] / s[0]) * 100)


def subsequence_group(s: list[int]) -> tuple[int, int]:
    change = percentage_change(s)
    for start, end in GROUPS:
        if change >= start and change < end:
            return (start, end)

    raise ValueError(f"subsequence out of range: {change}")


if __name__ == "__main__":
    subsequences = decreasing_contiguous_subsequences(data)
    dist = Counter(subsequence_group(s) for s in subsequences)

    for group in GROUPS:
        print(
            f"{group[0]}% - {group[1]}%".rjust(10),
            f"{dist[group]}",
        )
Output:
   0% - 4% 7
   4% - 8% 6
  8% - 12% 4
 12% - 16% 2
 16% - 25% 2
25% - 100% 0

Raku

Since these are percentages, no need to specify a span. The span is automatically 0-100. The carat in the bin ranges mean "upto, but not including".

my @values =
90, 90, 90, 91, 91, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 89, 88, 87, 87, 87, 86, 86, 86, 85, 85,
86, 86, 87, 87, 88, 89, 89, 89, 90, 90, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 91, 90,
90, 90, 90, 90, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89,
89, 90, 90, 90, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 87, 88, 88, 88, 88, 88, 88, 88, 88,
88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 89,
89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88,
88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 87, 87, 87, 87, 86, 86, 86, 86,
86, 86, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89,
88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 89, 89, 91,
94, 94, 95, 96, 96, 96, 97, 97, 96, 96, 96, 96, 95, 95, 94, 93, 93, 92, 92, 91, 91, 90, 89, 89, 88,
86, 86, 85, 83, 83, 81, 80, 80, 80, 79, 79, 79, 78, 78, 79, 81, 82, 82, 85, 89, 89, 91, 93, 93, 94,
95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 93, 93, 93, 92, 92, 91, 91, 91, 90, 90, 90, 88,
87, 87, 86, 85, 85, 84, 84, 84, 83, 84, 84, 84, 85, 86, 86, 87, 87, 87, 88, 88, 88, 89, 90, 90, 90,
91, 91, 92, 92, 92, 93, 94, 94, 94, 95, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 90,
89, 89, 87, 86, 85, 85, 84, 83, 83, 82, 82, 82, 81, 81, 81, 81, 81, 81, 82, 85, 85, 86, 89, 89, 91,
92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 89, 89,
88, 88, 88, 87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 86, 87, 87, 87, 88, 88, 88, 88, 88, 88,
89, 89, 89, 89, 89, 89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 95, 95, 96, 96, 96, 95, 95,
95, 94, 94, 93, 93, 93, 92, 90, 90, 89, 87, 87, 87, 85, 83, 83, 82, 81, 81, 81, 80, 80, 81, 81, 81,
81, 81, 81, 81, 81, 81, 81, 81, 81, 83, 86, 88, 88, 90, 91, 91, 91, 92, 92, 93, 93, 93, 94, 95, 95,
95, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 94, 93, 93, 92, 92, 92, 91, 90, 90, 90, 90, 90,
91, 93, 93, 94, 94, 94, 94, 95, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 92, 92,
91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 89, 89, 89, 89, 89, 89, 89, 89, 89,
89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95,
95, 95, 95, 95, 94, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 91, 90, 90, 90, 89, 89, 89, 88, 88,
88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91,
91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 92,
92, 93, 93, 93, 93, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 88,
88, 87, 87, 87, 86, 86, 85, 85, 85, 86, 86, 86, 87, 87, 88, 88, 88, 89, 90, 90, 90, 91, 91, 91, 91,
91, 91, 91, 91, 91, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 90, 90, 90, 89, 88,
87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, 86, 87, 88, 88, 88,
89, 89, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91,
90, 90, 90, 89, 89, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88,
90, 90, 91, 93, 93, 93, 93, 93, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89,
89, 89, 88, 87, 87, 87, 87, 87, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88,
89;

my @bins = 0^..^4, 4..^8, 8..^12, 12..^16, 16..^25, 25..100;

my @subseqs;

@values.map: {
    state $last = $_;
    state $incr = 0;
    ++$incr if $_ > $last;
    @subseqs[$incr].push: $_;
    $last = $_;
};

sub bin (@items, @bins, :&as) {
    my @classified;
    for @items {
        my $value = .&as;
        for @bins {
            state $index = 0;
            @classified[$index]++ if $value$_;
            ++$index;
        }
    }
    @classified
}

say "{.[0].gist}% : {.[1]}" for @bins Z flat @subseqs.&bin(@bins, :as{[R-] .minmax.bounds}), 0 xx *;
Output:
0^..^4% : 7
4..^8% : 6
8..^12% : 4
12..^16% : 2
16..^25% : 2
25..100% : 0

Rust

const SEQ: [i32; 901] = [
    90, 90, 90, 91, 91, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 89, 88, 87, 87, 87, 86, 86, 86, 85,
    85, 86, 86, 87, 87, 88, 89, 89, 89, 90, 90, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91,
    91, 90, 90, 90, 90, 90, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89,
    89, 89, 89, 89, 90, 90, 90, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 87, 88, 88, 88, 88,
    88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 88, 88,
    88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 87, 87, 87, 87,
    87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89,
    88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88,
    87, 87, 87, 87, 86, 86, 86, 86, 86, 86, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88,
    88, 88, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
    87, 87, 87, 87, 87, 87, 87, 89, 89, 91, 94, 94, 95, 96, 96, 96, 97, 97, 96, 96, 96, 96, 95, 95,
    94, 93, 93, 92, 92, 91, 91, 90, 89, 89, 88, 86, 86, 85, 83, 83, 81, 80, 80, 80, 79, 79, 79, 78,
    78, 79, 81, 82, 82, 85, 89, 89, 91, 93, 93, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94,
    94, 93, 93, 93, 92, 92, 91, 91, 91, 90, 90, 90, 88, 87, 87, 86, 85, 85, 84, 84, 84, 83, 84, 84,
    84, 85, 86, 86, 87, 87, 87, 88, 88, 88, 89, 90, 90, 90, 91, 91, 92, 92, 92, 93, 94, 94, 94, 95,
    95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 90, 89, 89, 87, 86, 85, 85, 84, 83, 83,
    82, 82, 82, 81, 81, 81, 81, 81, 81, 82, 85, 85, 86, 89, 89, 91, 92, 93, 93, 93, 94, 94, 94, 94,
    94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 89, 89, 88, 88, 88, 87, 87, 87, 86,
    86, 86, 85, 85, 85, 85, 85, 85, 86, 87, 87, 87, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89,
    90, 90, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 95, 95, 96, 96, 96, 95, 95, 95, 94, 94, 93, 93,
    93, 92, 90, 90, 89, 87, 87, 87, 85, 83, 83, 82, 81, 81, 81, 80, 80, 81, 81, 81, 81, 81, 81, 81,
    81, 81, 81, 81, 81, 83, 86, 88, 88, 90, 91, 91, 91, 92, 92, 93, 93, 93, 94, 95, 95, 95, 96, 96,
    96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 94, 93, 93, 92, 92, 92, 91, 90, 90, 90, 90, 90, 91, 93,
    93, 94, 94, 94, 94, 95, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 92, 92, 91,
    91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 89, 89, 89, 89, 89, 89, 89, 89, 89,
    89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95,
    95, 95, 95, 95, 95, 94, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 91, 90, 90, 90, 89, 89, 89,
    88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91,
    91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90,
    90, 90, 91, 92, 92, 93, 93, 93, 93, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91,
    90, 90, 90, 89, 88, 88, 87, 87, 87, 86, 86, 85, 85, 85, 86, 86, 86, 87, 87, 88, 88, 88, 89, 90,
    90, 90, 91, 91, 91, 91, 91, 91, 91, 91, 91, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 92, 92, 92,
    91, 91, 90, 90, 90, 89, 88, 87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
    86, 86, 86, 86, 87, 88, 88, 88, 89, 89, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94,
    94, 94, 93, 93, 93, 92, 92, 92, 91, 90, 90, 90, 89, 89, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87,
    87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 90, 90, 91, 93, 93, 93, 93, 93, 94, 93, 93, 93, 93, 93,
    93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 89, 89, 88, 87, 87, 87, 87, 87, 86, 87, 87, 87, 87,
    87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 89,
];

fn main() {
    const BIN: [i32; 7] = [0, 4, 8, 12, 16, 25, 100];
    let mut a = [0_i32; BIN.len()];
    let mut grade_percent: Vec<f64> = vec![];
    let (mut x, mut y) = (SEQ[0], SEQ[0]);
    for i in 1..SEQ.len() {
        if SEQ[i] > y {
            if x != y {
                grade_percent.push(100_f64 * (x - y) as f64 / x as f64);
            }
            (x, y) = (SEQ[i], SEQ[i]);
        } else {
            y = SEQ[i - 1];
        }
    }
    for g in grade_percent {
        a[(0..BIN.len() - 1).find(|i| g < BIN[*i] as f64).unwrap() - 1] += 1;
    }
    println!("  Interval   Count\n===================");
    for i in 0..BIN.len() - 1 {
        println!("({:>2}% - {:>3}%]    {}", BIN[i], BIN[i + 1], a[i]);
    }
}
Output:
  Interval   Count
===================
( 0% -   4%]    7
( 4% -   8%]    6
( 8% -  12%]    4
(12% -  16%]    2
(16% -  25%]    2
(25% - 100%]    0

Wren

Translation of: Python
Library: Wren-seq
Library: Wren-fmt
import "./seq" for Lst
import "./fmt" for Fmt

var data = [
    90, 90, 90, 91, 91, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 89, 88, 87, 87, 87, 86, 86, 86, 85, 85,
    86, 86, 87, 87, 88, 89, 89, 89, 90, 90, 91, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 91, 91, 90,
    90, 90, 90, 90, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89,
    89, 90, 90, 90, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 87, 88, 88, 88, 88, 88, 88, 88, 88,
    88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 89,
    89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87,
    87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 88, 88, 88, 88,
    88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, 88, 88, 88, 87, 87, 87, 87, 86, 86, 86, 86,
    86, 86, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 89, 89, 89,
    88, 88, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 89, 89, 91,
    94, 94, 95, 96, 96, 96, 97, 97, 96, 96, 96, 96, 95, 95, 94, 93, 93, 92, 92, 91, 91, 90, 89, 89, 88,
    86, 86, 85, 83, 83, 81, 80, 80, 80, 79, 79, 79, 78, 78, 79, 81, 82, 82, 85, 89, 89, 91, 93, 93, 94,
    95, 95, 95, 95, 95, 95, 95, 95, 95, 94, 94, 94, 94, 93, 93, 93, 92, 92, 91, 91, 91, 90, 90, 90, 88,
    87, 87, 86, 85, 85, 84, 84, 84, 83, 84, 84, 84, 85, 86, 86, 87, 87, 87, 88, 88, 88, 89, 90, 90, 90,
    91, 91, 92, 92, 92, 93, 94, 94, 94, 95, 95, 95, 95, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 90,
    89, 89, 87, 86, 85, 85, 84, 83, 83, 82, 82, 82, 81, 81, 81, 81, 81, 81, 82, 85, 85, 86, 89, 89, 91,
    92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 89, 89,
    88, 88, 88, 87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 86, 87, 87, 87, 88, 88, 88, 88, 88, 88,
    89, 89, 89, 89, 89, 89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 94, 94, 95, 95, 95, 96, 96, 96, 95, 95,
    95, 94, 94, 93, 93, 93, 92, 90, 90, 89, 87, 87, 87, 85, 83, 83, 82, 81, 81, 81, 80, 80, 81, 81, 81,
    81, 81, 81, 81, 81, 81, 81, 81, 81, 83, 86, 88, 88, 90, 91, 91, 91, 92, 92, 93, 93, 93, 94, 95, 95,
    95, 96, 96, 96, 96, 96, 96, 96, 95, 95, 95, 95, 95, 94, 93, 93, 92, 92, 92, 91, 90, 90, 90, 90, 90,
    91, 93, 93, 94, 94, 94, 94, 95, 94, 94, 94, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 92, 92,
    91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 89, 89, 89, 89, 89, 89, 89, 89, 89,
    89, 90, 90, 90, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 95, 95, 95, 95, 95,
    95, 95, 95, 95, 94, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 91, 90, 90, 90, 89, 89, 89, 88, 88,
    88, 88, 88, 88, 88, 88, 88, 89, 89, 89, 89, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 91, 91, 91,
    91, 91, 91, 91, 91, 91, 91, 91, 91, 91, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 91, 92,
    92, 93, 93, 93, 93, 94, 94, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89, 88,
    88, 87, 87, 87, 86, 86, 85, 85, 85, 86, 86, 86, 87, 87, 88, 88, 88, 89, 90, 90, 90, 91, 91, 91, 91,
    91, 91, 91, 91, 91, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 90, 90, 90, 89, 88,
    87, 87, 87, 86, 86, 86, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, 86, 86, 86, 86, 87, 88, 88, 88,
    89, 89, 90, 91, 91, 92, 93, 93, 93, 94, 94, 94, 94, 94, 94, 94, 94, 94, 93, 93, 93, 92, 92, 92, 91,
    90, 90, 90, 89, 89, 88, 88, 88, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88,
    90, 90, 91, 93, 93, 93, 93, 93, 94, 93, 93, 93, 93, 93, 93, 92, 92, 92, 91, 91, 91, 90, 90, 90, 89,
    89, 89, 88, 87, 87, 87, 87, 87, 86, 87, 87, 87, 87, 87, 87, 87, 87, 87, 88, 88, 88, 88, 88, 88, 88,
    89
]

var groups = [
    [0, 4],
    [4, 8],
    [8, 12],
    [12, 16],
    [16, 25],
    [25, 100]
]

var bb = ["()", "[)", "[)", "[)", "[)", "[]"]

var isFlat = Fn.new { |s| s.count < 2 || s[0] == s[-1] }

var percentageChange = Fn.new { |s| 100 - (s[-1] / s[0] * 100) }

// Assumes 'operator' is always less than or equal (<=).
var contiguousSubsequences = Fn.new { |s|
    var subsequences = []
    if (s.count == 0) return subsequences
    var subsequence = [s[0]]
    var i = 0
    while (i < s.count - 1) {
        if (s[i+1] <= s[i]) {
           subsequence.add(s[i+1])
        } else {
           subsequences.add(subsequence)
           subsequence = [s[i+1]]
        }
        i = i + 1
    }
    subsequences.add(subsequence)
    return subsequences
}

var trimPlateaus = Fn.new { |s|
    var indivs = Lst.individuals(s)
    var res = [indivs[0][0]]
    var i = 1
    while (i < indivs.count - 1) {
        for (j in 0...indivs[i][1]) res.add(indivs[i][0])
        i = i + 1
    }
    res.add(indivs[-1][0])
    return res    
}

var nonIncreasingContiguousSubsequences = Fn.new { |s|
    var subsequences = contiguousSubsequences.call(s).where { |t| !isFlat.call(t) }
    return subsequences.map { |t| trimPlateaus.call(t) }
}
     
// Returns the index of the relevant group rather than the group itself.
var subsequenceGroupsIndex = Fn.new { |s|
    var change = percentageChange.call(s)
    if (change == 100) return groups.count - 1
    for (i in 0...groups.count) {
        if (change >= groups[i][0] && change < groups[i][1]) return i
    }
    Fiber.abort("Subsequence out of range: %(change)")
}

var subsequences = nonIncreasingContiguousSubsequences.call(data)
var dist = List.filled(groups.count, 0)
for (s in subsequences) {
    var ix = subsequenceGroupsIndex.call(s)
    dist[ix] = dist[ix] + 1
}

for (i in 0...groups.count) {
    Fmt.print("$s$2d, $3d$s\% : $d", bb[i][0], groups[i][0], groups[i][1], bb[i][1], dist[i])
}
Output:
( 0,   4)% : 7
[ 4,   8)% : 6
[ 8,  12)% : 4
[12,  16)% : 2
[16,  25)% : 2
[25, 100]% : 0