كيفية التحقق مما إذا كانت التباديلات متساوية التكافؤ؟

StackOverflow https://stackoverflow.com/questions/1503072

سؤال

أنا أبحث عن وسيلة للتحقق إذا 2 التباديل (يمثلها قوائم) هي من نفس تعادل. وبعد لاحظ أنني لست مهتما إذا كانت حتى في أو غريب التكافؤ، فقط المساواة.

أنا جديد في بيثون وتردد الحل الساذج أدناه كرد. إنني أتطلع إلى Python Gurus تبين لي بعض الحيل الرائعة لتحقيق نفس الشيء في كود بيثون أقل وأكثر أناقة.

هل كانت مفيدة؟

المحلول

البديل البسيط للإجابة السابقة - نسخ بيرم 1، وحفظ البحث عن صفيف.

def arePermsEqualParity(perm0, perm1):
    """Check if 2 permutations are of equal parity.

    Assume that both permutation lists are of equal length
    and have the same elements. No need to check for these
    conditions.
    """
    perm1 = perm1[:] ## copy this list so we don't mutate the original

    transCount = 0
    for loc in range(len(perm0) - 1):                         # Do (len - 1) transpositions
        p0 = perm0[loc]
        p1 = perm1[loc]
        if p0 != p1:
            sloc = perm1[loc:].index(p0)+loc          # Find position in perm1
            perm1[loc], perm1[sloc] = p0, p1          # Swap in perm1
            transCount += 1

    # Even number of transpositions means equal parity
    if (transCount % 2) == 0:
        return True
    else:
        return False

نصائح أخرى

هنا هو قرصي من التعليمات البرمجية الخاصة بك

  • استخدم قائمة () لنسخ بيرم 1 - وهذا يعني أنه يمكنك تمرير tuples، إلخ في الوظيفة، مما يجعله أكثر عام
  • استخدام تعداد () في حلقة بدلا من Len (..) واختبئ الصفيف للحصول على رمز NEATER
  • قم بإجراء perm1_map واحتفظ بها حتى الآن لإيقاف البحث عن o (n) باهظة الثمن على بيرم 1، وقائمة قائمة باهظة الثمن
  • إرجاع المنطقي بشكل مباشر بدلا من إذا كنت ... عودة TRUE أخرى إرجاع خطأ

هاهو

def arePermsEqualParity(perm0, perm1):
    """Check if 2 permutations are of equal parity.

    Assume that both permutation lists are of equal length
    and have the same elements. No need to check for these
    conditions.
    """
    perm1 = list(perm1) ## copy this into a list so we don't mutate the original
    perm1_map = dict((v, i) for i,v in enumerate(perm1))
    transCount = 0
    for loc, p0 in enumerate(perm0):
        p1 = perm1[loc]
        if p0 != p1:
            sloc = perm1_map[p0]                       # Find position in perm1
            perm1[loc], perm1[sloc] = p0, p1           # Swap in perm1
            perm1_map[p0], perm1_map[p1] = sloc, loc   # Swap the map
            transCount += 1
    # Even number of transpositions means equal parity
    return (transCount % 2) == 0

إذا نجمعنا بين كلتا الشراءتين، فستكون النتيجة تكافؤا عندما يكون لكل التقليب نفس التكافؤ، والتكافؤ الفردي إذا كان لديهم تكافؤ مختلف. لذلك إذا نحل مشكلة التكافؤ انها تافهة لمقارنة شرحتين مختلفتين.

تعادل يمكن تحديدها على النحو التالي: اختيار عنصر تعسفي، ابحث عن الموضع الذي ينقله التقليب هذا، كرر حتى تعود إلى الشخص الذي بدأته به. لقد وجدت الآن دورة: إن التقليب يدور كل هذه العناصر جولة من موقع واحد. تحتاج إلى مبادلة واحدة أقل من عدد العناصر في الدورة إلى التراجع عنها. الآن اختيار عنصر آخر لم تعالجه بعد وكرر حتى ترى كل عنصر. لاحظ أنه في المجموع تحتاج إلى مبادلة واحدة لكل عنصر ناقص مبادلة واحدة لكل دورة.

تعقيد الوقت هو O (ن) في حجم التقليب. لاحظ أنه على الرغم من أن لدينا حلقة داخل حلقة، إلا أن الحلقة الداخلية يمكن أن تكرر مرة واحدة فقط لأي عنصر في التقليب.

def parity(permutation):
    permutation = list(permutation)
    length = len(permutation)
    elements_seen = [False] * length
    cycles = 0
    for index, already_seen in enumerate(elements_seen):
        if already_seen:
            continue
        cycles += 1
        current = index
        while not elements_seen[current]:
            elements_seen[current] = True
            current = permutation[current]
    return (length-cycles) % 2 == 0

def arePermsEqualParity(perm0, perm1):
    perm0 = list(perm0)
    return parity([perm0[i] for i in perm1])

أيضا، للمتعة فقط، وهنا تطبيق أقل كفاءة ولكن أقصر بكثير لوظيفة التكافؤ بناء على التعريف في ويكيبيديا (عودة TRUE حتى وكاذبة من أجل غريبة):

def parity(p):
    return sum(
        1 for (x,px) in enumerate(p)
          for (y,py) in enumerate(p)
          if x<y and px>py
        )%2==0

الحل الساغي:

def arePermsEqualParity(perm0, perm1):
    """Check if 2 permutations are of equal parity.

    Assume that both permutation lists are of equal length
    and have the same elements. No need to check for these
    conditions.
    """

    transCount = 0
    for loc in range(len(perm0) - 1):                         # Do (len - 1) transpositions
        if perm0[loc] != perm1[loc]:
            sloc = perm1.index(perm0[loc])                    # Find position in perm1
            perm1[loc], perm1[sloc] = perm1[sloc], perm1[loc] # Swap in perm1
            transCount += 1

    # Even number of transpositions means equal parity
    if (transCount % 2) == 0:
        return True
    else:
        return False

هنا أدعو قليلا إجابة weeble:

def arePermsEqualParity(perm0, perm1):
    """Whether permutations are of equal parity."""
    return parity(combine(perm0, perm1))

def combine(perm0, perm1):
    """Combine two permutations into one."""
    return map(perm0.__getitem__, perm1)

def parity(permutation):
    """Return even parity for the `permutation`."""
    return (len(permutation) - ncycles(permutation)) % 2 == 0

def ncycles(permutation):
    """Return number of cycles in the `permutation`."""
    ncycles = 0
    seen = [False] * len(permutation)
    for i, already_seen in enumerate(seen):
        if not already_seen:
            ncycles += 1
            # mark indices that belongs to the cycle
            j = i 
            while not seen[j]: 
                seen[j] = True
                j = permutation[j]
    return ncycles

الحل مع القاموس هو Bugged. هذا هو إصدار التصحيح:

def arePermsEqualParity(perm0, perm1):
    """Check if 2 permutations are of equal parity.

    Assume that both permutation lists are of equal length
    and have the same elements. No need to check for these
    conditions.
    """
    perm1 = list(perm1) ## copy this into a list so we don't mutate the original
    perm1_map = dict((v, i) for i,v in enumerate(perm1))
    transCount = 0
    for loc, p0 in enumerate(perm0):
        p1 = perm1[loc]
        if p0 != p1:
            sloc = perm1_map[p0]                       # Find position in perm1
            perm1[loc], perm1[sloc] = p0, p1           # Swap in perm1
            perm1_map[p0], perm1_map[p1] = loc, sloc   # Swap the map
            transCount += 1
    # Even number of transpositions means equal parity
    return (transCount % 2) == 0

الاختلافات الوحيدة هي أن المبادلة في القاموس لم تصنع بشكل صحيح.

أخبرني الحدس الخاص بي أنه، فقط عد الاختلافات بين الشراءتين ستمنحك أكثر من عدد المقايضات التي تحتاج إلى الوصول إليها من واحد إلى آخر. وهذا بدوره سوف يعطيك التكافؤ.

هذا يعني أنك لا تحتاج إلى القيام بمقايضات في التعليمات البرمجية الخاصة بك على الإطلاق.

علي سبيل المثال:

ABCD, BDCA.

هناك ثلاث اختلافات، وبالتالي هناك حاجة إلى اثنين من المبادلات للسماح بتحدث واحد في الآخر، وبالتالي لديك تكافؤ.

اخر:

ABCD, CDBA.

هناك أربع اختلافات، وبالتالي ثلاثة مقايضات، وبالتالي التكافؤ الفردي.

def equalparity(p,q):
    return sum([p[q[i]] > p[q[j]] for i in range(len(p)) for j in range(i)]) % 2 == 0
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top