স্ব-মিলের রেজেক্স [বন্ধ]


15

নিজের সাথে মেলে এমন একটি তুচ্ছ রেজেক্স লিখুন itself

উদাহরণস্বরূপ, #.*$পাইথনের লাইনের শেষ অবধি অজগরটির একটি স্ট্রিংয়ের বাইরে একটি মন্তব্যে মিলবে এবং পার্ল রেজেক্স সিনট্যাক্সেও নিজেকে মেলে।

বিধি :

  • নিয়মিত প্রকাশটি কার্যকর বা ব্যবহারিক কিছু করতে হবে।
  • আপনি কোন রেজেক্স সিনট্যাক্স ব্যবহার করছেন তা বলুন (যেমন পার্ল বা পোসিক্স)।
  • বিজয়ী হ'ল সর্বাধিক ভোটগ্রহণযোগ্য উত্তর।
  • সৃজনশীল হও!

6
একটি সময় আগে তাই একটা প্রশ্ন ছিল, একটি Regex যে বৈধ regexes ম্যাচ আছে কিনা: stackoverflow.com/questions/172303/...
প্যাট্রিক Oscity

5
অ-তুচ্ছ সংজ্ঞা দিন। মানে, ঠিক আছে, Aতুচ্ছ হবে, তবে আপনি রেখাটি কোথায় আঁকবেন? এবং "স্ব-ম্যাচিং" এর মাধ্যমে আপনি কী বোঝাতে চেয়েছেন এটি কেবল নিজের সাথেই মেলে, বা অন্য স্ট্রিংগুলির সাথেও এটি মেলানোর অনুমতি রয়েছে? চান .যোগ্যতা অর্জন?
মিস্টার লিস্টার

1
@ প্যাডে যা প্রকৃতপক্ষে একটি রেজেক্স ছিল না কারণ নিয়মিত প্রকাশের ব্যাকরণটি প্রসঙ্গমুক্ত।
FUZxxl

1
@FUZxxl হ্যাঁ, এটি সত্য তবে এখনও কেউ একটি রেইজেক্স লিখতে পারে যা অন্যান্য রেজেক্সের সাথে মিলে যায়, তবে ম্যাচ করা রেজেক্সসের বৈধতা সম্পর্কে তেমন যত্ন নেয় না।
প্যাট্রিক অসিটি

1
@ প্যাডে আচ্ছা, তাহলে একটি অবৈধ রেইগেক্স কী? একটি অবৈধ রেইজেক্স স্পষ্টতই একটি রেজেক্স নয়। সুতরাং আপনি মূলত বলবেন: "হ্যাঁ, এটি সত্য তবে একজন এখনও অন্য রেজেক্সের সাথে মিলে এমন একটি রেজেক্স লিখতে পারে, তবে ম্যাচ করা রেজেক্স সত্যই একটি রেজেক্স" (সিক!)
পরোয়া করে না

উত্তর:



11

পাইথন

নীচে একটি স্ব-ম্যাচিং রেজেক্স জেনারেটর রয়েছে। আপনি দুটি তালিকাগুলি সরবরাহ করেন, একটিতে ট্রেনিং ডেটা রয়েছে যা রেজেক্সের সাথে ম্যাচ করা উচিত (নিজের সাথে মিলে যাওয়ার পাশাপাশি), অন্যটিতে ট্রেনিং ডেটা রয়েছে যা রেজেক্সের সাথে মেলে না should

from random import choice, randrange
import re
from itertools import zip_longest, chain, islice
from operator import itemgetter

CHAR_SET = [chr(i) for i in range(128)] + [r"\\", r"\d", r"\D",
                                           r"\w", r"\W", r"\s",
                                           r"\S", r"?:", r"\1",
                                           r"\2", r"\A", r"\b",
                                           r"\B", r"\Z", r"\.",
                                           r"\[", r"\]", r"\(",
                                           r"\)", r"\{", r"\}",
                                           r"\+", r"\|", r"\?",
                                           r"\*"]

CHAR_SAMPLE = []
BREAKPOINT = re.compile(
    r"""
    \(.*?\)|
    \[.*?\]|
    \{.*?\}|
    \w+(?=[\(\[\{])?|
    \S+?|
    \.\*\??|
    \.\+\??|
    \.\?\??|
    \\.|
    .*?
    """,
    re.VERBOSE)

MATCH_BRACKETS = {'(': ')', '[': ']', '{': '}'}
CLOSE_BRACKETS = {')', ']', '}'}
REGEX_SEEDER = [
    r".*?",
    r"(?:.*?)",
    r"\w|\s",
    r"(?<.*?)",
    r"(?=.*?)",
    r"(?!.*?)",
    r"(?<=.*?)",
    r"(?<!.*?)",
    ]

LEN_LIMIT = 100

def distribute(distribution):
    global CHAR_SAMPLE
    for item in CHAR_SET:
        if item in distribution:
            CHAR_SAMPLE.extend([item] * distribution[item])
        else:
            CHAR_SAMPLE.append(item)

def rand_index(seq, stop=None):
    if stop is None:
        stop = len(seq)
    try:
        return randrange(0, stop)
    except ValueError:
        return 0

def rand_slice(seq):
    try:
        start = randrange(0, len(seq))
        stop = randrange(start, len(seq))
        return slice(start, stop)
    except ValueError:
        return slice(0,  0)


#Mutation Functions

def replace(seq):
    seq[rand_index(seq)] = choice(CHAR_SAMPLE)

def delete(seq):
    del seq[rand_index(seq)]

def insert(seq):
    seq.insert(rand_index(seq, len(seq) + 1), choice(CHAR_SAMPLE))

def duplicate(seq):
    source = rand_slice(seq)
    seq[source.stop: source.stop] = seq[source]

def swap(seq):
    if len(seq) < 2: return
    a = rand_index(seq, len(seq) - 1)
    seq[a], seq[a + 1] = seq[a + 1], seq[a]

dummy = lambda seq: None

MUTATE = (
    replace,
    delete,
    insert,
    duplicate,
    swap,
    dummy,
    dummy,
    )

def repair_brackets(seq):
    """Attempts to lower the percentage of invalid regexes by
    matching orphaned brackets"""

    p_stack, new_seq = [], []
    for item in seq:
        if item in MATCH_BRACKETS:
            p_stack.append(item)
        elif item in CLOSE_BRACKETS:
            while p_stack and MATCH_BRACKETS[p_stack[-1]] != item:
                new_seq.append(MATCH_BRACKETS[p_stack[-1]])
                p_stack.pop()
            if not p_stack:
                continue
            else:
                p_stack.pop()
        new_seq.append(item)
    while p_stack:
        new_seq.append(MATCH_BRACKETS[p_stack.pop()])
    return new_seq

def compress(seq):
    new_seq = [seq[0]]
    last_match = seq[0]
    repeat = 1
    for item in islice(seq, 1, len(seq)):
        if item == last_match:
            repeat += 1
        else:
            if repeat > 1:
                new_seq.extend(list("{{{0}}}".format(repeat)))
            new_seq.append(item)
            last_match = item
            repeat = 1
    else:
        if repeat > 1:
            new_seq.extend(list("{{{0}}}".format(repeat)))
    return new_seq


def mutate(seq):
    """Random in-place mutation of sequence"""
    if len(seq) > LEN_LIMIT:
        seq[:] = seq[:LEN_LIMIT]
    c = choice(MUTATE)
    c(seq)

def crossover(seqA, seqB):
    """Recombination of two sequences at optimal breakpoints
    along each regex strand"""

    bpA = [item.start() for item in BREAKPOINT.finditer(''.join(seqA))]
    bpB = [item.start() for item in BREAKPOINT.finditer(''.join(seqA))]
    slObjA = (slice(*item) for item in zip(bpA, bpA[1:]))
    slObjB = (slice(*item) for item in zip(bpB, bpB[1:]))
    slices = zip_longest(
        (seqA[item] for item in slObjA),
        (seqB[item] for item in slObjB),
        fillvalue=[]
        )
    recombinant = (choice(item) for item in slices)
    return list(chain.from_iterable(recombinant))

#Fitness testing

def match_percentage(match):
    """Calculates the percentage a text actually matched
    by a regular expression"""

    if match and match.endpos:
        return (match.end() - match.start()) / match.endpos
    else:
        return 0.001

def fitness_test(seq, pos_matches, neg_matches):
    """Scoring algorithm to determine regex fitness"""

    try:
        self_str = ''.join(seq)
        regex = re.compile(self_str)
    except (re.error, IndexError):
        seq[:] = repair_brackets(seq)
        try:
            self_str = ''.join(seq)
            regex = re.compile(self_str)
        except (re.error, IndexError):
            return 0.001

    pos_score = sum(match_percentage(regex.search(item))
                    for item in pos_matches) / len(pos_matches) / 3

    neg_score = (1 - sum(match_percentage(regex.search(item))
                    for item in neg_matches) / len(neg_matches)) / 3

    self_score = match_percentage(regex.search(self_str)) / 3

    return pos_score + self_score + neg_score

#Population Management

def generate_pop(pos_matches, neg_matches, pop_size):
    sources = (pos_matches, REGEX_SEEDER)
    return [crossover(
        choice(choice(sources)), choice(choice(sources))
        ) for i in range(pop_size)]

def glean_pop(population, cutoff, fit_test, ft_args=()):
    scores = (fit_test(bug, *ft_args) for bug in population)
    ranked = sorted(zip(population, scores), key=itemgetter(1), reverse=True)
    maxItem = ranked[0]
    new_pop = next(zip(*ranked))[:cutoff]
    return maxItem, new_pop

def repopulate(population, pop_size):
    cutoff = len(population)
    for i in range(pop_size // cutoff):
        population.extend([crossover(choice(population), choice(population))
                           for i in range(cutoff)])
    population.extend([population[i][:] for i in range(pop_size - len(population))])

#Simulator
def simulate(pos_matches, neg_matches, pop_size=50, cutoff=10, threshold=1.0):
    population = generate_pop(pos_matches, neg_matches, pop_size)
    while True:
        for bug in population:
            mutate(bug)

        #Scoring step
        max_item, population = glean_pop(
            population,
            cutoff,
            fitness_test,
            (pos_matches, neg_matches)
            )

        #Exit condition:
        max_regex, max_score = max_item
        if max_score >= threshold:
            return max_score, max_regex
        """
        print(max_score, ''.join(max_regex))
        input("next?")"""

        #Repopulation Step:
        population = list(population)
        repopulate(population, pop_size)

1
এটা কি পাইথন?
গ্রিফিন

1
@ জোয়েল কর্নেট আমার নিজস্ব simulateফাংশন লেখার ব্যবহারের অংশ? আপনার simulateফাংশন # 2 যুক্তি ব্যবহার করে না।
কেসি কুবাল

1
@ ডার্থফেট: আপনি ফাংশনটি কীভাবে ডাকবেন তার উদাহরণ এটি নয়। আমি পরিবর্তনশীল নামগুলি ব্যবহার করি যা তাদের (অনুমানমূলক) বিষয়বস্তুর বর্ণনামূলক ছিল। প্যারামিটার 2 সম্পর্কে আমার ভুল, এটি একটি টাইপ ছিল। no_matchনতুন নামকরণের কথা রয়েছে no_match_list। সম্পাদিত
জোয়েল করনেট

1
আপনি কেন কল করেন population = generate_pop(pos_matches, neg_matches, pop_size)তবে generate_popফাংশনটি কখনই neg_matchesপ্যারামিটারটি ব্যবহার করে না ? এছাড়াও, আপনি দয়া করে ফাংশন কল করার একটি উদাহরণ অন্তর্ভুক্ত করতে পারেন? আমি কি এটি কল করতে পারি simulate(["Hello","World","world"], ["woah","bad","dont match"])?
mbomb007

1
আরে, আমি এটি লেখার কয়েক বছর হয়ে গেল। কেবল কোডটি পরীক্ষা না করেই পড়া, দেখা যাচ্ছে যে হ্যাঁ, simulate()আপনি বর্ণিত হিসাবে ফাংশনটি কল করতে পারেন । এবং হ্যাঁ, আপনি ঠিক বলেছেন: আমি প্রাথমিক জনসংখ্যা তৈরির জন্য নেতিবাচক ডেটা ব্যবহার করি না।
জোয়েল করনেট

5

জাভাস্ক্রিপ্ট নিয়মিত প্রকাশ যা এর মতো স্টাফের সাথে মেলে।

/^\/\^\\\/\\\^[\\\[\]\/\^\${},\dd]{34}$/

আপনি এটির মতো পরীক্ষা করতে পারেন:

(function test() {
    var re =/^\/\^\\\/\\\^[\\\[\]\/\^\${},\dd]{34}$/;
    var m  =/=([^;]+)/.exec(test)[1];
    return re.exec(m);
})();

1
"এর মতো স্টাফ" কী? এটি কি কোনওভাবেই ব্যবহারিক বা কার্যকর?
কেসি কুবল

2
@ ডার্থফেট: এটি একই নিয়মিত অভিব্যক্তির সাথে মেলে যা নিজের এবং এই নিয়মিত প্রকাশের সাথে মেলে চেষ্টা করে। না, এটি কোনওভাবেই ব্যবহারিক বা কার্যকর নয়, তবে একমাত্র সম্ভাব্য ব্যবহারিক বা দরকারী, তবে আকর্ষণীয়, নিয়মিত প্রকাশ যা নিজের সাথে মেলে তা নিয়মিত প্রকাশের সাথে মেলে একটি নিয়মিত প্রকাশ। যা করা হয়েছে।
রাই-
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.