পাইথন, স্কোর: 2 1.5 1.25
এটি প্রিমোর উত্তর এবং আমার উত্তরের মধ্যে সরাসরি সংমিশ্রণ। তাই ক্রেডিটও তাকে!
প্রমাণটি এখনও চলছে, তবে এখানে কোডটি খেলতে হবে! আপনি যদি ১.২৫ এর চেয়ে বেশি স্কোরের একটি পাল্টা উদাহরণ খুঁজে পেতে পারেন (বা যদি কোনও বাগ থাকে) তবে আমাকে জানান!
বর্তমানে সবচেয়ে খারাপ পরিস্থিতি হ'ল:
আ ... এএ ডিসিবি ... সিবিডি
যেখানে "a", "b", "c", এবং "" (স্পেস) অক্ষরগুলির ঠিক এন থাকে এবং ঠিক দুটি "d" গুলি থাকে। স্ট্রিংয়ের দৈর্ঘ্য 4n + 2 এবং অ্যাসাইনমেন্টের সংখ্যা 5n + 2 , 5/4 = 1.25 এর স্কোর দেয় ।
অ্যালগরিদম দুটি ধাপে কাজ করে:
- এই
k
যে এই ধরনের string[k]
এবং string[n-1-k]
শব্দ সীমা রয়েছে
- অ্যালগরিদমকে বিপরীত করে কোনও শব্দ চালান
string[:k]+string[n-1-k:]
(অর্থাত্ প্রথম k
এবং শেষ k
অক্ষরের সংক্ষিপ্তকরণ) ছোট সংশোধন করে।
n
স্ট্রিং দৈর্ঘ্য যেখানে ।
উন্নতি এই অ্যালগরিদম দেয় পদক্ষেপ 2. মধ্যে "ছোট পরিবর্তন" থেকে আসে এটি মূলত যে জ্ঞান যোগসূত্র স্ট্রিং, অবস্থানে অক্ষর k
এবং k+1
শব্দ সীমানা (যা মানে তারা একটি শব্দ স্পেস বা প্রথম / শেষ চরিত্র হয়) হয়, এবং তাই আমরা সরাসরি অক্ষর অবস্থানে প্রতিস্থাপন করতে পারেন k
এবং k+1
চূড়ান্ত স্ট্রিং সংশ্লিষ্ট অক্ষর দিয়ে, কয়েক বরাদ্দকরণ সংরক্ষণ। এটি হোস্ট ওয়ার্ড-রিভার্সাল অ্যালগরিদম থেকে সবচেয়ে খারাপ কেসটি সরিয়ে দেয়
এমন কেস রয়েছে যেখানে আমরা আসলে এটি খুঁজে পাই না k
, সে ক্ষেত্রে আমরা পুরো স্ট্রিংয়ে কেবল "কোনও শব্দ বিপরীত অ্যালগরিদম" চালাই।
কোডটি "কনকেনটেটেড" স্ট্রিংয়ে বিপরীত অ্যালগরিদম শব্দটি চালানোর ক্ষেত্রে এই চারটি কেস পরিচালনা করতে দীর্ঘতর:
- কখন
k
পাওয়া যায় না ( f_long = -2
)
- কখন
string[k] != ' ' and string[n-1-k] != ' '
( f_long = 0
)
- কখন
string[k] != ' ' and string[n-1-k] == ' '
( f_long = 1
)
- কখন
string[k] == ' ' and string[n-1-k] != ' '
( f_long = -1
)
আমি নিশ্চিত যে কোডটি ছোট করা যেতে পারে। বর্তমানে এটি দীর্ঘ কারণ আমার শুরুতে পুরো অ্যালগরিদমের সুস্পষ্ট ছবি ছিল না। আমি নিশ্চিত যে এটি একটি সংক্ষিপ্ত কোডে উপস্থাপনের জন্য ডিজাইন করতে পারে =)
নমুনা রান (প্রথমটি আমার, দ্বিতীয়টি প্রিমোর):
স্ট্রিং প্রবেশ করান: একটি বিসি ডিএফ গিজ
"গিজ ডিএফ বিসি এ": 9, 13, 0.692
"গিজ ডিএফ বিসি এ": 9, 13, 0.692
স্ট্রিং প্রবেশ করান: ab cdefghijklmnopqrstuvw xyz
"zyxwvutsrqponMLkjihgf edc ab": 50, 50, 1.000
"zyxwvutsrqponMLkjihgf edc ab": 51, 50, 1.020
স্ট্রিং প্রবেশ করুন: abcdefg hijklmnopqrstuvwx
"hijklmnopqrstuvwx gfedcb a": 38, 31, 1.226
"hijklmnopqrstuvwx gfedcb a": 38, 31, 1.226
স্ট্রিংটি প্রবেশ করান: একটি বিসি ডি এফজি হাই জে কে এলএম নো পিক আরএস টু ভিডাব্লু এক্সওয়াই জেডি
"জেডিসি এক্স ভি ভি টু আরএসপিউ নো এলএম জে কে হি এফজি ডি বিসি এ": 46, 40, 1.150
"জেডিসি এক্স ভি ভি টু আরএসপিউ নো এলএম জে কে হি এফজি ডি বিসি এ": 53, 40, 1.325
স্ট্রিং লিখুন: aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa dcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbd
"Dcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbd aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaa একটি": 502, 402, 1,249
"Dcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbd aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaa একটি": 502, 402, 1,249
আপনি দেখতে পাচ্ছেন যে তৃতীয় উদাহরণের হোস্ট ওয়ার্ড-রিভার্সাল অ্যালগরিদমের সবচেয়ে খারাপ ক্ষেত্রে ব্যতীত স্কোর প্রায় একই রকম, যার জন্য আমার পদ্ধতির ১.২৫ এরও কম স্কোর পাওয়া যায়
DEBUG = False
def find_new_idx(string, pos, char, f_start, f_end, b_start, b_end, f_long):
if DEBUG: print 'Finding new idx for s[%d] (%s)' % (pos, char)
if f_long == 0:
f_limit = f_end-1
b_limit = b_start
elif f_long == 1:
f_limit = f_end-1
b_limit = b_start+1
elif f_long == -1:
f_limit = f_end-2
b_limit = b_start
elif f_long == -2:
f_limit = f_end
b_limit = b_start
if (f_start <= pos < f_limit or b_limit < pos < b_end) and char == ' ':
word_start = pos
word_end = pos+1
else:
if pos < f_limit+1:
word_start = f_start
if DEBUG: print 'Assigned word_start from f_start (%d)' % f_start
elif pos == f_limit+1:
word_start = f_limit+1
if DEBUG: print 'Assigned word_start from f_limit+1 (%d)' % (f_limit+1)
elif b_limit <= pos:
word_start = b_limit
if DEBUG: print 'Assigned word_start from b_limit (%d)' % b_limit
elif b_limit-1 == pos:
word_start = b_limit-1
if DEBUG: print 'Assigned word_start from b_limit-1 (%d)' % (b_limit-1)
i = pos
while f_start <= i <= f_limit or 0 < b_limit <= i < b_end:
if i==f_limit or i==b_limit:
cur_char = 'a'
elif i!=pos:
cur_char = string[i]
else:
cur_char = char
if cur_char == ' ':
word_start = i+1
if DEBUG: print 'Assigned word_start from loop'
break
i -= 1
if b_limit <= pos:
word_end = b_end
if DEBUG: print 'Assigned word_end from b_end (%d)' % b_end
elif b_limit-1 == pos:
word_end = b_limit
if DEBUG: print 'Assigned word_end from b_limit (%d)' % (b_limit)
elif pos < f_limit+1:
word_end = f_limit+1
if DEBUG: print 'Assigned word_end from f_limit+1 (%d)' % (f_limit+1)
elif pos == f_limit+1:
word_end = f_limit+2
if DEBUG: print 'Assigned word_end from f_limit+2 (%d)' % (f_limit+2)
i = pos
while f_start <= i <= f_limit or 0 < b_limit <= i < b_end:
if i==f_limit or i==b_limit:
cur_char = 'a'
elif i!=pos:
cur_char = string[i]
else:
cur_char = char
if cur_char == ' ':
word_end = i
if DEBUG: print 'Assigned word_end from loop'
break
i += 1
if DEBUG: print 'start, end: %d, %d' % (word_start, word_end)
word_len = word_end - word_start
offset = word_start-f_start
result = (b_end-offset-(word_end-pos)) % b_end
if string[result] == ' ' and (b_start == -1 or result not in {f_end-1, b_start}):
return len(string)-1-result
else:
return result
def process_loop(string, start_idx, f_start, f_end, b_start, b_end=-1, f_long=-2, dry_run=False):
assignments = 0
pos = start_idx
tmp = string[pos]
processed_something = False
count = 0
while pos != start_idx or not processed_something:
count += 1
if DEBUG and count > 20:
print '>>>>>Break!<<<<<'
break
new_pos = find_new_idx(string, pos, tmp, f_start, f_end, b_start, b_end, f_long)
if DEBUG:
if dry_run:
print 'Test:',
else:
print '\t',
print 'New idx for s[%d] (%s): %d (%s)' % (pos, tmp, new_pos, string[new_pos])
if dry_run:
tmp = string[new_pos]
if new_pos == dry_run:
return True
elif pos == new_pos:
break
elif tmp == string[new_pos]:
pass
else:
tmp, string[new_pos] = string[new_pos], tmp
assignments += 1
pos = new_pos
processed_something = True
if dry_run:
return False
return assignments
def reverse(string, f_start, f_end, b_start, b_end=-1, f_long=-2):
if DEBUG: print 'reverse: %d %d %d %d %d' % (f_start, f_end, b_start, b_end, f_long)
if DEBUG: print
if DEBUG: print ''.join(string)
assignments = 0
n = len(string)
if b_start == -1:
for i in range(f_start, f_end):
if string[i] == ' ':
continue
if DEBUG: print 'Starting from i=%d' % i
if any(process_loop(string, j, f_start, f_end, -1, f_end, dry_run=i) for j in range(f_start, i) if string[j] != ' '):
continue
if DEBUG:
print
print 'Finished test'
assignments += process_loop(string, i, f_start, f_end, -1, f_end)
if DEBUG: print
if DEBUG: print ''.join(string)
for i in range(f_start, (f_start+f_end-1)/2):
if (string[i] == ' ' and string[n-1-i] != ' ') or (string[i] != ' ' and string[n-1-i] == ' '):
string[i], string[n-1-i] = string[n-1-i], string[i]
assignments += 2
else:
for i in range(f_start, f_end)+range(b_start, b_end):
if string[i] == ' ' and i not in {f_end-1, b_start}:
continue
if DEBUG: print 'Starting from i=%d' % i
if any(process_loop(string, j, f_start, f_end, b_start, b_end, f_long, i) for j in range(f_start, f_end)+range(b_start, b_end) if j<i and (string[j] != ' ' or j in {f_end-1, b_start})):
continue
assignments += process_loop(string, i, f_start, f_end, b_start, b_end, f_long)
if DEBUG: print
if DEBUG: print ''.join(string)
for i in range(f_start, f_end-1):
if (string[i] == ' ' and string[n-1-i] != ' ') or (string[i] != ' ' and string[n-1-i] == ' '):
string[i], string[n-1-i] = string[n-1-i], string[i]
assignments += 2
return assignments
class SuperList(list):
def index(self, value, start_idx=0):
try:
return self[:].index(value, start_idx)
except ValueError:
return -1
def rindex(self, value, end_idx=-1):
end_idx = end_idx % (len(self)+1)
try:
result = end_idx - self[end_idx-1::-1].index(value) - 1
except ValueError:
return -1
return result
def min_reverse(string):
assignments = 0
lower = 0
upper = len(string)
while lower < upper:
front = string.index(' ', lower) % (upper+1)
back = string.rindex(' ', upper)
while abs(front-lower - (upper-1-back)) > 1 and front < back:
if front-lower < (upper-1-back):
front = string.index(' ', front+1) % (upper+1)
else:
back = string.rindex(' ', back)
if DEBUG: print lower, front, back, upper
if front > back:
break
if DEBUG: print lower, front, back, upper
if abs(front-lower - (upper-1-back)) > 1:
assignments += reverse(string, lower, upper, -1)
lower = upper
elif front-lower < (upper-1-back):
assignments += reverse(string, lower, front+1, back+1, upper, -1)
lower = front+1
upper = back+1
elif front-lower > (upper-1-back):
assignments += reverse(string, lower, front, back, upper, 1)
lower = front
upper = back
else:
assignments += reverse(string, lower, front, back+1, upper, 0)
lower = front+1
upper = back
return assignments
def minier_find_new_idx(string, pos, char):
n = len(string)
try:
word_start = pos - next(i for i, char in enumerate(string[pos::-1]) if char == ' ') + 1
except:
word_start = 0
try:
word_end = pos + next(i for i, char in enumerate(string[pos:]) if char == ' ')
except:
word_end = n
word_len = word_end - word_start
offset = word_start
result = (n-offset-(word_end-pos))%n
if string[result] == ' ':
return n-result-1
else:
return result
def minier_process_loop(string, start_idx, dry_run=False):
assignments = 0
pos = start_idx
tmp = string[pos]
processed_something = False
while pos != start_idx or not processed_something:
new_pos = minier_find_new_idx(string, pos, tmp)
#print 'New idx for s[%d] (%s): %d (%s)' % (pos, tmp, new_pos, string[new_pos])
if pos == new_pos:
break
elif dry_run:
tmp = string[new_pos]
if new_pos == dry_run:
return True
elif tmp == string[new_pos]:
pass
else:
tmp, string[new_pos] = string[new_pos], tmp
assignments += 1
pos = new_pos
processed_something = True
if dry_run:
return False
return assignments
def minier_reverse(string):
assignments = 0
for i in range(len(string)):
if string[i] == ' ':
continue
if any(minier_process_loop(string, j, dry_run=i) for j in range(i) if string[j] != ' '):
continue
assignments += minier_process_loop(string, i)
n = len(string)
for i in range(n/2):
if string[i] == ' ' and string[n-i-1] != ' ':
string[i], string[n-i-1] = string[n-i-1], string[i]
assignments += 2
elif string[n-i-1] == ' ' and string[i] != ' ':
string[i], string[n-i-1] = string[n-i-1], string[i]
assignments += 2
return assignments
def main():
while True:
str_input = raw_input('Enter string: ')
string = SuperList(str_input)
result = min_reverse(string)
n = len(string)
print '"%s": %d, %d, %.3f' % (''.join(string), result, n, 1.0*result/n)
string = SuperList(str_input)
result2 = minier_reverse(string)
print '"%s": %d, %d, %.3f' % (''.join(string), result2, n, 1.0*result2/n)
if __name__ == '__main__':
main()
পাইথন, স্কোর: 1.5
সূত্রের মাধ্যমে অ্যাসাইনমেন্টের সঠিক সংখ্যাটি প্রায় অনুমান করা যায়:
n <= 1.5 * দৈর্ঘ্য (স্ট্রিং)
সবচেয়ে খারাপ অবস্থা হচ্ছে:
abcdefghi jklmnopqrstuvwxyzzz
37 স্ট্রিংয়ের সাথে 55 এসাইনমেন্টের সাথে দৈর্ঘ্য 37।
ধারণাটি আমার আগেরটির মতোই, এটি কেবলমাত্র এই সংস্করণে আমি সর্বাধিক দৈর্ঘ্যের পার্থক্যের সাথে শব্দের সীমানায় উপসর্গ এবং প্রত্যয়টি সন্ধান করার চেষ্টা করেছি। তারপরে আমি আমার পূর্ববর্তী অ্যালগরিদমটিকে উপসর্গ এবং প্রত্যয়টিতে চালিয়েছি (তাদেরকে সংযুক্ত হিসাবে কল্পনা করুন) । তারপরে অপ্রয়োজনীয় অংশে চালিয়ে যান।
উদাহরণস্বরূপ, পূর্ববর্তী সবচেয়ে খারাপ ক্ষেত্রে:
AB | AB | গ
আমরা প্রথমে "আব" এবং "সি" (4 অ্যাসাইনমেন্ট) এর উপরে শব্দটি বিপরীত করব:
গ | AB | AB
আমরা জানি যে সীমানায় এটি স্থান ছিল (হ্যান্ডেল করার জন্য অনেকগুলি কেস রয়েছে, তবে আপনি এটি করতে পারেন), তাই আমাদের সীমানায় স্থানটি এনকোড করার দরকার নেই, এটি পূর্ববর্তী অ্যালগরিদম থেকে মূল উন্নতি is ।
তারপরে অবশেষে আমরা পেতে মাঝারি চারটি অক্ষরটিতে দৌড়েছি:
সিবিএ আব
মোট 8 টি কার্যভারে, সমস্ত 8 টি অক্ষর পরিবর্তিত হওয়ায় এই মামলার অনুকূল।
এটি পূর্ববর্তী অ্যালগরিদমের সবচেয়ে খারাপ কেসটি সরিয়ে দেয় কারণ আগের অ্যালগরিদমের সবচেয়ে খারাপ কেসটি নির্মূল করা হয়।
কিছু নমুনা রান দেখুন (এবং @ প্রিমোর উত্তরটির সাথে তুলনা করুন - এটি দ্বিতীয় লাইন):
স্ট্রিং প্রবেশ করান: আমি কিছু করতে পারি
"আমি কিছু করতে পারি": 20, 17
"আমি কিছু করতে পারি": 17, 17
স্ট্রিং প্রবেশ করুন: abcdef ghijklmnopqrs
"ghijklmnopqrs fedcb a": 37, 25
"ghijklmnopqrs fedcb a": 31, 25
স্ট্রিং প্রবেশ করুন: abcdef ghijklmnopqrst
"ghijklmnopqrst fedcb a": 38, 26
"ghijklmnopqrst fedcb a": 32, 26
স্ট্রিং প্রবেশ করুন: abcdefghi jklmnozzzzzzzzzzzzzzzzz
"jklmnozzzzzzzzzzzzzzzzz ihgfedcb a": 59, 41
"jklmnozzzzzzzzzzzzzzzzz ihgfedcb a": 45, 41
স্ট্রিং প্রবেশ করুন: abcdefghi jklmnopqrstuvwxyzzz
"jklmnopqrstuvwxyzzz ihgfedcb a": 55, 37
"jklmnopqrstuvwxyzzz ihgfedcb a": 45, 37
স্ট্রিং প্রবেশ করুন: আব আববাববাবাক
"কাবাববাববা আব": 30, 30
"কাবাববাববা আব": 31, 30
স্ট্রিং প্রবেশ করান: আব আববাববাবস
"সিবাবাবাবাবা আব": 32, 32
"সিবাবাবাবাবা আব": 33, 32
স্ট্রিং প্রবেশ করুন: abc d abc
"abc d abc": 0, 9
"abc d abc": 0, 9
স্ট্রিং প্রবেশ করুন: abc dca
"এসিডি এবিসি": 6, 9
"এসিডি এবিসি": 4, 9
স্ট্রিং প্রবেশ করুন: abc ababababababc
"সিবাবাববাবা এবিসি": 7, 29
"সিবাবাববাবা এবিসি": 5, 29
প্রিমোর উত্তরটি সাধারণত ভাল তবে কিছু ক্ষেত্রে আমার 1 পয়েন্ট সুবিধা থাকতে পারে =)
এছাড়াও তার কোডটি আমার চেয়ে অনেক ছোট ha
DEBUG = False
def find_new_idx(string, pos, char, f_start, f_end, b_start, b_end, f_long):
if DEBUG: print 'Finding new idx for s[%d] (%s)' % (pos, char)
if f_long == 0:
f_limit = f_end-1
b_limit = b_start
elif f_long == 1:
f_limit = f_end-1
b_limit = b_start+1
elif f_long == -1:
f_limit = f_end-2
b_limit = b_start
elif f_long == -2:
f_limit = f_end
b_limit = b_start
if (f_start <= pos < f_limit or b_limit < pos < b_end) and (char == ' ' or char.isupper()):
word_start = pos
word_end = pos+1
else:
if pos < f_limit+1:
word_start = f_start
if DEBUG: print 'Assigned word_start from f_start (%d)' % f_start
elif pos == f_limit+1:
word_start = f_limit+1
if DEBUG: print 'Assigned word_start from f_limit+1 (%d)' % (f_limit+1)
elif b_limit <= pos:
word_start = b_limit
if DEBUG: print 'Assigned word_start from b_limit (%d)' % b_limit
elif b_limit-1 == pos:
word_start = b_limit-1
if DEBUG: print 'Assigned word_start from b_limit-1 (%d)' % (b_limit-1)
i = pos
if not (i < f_limit and b_limit < i):
i -= 1
while f_start <= i < f_limit or 0 < b_limit < i < b_end:
if i!=pos:
cur_char = string[i]
else:
cur_char = char
if cur_char == ' ' or cur_char.isupper():
word_start = i+1
if DEBUG: print 'Assigned word_start from loop'
break
i -= 1
if b_limit <= pos:
word_end = b_end
if DEBUG: print 'Assigned word_end from b_end (%d)' % b_end
elif b_limit-1 == pos:
word_end = b_limit
if DEBUG: print 'Assigned word_end from b_limit (%d)' % (b_limit)
elif pos < f_limit+1:
word_end = f_limit+1
if DEBUG: print 'Assigned word_end from f_limit+1 (%d)' % (f_limit+1)
elif pos == f_limit+1:
word_end = f_limit+2
if DEBUG: print 'Assigned word_end from f_limit+2 (%d)' % (f_limit+2)
i = pos
if not (i < f_limit and b_limit < i):
i += 1
while f_start <= i < f_limit or 0 < b_limit < i < b_end:
if i!=pos:
cur_char = string[i]
else:
cur_char = char
if cur_char == ' ' or cur_char.isupper():
word_end = i
if DEBUG: print 'Assigned word_end from loop'
break
i += 1
if DEBUG: print 'start, end: %d, %d' % (word_start, word_end)
word_len = word_end - word_start
offset = word_start-f_start
return (b_end-offset-(word_end-pos)) % b_end
def process_loop(string, start_idx, f_start, f_end, b_start, b_end=-1, f_long=-2, dry_run=False):
assignments = 0
pos = start_idx
tmp = string[pos]
processed_something = False
count = 0
while pos != start_idx or not processed_something:
count += 1
if count > 20:
if DEBUG: print 'Break!'
break
new_pos = find_new_idx(string, pos, tmp, f_start, f_end, b_start, b_end, f_long)
#if dry_run:
# if DEBUG: print 'Test:',
if DEBUG: print 'New idx for s[%d] (%s): %d (%s)' % (pos, tmp, new_pos, string[new_pos])
if pos == new_pos:
break
elif dry_run:
tmp = string[new_pos]
if new_pos == dry_run:
return True
elif tmp == string[new_pos]:
pass
elif tmp == ' ':
if b_start!=-1 and new_pos in {f_end-1, b_start}:
tmp, string[new_pos] = string[new_pos], tmp
else:
tmp, string[new_pos] = string[new_pos], '@'
assignments += 1
elif string[new_pos] == ' ':
if b_start!=-1 and new_pos in {f_end-1, b_start}:
tmp, string[new_pos] = string[new_pos], tmp
else:
tmp, string[new_pos] = string[new_pos], tmp.upper()
assignments += 1
else:
tmp, string[new_pos] = string[new_pos], tmp
assignments += 1
pos = new_pos
processed_something = True
if dry_run:
return False
return assignments
def reverse(string, f_start, f_end, b_start, b_end=-1, f_long=-2):
if DEBUG: print 'reverse: %d %d %d %d %d' % (f_start, f_end, b_start, b_end, f_long)
if DEBUG: print
if DEBUG: print ''.join(string)
assignments = 0
if b_start == -1:
for i in range(f_start, (f_start+f_end)/2):
if DEBUG: print 'Starting from i=%d' % i
if any(process_loop(string, j, f_start, f_end, -1, f_end, dry_run=i) for j in range(f_start, i)):
continue
assignments += process_loop(string, i, f_start, f_end, -1, f_end)
if DEBUG: print
if DEBUG: print ''.join(string)
else:
for i in range(f_start, f_end):
if DEBUG: print 'Starting from i=%d' % i
if any(process_loop(string, j, f_start, f_end, b_start, b_end, f_long, i) for j in range(f_start, i)):
continue
assignments += process_loop(string, i, f_start, f_end, b_start, b_end, f_long)
if DEBUG: print
if DEBUG: print ''.join(string)
for i in range(len(string)):
if string[i] == '@':
string[i] = ' '
assignments += 1
if string[i].isupper():
string[i] = string[i].lower()
assignments += 1
return assignments
class SuperList(list):
def index(self, value, start_idx=0):
try:
return self[:].index(value, start_idx)
except ValueError:
return -1
def rindex(self, value, end_idx=-1):
end_idx = end_idx % (len(self)+1)
try:
result = end_idx - self[end_idx-1::-1].index(value) - 1
except ValueError:
return -1
return result
def min_reverse(string):
# My algorithm
assignments = 0
lower = 0
upper = len(string)
while lower < upper:
front = string.index(' ', lower) % (upper+1)
back = string.rindex(' ', upper)
while abs(front-lower - (upper-1-back)) > 1 and front < back:
if front-lower < (upper-1-back):
front = string.index(' ', front+1) % (upper+1)
else:
back = string.rindex(' ', back)
if DEBUG: print lower, front, back, upper
if front > back:
break
if DEBUG: print lower, front, back, upper
if abs(front-lower - (upper-1-back)) > 1:
assignments += reverse(string, lower, upper, -1)
lower = upper
elif front-lower < (upper-1-back):
assignments += reverse(string, lower, front+1, back+1, upper, -1)
lower = front+1
upper = back+1
elif front-lower > (upper-1-back):
assignments += reverse(string, lower, front, back, upper, 1)
lower = front
upper = back
else:
assignments += reverse(string, lower, front, back+1, upper, 0)
lower = front+1
upper = back
return assignments
def minier_find_new_idx(string, pos, char):
n = len(string)
try:
word_start = pos - next(i for i, char in enumerate(string[pos::-1]) if char == ' ') + 1
except:
word_start = 0
try:
word_end = pos + next(i for i, char in enumerate(string[pos:]) if char == ' ')
except:
word_end = n
word_len = word_end - word_start
offset = word_start
result = (n-offset-(word_end-pos))%n
if string[result] == ' ':
return n-result-1
else:
return result
def minier_process_loop(string, start_idx, dry_run=False):
assignments = 0
pos = start_idx
tmp = string[pos]
processed_something = False
while pos != start_idx or not processed_something:
new_pos = minier_find_new_idx(string, pos, tmp)
#print 'New idx for s[%d] (%s): %d (%s)' % (pos, tmp, new_pos, string[new_pos])
if pos == new_pos:
break
elif dry_run:
tmp = string[new_pos]
if new_pos == dry_run:
return True
elif tmp == string[new_pos]:
pass
else:
tmp, string[new_pos] = string[new_pos], tmp
assignments += 1
pos = new_pos
processed_something = True
if dry_run:
return False
return assignments
def minier_reverse(string):
# primo's answer for comparison
assignments = 0
for i in range(len(string)):
if string[i] == ' ':
continue
if any(minier_process_loop(string, j, dry_run=i) for j in range(i) if string[j] != ' '):
continue
assignments += minier_process_loop(string, i)
n = len(string)
for i in range(n/2):
if string[i] == ' ' and string[n-i-1] != ' ':
string[i], string[n-i-1] = string[n-i-1], string[i]
assignments += 2
elif string[n-i-1] == ' ' and string[i] != ' ':
string[i], string[n-i-1] = string[n-i-1], string[i]
assignments += 2
return assignments
def main():
while True:
str_input = raw_input('Enter string: ')
string = SuperList(str_input)
result = min_reverse(string)
print '"%s": %d, %d' % (''.join(string), result, len(string))
string = SuperList(str_input)
result2 = minier_reverse(string)
print '"%s": %d, %d' % (''.join(string), result2, len(string))
if __name__ == '__main__':
main()
পাইথন, স্কোর: asympototically 2, সাধারণ ক্ষেত্রে খুব কম
পুরানো কোড স্থান সীমাবদ্ধতার কারণে সরানো হয়েছে
ধারণা প্রতিটি সূচক মাধ্যমে পুনরুক্তি করতে, এবং প্রতিটি সূচির জন্য i
, আমরা চরিত্র নিয়ে নতুন অবস্থান নিরূপণ j
, অবস্থানে চরিত্র মুখস্থ j
এ চরিত্র নির্ধারণ i
করতে j
সূচিতে অক্ষর দিয়ে, এবং পুনরাবৃত্তি j
। যেহেতু নতুন অবস্থান গণনা করার জন্য আমাদের স্থানের তথ্য দরকার, তাই আমি পুরানো স্থানটিকে নতুন চিঠির বড় আকারের সংস্করণ হিসাবে এবং নতুন স্থানটিকে '@' হিসাবে এনকোড করি।