একটি স্ট্রিং পার্টিশন ব্লক করুন


11

অনুপ্রেরণা

lসংখ্যা নিয়ে গঠিত একটি তালিকা বিবেচনা করুন । সূচিতে একটি ব্লক অপারেশন নির্ধারণ iতালিকায় l3 পরপর থেকে শুরু উপাদান চলন্ত আইন হতে iমধ্যে lশেষ।

উদাহরণ:

l, i (1-indexing) -> l (after applying block operation at index i)
[1,2,3,4,5], 1 -> [4,5,1,2,3]
[1,2,3,4,5,6,7], 3 -> [1,2,6,7,3,4,5]

কেবল 0 এবং 1 এর সমন্বিত একটি তালিকা দেওয়া, আপনার চ্যালেঞ্জটি এটির বিভাজন করা যাতে জিরোগুলি সামনে থাকে এবং কেবলমাত্র ব্লক ক্রিয়াকলাপগুলি ব্যবহার করে পিছনে থাকে। আউটপুট সেই তালিকাগুলিতে প্রয়োগ করা হয় সে অনুযায়ী সূচিগুলি হওয়া উচিত।

কারণ এটি তালিকার পক্ষে অসম্ভব [1,0,1,0], তালিকাটির দৈর্ঘ্য কমপক্ষে 5 হওয়ার নিশ্চয়তা রয়েছে।

পরীক্ষার কেস (1-ইনডেক্সিং)

(অন্যান্য বৈধ আউটপুট আছে)

[1,1,1,0,0] -> [1]
[0,1,0,1,0] -> [1,2,1,1]
[0,0,0,1,1,1,0,0,0] -> [4]

আরও পরীক্ষার কেস উত্পন্ন করতে এই স্ক্রিপ্টটি ব্যবহার করুন । (কেবলমাত্র ইনপুট The rplc ' ';','অংশটি আউটপুটে কমা দিয়ে একটি সি ই স্পেসে r e pl করতে ব্যবহৃত হয় )

জয়ের মানদণ্ড

হ'ল মূল বিজয়ী মানদণ্ড, এবং টাই-ব্রেকার break নির্দিষ্টভাবে:

  • পরীক্ষার কেস ( n_elem= 500, random_seed= {গোপনীয় মান}) দিয়ে স্বল্পতম আউটপুট দৈর্ঘ্যের (ব্লক অপারেশনের ন্যূনতম সংখ্যা) সহ সমাধানটি জয়লাভ করে। আপনি পরীক্ষার কেস ( n_elem= 500, random_seed= 123456) দিয়ে সমাপ্তির জন্য আপনার সমাধানটি চালাতে সক্ষম হবেন ।
  • সম্পর্কের ক্ষেত্রে, এমন সমাধান যা 10 সেকেন্ডের মধ্যে (for গোপনীয় মান}) এর n_elemসাথে সবচেয়ে বড় পাওয়ার-অফ -2 মানটি পরিচালনা করতে পারে random_seed(আমার পক্ষে) জয়ী।
  • সম্পর্কগুলির ক্ষেত্রে, সেই পরীক্ষার ক্ষেত্রে যে সমাধানটি কম সময় নেয় সেটি জয়ী হয়।

স্যান্ডবক্স পোস্ট । (দ্রষ্টব্য) আমার কাছে লিনিয়ার-টাইম লিনিয়ার-স্পেস সমাধান রয়েছে তবে এর বিশাল ধ্রুবক ফ্যাক্টর রয়েছে, তাছাড়া এটি কার্যকর করা সহজ নয়। ধ্রুবক ফ্যাক্টর হ্রাস করা সম্ভব তবে এর বাস্তবায়ন আরও কঠিন।
ব্যবহারকারী 202729

(অস্বীকৃতি: আমি সংযুক্ত চ্যালেঞ্জটি সমাধান করেছি)
ব্যবহারকারী 202729

কেবল পরিষ্কার করার জন্য, আউটপুটটির সংক্ষিপ্ততম আউটপুট হওয়ার দরকার নেই?
জংহওয়ান মিন

পুনঃটুইট
ব্যবহারকারী 202729

উত্তর:


8

পাইথন 3 , (0.397 এন + 3.58) পদক্ষেপ

1000 দফা দ্বারা বহুপদী রিগ্রেশন numpy.polyfit


  • সংস্করণ 1 এর জন্য পদক্ষেপের সংখ্যা: 0.0546 n² + 2.80 এন - 221
  • সংস্করণ 2 এর জন্য পদক্ষেপের সংখ্যা: 0.0235 n² + 0.965 এন - 74
  • সংস্করণ 3 এর জন্য পদক্ষেপের সংখ্যা: 0.00965 n² + 2.35 এন - 111
  • সংস্করণ 4 এর জন্য পদক্ষেপের সংখ্যা: 1.08 এন - 36.3
  • সংস্করণ 5 এর জন্য পদক্ষেপের সংখ্যা: 0.397 এন + 3.58

  • সংস্করণ 1: 14468 এর গোপন পরীক্ষার কেস স্কোর
  • সংস্করণ 2: 5349 এর গোপন পরীক্ষার কেস স্কোর
  • সংস্করণ 3: 4143 এর গোপন পরীক্ষার কেস স্কোর
  • সংস্করণ 4: 450 এর গোপন পরীক্ষার কেস স্কোর
  • সংস্করণ 5: 205 এর গোপন পরীক্ষার কেস স্কোর

def partite(L):
	endgame5 = [9,9,1,9,0,0,1,9,
		0,1,0,1,0,1,1,9,
		0,0,1,0,0,0,1,0,
		0,0,0,1,0,0,0,9]
	endgame6 = [9,9,2,9,1,1,2,9,0,2,0,0,1,2,2,9,
		0,1,2,1,0,1,2,1,0,1,0,2,1,1,0,9,
		0,0,1,0,1,0,1,1,0,0,0,0,1,1,1,1,
		0,0,2,2,0,0,2,2,0,0,0,0,0,0,0,9]
	endgame = [9,9,3,9,2,2,3,9,1,0,3,0,2,0,3,9,0,1,3,3,2,2,3,0,1,0,1,0,2,1,0,9,
		0,0,2,1,0,0,2,2,1,0,1,2,0,0,0,2,0,1,3,3,3,3,3,0,1,1,1,1,1,3,0,9,
		0,0,0,0,1,0,1,1,1,0,3,0,1,0,1,0,0,1,0,0,1,1,0,0,1,0,0,0,2,0,1,0,
		0,0,2,0,0,0,2,0,0,0,2,0,0,0,2,0,0,0,3,0,3,0,3,0,3,0,2,3,3,0,0,9]
	offset = 1
	steps = []
	def update(L,steps,ind):
		steps.append(offset + ind)
		if 0 <= ind and ind+3 < len(L):
			return (steps,L[:ind]+L[ind+3:]+L[ind:ind+3])
		else:
			print(offset,ind,L)
			raise
	if len(L) == 5:
		while endgame5[L[0]*16+L[1]*8+L[2]*4+L[3]*2+L[4]] != 9:
			steps, L = update(L,steps,endgame5[L[0]*16+L[1]*8+L[2]*4+L[3]*2+L[4]])
		return steps
	if len(L) == 6:
		while endgame6[L[0]*32+L[1]*16+L[2]*8+L[3]*4+L[4]*2+L[5]] != 9:
			steps, L = update(L,steps,endgame6[L[0]*32+L[1]*16+L[2]*8+L[3]*4+L[4]*2+L[5]])
		return steps
	if 1 not in L:
		return []
	while len(L) > 7 and 0 in L:
		wf_check = len(L)
		while L[0] != 0:
			pos = [-1]
			wf_check2 = -1
			while True:
				i = pos[-1]+1
				while i < len(L):
					if L[i] == 0:
						pos.append(i)
						i += 1
					else:
						i += 3
				assert len(pos) > wf_check2
				wf_check2 = len(pos)
				space = (pos[-1]-len(L)+1)%3
				ind = -1
				tail = pos.pop()
				i = len(L)-1
				while i >= 0:
					if tail == i:
						while tail == i:
							i -= 1
							tail = pos.pop() if pos else -1
						i -= 2
					elif i < len(L)-3 and L[i+space] == 0:
						ind = i
						break
					else:
						i -= 1
				if ind == -1:
					break
				steps, L = update(L, steps, ind)
				pos = pos or [-1]
			if L[0] == 0:
				break
			pos = [-1]
			while L[0] != 0:
				pos = [-1]
				found = False
				for i in range(1,len(L)):
					if L[i] == 0:
						if i%3 == (pos[-1]+1)%3:
							pos.append(i)
						else:
							found = found or i
				if found > len(L)-4:
					found = False
				if not found:
					break
				triple = []
				for i in range(1,len(L)-1):
					if L[i-1] == 1 and L[i] == 1 and L[i+1] == 1:
						triple.append(i)
					if len(triple) > 3:
						break
				space = (pos[-1]-len(L)+1)%3
				if space == 0:
					if found >= 2 and found-2 not in pos and found-1 not in pos:
						# ... _ 1 _ [0] 0 ...
						if found-2 in triple:
							triple.remove(found-2)
						if found-3 in triple:
							triple.remove(found-3)
						if L[-1] == 1:
							steps, L = update(L, steps, found-2)
							steps, L = update(L, steps, len(L)-4)
							steps, L = update(L, steps, len(L)-4)
						elif triple:
							steps, L = update(L, steps, found-2)
							if found < triple[0]:
								triple[0] -= 3
							steps, L = update(L, steps, triple[0]-1)
							steps, L = update(L, steps, len(L)-4)
						else:
							break
						assert L[-3] == 0
					elif found >= 1 and found-1 not in pos and found+1 not in pos:
						# ... _ 1 [0] _ 0 ...
						if found-2 in triple:
							triple.remove(found-2)
						if L[-2] == 1 and L[-1] == 1:
							steps, L = update(L, steps, found-1)
							steps, L = update(L, steps, len(L)-5)
							steps, L = update(L, steps, len(L)-5)
						elif triple:
							steps, L = update(L, steps, found-1)
							if found < triple[0]:
								triple[0] -= 3
							steps, L = update(L, steps, triple[0]-1)
							steps, L = update(L, steps, len(L)-5)
						elif L[-1] == 1:
							steps, L = update(L, steps, found-1)
							steps, L = update(L, steps, len(L)-4)
							steps, L = update(L, steps, len(L)-4)
							steps, L = update(L, steps, len(L)-4)
						else:
							break
						assert L[-3] == 0
					else:
						break
				elif space == 1:
					# ... 1 1 [0] 0 ...
					if found >= 2 and found-2 not in pos and found-1 not in pos:
						if found-2 in triple:
							triple.remove(found-2)
						if found-3 in triple:
							triple.remove(found-3)
						if triple:
							steps, L = update(L, steps, found-2)
							if found < triple[0]:
								triple[0] -= 3
							steps, L = update(L, steps, triple[0]-1)
							steps, L = update(L, steps, len(L)-5)
						elif L[-2] == 1 and L[-1] == 1:
							steps, L = update(L, steps, found-2)
							steps, L = update(L, steps, len(L)-4)
							steps, L = update(L, steps, len(L)-5)
						else:
							break
						assert L[-2] == 0
					else:
						break
				else:
					if found+1 not in pos and found+2 not in pos:
						# ... 0 [0] _ 1 _ ...
						if found+2 in triple:
							triple.remove(found+2)
						if found+3 in triple:
							triple.remove(found+3)
						if L[-2] == 1 and L[-1] == 1:
							steps, L = update(L, steps, found)
							steps, L = update(L, steps, len(L)-5)
						elif L[-1] == 1:
							steps, L = update(L, steps, found)
							steps, L = update(L, steps, len(L)-4)
							steps, L = update(L, steps, len(L)-4)
						elif triple:
							steps, L = update(L, steps, triple[0]-1)
							if triple[0] < found:
								found -= 3
							steps, L = update(L, steps, found)
							steps, L = update(L, steps, len(L)-5)
						else:
							break
						assert L[-1] == 0
					elif found >= 1 and found-1 not in pos and found+1 not in pos:
						# ... 0 _ [0] 1 _ ...
						if found+2 in triple:
							triple.remove(found+2)
						if L[-1] == 1:
							steps, L = update(L, steps, found-1)
							steps, L = update(L, steps, len(L)-4)
						elif triple:
							steps, L = update(L, steps, triple[0]-1)
							if triple[0] < found:
								found -= 3
							steps, L = update(L, steps, found-1)
							steps, L = update(L, steps, len(L)-4)
						else:
							break
						assert L[-1] == 0
					else:
						break
			if L[0] == 0:
				break
			if 0 in L[::3]:
				assert L[::3].index(0) < wf_check
				wf_check = L[::3].index(0)
			steps, L = update(L, steps, 0)
		assert L[0] == 0
		offset += L.index(1)
		del L[:L.index(1)]
		continue
	if 0 in L:
		offset -= 7-len(L)
		L = [0]*(7-len(L))+L
		assert(len(L) == 7)
		while endgame[L[0]*64+L[1]*32+L[2]*16+L[3]*8+L[4]*4+L[5]*2+L[6]] != 9:
			steps, L = update(L,steps,endgame[L[0]*64+L[1]*32+L[2]*16+L[3]*8+L[4]*4+L[5]*2+L[6]])
	return steps

এটি অনলাইন চেষ্টা করুন!


3

পাইথন 3, এন = 500 (গড়) এর জন্য 179 পদক্ষেপ

একটি তাত্পর্যপূর্ণ লোভী পদ্ধতির। কিন্ডা ধীর হলেও এখনও কাজ করে। ছোট আকারের জন্য একটি অনুকূল দ্রাবক ব্যবহার করে।

def incomplete_groups(l):
    r = 0
    ones = 0
    for x in l:
        if x == "1":
            ones += 1
        else:
            if ones % 3:
                r += 1
            ones = 0
    # Ones at the end don't count as an incomplete group.

    return r

def move(l, i):
    return l[:i] + l[i+3:] + l[i:i+3]

def best_pos(l, hist):
    r = []
    cleanup = incomplete_groups(l) == 0

    candidates = []
    for i in range(len(l) - 3):
        block = l[i:i+3]
        if block == "111" and cleanup:
            return i
        elif block == "111":
            continue

        new = move(l, i)
        bad_start = i < 3 and "10" in l[:3]
        candidates.append((new not in hist, -incomplete_groups(new), bad_start, block != "000", i))

    candidates.sort(reverse=True)
    return candidates[0][-1]

def done(l):
    return list(l) == sorted(l)



class IDAStar:
    def __init__(self, h, neighbours):
        """ Iterative-deepening A* search.

        h(n) is the heuristic that gives the cost between node n and the goal node. It must be admissable, meaning that h(n) MUST NEVER OVERSTIMATE the true cost. Underestimating is fine.

        neighbours(n) is an iterable giving a pair (cost, node, descr) for each node neighbouring n
        IN ASCENDING ORDER OF COST. descr is not used in the computation but can be used to
        efficiently store information about the path edges (e.g. up/left/right/down for grids).
        """

        self.h = h
        self.neighbours = neighbours
        self.FOUND = object()


    def solve(self, root, is_goal, max_cost=None):
        """ Returns the shortest path between the root and a given goal, as well as the total cost.
        If the cost exceeds a given max_cost, the function returns None. If you do not give a
        maximum cost the solver will never return for unsolvable instances."""

        self.is_goal = is_goal
        self.path = [root]
        self.is_in_path = {root}
        self.path_descrs = []
        self.nodes_evaluated = 0

        bound = self.h(root)

        while True:
            t = self._search(0, bound)
            if t is self.FOUND: return self.path, self.path_descrs, bound, self.nodes_evaluated
            if t is None: return None
            bound = t

    def _search(self, g, bound):
        self.nodes_evaluated += 1

        node = self.path[-1]
        f = g + self.h(node)
        if f > bound: return f
        if self.is_goal(node): return self.FOUND

        m = None # Lower bound on cost.
        for cost, n, descr in self.neighbours(node):
            if n in self.is_in_path: continue

            self.path.append(n)
            self.is_in_path.add(n)
            self.path_descrs.append(descr)
            t = self._search(g + cost, bound)

            if t == self.FOUND: return self.FOUND
            if m is None or (t is not None and t < m): m = t

            self.path.pop()
            self.path_descrs.pop()
            self.is_in_path.remove(n)

        return m

def h(l):
    """Number of groups of 1 with length <= 3 that come before a zero."""
    h = 0
    num_ones = 0
    complete_groups = 0
    incomplete_groups = 0
    for x in l:
        if x == "1":
            num_ones += 1
        else:
            while num_ones > 3:
                num_ones -= 3
                h += 1
                complete_groups += 1
            if num_ones > 0:
                h += 1
                incomplete_groups += 1
            num_ones = 0

    return complete_groups + incomplete_groups

def neighbours(l):
    inc_groups = incomplete_groups(l)
    final = inc_groups == 0

    candidates = []
    for i in range(len(l) - 3):
        left = l[:i]
        block = l[i:i+3]
        right = l[i+3:]
        cand = (1, left + right + block, i)

        # Optimal choice.
        if final and (block != "111" or i >= len(l.rstrip("1"))):
            continue

        candidates.append(cand)

    candidates.sort(key=lambda c: c[2], reverse=True)

    return candidates


def is_goal(l):
    return all(l[i] <= l[i+1] for i in range(len(l)-1))

opt_solver = IDAStar(h, neighbours)

def partite(l):
    if isinstance(l, list):
        l = "".join(map(str, l))
    if len(l) < 10:
        return [i + 1 for i in opt_solver.solve(l, is_goal)[1]]
    moves = []
    hist = [l]
    while not done(l):
        i = best_pos(l, hist)
        l = move(l, i)
        moves.append(i+1)
        hist.append(l)
    return moves
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.