পাইথনে দুটি তালিকা বৃত্তাকারে অভিন্ন কিনা তা কীভাবে পরীক্ষা করবেন


145

উদাহরণস্বরূপ, আমার তালিকাগুলি রয়েছে:

a[0] = [1, 1, 1, 0, 0]
a[1] = [1, 1, 0, 0, 1]
a[2] = [0, 1, 1, 1, 0]
# and so on

এগুলি পৃথক বলে মনে হচ্ছে, তবে যদি মনে করা হয় যে শুরু এবং শেষটি সংযুক্ত রয়েছে, তবে তারা বৃত্তাকারে অভিন্ন।

সমস্যাটি হ'ল প্রতিটি তালিকার আমার দৈর্ঘ্য 55 টি এবং এতে কেবল তিনটি এবং 52 টি শূন্য রয়েছে। বিজ্ঞপ্তি শর্ত ব্যতীত, 26,235 (55 টি পছন্দ 3) তালিকা রয়েছে। তবে 'সার্কুলার' শর্তটি বিদ্যমান থাকলে প্রচুর পরিমাণে বিজ্ঞপ্তিযুক্ত অভিন্ন তালিকা রয়েছে

বর্তমানে আমি নিম্নলিখিত দ্বারা বৃত্তাকার পরিচয় পরীক্ষা:

def is_dup(a, b):
    for i in range(len(a)):
        if a == list(numpy.roll(b, i)): # shift b circularly by i
            return True
    return False

এই ফাংশনটির জন্য সবচেয়ে খারাপ ক্ষেত্রে 55 টি চক্রীয় শিফট অপারেশন প্রয়োজন। এবং একে অপরের সাথে তুলনা করার জন্য 26,235 টি তালিকা রয়েছে। সংক্ষেপে, আমার 55 * 26,235 * (26,235 - 1) / 2 = 18,926,847,225 গণনা প্রয়োজন। এটি প্রায় 20 গিগা!

কম গণনা সহ এটি করার কোনও ভাল উপায় আছে কি? বা কোন তথ্য টাইপ যা বিজ্ঞপ্তি সমর্থন করে ?


কেবল একটি কুঁচক: আমি অনুভব করি যে প্রত্যয় গাছগুলি এখানে সহায়তা করতে পারে। en.wikedia.org/wiki/Suffix_tree । এক নির্মাণ করতে, দেখতে en.wikipedia.org/wiki/Ukkonen%27s_algorithm
Rerito

1
@ মেহরদাদ কিন্তু কোনও জবাবের চেয়ে অনেক বেশি চলমান সময় যা একটি আধ্যাত্মিক রূপে রূপান্তরিত হয়, পূর্ণসংখ্যায় রূপান্তরিত হওয়ার চেয়ে চলমান সময় এবং ডেভিড আইজেনস্ট্যাট এর চেয়ে অনেক খারাপ চলমান সময়।
Veedrac

2
সমস্ত উত্তর সাধারণ সমস্যার সমাধান করার চেষ্টা করছে, তবে এই বিশেষ ক্ষেত্রে কেবল 3 টির সাথে আপনি প্রতিটি তালিকার 3 টি সংখ্যার সাথে প্রতিনিধিত্ব করতে পারেন যার মধ্যে একটি সংখ্যা হ'ল জিরো। প্রশ্ন থেকে তালিকাটি [0,0,2], [0,2,0], [2,0,0] হিসাবে উপস্থাপিত হতে পারে। আপনি কেবলমাত্র এক রানের মধ্যে তালিকা হ্রাস করতে পারেন এবং তারপরে হ্রাস তালিকাটি পরীক্ষা করতে পারেন। সেগুলি যদি "বৃত্তাকারে অভিন্ন" হয় তবে মূলগুলিও খুব বেশি।
abc667

1
আমার ধারণা স্ট্যাক ওভারফ্লো তখন ভোটদানের দরকার নেই। আমাদের কেবলমাত্র সমস্ত সমাধানগুলিতে কোড চালানো এবং সেগুলি শেষ করার ক্রমে তাদের উপস্থাপন করা দরকার।
দাউদ ইবনে করিম

2
যেহেতু এটা এতদূর উল্লেখ করা হয়েছে, "ক্যাননিকাল ফর্ম" @ abc667, Veedrac দ্বারা উল্লেখ করা, এবং Eisenstat রান দৈর্ঘ্য এনকোডিং বলা হয় en.wikipedia.org/wiki/Run-length_encoding
ডেভিড Lovell

উত্তর:


133

প্রথমে, O(n)তালিকার দৈর্ঘ্যের ক্ষেত্রে এটি করা যেতে পারে আপনি খেয়াল করতে পারেন যে আপনি যদি নিজের তালিকাটি 2 বার নকল করবেন ( [1, 2, 3]) [1, 2, 3, 1, 2, 3]তখন আপনার নতুন তালিকাটি অবশ্যই সম্ভাব্য সমস্ত চক্রীয় তালিকা ধারণ করবে।

সুতরাং আপনার যা যা দরকার তা হ'ল অনুসন্ধান করা তালিকাটি আপনার শুরুর তালিকার 2 বারের মধ্যে রয়েছে কিনা তা যাচাই করা উচিত। অজগরটিতে আপনি নিম্নলিখিত উপায়ে এটি অর্জন করতে পারেন (ধরে নিলে দৈর্ঘ্য একই)

list1 = [1, 1, 1, 0, 0]
list2 = [1, 1, 0, 0, 1]
print ' '.join(map(str, list2)) in ' '.join(map(str, list1 * 2))

আমার অনেলাইনার সম্পর্কে কিছু ব্যাখ্যা: list * 2নিজের সাথে একটি তালিকা একত্রিত করবে, map(str, [1, 2])সমস্ত সংখ্যাকে স্ট্রিংয়ে ' '.join()রূপান্তর করবে এবং অ্যারেটিকে ['1', '2', '111']একটি স্ট্রিংয়ে রূপান্তর করবে '1 2 111'

মন্তব্যগুলিতে কিছু লোকের নির্দেশ অনুসারে, অনেলাইনার সম্ভাব্য কয়েকটি ভ্রান্ত ইতিবাচক দিক দিতে পারে, তাই সম্ভাব্য সমস্ত প্রান্তের বিষয়গুলি কভার করার জন্য:

def isCircular(arr1, arr2):
    if len(arr1) != len(arr2):
        return False

    str1 = ' '.join(map(str, arr1))
    str2 = ' '.join(map(str, arr2))
    if len(str1) != len(str2):
        return False

    return str1 in str2 + ' ' + str2

পিএস 1 সময় জটিলতার কথা বলার সময়, এটি লক্ষ্য করার মতো যে O(n)যদি স্ট্রিংয়ের O(n)সময় পাওয়া যায় তবে এটি অর্জন করা উচিত । এটি সর্বদা এটি হয় না এবং এটি আপনার ভাষার প্রয়োগের উপর নির্ভর করে ( যদিও এটি সম্ভাব্য উদাহরণস্বরূপ রৈখিক সময়ের কেএমপিতে করা যেতে পারে )।

যারা স্ট্রিং অপারেশন করতে ভয় পান এবং এই সত্যের কারণে PS2 তাদের মনে হয় যে উত্তরটি ভাল নয়। জটিলতা এবং গতি কি গুরুত্বপূর্ণ। এই অ্যালগরিদম সম্ভাব্যভাবে O(n)সময় এবং O(n)স্পেসে চলে যা এটি O(n^2)ডোমেনের যে কোনও কিছুর চেয়ে অনেক ভাল করে তোলে । এটি নিজের দ্বারা দেখার জন্য, আপনি একটি ছোট বেঞ্চমার্ক চালাতে পারেন (একটি এলোমেলো তালিকা তৈরি করে প্রথম উপাদানটি পপ করে এবং এটিকে শেষের দিকে যুক্ত করে তোলে যাতে একটি চক্রীয় তালিকা তৈরি করে You আপনি নিজের নিজের হেরফেরগুলি করতে পারেন)

from random import random
bigList = [int(1000 * random()) for i in xrange(10**6)]
bigList2 = bigList[:]
bigList2.append(bigList2.pop(0))

# then test how much time will it take to come up with an answer
from datetime import datetime
startTime = datetime.now()
print isCircular(bigList, bigList2)
print datetime.now() - startTime    # please fill free to use timeit, but it will give similar results

আমার মেশিনে 0.3 সেকেন্ড সত্যিই দীর্ঘ নয়। O(n^2)সমাধানের সাথে এটির তুলনা করার চেষ্টা করুন । এটির তুলনা করার সময়, আপনি মার্কিন যুক্তরাষ্ট্র থেকে অস্ট্রেলিয়া ভ্রমণ করতে পারেন (সম্ভবত কোনও ক্রুজ জাহাজে করে)


3
কেবল প্যাডিং স্পেস যুক্ত করুন (প্রতিটি স্ট্রিংয়ের আগে 1 এবং 1) কৌশলটি করবে। রেজিক্সের সাহায্যে জিনিসগুলিকে অতিরিক্ত জটিল করার দরকার নেই। (অবশ্যই আমি ধরে নিচ্ছি যে আমরা একই দৈর্ঘ্যের তালিকাগুলির তুলনা করছি)
রেরিতো

2
@ রিরিটো যদি না হয় উভয় তালিকায় স্ট্রিং অন্তর্ভুক্ত থাকে, যার মধ্যে তারা নিজেরাই নেতৃত্বাধীন বা চলমান স্থান থাকতে পারে। এখনও সংঘর্ষের কারণ হতে পারে।
অ্যাডাম স্মিথ

12
আমি এই উত্তর পছন্দ করি না। স্ট্রিং অপারেশন বাজে কথা আমাকে এটিকে অপছন্দ করে এবং ডেভিড আইজেনস্ট্যাট এর উত্তর আমাকে এটিকে হ্রাস করতে ইচ্ছুক করে তোলে। এই তুলনা করতে একটি স্ট্রিং সঙ্গে হে (ঢ) সময় মধ্যে সম্পন্ন করা কিন্তু এটি একটি পূর্ণসংখ্যা সঙ্গে হে (ঢ) সময় করা যাবে [যেমন প্রয়োজন 10k স্ব-মোছা] যা দ্রুততর। যাইহোক, ডেভিড আইজেনস্ট্যাট এর উত্তর দেখায় যে কোনও তুলনা করা মোটেই অর্থহীন কারণ যেহেতু উত্তরটির প্রয়োজন নেই।
Veedrac

7
@ বিদ্রাক আপনি কি আমাকে মজা করছেন? আপনি গণনা জটিলতার কথা শুনেছেন? ডেভিডের উত্তরে তার সমস্ত পুনরাবৃত্তি উত্পন্ন করতে কেবল (এন ^ 2) সময় এবং ও (এন ^ 2) স্পেস লাগে যা ছোট ইনপুটগুলির জন্যও 10 ^ 4 দৈর্ঘ্য 22 সেকেন্ডের মতো লাগে এবং কে কতটা র্যাম জানেন। উল্লেখ করার দরকার নেই যে আমরা এখনই কোনও কিছুর সন্ধান শুরু করি নি (আমরা স্রেফ সমস্ত চক্রীয় ঘূর্ণন উত্পন্ন করেছি)। এবং আমার স্ট্রিং বাজে কথা আপনাকে 0.5 seconds সেকেন্ডেরও কম সময়ে 10 ^ 6 এর মতো ইনপুটগুলির জন্য একটি সম্পূর্ণ ফলাফল দেয়। এটি সঞ্চয় করতে এটি ও (এন) স্থানেরও প্রয়োজন। সুতরাং সিদ্ধান্তে ঝাঁপ দেওয়ার আগে দয়া করে উত্তরটি বুঝতে কিছু সময় দিন।
সালভাদোর ডালি

1
@ সালভাদোরডালি আপনি খুব (নরম) সময়কেন্দ্রিক বলে মনে করছেন ;-)
e2-e4

38

পাইথনে আপনার অনুরোধকৃত ভাষায় এর উত্তর দেওয়ার পক্ষে যথেষ্ট জ্ঞানহীন নয়, তবে সি / সি ++ এ আপনার প্রশ্নের প্যারামিটারগুলি দিয়ে আমি শূন্যগুলি এবং বিটগুলিকে রূপান্তরিত করে একটি uint64_t এর ন্যূনতম উল্লেখযোগ্য বিটগুলিতে ঠেলাচ্ছি push এটি আপনাকে এক ঝরনা - 1 ঘড়ির মধ্যে 55 টি বিটের তুলনা করতে দেয়।

দুর্ভাগ্যক্রমে দ্রুত এবং পুরো জিনিস অন চিপ ক্যাশে (209,880 বাইট) ফিট করবে। একই সাথে সমস্ত 55 তালিকা সদস্যকে স্থানান্তরিত করার জন্য হার্ডওয়্যার সমর্থন কেবলমাত্র সিপিইউ'র রেজিস্টারে উপলব্ধ। একই সাথে সমস্ত 55 সদস্যের তুলনা করা যায়। এটি সফ্টওয়্যার সমাধানে সমস্যার 1-for-1 ম্যাপিংয়ের অনুমতি দেয়। (এবং সিমডি / এসএসই 256 বিট রেজিস্টারগুলি ব্যবহার করা প্রয়োজন, 256 জন সদস্য প্রয়োজন হলে) ফলস্বরূপ কোডটি তাত্ক্ষণিকভাবে পাঠকের কাছে সুস্পষ্ট।

আপনি পাইথনে এটি বাস্তবায়ন করতে সক্ষম হতে পারেন, আমি এটি যথেষ্ট জানি না এটি সম্ভব কিনা বা পারফরম্যান্স কী হতে পারে তা জানার জন্য।

এটির পরে ঘুমানোর পরে কয়েকটি বিষয় সুস্পষ্ট হয়ে উঠল এবং সর্বোপরি ভাল।

1.) বিটগুলি ব্যবহার করে বিজ্ঞপ্তিযুক্ত লিঙ্কযুক্ত তালিকাকে স্পিন করা এত সহজ যে ডালির খুব চালাক কৌশলটি প্রয়োজনীয় নয়। একটি 64৪-বিট রেজিস্ট্রারের অভ্যন্তরে স্ট্যান্ডার্ড বিট শিফটিংটি খুব সহজেই আবর্তনটি সম্পন্ন করবে এবং বিট অপ্সের পরিবর্তে পাটিগণিত ব্যবহার করে আরও সমস্ত পাইথনকে বন্ধুত্বপূর্ণ করার প্রয়াসে।

২) বিট শিফটিংটি 2 দ্বারা ভাগ করে সহজেই সম্পাদন করা যায়।

৩) তালিকার শেষে 0 বা 1 এর জন্য চেক করা খুব সহজে মডুলো 2 দ্বারা করা যেতে পারে।

৪) লেজ থেকে তালিকার শীর্ষে a 0 এ "সরানো" ২ দ্বারা ভাগ করে করা যায় can এটি কারণ যদি শূন্যটি সরানো থাকে তবে এটি 55 তম বিটকে মিথ্যা করে দেবে, এটি ইতিমধ্যে সম্পূর্ণরূপে কিছুই না করে।

৫) লেজ থেকে তালিকার শীর্ষে "1" এ 1 মুভিং 2 দ্বারা ভাগ করে 18,014,398,509,481,984 যোগ করে করা যায় - যা 55 তম বিট সত্য এবং বাকীটি মিথ্যা চিহ্নিত করে তৈরি করা মান।

)) যদি কোনও অ্যাঙ্কর এবং রচনাযুক্ত uint64_t এর তুলনা যদি কোনও প্রদত্ত ঘোরাঘুরির পরে সত্য হয় তবে বিরতি দিন এবং সত্য প্রত্যাবর্তন করুন।

বার বার রূপান্তর না করতে এড়াতে আমি তালিকার পুরো অ্যারেটিকে সরাসরি uint64_ts এর অ্যারে রূপান্তর করব।

কোডটি অপ্টিমাইজ করার চেষ্টা করে কয়েক ঘন্টা ব্যয় করার পরে, এসেম্বলির ভাষা অধ্যয়ন করে আমি রানটাইম থেকে 20% শেভ করতে সক্ষম হয়েছি। আমার যুক্ত করা উচিত যে ও / এস এবং এমএসভিসি সংকলক গতকাল মধ্য-দিন আপডেট হয়েছিল। যে কোনও কারণেই হোক না কেন, সি সংকলক উত্পাদিত কোডের মান আপডেটের পরে (11/15/2014) নাটকীয়ভাবে উন্নত হয়েছিল। রান-টাইম এখন ~ 70 টি ঘড়ি, একটি পরীক্ষার রিংয়ের 55 টি টার্নের সাথে একটি অ্যাঙ্কর রিংটি রচনা এবং তুলনা করতে 17 ন্যানোসেকেন্ড এবং অন্য সকলের বিপরীতে সমস্ত রিংয়ের এনএক্সএন 12.5 সেকেন্ডে সম্পন্ন হয় ।

এই কোডটি এতই কঠোর তবে 4 টি রেজিস্ট্রার 99% সময় কিছু না করে বসে আছেন sitting সমাবেশ ভাষা লাইন জন্য প্রায় লাইন সি কোড মেলে। পড়তে ও বুঝতে খুব সহজ। একটি দুর্দান্ত সমাবেশ প্রকল্প যদি কেউ নিজেরাই তা শিখিয়ে থাকেন।

হার্ডওয়্যার হ্যাজওয়েল আই 7, এমএসভিসি 64-বিট, সম্পূর্ণ অপ্টিমাইজেশন।

#include "stdafx.h"
#include "stdafx.h"
#include <string>
#include <memory>
#include <stdio.h>
#include <time.h>

const uint8_t  LIST_LENGTH = 55;    // uint_8 supports full witdth of SIMD and AVX2
// max left shifts is 32, so must use right shifts to create head_bit
const uint64_t head_bit = (0x8000000000000000 >> (64 - LIST_LENGTH)); 
const uint64_t CPU_FREQ = 3840000000;   // turbo-mode clock freq of my i7 chip

const uint64_t LOOP_KNT = 688275225; // 26235^2 // 1000000000;

// ----------------------------------------------------------------------------
__inline uint8_t is_circular_identical(const uint64_t anchor_ring, uint64_t test_ring)
{
    // By trial and error, try to synch 2 circular lists by holding one constant
    //   and turning the other 0 to LIST_LENGTH positions. Return compare count.

    // Return the number of tries which aligned the circularly identical rings, 
    //  where any non-zero value is treated as a bool TRUE. Return a zero/FALSE,
    //  if all tries failed to find a sequence match. 
    // If anchor_ring and test_ring are equal to start with, return one.

    for (uint8_t i = LIST_LENGTH; i;  i--)
    {
        // This function could be made bool, returning TRUE or FALSE, but
        // as a debugging tool, knowing the try_knt that got a match is nice.
        if (anchor_ring == test_ring) {  // test all 55 list members simultaneously
            return (LIST_LENGTH +1) - i;
        }

        if (test_ring % 2) {    //  ring's tail is 1 ?
            test_ring /= 2;     //  right-shift 1 bit
            // if the ring tail was 1, set head to 1 to simulate wrapping
            test_ring += head_bit;      
        }   else    {           // ring's tail must be 0
            test_ring /= 2;     // right-shift 1 bit
            // if the ring tail was 0, doing nothing leaves head a 0
        }
    }
    // if we got here, they can't be circularly identical
    return 0;
}
// ----------------------------------------------------------------------------
    int main(void)  {
        time_t start = clock();
        uint64_t anchor, test_ring, i,  milliseconds;
        uint8_t try_knt;

        anchor = 31525197391593472; // bits 55,54,53 set true, all others false
        // Anchor right-shifted LIST_LENGTH/2 represents the average search turns
        test_ring = anchor >> (1 + (LIST_LENGTH / 2)); //  117440512; 

        printf("\n\nRunning benchmarks for %llu loops.", LOOP_KNT);
        start = clock();
        for (i = LOOP_KNT; i; i--)  {
            try_knt = is_circular_identical(anchor, test_ring);
            // The shifting of test_ring below is a test fixture to prevent the 
            //  optimizer from optimizing the loop away and returning instantly
            if (i % 2) {
                test_ring /= 2;
            }   else  {
                test_ring *= 2;
            }
        }
        milliseconds = (uint64_t)(clock() - start);
        printf("\nET for is_circular_identical was %f milliseconds."
                "\n\tLast try_knt was %u for test_ring list %llu", 
                        (double)milliseconds, try_knt, test_ring);

        printf("\nConsuming %7.1f clocks per list.\n",
                (double)((milliseconds * (CPU_FREQ / 1000)) / (uint64_t)LOOP_KNT));

        getchar();
        return 0;
}

এখানে চিত্র বর্ণনা লিখুন


23
লোকেরা "সালভাদোর ডালির সমাধান" সম্পর্কে কথা বলতে থাকে এবং আমি কেবল এখানে বিভ্রান্ত হয়ে বসে ছিলাম, ভাবছিলাম যে একই নামের চিত্রকটিও কোনও গণিতবিদ ছিলেন যিনি কিছু উল্লেখযোগ্য উপায়ে শাস্ত্রীয় অ্যালগরিদমে অবদান রেখেছিলেন? তখন আমি বুঝতে পারি যে সেই ব্যক্তির ব্যবহারকারীর নাম যা সবচেয়ে জনপ্রিয় উত্তর পোস্ট করেছে। আমি কোনও স্মার্ট মানুষ নই
উড্রো বার্লো

10 কে প্রতিনিধিত্বকারী এবং বাস্তবায়নের যে কারও জন্য নম্পি এবং ভেক্টরাইজেশন ব্যবহার করে এখানে উপলভ্যঐ <10k জন্য সারকথা আয়না । আমি আমার উত্তর মোছা কারণ ডেভিড Eisenstat এর উত্তর খুঁজে যে আপনার তুলনা করতে প্রয়োজন হবে না পয়েন্ট এ সব হিসাবে আপনি শুধু অনন্য তালিকা সোজা দূরে তৈরি করতে পারেন এবং আমি মানুষ তার অনেক ভালো উত্তর ব্যবহার করার জন্য উৎসাহিত করতে চাই।
Veedrac

@ রকেটরোয় আপনি কী ভাবেন যে পাইথনের বিট অপারেশন হবে না? হেক, আমি কোডটি সংযুক্ত করেছি তাতে বিট অপারেশনগুলি ব্যবহার করি । আমি এখনও মনে করি এই উত্তরটি বেশিরভাগই অনিবদ্ধ ( 262 এম- "তালিকাগুলি" অনুসন্ধানের জন্য নম্পির অনুরূপ অ্যালগরিদম এফডব্লিউআইডাব্লু আমার কম্পিউটারে প্রায় 15 সেকেন্ড লাগে (ধরে নিলেন কোনও মিল খুঁজে পাওয়া যায় নি), কেবল তালিকার আবর্তনটি বাইরের লুপে ঘটে, অভ্যন্তরীণটি নয়।
Veedrac

@ কুইনকুনাক্স, সি ++ এর জন্য সিনট্যাক্স রঙটি সঠিক করতে আপনার সম্পাদনার জন্য আপনাকে ধন্যবাদ। ব্যাপকভাবে প্রশংসা করেছিল!

পুনঃটুইট আপনি যখন পিপিসি- তে প্রচুর প্রশ্নের উত্তর দেন , আপনি সিনট্যাক্স রঙ কিভাবে করবেন তা শিখবেন।
জাস্টিন

33

লাইনের মধ্যে পড়া, মনে হচ্ছে আপনি 3 টি এবং 52 জিরো দিয়ে স্ট্রিংয়ের প্রতিটি বৃত্তাকার সমতুল্য শ্রেণির একজন প্রতিনিধি গণনা করার চেষ্টা করছেন। আসুন ঘন উপস্থাপনা থেকে একটি বিরল এক (তিনটি সংখ্যার সেট range(55)) এ পরিবর্তন করা যাক। এই প্রতিনিধিত্ব সালে, বিজ্ঞপ্তি শিফট sদ্বারা kধী দেওয়া হয় set((i + k) % 55 for i in s)। কোন ক্লাসে lexicographic ন্যূনতম প্রতিনিধি সবসময় অবস্থান 0. ফর্ম একটি সেট দেওয়া রয়েছে {0, i, j}সঙ্গে 0 < i < j, বর্গ ন্যূনতম জন্য অন্যান্য প্রার্থীদের {0, j - i, 55 - i}এবং {0, 55 - j, 55 + i - j}। সুতরাং, আমাদের (i, j) <= min((j - i, 55 - i), (55 - j, 55 + i - j))মূলটি ন্যূনতম হওয়া দরকার। এখানে কিছু গণনার কোড দেওয়া আছে।

def makereps():
    reps = []
    for i in range(1, 55 - 1):
        for j in range(i + 1, 55):
            if (i, j) <= min((j - i, 55 - i), (55 - j, 55 + i - j)):
                reps.append('1' + '0' * (i - 1) + '1' + '0' * (j - i - 1) + '1' + '0' * (55 - j - 1))
    return reps

2
@ সালভাদোরডালি আপনি উত্তরটি ভুল বুঝে গেছেন (তিনি এটি নির্দেশ না করা পর্যন্ত আমিও তা করেছিলাম!)। এটি সরাসরি "3 টি এবং 52 জিরো সহ স্ট্রিংয়ের প্রতিটি বৃত্তাকার সমতুল্য শ্রেণীর এক প্রতিনিধি" উত্পন্ন করে। তার কোডটি সমস্ত চক্রীয় ঘূর্ণন তৈরি করে না। মূল ব্যয়টি টি (55² · 26235²)। আপনার কোড 55² থেকে 55 উন্নতি করে, তাই কেবল টি (55 * 26235²)। পুরো বিষয়টির জন্য ডেভিড আইজেনস্ট্যাট এর উত্তর 55² থেকে 55³ এর মধ্যে । 55³ ≪ 55 · 26235² ² Big সমস্ত ক্ষেত্রে ও (1) এর আসল ব্যয় হিসাবে এখানে বিগ-ও কথা বলছেন না।
Veedrac

1
@ উইড্রাক তবে 99% পাঠক যারা ভবিষ্যতে এই প্রশ্নে আসবেন, তার প্রতিবন্ধকতা থাকবে না এবং আমি বিশ্বাস করি যে আমার উত্তর তাদের আরও ভাল মানাবে। কথোপকথনটি আরও ফুলে না নিয়ে আমি ওপি-র কাছে যাব তিনি ঠিক কী চান তা বোঝাতে।
সালভাদোর ডালি

5
@ সালভাদোরডালি ওপি এক্সওয়াই সমস্যাটির শিকার হয়েছেন বলে মনে হয় । ভাগ্যক্রমে, প্রশ্ন নিজেই পরিষ্কার করে দিয়েছে শিরোনামটি কী দেয় না এবং ডেভিড লাইনের মধ্যে পড়তে সক্ষম হয়েছিল। যদি এটি প্রকৃতপক্ষে হয় তবে সঠিক কাজটি হ'ল শিরোনাম পরিবর্তন করা এবং আসল সমস্যাটি সমাধান করা বরং শিরোনামের উত্তর দেওয়া এবং প্রশ্নটিকে উপেক্ষা করা।
অ্যারন ডুফর

1
@ সালভাদোরডালি, কভারগুলির নীচে আপনার পাইথন কোডটি সি এর স্ট্রাস্টারের সমতুল্য কল করছে () যা একটি সাব-স্ট্রিংয়ের জন্য একটি স্ট্রিং অনুসন্ধান করে। যার ফলে স্ট্রিং 2 দিয়ে স্ট্রিং 1 এর সাথে প্রতিটি চরকে তুলনা করে () লুপ সঞ্চালিত হয়, যা স্ট্রাইক 2 দিয়ে কল করে c সুতরাং, ও (এন) এর মতো দেখতে হ'ল ও (এন * 55 * 55) অনুসন্ধান ব্যর্থতার সন্ধান করে। উচ্চ স্তরের ভাষাগুলি একটি 2-ধারযুক্ত তরোয়াল। তারা আপনার কাছ থেকে বাস্তবায়নের বিশদটি গোপন করে তবে তারপরে তারা আপনার কাছ থেকে বাস্তবায়ন বিবরণও গোপন করে। এফডাব্লুআইডাব্লু, তালিকার সাথে তাল মিলানোর আপনার অন্তর্দৃষ্টি উজ্জ্বল ছিল। এখনও uint8 হিসাবে আরও দ্রুত এবং বিটের চেয়ে আরও দ্রুত - যা সহজেই হার্ডওয়্যারে আবর্তিত হতে পারে।

2
কম্পিউটারের জন্য অ্যালেক্সান্ডারডুবিনস্কি সিম্পলার, মানুষের জন্য আরও জটিল। এটি যেমন আছে তেমন দ্রুত
ডেভিড আইজেনস্ট্যাট

12

প্রথম অ্যারের পুনরাবৃত্তি করুন, তারপরে প্রথমটির মধ্যে দ্বিতীয় অ্যারেটি খুঁজে পেতে জেড অ্যালগরিদম (ও (এন) সময়) ব্যবহার করুন ।

(দ্রষ্টব্য: আপনাকে প্রথম অ্যারে শারীরিকভাবে অনুলিপি করতে হবে না matching ম্যাচের সময় আপনি কেবল গুটিয়ে রাখতে পারেন))

জেড অ্যালগরিদম সম্পর্কে দুর্দান্ত জিনিসটি হ'ল কেএমপি, বিএম ইত্যাদির তুলনায় এটি খুব সহজ
However তবে আপনি যদি উচ্চাকাঙ্ক্ষী বোধ করেন তবে আপনি লিনিয়ার সময় এবং ধ্রুবক স্পেসে স্ট্রিং মেলাতে পারেন - strstrউদাহরণস্বরূপ, এটি করে। যদিও এটি প্রয়োগ করা আরও বেদনাদায়ক হবে।


6

সালভাদোর ডালির খুব স্মার্ট সমাধান অনুসরণ করে, এটি হ্যান্ডেল করার সর্বোত্তম উপায় হ'ল সমস্ত উপাদান একই দৈর্ঘ্যের এবং একই সাথে উভয়টি তালিকা একই দৈর্ঘ্যের হয় তা নিশ্চিত করা।

def is_circular_equal(lst1, lst2):
    if len(lst1) != len(lst2):
        return False
    lst1, lst2 = map(str, lst1), map(str, lst2)
    len_longest_element = max(map(len, lst1))
    template = "{{:{}}}".format(len_longest_element)
    circ_lst = " ".join([template.format(el) for el in lst1]) * 2
    return " ".join([template.format(el) for el in lst2]) in circ_lst

সালভাদোর ডালির উত্তরে এটি অশ্বিনীচৌধরীর সুপারিশকৃত রেজেক্স সমাধানের চেয়ে দ্রুত বা ধীর গতির কোনও চিহ্ন নেই, যা লেখা আছে:

import re

def is_circular_equal(lst1, lst2):
    if len(lst2) != len(lst2):
        return False
    return bool(re.search(r"\b{}\b".format(' '.join(map(str, lst2))),
                          ' '.join(map(str, lst1)) * 2))

1
উইকির বিষয়টি এইহেতু আমি মূলত সালভাদোর ডালির উত্তরটি টুইট করেছিলাম এবং অশ্বিনীর পরিবর্তনগুলি বিন্যাস করেছি। এর খুব সামান্যই আসলে আমার।
অ্যাডাম স্মিথ

1
ইনপুট জন্য আপনাকে ধন্যবাদ। আমি মনে করি আমি আমার সম্পাদিত সমাধানে সমস্ত সম্ভাব্য কেস কভার করেছি। যদি কিছু অনুপস্থিত থাকে তবে আমাকে জানান।
সালভাদোর ডালি

সালভাদোরডালি আহ, হ্যাঁ ... স্ট্রিংগুলি একই দৈর্ঘ্যের কিনা তা পরীক্ষা করে। আমি সাপ্স করি যা দীর্ঘতম উপাদানটির তালিকায় তালিকার মধ্য দিয়ে চলার চেয়ে সহজ হবে, তারপরে str.format nফলাফলটি স্ট্রিংটি ফর্ম্যাট করার জন্য বার কল করে । আমি সাপোজি .... :)
অ্যাডাম স্মিথ

3

আপনার তালিকার মধ্য দিয়ে প্রাথমিক পাস করার সময় এগুলিকে সহজেই তুলনা করা যায় এমন কোনও আকারের রূপকে রূপান্তর করার জন্য আপনার এতগুলি তুলনা করার দরকার আছে কিনা তা দেওয়া উচিত?

আপনি বৃত্তাকার-অনন্য তালিকার একটি সেট পেতে চেষ্টা করছেন? যদি তাই হয় তবে এগুলিকে টিপলে রূপান্তর করার পরে সেটে সেটগুলিতে ফেলে দিতে পারেন।

def normalise(lst):
    # Pick the 'maximum' out of all cyclic options
    return max([lst[i:]+lst[:i] for i in range(len(lst))])

a_normalised = map(normalise,a)
a_tuples = map(tuple,a_normalised)
a_unique = set(a_tuples)

ডেভিড আইসেনস্টাটের কাছে তার অনুরোধের উত্তর মিলেছে না বলে দুঃখিত।


3

আপনি এটির মতো একটি তালিকা রোল করতে পারেন:

list1, list2 = [0,1,1,1,0,0,1,0], [1,0,0,1,0,0,1,1]

str_list1="".join(map(str,list1))
str_list2="".join(map(str,list2))

def rotate(string_to_rotate, result=[]):
    result.append(string_to_rotate)
    for i in xrange(1,len(string_to_rotate)):
        result.append(result[-1][1:]+result[-1][0])
    return result

for x in rotate(str_list1):
    if cmp(x,str_list2)==0:
        print "lists are rotationally identical"
        break

3

প্রথমে আপনার প্রতিটি তালিকার উপাদানকে (প্রয়োজনে একটি অনুলিপিতে) সেই আবর্তিত সংস্করণে রূপান্তর করুন যা বর্ণনামূলকভাবে সবচেয়ে বড়।

তারপরে তালিকাগুলির ফলাফলের তালিকাটি সাজান (মূল তালিকা অবস্থানে একটি সূচক ধরে রাখা) এবং সাজানো তালিকাটি একীভূত করুন, প্রয়োজনীয় তালিকায় সমস্ত নকলকে চিহ্নিত করে।


2

@ সালভাদোরডালির বি + বিতে যে কোনও একটি দৈর্ঘ্যের আকারের স্লাইসে ম্যাচের সন্ধানের বিষয়ে পর্যবেক্ষণের উপর পিগব্যাকিং, কেবলমাত্র তালিকা ক্রিয়াকলাপ ব্যবহার করে একটি সমাধান এখানে দেওয়া হয়েছে।

def rollmatch(a,b):
    bb=b*2
    return any(not any(ax^bbx for ax,bbx in zip(a,bb[i:])) for i in range(len(a)))

l1 = [1,0,0,1]
l2 = [1,1,0,0]
l3 = [1,0,1,0]

rollmatch(l1,l2)  # True
rollmatch(l1,l3)  # False

২ য় পন্থা: [মোছা]


প্রথম সংস্করণ হ'ল (n () এবং দ্বিতীয়টি এর জন্য কাজ করে না rollmatch([1, 0, 1, 1], [0, 1, 1, 1])
Veedrac

ভাল ধরা, আমি মুছে ফেলব!
PaulMcG

1

একটি সম্পূর্ণ, মুক্ত-স্থায়ী উত্তর নয়, তবে তুলনা হ্রাস করে অনুকূলিতকরণের বিষয়ে আমিও সাধারণ উপস্থাপনাগুলির কথা ভাবছিলাম।

যথা, যদি আপনার ইনপুট বর্ণমালা {0, 1 is হয়, তবে আপনি অনুমোদিত অনুমতিগুলির সংখ্যা উল্লেখযোগ্যভাবে হ্রাস করতে পারবেন। প্রথম তালিকাটি একটি (সিউডো-) নর্মাল ফর্মটিতে ঘোরান (আপনার প্রশ্নের বিতরণে প্রদত্ত, আমি যেখানে 1 টি বিটগুলির মধ্যে একটি চূড়ান্ত বাম দিকে আছে সেখানে একটি বেছে নেব এবং 0 টি বিটের মধ্যে একটি চূড়া ডানদিকে রয়েছে)। এখন প্রতিটি তুলনার আগে, একই প্রান্তিককরণ প্যাটার্ন সহ সম্ভাব্য পজিশনের মাধ্যমে ক্রমান্বয়ে অন্যান্য তালিকাটি ঘোরান।

উদাহরণস্বরূপ, আপনার কাছে মোট চারটি 1 টি বিট থাকলে এই সারিবদ্ধকরণের সাথে সর্বাধিক 4 ক্রমায়ন থাকতে পারে এবং আপনার যদি সংলগ্ন 1 বিটের ক্লাস্টার থাকে তবে এই জাতীয় ক্লাস্টারে প্রতিটি অতিরিক্ত বিট পজিশনের পরিমাণ হ্রাস করে।

List 1   1 1 1 0 1 0

List 2   1 0 1 1 1 0  1st permutation
         1 1 1 0 1 0  2nd permutation, final permutation, match, done

এটি বৃহত্তর বর্ণমালা এবং বিভিন্ন প্রান্তিককরণের ধরণগুলিকে সাধারণীকরণ করে; প্রধান চ্যালেঞ্জটি হ'ল কয়েকটি সম্ভাব্য উপস্থাপনা সহ একটি ভাল স্বাভাবিককরণের সন্ধান করা। আদর্শভাবে, এটি একক অনন্য প্রতিনিধিত্ব সহ একটি যথাযথ স্বাভাবিককরণ হবে, তবে সমস্যাটি দেখলে আমি মনে করি এটি সম্ভব নয়।


0

রকেটরোয়ের উত্তরে আরও বিল্ডিং: আপনার সমস্ত তালিকাটি স্বাক্ষরযুক্ত স্বাক্ষরিত 64 বিট সংখ্যায় রূপান্তর করুন। প্রতিটি তালিকার জন্য, এই 55 টি বিটকে ঘোরান ছোট ছোট সংখ্যার মানটি খুঁজে পেতে।

আপনি এখন প্রতিটি তালিকার একক স্বাক্ষরিত 64 বিট মান রেখে গেছেন যা আপনি অন্য তালিকার মানের সাথে সরাসরি তুলনা করতে পারেন। Is_circular_identical () এর ফাংশন আর প্রয়োজন হয় না।

(সংক্ষেপে, আপনি আপনার তালিকার জন্য একটি পরিচয় মান তৈরি করেন যা তালিকার উপাদানগুলির ঘূর্ণন দ্বারা প্রভাবিত হয় না) এমনকি যদি আপনার তালিকাগুলির মধ্যে একটি স্বেচ্ছাসেবী সংখ্যা থাকে তবে তা কাজ করবে।


0

এটি সালভাদোর ডালির একই ধারণা তবে স্ট্রিং রূপান্তরটির প্রয়োজন নেই। অসম্ভব শিফট পরিদর্শন এড়ানোর জন্য একই কেএমপি পুনরুদ্ধার ধারণা পিছনে। এগুলি কেবল কেএমপি মোডাফায়েড (তালিকা 1, তালিকা 2 + তালিকা 2) কল করুন।

    public class KmpModified
    {
        public int[] CalculatePhi(int[] pattern)
        {
            var phi = new int[pattern.Length + 1];
            phi[0] = -1;
            phi[1] = 0;

            int pos = 1, cnd = 0;
            while (pos < pattern.Length)
                if (pattern[pos] == pattern[cnd])
                {
                    cnd++;
                    phi[pos + 1] = cnd;
                    pos++;
                }
                else if (cnd > 0)
                    cnd = phi[cnd];
                else
                {
                    phi[pos + 1] = 0;
                    pos++;
                }

            return phi;
        }

        public IEnumerable<int> Search(int[] pattern, int[] list)
        {
            var phi = CalculatePhi(pattern);

            int m = 0, i = 0;
            while (m < list.Length)
                if (pattern[i] == list[m])
                {
                    i++;
                    if (i == pattern.Length)
                    {
                        yield return m - i + 1;
                        i = phi[i];
                    }
                    m++;
                }
                else if (i > 0)
                {
                    i = phi[i];
                }
                else
                {
                    i = 0;
                    m++;
                }
        }

        [Fact]
        public void BasicTest()
        {
            var pattern = new[] { 1, 1, 10 };
            var list = new[] {2, 4, 1, 1, 1, 10, 1, 5, 1, 1, 10, 9};
            var matches = Search(pattern, list).ToList();

            Assert.Equal(new[] {3, 8}, matches);
        }

        [Fact]
        public void SolveProblem()
        {
            var random = new Random();
            var list = new int[10];
            for (var k = 0; k < list.Length; k++)
                list[k]= random.Next();

            var rotation = new int[list.Length];
            for (var k = 1; k < list.Length; k++)
                rotation[k - 1] = list[k];
            rotation[rotation.Length - 1] = list[0];

            Assert.True(Search(list, rotation.Concat(rotation).ToArray()).Any());
        }
    }

এই সাহায্য আশা করি!


0

সমস্যাটি সরলকরণ

  • সমস্যাটিতে অর্ডার করা আইটেমগুলির তালিকা রয়েছে
  • মান ডোমেন বাইনারি হয় (0,1)
  • আমরা 1একটি গণনায় টানা গুলি ম্যাপ করে সমস্যা হ্রাস করতে পারি
  • এবং একটানা 0aণাত্মক গণনায় into

উদাহরণ

A = [ 1, 1, 1, 0, 0, 1, 1, 0 ]
B = [ 1, 1, 0, 1, 1, 1, 0, 0 ]
~
A = [ +3, -2, +2, -1 ]
B = [ +2, -1, +3, -2 ]
  • এই প্রক্রিয়াটির জন্য প্রথম আইটেম এবং শেষ আইটেমটি পৃথক হওয়া উচিত
  • এটি সামগ্রিক তুলনার পরিমাণ হ্রাস করবে

প্রক্রিয়া পরীক্ষা করা হচ্ছে

  • যদি আমরা ধরে নিই যে সেগুলি সদৃশ, তবে আমরা কী সন্ধান করছি তা অনুমান করতে পারি
  • মূলত প্রথম তালিকা থেকে প্রথম আইটেমটি অন্য তালিকার কোথাও উপস্থিত থাকতে হবে
  • প্রথম তালিকায় যা অনুসরণ করা হয় তা অনুসরণ করে এবং একই পদ্ধতিতে
  • পূর্ববর্তী আইটেমগুলি প্রথম তালিকা থেকে শেষ আইটেম হওয়া উচিত
  • যেহেতু এটি বিজ্ঞপ্তি, ক্রম একই is

গ্রিপ

  • প্রশ্ন এখানে যেখানে শুরু, টেকনিক্যালি হিসাবে পরিচিত lookupএবংlook-ahead
  • প্রথম তালিকার প্রথম উপাদানটি দ্বিতীয় তালিকার মাধ্যমে কোথায় রয়েছে তা আমরা খতিয়ে দেখব
  • আমরা তালিকাগুলিকে হিস্টোগ্রামে ম্যাপ করেছি বলে ঘন ঘন উপাদানগুলির সম্ভাবনা কম থাকে

সুডোকোড

FUNCTION IS_DUPLICATE (LIST L1, LIST L2) : BOOLEAN

    LIST A = MAP_LIST(L1)
    LIST B = MAP_LIST(L2)

    LIST ALPHA = LOOKUP_INDEX(B, A[0])

    IF A.SIZE != B.SIZE
       OR COUNT_CHAR(A, 0) != COUNT_CHAR(B, ALPHA[0]) THEN

        RETURN FALSE

    END IF

    FOR EACH INDEX IN ALPHA

        IF ALPHA_NGRAM(A, B, INDEX, 1) THEN

            IF IS_DUPLICATE(A, B, INDEX) THEN

                RETURN TRUE

            END IF

        END IF

    END FOR

    RETURN FALSE

END FUNCTION

FUNCTION IS_DUPLICATE (LIST L1, LIST L2, INTEGER INDEX) : BOOLEAN

    INTEGER I = 0

    WHILE I < L1.SIZE DO

        IF L1[I] != L2[(INDEX+I)%L2.SIZE] THEN

            RETURN FALSE

        END IF

        I = I + 1

    END WHILE

    RETURN TRUE

END FUNCTION

ক্রিয়াকলাপ

  • MAP_LIST(LIST A):LIST একটি নতুন তালিকাসমূহ অনুসারে ম্যাসক্রোসিটিভ এলিমেন্টস ম্যাপ করুন

  • LOOKUP_INDEX(LIST A, INTEGER E):LISTসূচকের ফেরত তালিকা যেখানে উপাদান Eতালিকা মধ্যে উপস্থিতA

  • COUNT_CHAR(LIST A , INTEGER E):INTEGERগণনা কত তালিকায় একটি মৌলিক Eমৌলিক সময় নির্ধারণ করেA

  • ALPHA_NGRAM(LIST A,LIST B,INTEGER I,INTEGER N):BOOLEANচেক B[I]সমতূল্য IS A[0] N-GRAMইন উভয় নির্দেশাবলী


পরিশেষে

যদি তালিকার আকারটি বেশ বিশাল হতে চলেছে বা আমরা যে উপাদানটি থেকে চক্রটি পরীক্ষা করতে শুরু করছি এটি ঘন ঘন বেশি হয়, তবে আমরা নিম্নলিখিতটি করতে পারি:

  • শুরু করার জন্য প্রথম তালিকার সর্বনিম্ন-ঘন ঘন আইটেমটি সন্ধান করুন

  • রৈখিক চেকের মধ্য দিয়ে যাওয়ার সম্ভাবনা কমাতে এন-গ্রাম এন প্যারামিটার বাড়িয়ে দিন


0

প্রশ্নের মধ্যে তালিকাগুলির জন্য একটি দক্ষ, দ্রুত-গণনা "ক্যানোনিকাল ফর্ম" হিসাবে নেওয়া যেতে পারে:

  • তিনটি নম্বর পেতে, এর মধ্যে শূন্যের সংখ্যা গণনা করুন (মোড়ানো চারপাশে উপেক্ষা করে)।
  • তিনটি সংখ্যা ঘোরান যাতে বৃহত্তম সংখ্যাটি প্রথম হয়।
  • প্রথম সংখ্যা ( a) অবশ্যই অবশ্যই ( 18এবং 52) সহকারে হবে। মধ্যে হিসেবে পুনরায় সঙ্কেতাক্ষরে লিখা এটা 0এবং 34
  • দ্বিতীয় সংখ্যাটি ( b) অবশ্যই এর মধ্যে 0এবং 26তবে এটি বেশি কিছু দেয় না।
  • তৃতীয় নম্বরটি ড্রপ করুন, কারণ এটি ঠিক 52 - (a + b)এবং কোনও তথ্য যুক্ত করে না

ক্যানোনিকাল ফর্মটি পূর্ণসংখ্যা b * 35 + a, যা এর মধ্যে 0এবং 936(অন্তর্ভুক্ত) হয়, যা মোটামুটি কমপ্যাক্ট ( 477মোটে বৃত্তাকার-অনন্য তালিকাগুলি রয়েছে)।


0

আমি একটি সরল সমাধান লিখেছি যা উভয় তালিকার সাথে তুলনা করে এবং প্রতিটি পুনরাবৃত্তির জন্য তুলনামূলক মানের সূচককে বাড়িয়ে তোলে (এবং প্রায় মোড়ানো)।

আমি অজগরটি ভাল করে জানি না তাই আমি এটি জাভাতে লিখেছি, তবে এটি সত্যিই সহজ তাই এটি অন্য কোনও ভাষায় খাপ খাইয়ে নেওয়া সহজ হওয়া উচিত।

এটির মাধ্যমে আপনি অন্যান্য ধরণের তালিকাও তুলনা করতে পারেন।

public class Main {

    public static void main(String[] args){
        int[] a = {0,1,1,1,0};
        int[] b = {1,1,0,0,1};

        System.out.println(isCircularIdentical(a, b));
    }

    public static boolean isCircularIdentical(int[] a, int[]b){
        if(a.length != b.length){
            return false;
        }

        //The outer loop is for the increase of the index of the second list
        outer:
        for(int i = 0; i < a.length; i++){
            //Loop trough the list and compare each value to the according value of the second list
            for(int k = 0; k < a.length; k++){
                // I use modulo length to wrap around the index
                if(a[k] != b[(k + i) % a.length]){
                    //If the values do not match I continue and shift the index one further
                    continue outer;
                }
            }
            return true;
        }
        return false;
    }
}

0

অন্যরা যেমন উল্লেখ করেছে, একবার আপনি কোনও তালিকার সাধারণ ঘূর্ণনটি খুঁজে পেয়েছেন, আপনি সেগুলি তুলনা করতে পারেন।

Heres কিছু কার্যকরী কোড যা এটি করে, বেসিক পদ্ধতিটি প্রতিটি তালিকার জন্য একটি সাধারণ ঘূর্ণন সন্ধান এবং তুলনা করা হয়:

  • প্রতিটি তালিকার একটি সাধারণ রোটেশন সূচক গণনা করুন।
  • উভয় তালিকার উপরের অফসেটের সাহায্যে লুপ করুন, প্রতিটি আইটেমের তুলনা করুন, যদি তারা ভুল মেলে তবে ফিরে আসুন।

নোট করুন যে এই পদ্ধতিটি এটি সংখ্যার উপর নির্ভর করে না, আপনি স্ট্রিংগুলির তালিকায় পাস করতে পারেন (যে কোনও মান যা তুলনা করা যায়)।

তালিকার ইন-তালিকা অনুসন্ধানের পরিবর্তে, আমরা জানি আমরা তালিকাটি ন্যূনতম মান দিয়ে শুরু করতে চাই - সুতরাং আমরা সর্বনিম্ন মানগুলি লুপ করতে পারি, যতক্ষণ না খুঁজে পাওয়া যায় কোনটির মধ্যে সবচেয়ে কম ধারাবাহিক মান রয়েছে, এটি আরও তুলনা করার জন্য সংরক্ষণ করে আমাদের সেরা না হওয়া পর্যন্ত

সূচক গণনা করার সময় প্রারম্ভিক প্রস্থান করার অনেক সুযোগ রয়েছে, কিছু অপ্টিমাইজেশনের বিশদ।

  • যখন সর্বনিম্ন মানটি থাকে তখন সর্বাধিক ন্যূনতম মান অনুসন্ধান করা ছেড়ে যান।
  • পূর্ববর্তীটিও যখন সর্বনিম্ন মান হয় তখন এটি সর্বনিম্ন মানগুলি অনুসন্ধানে এড়িয়ে যান (এটি এর চেয়ে ভাল ম্যাচ হবে না)।
  • যখন সমস্ত মান একই হয় তখন সন্ধান ছেড়ে যান।
  • তালিকার বিভিন্ন ন্যূনতম মান থাকলে তাড়াতাড়ি ব্যর্থ হয়।
  • অফসেট মিললে নিয়মিত তুলনা ব্যবহার করুন।
  • তুলনার সময় তালিকার একটিতে সূচকের মানগুলি মোড়ানো এড়াতে অফসেটগুলি সামঞ্জস্য করুন।

দ্রষ্টব্য যে পাইথনে একটি তালিকা-ইন-তালিকা অনুসন্ধানটি দ্রুততর হতে পারে, তবে আমি একটি দক্ষ অ্যালগরিদম খুঁজে পেতে আগ্রহী ছিল - যা অন্যান্য ভাষায়ও ব্যবহৃত হতে পারে। এছাড়াও, নতুন তালিকা তৈরি করা এড়িয়ে চলার কিছু সুবিধা রয়েছে।

def normalize_rotation_index(ls, v_min_other=None):
    """ Return the index or -1 (when the minimum is above `v_min_other`) """

    if len(ls) <= 1:
        return 0

    def compare_rotations(i_a, i_b):
        """ Return True when i_a is smaller.
            Note: unless there are large duplicate sections of identical values,
            this loop will exit early on.
        """
        for offset in range(1, len(ls)):
            v_a = ls[(i_a + offset) % len(ls)]
            v_b = ls[(i_b + offset) % len(ls)]
            if v_a < v_b:
                return True
            elif v_a > v_b:
                return False
        return False

    v_min = ls[0]
    i_best_first = 0
    i_best_last = 0
    i_best_total = 1
    for i in range(1, len(ls)):
        v = ls[i]
        if v_min > v:
            v_min = v
            i_best_first = i
            i_best_last = i
            i_best_total = 1
        elif v_min == v:
            i_best_last = i
            i_best_total += 1

    # all values match
    if i_best_total == len(ls):
        return 0

    # exit early if we're not matching another lists minimum
    if v_min_other is not None:
        if v_min != v_min_other:
            return -1
    # simple case, only one minimum
    if i_best_first == i_best_last:
        return i_best_first

    # otherwise find the minimum with the lowest values compared to all others.
    # start looking after the first we've found
    i_best = i_best_first
    for i in range(i_best_first + 1, i_best_last + 1):
        if (ls[i] == v_min) and (ls[i - 1] != v_min):
            if compare_rotations(i, i_best):
                i_best = i

    return i_best


def compare_circular_lists(ls_a, ls_b):
    # sanity checks
    if len(ls_a) != len(ls_b):
        return False
    if len(ls_a) <= 1:
        return (ls_a == ls_b)

    index_a = normalize_rotation_index(ls_a)
    index_b = normalize_rotation_index(ls_b, ls_a[index_a])

    if index_b == -1:
        return False

    if index_a == index_b:
        return (ls_a == ls_b)

    # cancel out 'index_a'
    index_b = (index_b - index_a)
    if index_b < 0:
        index_b += len(ls_a)
    index_a = 0  # ignore it

    # compare rotated lists
    for i in range(len(ls_a)):
        if ls_a[i] != ls_b[(index_b + i) % len(ls_b)]:
            return False
    return True


assert(compare_circular_lists([0, 9, -1, 2, -1], [-1, 2, -1, 0, 9]) == True)
assert(compare_circular_lists([2, 9, -1, 0, -1], [-1, 2, -1, 0, 9]) == False)
assert(compare_circular_lists(["Hello" "Circular", "World"], ["World", "Hello" "Circular"]) == True)
assert(compare_circular_lists(["Hello" "Circular", "World"], ["Circular", "Hello" "World"]) == False)

দেখুন: আরও কিছু পরীক্ষা / উদাহরণের জন্য এই স্নিপেট


0

খুব সহজেই প্রত্যাশিত ও (এন) সময়ে তালিকা তালিকা বি এর চক্রাকার শিফটের সমান কিনা তা দেখতে আপনি পরীক্ষা করতে পারেন।

আমি তালিকার এ এর ​​হ্যাশ গণনা করার জন্য একটি বহুবর্ষীয় হ্যাশ ফাংশন এবং তালিকা বিয়ের প্রতিটি চক্রীয় শিফট ব্যবহার করব, যেখানে তালিকার বিয়ের শিফট তালিকার এ-এর সমান হ্যাশ রয়েছে, আমি প্রকৃত উপাদানগুলি সমান কিনা তা দেখতে তুলনা করব ।

এটি দ্রুত হওয়ার কারণটি হ'ল পলিনোমিয়াল হ্যাশ ফাংশনগুলি (যা অত্যন্ত সাধারণ!) সহ আপনি স্থির সময়ে প্রতিটি চক্রিক শিফটের হ্যাশ গণনা করতে পারেন, তাই আপনি ও-তে সমস্ত চক্রীয় শিফটের জন্য হ্যাশ গণনা করতে পারেন ( এন) সময়।

এটি এর মতো কাজ করে:

ধরা যাক বি এর এন উপাদান রয়েছে, তারপরে প্রাইম পি ব্যবহার করে বি এর হ্যাশটি হ'ল:

Hb=0;
for (i=0; i<N ; i++)
{
    Hb = Hb*P + B[i];
}

এটি পি এর বহুবচন মূল্যায়ন করার একটি অনুকূলিত উপায়, এবং এর সমতুল্য:

Hb=0;
for (i=0; i<N ; i++)
{
    Hb += B[i] * P^(N-1-i);  //^ is exponentiation, not XOR
}

প্রতিটি বি [i] কীভাবে পি ^ (এন-1-আই) দ্বারা গুণিত হয় তা লক্ষ্য করুন। আমরা যদি 1 কে বি দ্বারা বামে স্থানান্তরিত করি, তবে প্রতিটি বি [i] প্রথমটি বাদ দিয়ে অতিরিক্ত পি দ্বারা গুণিত হবে। যেহেতু গুণগুলি অতিরিক্ত পরিমাণে বিতরণ করে, তাই আমরা পুরো হ্যাশকে কেবল একবারে গুটিয়ে নিয়ে সমস্ত উপাদানকে গুণতে পারি এবং তারপরে প্রথম উপাদানটির জন্য ফ্যাক্টরটি ঠিক করতে পারি।

বি এর বাম শিফটের হ্যাশটি ঠিক

Hb1 = Hb*P + B[0]*(1-(P^N))

দ্বিতীয় বাম শিফট:

Hb2 = Hb1*P + B[1]*(1-(P^N))

এবং তাই ...

দ্রষ্টব্য: উপরের সমস্ত গণিতটি কিছু মেশিন শব্দের আকারের মডিউল করা হয় এবং আপনাকে কেবল একবার P ^ N গণনা করতে হবে।


-1

এটি করার জন্য সর্বাধিক পাইথোনিক উপায়ে আঠালো করতে, সেটগুলি ব্যবহার করুন!

from sets import Set
a = Set ([1, 1, 1, 0, 0])
b = Set ([0, 1, 1, 1, 0]) 
c = Set ([1, 0, 0, 1, 1])
a==b
True
a==b==c
True

এটি একই সংখ্যায় 0 এবং 1 এর একই সংখ্যার সাথে স্ট্রিংগুলিও মেলে
জেনারেল বেকোস

জেনারেল বেকোস: কেবল সেই স্ট্রিংগুলি নির্বাচন করুন এবং দ্বিতীয় ধাপে
লুই

তারা একই রৈখিক ক্রমে নেই। তারা একই 'বিজ্ঞপ্তি' ক্রমে। দ্বিতীয় ধাপ হিসাবে আপনি যা বর্ণনা করেন তা হ'ল আসল সমস্যা।
জেনারেল বেকোস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.