Python, Nilai: 2 1,5 1,25
Ini adalah kombinasi langsung antara jawaban primo dan jawaban saya. Jadi kredit untuknya juga!
Buktinya masih dalam proses, tapi ini kode untuk bermain! Jika Anda dapat menemukan contoh balasan skor lebih besar dari 1,25 (atau jika ada bug), beri tahu saya!
Saat ini kasus terburuk adalah:
aa ... aa dcb ... cbd
di mana ada persis n dari masing-masing huruf "a", "b", "c", dan "" (spasi), dan tepat dua "d" s. Panjang string adalah 4n + 2 dan jumlah tugas adalah 5n + 2 , memberikan skor 5/4 = 1,25 .
Algoritma ini bekerja dalam dua langkah:
- Temukan
kitu string[k]dan string[n-1-k]merupakan batasan kata
- Jalankan algoritma pembalikan kata apa pun pada
string[:k]+string[n-1-k:](yaitu, rangkaian karakter pertama kdan terakhir k) dengan modifikasi kecil.
di mana npanjang tali.
Peningkatan yang diberikan algoritma ini berasal dari "modifikasi kecil" pada Langkah 2. Pada dasarnya adalah pengetahuan bahwa dalam string gabungan, karakter pada posisi kdan k+1merupakan batas kata (yang berarti spasi atau karakter pertama / terakhir dalam sebuah kata), dan jadi kita bisa langsung mengganti karakter di posisi kdan k+1dengan karakter yang sesuai di string terakhir, menyimpan beberapa tugas. Ini menghapus kasus terburuk dari algoritma pembalikan kata host
Ada kasus-kasus di mana kita tidak dapat menemukan itu k, dalam hal itu, kita hanya menjalankan "algoritma pembalikan kata" pada seluruh string.
Kode ini panjang untuk menangani keempat kasus ini dalam menjalankan kata pembalikan algoritma pada string "concatenated":
- Kapan
ktidak ditemukan ( f_long = -2)
- Kapan
string[k] != ' ' and string[n-1-k] != ' '( f_long = 0)
- Kapan
string[k] != ' ' and string[n-1-k] == ' '( f_long = 1)
- Kapan
string[k] == ' ' and string[n-1-k] != ' '( f_long = -1)
Saya yakin kode ini dapat dipersingkat. Saat ini lama karena saya tidak memiliki gambaran yang jelas tentang keseluruhan algoritma pada awalnya. Saya yakin orang dapat mendesainnya untuk diwakili dalam kode yang lebih pendek =)
Contoh dijalankan (pertama adalah milik saya, kedua adalah milik primo):
Masukkan string: a bc def ghij
"ghij def bc a": 9, 13, 0.692
"ghij def bc a": 9, 13, 0.692
Masukkan string: ab cdefghijklmnopqrstuvw xyz
"zyxwvutsrqponmlkjihgf edc ab": 50, 50, 1.000
"zyxwvutsrqponmlkjihgf edc ab": 51, 50, 1.020
Masukkan string: abcdefg hijklmnopqrstuvwx
"hijklmnopqrstuvwx gfedcb a": 38, 31, 1.226
"hijklmnopqrstuvwx gfedcb a": 38, 31, 1.226
Masukkan string: a bc de fg hai jk lm no pq rs tu vw xy zc
"zc xy vw tu rs pq no lm jk hai fg de bc a": 46, 40, 1.150
"zc xy vw tu rs pq no lm jk hai fg de bc a": 53, 40, 1.325
Masukkan string: aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa dcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbd
"Dcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbd aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaa a": 502, 402, 1,249
"Dcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbd aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaa a": 502, 402, 1,249
Anda dapat melihat bahwa skornya hampir sama, kecuali untuk kasus terburuk dari algoritma pembalikan kata host pada contoh ketiga, yang mana pendekatan saya menghasilkan skor kurang dari 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()
Python, Nilai: 1,5
Jumlah tugas yang tepat dapat diperkirakan dengan rumus:
n <= 1,5 * panjang (string)
dengan kasus terburuk adalah:
abcdefghi jklmnopqrstuvwxyzzz
dengan 55 tugas pada string dengan panjang 37.
Idenya mirip dengan yang saya sebelumnya, hanya saja dalam versi ini saya mencoba untuk menemukan awalan dan akhiran pada batas kata paling banyak 1. Lalu saya menjalankan algoritma saya sebelumnya pada awalan dan akhiran itu (bayangkan mereka digabungkan) . Kemudian lanjutkan pada bagian yang belum diproses.
Misalnya, untuk kasus terburuk sebelumnya:
ab | ab | c
pertama-tama kita akan melakukan pembalikan kata pada "ab" dan "c" (4 tugas) menjadi:
c | ab | ab
Kita tahu bahwa di perbatasan dulu ruang (ada banyak kasus yang harus ditangani, tetapi Anda bisa melakukannya), jadi kami tidak perlu menyandikan ruang di batas, ini adalah peningkatan utama dari algoritma sebelumnya .
Lalu akhirnya kita jalankan di empat karakter tengah untuk mendapatkan:
cba ab
dalam total 8 tugas, optimal untuk kasus ini, karena semua 8 karakter berubah.
Ini menghilangkan kasus terburuk dalam algoritma sebelumnya karena kasus terburuk dalam algoritma sebelumnya dihilangkan.
Lihat beberapa contoh dijalankan (dan perbandingan dengan jawaban @ primo - ini adalah baris kedua):
Masukkan string: saya bisa melakukan apa saja
"Apa pun yang bisa aku": 20, 17
"apapun yang aku bisa": 17, 17
Masukkan string: abcdef ghijklmnopqrs
"ghijklmnopqrs fedcb a": 37, 25
"ghijklmnopqrs fedcb a": 31, 25
Masukkan string: abcdef ghijklmnopqrst
"ghijklmnopqrst fedcb a": 38, 26
"ghijklmnopqrst fedcb a": 32, 26
Masukkan string: abcdefghi jklmnozzzzzzzzzzzzzzzzz
"jklmnozzzzzzzzzzzzzzzzz ihgfedcb a": 59, 41
"jklmnozzzzzzzzzzzzzzzzz ihgfedcb a": 45, 41
Masukkan string: abcdefghi jklmnopqrstuvwxyzzz
"jklmnopqrstuvwxyzzz ihgfedcb a": 55, 37
"jklmnopqrstuvwxyzzz ihgfedcb a": 45, 37
Masukkan string: ab ababababababac
"cababababababa ab": 30, 30
"cababababababa ab": 31, 30
Masukkan string: ab abababababababc
"cbababababababa ab": 32, 32
"cbababababababa ab": 33, 32
Masukkan string: abc d abc
"abc d abc": 0, 9
"abc d abc": 0, 9
Masukkan string: abc dca
"acd abc": 6, 9
"acd abc": 4, 9
Masukkan string: abc ababababababc
"cbabababababa abc": 7, 29
"cbabababababa abc": 5, 29
jawaban primo umumnya lebih baik, walaupun dalam beberapa kasus saya dapat memiliki 1 poin keunggulan =)
Juga kodenya jauh lebih pendek daripada milikku, haha.
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()
Python, Score: asymptotically 2, dalam kasus normal jauh lebih sedikit
kode lama dihapus karena kendala ruang
Idenya adalah untuk iterate melalui setiap indeks, dan untuk setiap indeks i, kita mengambil karakter, menghitung posisi baru j, menghafal karakter pada posisi j, menetapkan karakter di iuntuk j, dan ulangi dengan karakter pada indeks j. Karena kita memerlukan informasi ruang untuk menghitung posisi baru, saya menyandikan ruang lama sebagai versi huruf besar dari surat baru, dan ruang baru sebagai '@'.