এটি থাইজারের বর্তমানে অসম্পূর্ণ সিউডোকোডের লাইন বরাবর রয়েছে। এই ধারণাটি হ'ল কেবলমাত্র নেওয়া না হলে বাকী আইটেম ধরণের সর্বাধিক ঘন ঘন গ্রহণ করা। ( এই অ্যালগরিদমের কোডির বাস্তবায়নও দেখুন ))
import collections
import heapq
class Sentinel:
pass
def david_eisenstat(lst):
counts = collections.Counter(lst)
heap = [(-count, key) for key, count in counts.items()]
heapq.heapify(heap)
output = []
last = Sentinel()
while heap:
minuscount1, key1 = heapq.heappop(heap)
if key1 != last or not heap:
last = key1
minuscount1 += 1
else:
minuscount2, key2 = heapq.heappop(heap)
last = key2
minuscount2 += 1
if minuscount2 != 0:
heapq.heappush(heap, (minuscount2, key2))
output.append(last)
if minuscount1 != 0:
heapq.heappush(heap, (minuscount1, key1))
return output
সঠিকতার প্রমাণ
দুটি আইটেমের জন্য, কে 1 এবং কে 2 গণনা করে, সর্বোত্তম সমাধানে কে 2 <কে 2 - 1 ত্রুটি থাকে, কে 1 = কে 2 হলে 0 ত্রুটি, এবং কে 1 - কে 2 - 1 ত্রুটি কে 1> কে 2 থাকে। = কেসটি সুস্পষ্ট। অন্যরা প্রতিসম হয়; সংখ্যালঘু উপাদানের প্রতিটি উদাহরণ সম্পূর্ণ কে 1 + কে 2 - 1 এর মধ্যে সর্বোচ্চ দুটি ত্রুটি প্রতিরোধ করে।
এই লোভী অ্যালগরিদম নিম্নলিখিত যুক্তি দ্বারা অনুকূল সমাধানগুলি প্রদান করে। আমরা একটি উপসর্গ (আংশিক সমাধান) নিরাপদ কল যদি এটি একটি অনুকূল সমাধান প্রসারিত। স্পষ্টতই খালি উপসর্গটি নিরাপদ এবং যদি কোনও নিরাপদ উপসর্গ সম্পূর্ণ সমাধান হয় তবে সমাধানটি সর্বোত্তম। প্রতিটি লোভী পদক্ষেপ সুরক্ষা বজায় রাখে তা প্ররোচিতভাবে দেখানোর পক্ষে যথেষ্ট।
লোভী পদক্ষেপটি একটি ত্রুটি পরিচয় করিয়ে দেওয়ার একমাত্র উপায় হ'ল যদি কেবলমাত্র একটি আইটেম ধরণের থাকে, সেক্ষেত্রে চালিয়ে যাওয়ার একমাত্র উপায় থাকে এবং সেই পথটি নিরাপদ। অন্যথায়, বিবেচনাধীন পদক্ষেপের ঠিক আগে পি-কে (নিরাপদ) উপসর্গ হিসাবে ধরা দিন, পি'র ঠিক পরের উপসর্গ হওয়া যাক এবং এসকে পি প্রসারিত করার একটি সর্বোত্তম সমাধান হতে দিন। যদি এস পি'কেও প্রসারিত করে, তবে আমরা সম্পন্ন করেছি। অন্যথায়, P '= Px এবং S = PQ এবং Q = yQ' দিন, যেখানে x এবং y আইটেম এবং Q এবং Q 'সিকোয়েন্স।
ধরা যাক প্রথমে পি এর y দিয়ে শেষ হবে না। অ্যালগরিদমের পছন্দ অনুসারে, x কমপক্ষে y হিসাবে ঘন ঘন হিসাবে y হয়। কেবলমাত্র x এবং y যুক্ত Q এর সর্বাধিক সাবস্ট্রিংগুলি বিবেচনা করুন। যদি প্রথম সাবস্ট্রিংয়ের কমপক্ষে Y এর মতো কম বেশি x থাকে তবে এক্স দিয়ে শুরু করার জন্য অতিরিক্ত ত্রুটিগুলি না পরিচয় দিয়ে এটি আবার লেখা যেতে পারে। প্রথম স্ট্রিংটিতে যদি x এর চেয়ে বেশি y থাকে তবে অন্য কিছু স্ট্রিংয়ের y এর চেয়ে আরও বেশি x থাকে এবং আমরা অতিরিক্ত ত্রুটি ছাড়াই এই সাবস্ট্রিংগুলিকে আবার লিখতে পারি যাতে এক্স প্রথমে যায়। উভয় ক্ষেত্রেই আমরা একটি অনুকূল সমাধান টি খুঁজে পাই যা প্রয়োজন অনুযায়ী পি 'প্রসারিত করে।
এখন ধরুন যে পি এর শেষ হবে y দিয়ে। এক্স এর প্রথম উপস্থিতিটি সামনের দিকে নিয়ে গিয়ে কিউ সংশোধন করুন। এটি করার মাধ্যমে, আমরা সর্বাধিক একটি ত্রুটি (যেখানে এক্স ব্যবহৃত হত) উপস্থাপন করি এবং একটি ত্রুটি (ইয়ি) নির্মূল করি।
সমস্ত সমাধান তৈরি করা হচ্ছে
বর্তমানে বিবেচনাধীন পছন্দটি কোনওভাবে বিশ্বব্যাপী সীমাবদ্ধ রয়েছে তা সনাক্ত করার জন্য এটি টোবিয়াস_কে এর উত্তর এবং দক্ষ পরীক্ষা। অ্যাসিম্পটোটিক চলমান সময়টি সর্বোত্তম, যেহেতু প্রজন্মের ওভারহেড আউটপুট দৈর্ঘ্যের ক্রম হয়। দুর্ভাগ্যক্রমে সবচেয়ে খারাপ ক্ষেত্রে বিলম্ব চতুর্ভুজযুক্ত; এটি আরও ভাল ডেটা স্ট্রাকচার সহ রৈখিক (অনুকূল) কমে যেতে পারে।
from collections import Counter
from itertools import permutations
from operator import itemgetter
from random import randrange
def get_mode(count):
return max(count.items(), key=itemgetter(1))[0]
def enum2(prefix, x, count, total, mode):
prefix.append(x)
count_x = count[x]
if count_x == 1:
del count[x]
else:
count[x] = count_x - 1
yield from enum1(prefix, count, total - 1, mode)
count[x] = count_x
del prefix[-1]
def enum1(prefix, count, total, mode):
if total == 0:
yield tuple(prefix)
return
if count[mode] * 2 - 1 >= total and [mode] != prefix[-1:]:
yield from enum2(prefix, mode, count, total, mode)
else:
defect_okay = not prefix or count[prefix[-1]] * 2 > total
mode = get_mode(count)
for x in list(count.keys()):
if defect_okay or [x] != prefix[-1:]:
yield from enum2(prefix, x, count, total, mode)
def enum(seq):
count = Counter(seq)
if count:
yield from enum1([], count, sum(count.values()), get_mode(count))
else:
yield ()
def defects(lst):
return sum(lst[i - 1] == lst[i] for i in range(1, len(lst)))
def test(lst):
perms = set(permutations(lst))
opt = min(map(defects, perms))
slow = {perm for perm in perms if defects(perm) == opt}
fast = set(enum(lst))
print(lst, fast, slow)
assert slow == fast
for r in range(10000):
test([randrange(3) for i in range(randrange(6))])
[1, 2, 1, 3, 1, 4, 1, 5]
কিছু ঠিক[1, 3, 1, 2, 1, 4, 1, 5]
আপনার মানদণ্ডের মতোই ?