Заменить комбинации символов - PullRequest
0 голосов
/ 18 сентября 2018

У меня есть строка 27AAGCB5913L2ZF. Если в строке появляются какие-либо из A или J или K, тогда мне нужно изменить их на все возможные комбинации трех букв. Если я передам введенный выше строковый ввод в программу, то результат должен быть таким:

27AAGCB5913L2ZF
27AJGCB5913L2ZF
27AKGCB5913L2ZF
27JAGCB5913L2ZF
27KAGCB5913L2ZF
27KJGCB5913L2ZF
27JKGCB5913L2ZF
27JJGCB5913L2ZF
27KKGCB5913L2ZF

Буквы могут присутствовать в любом месте строки. Если присутствует только одна буква, то она должна быть заменена на A, J и K по очереди. Например, вывод для строки 27ABGCB5913L2ZF должен быть следующим:

27ABGCB5913L2ZF
27JBGCB5913L2ZF
27kBGCB5913L2ZF

Я могу найти заданный символ с кодом, подобным этому

while ( $string =~ /(B)/g ) {
    say $1, ' at ', pos $string;
}

Как можно создать все возможные строки, если в любых позициях может быть любое число A, J или K?

Ответы [ 4 ]

0 голосов
/ 18 сентября 2018

Краткое решение:

Начните с разбиения строки на кортежи символов, которые могут появляться в каждой позиции

>>> s = "27AAGCB5913L2ZF"
>>> p2 = [("A","J","K") if c in "AJK" else (c,) for c in s]
>>> p2
[('2',), ('7',), ('A', 'J', 'K'), ('A', 'J', 'K'), ('G',), ('C',), ('B',), ('5',), ('9',), ('1',), ('3',), ('L',), ('2',), ('Z',), ('F',)]

Затем эта функция соберет список кортежей обратно в строку:

def assemble(t, s=''):
    if t:
        for c in t[0]:
            assemble(t[1:], s+c)
    else:
        print(s)

>>> assemble(p2)
27AAGCB5913L2ZF
27AJGCB5913L2ZF
27AKGCB5913L2ZF
27JAGCB5913L2ZF
27JJGCB5913L2ZF
27JKGCB5913L2ZF
27KAGCB5913L2ZF
27KJGCB5913L2ZF
27KKGCB5913L2ZF
0 голосов
/ 18 сентября 2018

Это можно сделать в Perl с помощью оператора glob.glob предназначен для поиска подходящих файлов, но если в шаблон не включены универсальные символы подстановки (*, ? или [...]), он просто вернет все возможные совпадения, независимо от того, существуют они в виде файлов или нет

Этот код Perl использует подстановку для формирования шаблона глоба, заменяя все вхождения A, J или K на множественный шаблон {A,J,K}.Отправка результата в glob дает нам необходимый вывод

use strict;
use warnings 'all';
use feature 'say';

for my $s ( qw/ 27AAGCB5913L2ZF 27KBGCB5913L2ZF / ) {

    (my $patt = $s) =~ s/[AJK]/{A,J,K}/g;

    say for glob $patt;
    say "";
}

output

27AAGCB5913L2ZF
27AJGCB5913L2ZF
27AKGCB5913L2ZF
27JAGCB5913L2ZF
27JJGCB5913L2ZF
27JKGCB5913L2ZF
27KAGCB5913L2ZF
27KJGCB5913L2ZF
27KKGCB5913L2ZF

27ABGCB5913L2ZF
27JBGCB5913L2ZF
27KBGCB5913L2ZF
0 голосов
/ 18 сентября 2018

Вот рекурсивное решение в Perl:

my $str = '27AAGCB5913L2ZF';
my @replace = qw (A J K);
print_string( $str);

sub print_string {
    my ( $str, $replace, $start) = @_;

    if (defined $replace) {
        substr( $str, $start, 1) = $replace;
    }
    else {
        $start = -1;
    }
    pos( $str) = $start +1;
    if ($str =~ /\G.*?(A|J|K)/g) {
        my $cur_start = $-[-1];
        print_string( $str, $_, $cur_start) for @replace;
    }
    else {
        say $str;
    }
}

выход

27AAGCB5913L2ZF
27AJGCB5913L2ZF
27AKGCB5913L2ZF
27JAGCB5913L2ZF
27JJGCB5913L2ZF
27JKGCB5913L2ZF
27KAGCB5913L2ZF
27KJGCB5913L2ZF
27KKGCB5913L2ZF
0 голосов
/ 18 сентября 2018

Набор комбинаций ваших ключевых букв A, J и K называется Декартово произведение . В Python вы можете использовать itertools.product для их генерации.

Во-первых, нам нужно найти позиции всех букв ключа во входной строке. Самый простой способ сделать это использует встроенный enumerate функция. Как только я узнаю эти позиции и сколько ключевых букв содержит строка, мы можем сгенерировать каждый элемент декартового произведения, заменить ключевые буквы и напечатать новую строку.

В Python строки являются неизменяемыми (их нельзя изменить), поэтому я преобразую строку в список символов, заменяю символы в ключевых позициях, а затем строю новую строку из списка, используя str.join Метод. * * тысяча двадцать-один

Следующий код будет работать с обеими версиями Python 2 и 3

Python

from itertools import product

def make_patterns(s):

    keyletters = 'AJK'

    # Convert input string into a list so we can easily substitute letters
    seq = list(s)

    # Find indices of key letters in seq
    indices = [ i for i, c in enumerate(seq) if c in keyletters ]

    # Generate key letter combinations & place them into the list
    for t in product(keyletters, repeat=len(indices)):
        for i, c in zip(indices, t):
            seq[i] = c
        print(''.join(seq))

# Test

data = (
    '1ABC2',
    '27AAGCB5913L2ZF',
    '3A4J',
    '5K67KA',
)

for s in data:
    print('\nInput:', s)
    make_patterns(s)

выход

Input: 1ABC2
1ABC2
1JBC2
1KBC2

Input: 27AAGCB5913L2ZF
27AAGCB5913L2ZF
27AJGCB5913L2ZF
27AKGCB5913L2ZF
27JAGCB5913L2ZF
27JJGCB5913L2ZF
27JKGCB5913L2ZF
27KAGCB5913L2ZF
27KJGCB5913L2ZF
27KKGCB5913L2ZF

Input: 3A4J
3A4A
3A4J
3A4K
3J4A
3J4J
3J4K
3K4A
3K4J
3K4K

Input: 5K67KA
5A67AA
5A67AJ
5A67AK
5A67JA
5A67JJ
5A67JK
5A67KA
5A67KJ
5A67KK
5J67AA
5J67AJ
5J67AK
5J67JA
5J67JJ
5J67JK
5J67KA
5J67KJ
5J67KK
5K67AA
5K67AJ
5K67AK
5K67JA
5K67JJ
5K67JK
5K67KA
5K67KJ
5K67KK

С небольшим изменением мы можем превратить нашу функцию в генератор. Это позволяет легко зацикливать выходные строки или превращать их в список, если хотите.

Python

from itertools import product

def make_patterns(s):

    keyletters = 'AJK'

    # Convert input string into a list so we can easily substitute letters
    seq = list(s)

    # Find indices of key letters in seq
    indices = [i for i, c in enumerate(seq) if c in keyletters]

    # Generate key letter combinations & place them into the list
    for t in product(keyletters, repeat=len(indices)):
        for i, c in zip(indices, t):
            seq[i] = c
        yield ''.join(seq)

# Test

print(list(make_patterns('A12K')))

for s in make_patterns('3KJ4'):
    print(s)

выход

['A12A', 'A12J', 'A12K', 'J12A', 'J12J', 'J12K', 'K12A', 'K12J', 'K12K']
3AA4
3AJ4
3AK4
3JA4
3JJ4
3JK4
3KA4
3KJ4
3KK4
...