Извлечение целочисленных подпоследовательностей, начинающихся с повторяющегося числа

Извлечение целочисленных подпоследовательностей, начинающихся с повторяющегося числа

У меня есть файл, содержащий один столбец целых чисел. Я хочу извлечь из этого файла список всех смежных подпоследовательностей (т. е. подпоследовательностей, идущих в последовательном порядке), которые начинаются с одного и того же числа дважды подряд и имеют длину 12 целых чисел (включая перекрывающиеся подпоследовательности).

Кроме того, все нецелочисленные строки в файле следует игнорировать/удалять, и если какая-либо последовательность достигает конца ввода до того, как будут достигнуты 12 целых чисел, то укороченная последовательность все равно должна быть выведена.

Например, предположим, что мой входной файл содержит следующие данные:

1
junk
1

1
2
3
4
4
5
6
7
8
9
10
11
12
13
14
15
15
16

Тогда решение должно выдать следующий результат:

1 1 1 2 3 4 4 5 6 7 8 9
1 1 2 3 4 4 5 6 7 8 9 10
4 4 5 6 7 8 9 10 11 12 13 14
15 15 16

Обратите внимание, что junkстрока и пустая строка игнорируются, поэтому первые три 1строки рассматриваются как смежные.

решение1

Вот скрипт на Python, который делает то, что вам нужно:

#!/usr/bin/env python2
# -*- coding: ascii -*-
"""extract_subsequences.py"""

import sys
import re

# Open the file
with open(sys.argv[1]) as file_handle:

    # Read the data from the file
    # Remove white-space and ignore non-integers
    numbers = [
        line.strip()
        for line in file_handle.readlines()
        if re.match("^\d+$", line) 
    ]

    # Set a lower bound so that we can output multiple lists
    lower_bound = 0
    while lower_bound < len(numbers)-1:

        # Find the "start index" where the same number
        # occurs twice at consecutive locations
        start_index = -1 
        for i in range(lower_bound, len(numbers)-1):
            if numbers[i] == numbers[i+1]:
                start_index = i
                break

        # If a "start index" is found, print out the two rows
        # values and the next 10 rows as well
        if start_index >= lower_bound:
            upper_bound = min(start_index+12, len(numbers))
            print(' '.join(numbers[start_index:upper_bound]))

            # Update the lower bound
            lower_bound = start_index + 1

        # If no "start index" is found then we're done
        else:
            break

Предположим, что ваши данные находятся в файле с именем data.txt. Тогда вы можете запустить этот скрипт следующим образом:

python extract_subsequences.py data.txt

Предположим, ваш входной файл data.txtвыглядит следующим образом:

1
1
1
2
3
4
5
6
7
8
9
10
11
12

Тогда ваш вывод будет выглядеть так:

1 1 1 2 3 4 5 6 7 8 9 10
1 1 2 3 4 5 6 7 8 9 10 11

Чтобы сохранить вывод в файл, используйте перенаправление вывода:

python extract_subsequences.py data.txt > output.txt

решение2

AWKподход:

Рассматриваются только впервые встреченные 2 одинаковых последовательных числа, т.е. это подходит для множественного извлечения, но без учета условия, что 2 одинаковых последовательных числа могут входить в следующую 10-числовую последовательность под одним обрабатываемым срезом.

awk 'NR==n && $1==v{ print v ORS $1 > "file"++c; tail=n+11; next }
     { v=$1; n=NR+1 }NR<tail{ print > "file"c }' file

решение3

Первый вариант - O(n)

awk '
/^[0-9]+$/{
    arr[cnt++] = $0;
}

END {
    for(i = 1; i < cnt; i++) {
        if(arr[i] != arr[i - 1])
            continue;

        last_element = i + 11; 
        for(j = i - 1; j < cnt && j < last_element; j++) {
            printf arr[j] " ";
        }
        print "";
    }
}' input.txt

Второй вариант - O(n * n)

awk '
BEGIN {
    cnt = 0;
}

/^[0-9]+$/{
    if(prev == $0) {
        arr[cnt] = prev;
        cnt_arr[cnt]++;
        cnt++;
    }
    
    for(i = 0; i < cnt; i++) {
        if(cnt_arr[i] < 12) {
            arr[i] = arr[i] " " $0; 
            cnt_arr[i]++;
        }
    }

    prev = $0;        
}

END {
    for(i = 0; i < cnt; i++)
        print arr[i];
}' input.txt

Выход

1 1 1 2 3 4 4 5 6 7 8 9
1 1 2 3 4 4 5 6 7 8 9 10
4 4 5 6 7 8 9 10 11 12 13 14
15 15 16

Связанный контент