একটি অনুক্রম পুনর্গঠন


16

ভূমিকা

মনে করুন যে আপনাকে nঅবজেক্টের একটি এলোমেলো অনুগমন দেওয়া হয়েছে । ক্রমটিশনটি একটি বাক্সে সিল করা হয়েছে, সুতরাং এটি n!সম্ভাব্য কোনটি তা আপনার কোনও ধারণা নেই । আপনি যদি nপৃথক বস্তুগুলিতে অনুমতিটি প্রয়োগ করতে পরিচালিত হন , আপনি তাত্ক্ষণিকভাবে তার পরিচয়টি কমিয়ে আনতে পারেন। তবে, আপনাকে কেবল দৈর্ঘ্য- nবাইনারি ভেক্টরগুলিতেই অনুমতি প্রয়োগ করতে দেওয়া হয় , যার অর্থ এটি সনাক্ত করতে আপনাকে বেশ কয়েকবার প্রয়োগ করতে হবে। স্পষ্টতই, এটি nকেবলমাত্র একজনের সাথে ভেক্টরগুলিতে প্রয়োগ করা 1কাজ করে তবে আপনি যদি চালাক হন তবে আপনি log(n)অ্যাপ্লিকেশন দিয়ে এটি করতে পারেন। এই পদ্ধতির কোডটি দীর্ঘতর হবে, যদিও ...

এটি একটি পরীক্ষামূলক চ্যালেঞ্জ যেখানে আপনার স্কোরটি কোড দৈর্ঘ্যের এবং ক্যোয়ারী জটিলতার সংমিশ্রণ , যার অর্থ সহায়ক পদ্ধতির কলগুলির সংখ্যা। অনুমানটি কিছুটা দীর্ঘ, তাই আমাকে সহ্য করুন।

কাজটি

আপনার কাজটি হল একটি নামযুক্ত ফাংশন (বা নিকটতম সমতুল্য) লিখুন f যা 0-ভিত্তিক বা 1-ভিত্তিক সূচক ব্যবহার করে কোনও ধনাত্মক পূর্ণসংখ্যার nএবং pপ্রথম nপূর্ণসংখ্যার ক্রমবিন্যাস গ্রহণ করে । তার আউটপুট বিন্যাস হয় p। তবে আপনাকে pসরাসরি অনুমতিটি অ্যাক্সেস করার অনুমতি নেই । এটির সাথে কেবলমাত্র আপনি যা করতে পারেন তা হ'ল এটি কোনও nবিটের ভেক্টরকে প্রয়োগ করা । এই উদ্দেশ্যে, আপনি একটি সহায়ক ক্রিয়াকলাপ ব্যবহার করতে পারেন Pযা একটি ক্রম pএবং বিটগুলির একটি ভেক্টর গ্রহণ করে vএবং অনুমতিযুক্ত ভেক্টরকে ফিরিয়ে দেয় যার p[i]তম স্থানাঙ্কটিতে বিট রয়েছে v[i]। উদাহরণ স্বরূপ:

P([1,2,3,4,0], [1,1,0,0,0]) == [0,1,1,0,0]

আপনি যেমন কোন দুটি স্বতন্ত্র মূল্যবোধ, সঙ্গে "বিট" প্রতিস্থাপন করতে পারেন 3এবং -4, বা 'a'এবং 'b'যাতে আপনি কল করতে পারেন, এবং তারা সংশোধন করা প্রয়োজন নেই, Pউভয় সঙ্গে [-4,3,3,-4]এবং [2,2,2,1]এ একই কলে f। সংজ্ঞাটি Pআপনার স্কোরের দিকে গণনা করা হয় না।

স্কোরিং

ক্যোয়ারী জটিলতা একটি প্রদত্ত ইনপুট আপনার সমাধান কলের সংখ্যা এটা অক্জিলিয়ারী ফাংশন করে তোলে P। এই পরিমাপটিকে দ্ব্যর্থহীন করার জন্য, আপনার সমাধানটি অবশ্যই নির্বিচারক হওয়া উচিত। আপনি ছদ্ম-এলোমেলোভাবে উত্পন্ন সংখ্যাগুলি ব্যবহার করতে পারেন তবে তার পরে আপনাকে জেনারেটরের জন্য একটি প্রাথমিক বীজও ঠিক করতে হবে।

ইন এই সংগ্রহস্থলের আপনি একটি ফাইল নামক পাবেন permutations.txtযে 505 একাধিক বিন্যাসন, 50 এবং 150 সমেত মধ্যে প্রতিটি দৈর্ঘ্য 5, 0-ভিত্তিক ইন্ডেক্স (1 ভিত্তিক ক্ষেত্রে প্রতিটি সংখ্যা বাড়ায়) ব্যবহার করে থাকে। প্রতিটি অনুক্রমটি তার নিজস্ব লাইনে থাকে এবং এর সংখ্যা ফাঁক দিয়ে আলাদা হয়। আপনার স্কোরটি এই ইনপুটগুলিতে + গড় ক্যোয়ারী জটিলতার বাইট গণনাf । সর্বনিম্ন স্কোর জয়।

অতিরিক্ত বিধি

ব্যাখ্যা সহ কোডটি অগ্রাধিকার দেওয়া হয় এবং মানক লুফোলগুলি অনুমোদিত নয়। বিশেষত, পৃথক বিটগুলি পৃথক বিভেদযুক্ত (যাতে আপনি তাদের পরিচয়গুলির সাথে কোনও Integerবস্তুর ভেক্টর দিতে Pএবং তুলনা করতে পারবেন না ), এবং ফাংশনটি Pসর্বদা তার ইনপুটটিকে নতুন করে সাজানোর পরিবর্তে একটি নতুন ভেক্টর ফেরত দেয়। আপনি এবং এর নাম fএবং যেভাবে Pতারা তাদের যুক্তি গ্রহণ করে সেগুলি অবাধে পরিবর্তন করতে পারেন change

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

def f(n,p):
    pass # Your submission goes here

num_calls = 0

def P(permutation, bit_vector):
    global num_calls
    num_calls += 1
    permuted_vector = [0]*len(bit_vector)
    for i in range(len(bit_vector)):
        permuted_vector[permutation[i]] = bit_vector[i]
    return permuted_vector

num_lines = 0
file_stream = open("permutations.txt")
for line in file_stream:
    num_lines += 1
    perm = [int(n) for n in line.split()]
    guess = f(len(perm), perm)
    if guess != perm:
        print("Wrong output\n %s\n given for input\n %s"%(str(guess), str(perm)))
        break
else:
    print("Done. Average query complexity: %g"%(num_calls/num_lines,))
file_stream.close()

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


আমরা যত, উদাহরণস্বরূপ "দুটি স্বতন্ত্র আইটেম ভেক্টর" "বিট ভেক্টর" ব্যাখ্যা করতে পারে না, এই সংজ্ঞা অধীনে উভয় abaaabababaaএবং -4 3 3 3 -4 3বিট একটি ভেক্টর হবে।
এফইউজএক্সএক্সএলএল

@FUZxxl হ্যাঁ, যতক্ষণ না পৃথক আইটেমগুলি অবিচ্ছেদ্য হয়।
জাগারব

আমার কাছে প্রয়োগের পদ্ধতির মধ্যে তারা সংখ্যা।
FUZxxl

@FUZxxl আমি চশমাটি সম্পাদনা করেছি।
জাগারব

উত্তর:


11

জে, 44.0693 22.0693 = 37 15 + 7.06931

আমরা যদি কল করতে পারবেন না Pউপর i. n, আমরা অন্তত কল এ যা করতে পারেন Pপ্রতিটি বিট উপর i. nআলাদাভাবে। এর আমন্ত্রণ সংখ্যা Pহয় >. 2 ^. n(⌈log 2 এন ⌉)। আমি বিশ্বাস করি এটি সর্বোত্তম।

f=:P&.|:&.#:@i.

এখানে ক্রিয়াকলাপ Pভেক্টর ব্যবহার করে pএবং আমন্ত্রণের সংখ্যাটি সংরক্ষণ করে যা ফাংশনটির একটি বাস্তবায়ন Pinv

P =: 3 : 0"1
 Pinv =: Pinv + 1
 assert 3 > # ~. y    NB. make sure y is binary
 p { y
)

এখানে একটি পরীক্ষার জোতা দেওয়া যা একটি অনুগতি লাভ করে এবং এর আহ্বানের সংখ্যা প্রদান করে p:

harness =: 3 : 0
 Pinv =: 0
 p =: y
 assert y = f # y     NB. make sure f computed the right permutation
 Pinv
)

এবং আপনি এখানে ফাইলটিতে এটি কীভাবে ব্যবহার করতে পারেন তা এখানে permutations.txt:

NB. average P invocation count
(+/ % #) harness@".;._2 fread 'permutations.txt'

ব্যাখ্যা

সংক্ষিপ্ত ব্যাখ্যাটি ইতিমধ্যে উপরে সরবরাহ করা হয়েছে, তবে এখানে আরও বিশদ বিবরণ দেওয়া হল। প্রথমত, fস্পেসগুলি sertedোকানো এবং একটি স্পষ্ট ফাংশন হিসাবে:

f =: P&.|:&.#:@i.
f =: 3 : 'P&.|:&.#: i. y'

পড়ুন:

প্রথম y এর পূর্ণসংখ্যার বেস -2 উপস্থাপনার অধীনে স্থানচর্চায় পি হতে দিন ।

যেখানে y হ'ল আনুষ্ঠানিক প্যারামিটার জেতে, ক্রিয়াটি ডায়াডিক (দুটি পরামিতি থাকে) এবং y যদি monadic হয় (একটি পরামিতি থাকে) তবে a (ফাংশন) এর পরামিতিগুলিকে x এবং y বলা হয় ।

Invoking পরিবর্তে Pউপর i. n(অর্থাত 0 1 2 ... (n - 1)), আমরা ডাকা Pমধ্যে সংখ্যার প্রতিটি বিট অবস্থানের উপর i. n। যেহেতু সমস্ত অনুমতিগুলি একইভাবে অনুমতি দেয়, তাই আমরা অনুমতি বিটগুলি সংখ্যার মধ্যে পুনরায় জমা করতে পারি অনুগ্রহকারী ভেক্টর পেতে:

  • i. y- থেকে পূর্ণসংখ্যার 0থেকে y - 1
  • #: y- yবেস 2 তে প্রতিনিধিত্ব করা এটি প্রাকৃতিক উপায়ে সংখ্যার ভেক্টরগুলিতে প্রসারিত। উদাহরণস্বরূপ, #: i. 16ফলন:

    0 0 0 0
    0 0 0 1
    0 0 1 0
    0 0 1 1
    0 1 0 0
    0 1 0 1
    0 1 1 0
    0 1 1 1
    1 0 0 0
    1 0 0 1
    1 0 1 0
    1 0 1 1
    1 1 0 0
    1 1 0 1
    1 1 1 0
    1 1 1 1
    
  • #. y- yবেস 2 নম্বর হিসাবে ব্যাখ্যা করা। উল্লেখযোগ্যভাবে, এটি বিপরীত #:; y ~: #. #:সবসময় ধরে।

  • |: y- yস্থানান্তরিত
  • u&.v y- এর uঅধীনে v, vinv u v yএখানেই vinvবিপরীত v। লক্ষ্য করুন যে |:এটি তার নিজস্ব বিপরীত।

  • P y- সংজ্ঞা অনুসারে Pপ্রতিটি ভেক্টরের সাথে ফাংশন প্রয়োগ করা হয় y


3

পাইথ 32 + 7.06931 = 37.06931

আমি নিম্নলিখিত অ্যালগরিদম সম্পূর্ণ স্বাধীন পেয়েছি। তবে এটি FUZxxl খুব সংক্ষিপ্ত জ সলিউশন হিসাবে কম-বেশি একই জিনিস (যতদূর আমি এটি বুঝতে পারি)।

প্রথমে ফাংশনটির সংজ্ঞা P, যা অজানা আদেশ অনুসারে বিট-অ্যারে অনুমতি দেয়।

D%GHJHVJ XJ@HN@GN)RJ

এবং তারপরে কোডটি যা ক্রমানুসরণ নির্ধারণ করে।

Mmxmi_mbk2Cm%dHCm+_jk2*sltG]0GdG

এটি একটি ফাংশন সংজ্ঞায়িত করে g, যা দুটি আর্গুমেন্ট নেয়। আপনি এটি কল করতে পারেন g5[4 2 1 3 0। এখানে একটি অনলাইন প্রদর্শন । এতগুলি (5) নেস্টেড মানচিত্র কখনও ব্যবহার করেন নি।

বিটিডব্লিউ আমি আসলে পরীক্ষার জোতা তৈরি করি নি। ফাংশনটিও এটি Pগণনা করে না যে আমি এটি কতবার কল করি। আমি ইতিমধ্যে অ্যালগরিদম বের করার জন্য অনেক সময় ব্যয় করেছি। তবে আপনি যদি আমার ব্যাখ্যাটি পড়েন তবে এটি স্পষ্ট it এটি int(log2(n-1)) + 1কল ( = ceil(log2(n))) ব্যবহার করে । এবং sum(int(log2(n-1)) + 1 for n in range(50, 151)) / 101.0 = 7.069306930693069

ব্যাখ্যা:

এই অ্যালগরিদমটি খুঁজে পেতে আমার আসলে বেশ কঠিন সময় ছিল। কীভাবে অর্জন করা যায় তা আমার কাছে মোটেই পরিষ্কার ছিল না log(n)। তাই ছোট নিয়ে কিছু পরীক্ষা-নিরীক্ষা শুরু করলাম n

প্রথম দ্রষ্টব্য: একটি বিট-অ্যারে পরিপূরক বিট-অ্যারের হিসাবে একই তথ্য সংগ্রহ করে। সুতরাং আমার সমাধানে সমস্ত বিট-অ্যারে সর্বাধিক n/2সক্রিয় বিট রয়েছে have

n = 3:

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

n = 4:

এখানে এটি কিছুটা আকর্ষণীয় হয়ে উঠেছে। আমরা এখন দুই ধরণের বিট-অ্যারে ব্যবহার করতে পারি। যাঁরা 1 অ্যাক্টিভ বিট এবং 2 অ্যাক্টিভ বিট সহ তাদের। যদি আমরা একটি অ্যাক্টিভ বিট সহ একটি বিট-অ্যারে ব্যবহার করি, আমরা কেবলমাত্র একাধিক ক্রমের ক্রম সম্পর্কে তথ্য সংগ্রহ করি এবং এর পিছনে পিছনে পড়ে যাই n = 3যার ফলস্বরূপ 1 + 2 = 3কল আসে P। মজার অংশটি হ'ল আমরা যদি 2 টি সক্রিয় বিট সহ বিট-অ্যারে ব্যবহার করি তবে আমরা কেবল 2 টি কল দিয়ে একই জিনিসটি করতে পারি। যেমন P([1, 1, 0, 0])এবং P([1, 0, 1, 0])

ধরা যাক আমরা ফলাফলগুলি পাই [1, 0, 0, 1]এবং [0, 0, 1, 1]। আমরা দেখতে পাচ্ছি যে বিট সংখ্যা 4 উভয় আউটপুট অ্যারেতে সক্রিয়। উভয় ইনপুট অ্যারেগুলিতে সক্রিয় ছিল কেবলমাত্র বিটটি 1 নম্বর বিট ছিল, সুতরাং স্পষ্টতই অনুচ্ছেদটি শুরু হয় 4। এখন এটি দেখতে সহজ, বিট 2 বিট 1 এ স্থানান্তরিত হয়েছিল (প্রথম আউটপুট), এবং বিট 3 বিট 3 এ স্থানান্তরিত হয়েছিল (দ্বিতীয় আউটপুট)। সুতরাং আদেশটি অবশ্যই হতে হবে [4, 1, 3, 2]

n = 7:

এখন আরও বড় কিছু। আমি Pসঙ্গে সঙ্গে কলগুলি প্রদর্শন করব । তারা একবার, আমি কিছু চিন্তা এবং পরীক্ষার পরে এসেছিল। (লক্ষ্য করুন যে এগুলি সেগুলি নয়, যা আমি আমার কোডে ব্যবহার করি))

P([1, 1, 1, 0, 0, 0, 0])
P([1, 0, 0, 1, 1, 0, 0])
P([0, 0, 1, 1, 0, 1, 0])

যদি প্রথম দুটি আউটপুট অ্যারেগুলিতে (এবং তৃতীয়টিতে নয়) বিট 2 সক্রিয় থাকে, আমরা জানি যে ক্রমশক্তিটি বিট 1 থেকে বিট 2 তে সরবে, কারণ বিট একমাত্র বিট যা প্রথম দুটি ইনপুট অ্যারেতে সক্রিয়।

গুরুত্বপূর্ণ বিষয়টি হ'ল, (ম্যাট্রিক্স হিসাবে ইনপুটগুলি ব্যাখ্যা করা) প্রতিটি কলামই স্বতন্ত্র। এটি হামিং কোডগুলিতে আমার মনে পড়েছিল , যেখানে একই জিনিসটি সম্পন্ন হয়। তারা কেবল 1 থেকে 7 নম্বর নিয়ে যায় এবং কলাম হিসাবে তাদের বিট-উপস্থাপনা ব্যবহার করে। আমি 0 থেকে 6 নম্বরগুলি ব্যবহার করব এখন দুর্দান্ত অংশটি, আমরা আউটপুটগুলি (আবার কলামগুলি) আবার সংখ্যা হিসাবে ব্যাখ্যা করতে পারি। এগুলি প্রয়োগ করার অনুমতিটির ফলাফল আমাদের বলে [0, 1, 2, 3, 4, 5, 6]

   0  1  2  3  4  5  6      1  3  6  4  5  0  2
P([0, 1, 0, 1, 0, 1, 0]) = [1, 1, 0, 0, 1, 0, 0]
P([0, 0, 1, 1, 0, 0, 1]) = [0, 1, 1, 0, 0, 0, 1]
P([0, 0, 0, 0, 1, 1, 1]) = [0, 0, 1, 1, 1, 0, 0]

সুতরাং আমরা কেবল সংখ্যাগুলি ট্রেস করতে হবে। বিট 0 বিট 5 এ শেষ হয়েছে, বিট 1 বিট 0 এ শেষ হয়েছে, বিট 2 বিট 6 এ শেষ হয়েছে, ... সুতরাং ক্রমান্বন ছিল [5, 0, 6, 1, 3, 4, 2]

Mmxmi_mbk2Cm%dHCm+_jk2*sltG]0GdG
M                                 define a function g(G, H), that will return
                                  the result of the following computation:
                                  G is n, and H is the permutation. 
                m            G     map each k in [0, 1, ..., Q-1] to:
                  _                   their inverse
                   jk2                binary representation (list of 1s and 0s)
                 +                    extended with 
                      *sltG]0         int(log2(Q - 1)) zeros
               C                   transpose matrix # rows that are longer 
                                                   # than others are shortened
           m%dH                    map each row (former column) d of 
                                   the matrix to the function P (here %)
          C                        transpose back
   m                              map each row k to:                         
    i    2                           the decimal number of the 
     _mbk                            inverse list(k) # C returns tuple :-(
Let's call the result X.  
 m                             G   map each d in [0, 1, ..., Q - 1] to:
  x         X                 d       the index of d in X

এবং ক্রমান্বয়ে ফাংশনের কোড:

D%GHJHVJ XJ@HN@GN)RJ
D%GH                     def %(G, H):  # the function is called %
    JH                     J = copy(H)
      VJ         )        for N in [0, 1, ..., len(J) - 1]: 
         XJ@HN@GN            J[H[N]] = G[N]           
                  RJ      return J

1
তোমাদের স্থলাভিষিক্ত তাহলে *sltQ]0সঙ্গে m0sltQ, আপনি একই দৈর্ঘ্য এ 6 নেস্টেড মানচিত্রগুলি ফেলতে পারে।
isaacg

আপনার, চ্যালেঞ্জের সাথে সামঞ্জস্য রেখে, আপনার কোডটি অর্পণ করা উচিত যা fঅন্য নামের অনুমতি থাকলেও আদর্শভাবে দেওয়া কোনও কার্যক্রমে চ্যালেঞ্জটি সমাধান করে । অ্যাসাইনমেন্টটি আপনার স্কোরের দিকে গুনে।
FUZxxl

@FUZxxl আমার কোড আপডেট করেছে। এখন gSTDIN থেকে পড়ার পরিবর্তে একটি ফাংশন সংজ্ঞায়িত করে ।
জাকুবে

2

গণিত, 63 + 100 = 163

আমি এক-ভিত্তিক ক্রম ব্যবহার করছি, যেহেতু ম্যাথমেটিকায় সূচকগুলি এইভাবে কাজ করে।

প্রথম, পরীক্ষার জোতা। এটি ক্যোয়ারী ফাংশন p(ব্যবহারকারী-সংজ্ঞায়িত নামগুলি ম্যাথামেটিকায় বড় আকারের হওয়া উচিত নয়):

p[perm_, vec_] := (
   i += 1;
   vec[[Ordering@perm]]
   );

এবং পরীক্ষার লুপের সাথে ইনপুট প্রস্তুতি:

permutations = 
  ToExpression@StringSplit@# + 1 & /@ 
   StringSplit[Import[
     "https://raw.githubusercontent.com/iatorm/permutations/master/permutations.txt"
   ], "\n"];
total = 0;
(
    i = 0;
    result = f@#;
    If[# != result, 
      Print["Wrong result for ", #, ". Returned ," result ", instead."]
    ];
    total += i;
    ) & /@ permutations;
N[total/Length@permutations]

এবং পরিশেষে, আমার আসল জমা যা আপাতত নিষ্পাপ অ্যালগরিদম ব্যবহার করে:

f=(v=0q;v[[#]]=1;Position[q~p~v,1][[1,1]])&/@Range@Length[q=#]&

বা ইন্ডেন্টেশন সহ:

f = (
     v = 0 q;
     v[[#]] = 1;
     Position[q~p~v, 1][[1, 1]]
) & /@ Range@Length[q = #] &
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.