पायथन, स्कोर: 2 1.5 1.25
यह प्रत्यक्ष है प्राइमो के उत्तर और मेरे उत्तर के बीच संयोजन है। तो उसे भी श्रेय!
सबूत अभी भी जारी है, लेकिन यहाँ कोड के साथ खेलना है! यदि आप 1.25 से अधिक स्कोर का एक काउंटर उदाहरण पा सकते हैं (या यदि कोई बग है), तो मुझे बताएं!
वर्तमान में सबसे खराब स्थिति यह है:
आ… आ डीसीबी… सीबीडी
जहाँ प्रत्येक अक्षर "a", "b", "c", और "" (स्थान) के बिल्कुल n होते हैं , और वास्तव में दो "d" s होते हैं। स्ट्रिंग की लंबाई 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
)
मुझे यकीन है कि कोड को छोटा किया जा सकता है। वर्तमान में यह लंबा है क्योंकि मेरे पास शुरुआत में पूरे एल्गोरिथ्म की स्पष्ट तस्वीर नहीं थी। मुझे यकीन है कि कोई इसे एक छोटे कोड में दर्शाने के लिए डिज़ाइन कर सकता है =)
नमूना रन (पहला मेरा है, दूसरा है प्राइमो का):
स्ट्रिंग दर्ज करें: bc def ghij
"घीज बीसी बीसी": 9, 13, 0.692
"घीज बीसी बीसी": 9, 13, 0.692
स्ट्रिंग दर्ज करें: अब cdefghijklmnopqrstuvw xyz
"zyxwvutsrqponmlkjihgf edc ab": 50, 50, 1.000
"zyxwvutsrqponmlkjihgf edc ab": 51, 50, 1.020
स्ट्रिंग दर्ज करें: abcdefg hijklmnopqrstuvwx
"हिज्कलमोनोपक्रस्टवुवएक्स गफ़ेडकब": 38, 31, 1.226
"हिज्कलमोनोपक्रस्टवुवएक्स गफ़ेडकब": 38, 31, 1.226
स्ट्रिंग दर्ज करें: bc de fg hi jk lm no pq rs tu vw xy zc
"zc xy vw tu rs pq no lm jk hi fg de bc de": 46, 40, 1.150
"zc xy vw tu rs pq no lm jk hi fg de bc de": 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
आप देख सकते हैं कि तीसरे उदाहरण में होस्ट वर्ड-रिवर्सल एल्गोरिदम के सबसे खराब मामले को छोड़कर स्कोर लगभग समान है, जिसके लिए मेरा दृष्टिकोण 1.25 से कम का स्कोर देता है
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 असाइनमेंट के साथ।
यह विचार मेरे पिछले एक के समान है, यह सिर्फ इस संस्करण में है कि मैंने सबसे अधिक 1. लंबाई में अंतर के साथ उपसर्ग और प्रत्यय खोजने की कोशिश की। फिर मैं उस उपसर्ग और प्रत्यय पर अपने पिछले एल्गोरिथ्म को चलाता हूं (कल्पना करें कि उन्हें संक्षिप्त किया जा रहा है) । फिर असंसाधित हिस्से पर जारी रखें।
उदाहरण के लिए, पिछले सबसे खराब स्थिति के लिए:
अब | अब | सी
हम पहले "ab" और "c" (4 असाइनमेंट) पर शब्द को उलटा कर देंगे:
सी | अब | अब
हम जानते हैं कि सीमा पर यह स्थान हुआ करता था (कई मामलों को संभालने के लिए है, लेकिन आप ऐसा कर सकते हैं), इसलिए हमें सीमा पर अंतरिक्ष को घेरने की आवश्यकता नहीं है, यह पिछले एल्गोरिथ्म से मुख्य सुधार है। ।
फिर अंत में हम पाने के लिए मध्य चार वर्णों पर चलते हैं:
cba ab
कुल 8 असाइनमेंट में, इस मामले के लिए इष्टतम, क्योंकि सभी 8 अक्षर बदल गए।
यह पिछले एल्गोरिथम में सबसे खराब स्थिति को समाप्त करता है क्योंकि पिछले एल्गोरिथ्म में सबसे खराब मामला समाप्त हो गया है।
कुछ नमूना रन देखें (और @ प्राइमो के जवाब के साथ तुलना करें - वह दूसरी पंक्ति है):
स्ट्रिंग दर्ज करें: मैं कुछ भी कर सकता हूं
"कुछ भी मैं कर सकता हूँ": 20, 17
"कुछ भी मैं कर सकता हूं": 17, 17
स्ट्रिंग दर्ज करें: abcdef ghijklmnopqrs
"ग़ज़लक्म्नोपकार्स फेडकब": ३m, २५
"ग़ज़लक्म्नोपकार्स फेडकब": ३१, २५
स्ट्रिंग दर्ज करें: abcdef ghijklmnopqrst
"ग़ज़लक्म्नोपक्रस्ट फेडकब": 38, 26
"ग़ज़लक्म्नोपक्रस्ट फेडकब": 32, 26
स्ट्रिंग दर्ज करें: abcdefghi jklmnozzzzzzzzzzzzzzzzzzz
"jklmnozzzzzzzzzzzzzzzzzzzzz ihgfedcb a": 59, 41
"jklmnozzzzzzzzzzzzzzzzzzzzz ihgfedcb a": 45, 41
स्ट्रिंग दर्ज करें: abcdefghi jklmnopqrstuvwxyzzz
"jklmnopqrstuvwxyzzz ihgfedcb a": 55, 37
"jklmnopqrstuvwxyzzz ihgfedcb a": 45, 37
स्ट्रिंग दर्ज करें: ab ababababababac
"काबाबाबाबाबा अब्बू": 30, 30
"काबाबाज़ाबाबा अब": 31, 30
स्ट्रिंग दर्ज करें: ab abababababababc
"cbababababababa ab": 32, 32
"cbababababababa ab": 33, 32
स्ट्रिंग दर्ज करें: एबीसी डी एबीसी
"एबीसी डी एबीसी": 0, 9
"एबीसी डी एबीसी": 0, 9
स्ट्रिंग दर्ज करें: एबीसी dca
"एसीडी एबीसी": 6, 9
"एसीडी एबीसी": 4, 9
स्ट्रिंग दर्ज करें: abc ababababababc
"cbabababababa abc": 7, 29
"cbabababababa abc": 5, 29
प्राइमो का जवाब आम तौर पर बेहतर होता है, हालांकि कुछ मामलों में मुझे 1 अंक का फायदा हो सकता है =)
इसके अलावा उसका कोड मेरा, हाहा से बहुत छोटा है।
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()
अजगर, स्कोर: सामान्य रूप से बहुत कम, विषम 2,
अंतरिक्ष अवरोध के कारण हटा दिया गया पुराना कोड
विचार प्रत्येक सूचकांक के माध्यम से पुनरावृति है, और प्रत्येक सूचकांक के लिए i
, हम चरित्र ले, नई स्थिति की गणना j
, के स्थान पर चरित्र को याद j
, पर चरित्र आवंटित i
करने के लिए j
सूचकांक में चरित्र के साथ, और बार-बार j
। चूंकि हमें नई स्थिति की गणना करने के लिए अंतरिक्ष जानकारी की आवश्यकता है, इसलिए मैं पुराने स्थान को नए अक्षर के अपरकेस संस्करण के रूप में और नए स्थान को '@' के रूप में एन्कोड करता हूं।