Python, оценка: 2 1,5 1,25
Это прямой комбинация ответа Примо и моего ответа. Так что кредиты ему тоже!
Доказательство еще в процессе, но вот код для игры! Если вы можете найти встречный пример оценки выше 1,25 (или если есть ошибка), дайте мне знать!
В настоящее время худший случай:
аа ... аа dcb ... cbd
где каждая буква «a», «b», «c» и «» (пробел) содержит ровно n букв, и ровно две буквы «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
)
Я уверен, что код может быть сокращен. В настоящее время это долго, потому что у меня не было четкой картины всего алгоритма в начале. Я уверен, что можно разработать его так, чтобы он был представлен более коротким кодом =)
Примерный прогон (первый мой, второй - primo):
Введите строку: bc def ghij
"ghij def bc a": 9, 13, 0,692
"ghij def bc a": 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
Введите строку: 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 a": 46, 40, 1,150
"zc xy vw tu rs pq no lm jk hi fg de bc a": 53, 40, 1.325
Введите строку: 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
Вы можете видеть, что оценка почти одинакова, за исключением наихудшего случая алгоритма обращения слов в третьем примере, для которого мой подход дает оценку ниже 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, оценка: 1,5
Точное количество назначений можно аппроксимировать по формуле:
n <= 1,5 * длина (строка)
в худшем случае:
abcdefghi jklmnopqrstuvwxyzzz
с 55 назначениями на строку длиной 37.
Идея похожа на мою предыдущую, просто в этой версии я попытался найти префикс и суффикс на границах слов с разницей в длине не более 1. Затем я запустил свой предыдущий алгоритм с этим префиксом и суффиксом (представьте, что они объединены) , Затем перейдите к необработанной части.
Например, для предыдущего наихудшего случая:
аб | аб | с
сначала мы сделаем обращение слов «ab» и «c» (4 назначения):
с | абы | абы
Мы знаем, что на границе это было пространство (есть много случаев, которые нужно обрабатывать, но вы можете это сделать), поэтому нам не нужно кодировать пространство на границе, это главное улучшение по сравнению с предыдущим алгоритмом. ,
Затем, наконец, мы бежим по четырем средним символам, чтобы получить:
CBA AB
всего 8 назначений, оптимальных для этого случая, поскольку все 8 символов изменены.
Это устраняет наихудший случай в предыдущем алгоритме, поскольку наихудший случай в предыдущем алгоритме исключается.
Посмотрите пример прогона (и сравнение с ответом @ primo - его вторая строка):
Введите строку: я могу сделать все, что угодно
«Все, что я могу сделать»: 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
Введите строку: ab ababababababac
"cababababababa ab": 30, 30
"cababababababa ab": 31, 30
Введите строку: ab ababababababcc
"cbababababababa ab": 32, 32
"cbababababababa ab": 33, 32
Введите строку: abc d abc
"abc d abc": 0, 9
"abc d abc": 0, 9
Введите строку: abc dca
"acd abc": 6, 9
"acd abc": 4, 9
Введите строку: abc abababababcc
"cbabababababa abc": 7, 29
"cbabababababa abc": 5, 29
Ответ primo, как правило, лучше, хотя в некоторых случаях я могу иметь преимущество в 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()
Python, оценка: асимптотически 2, в обычном случае гораздо меньше
старый код удален из-за нехватки места
Идея заключается в том , чтобы перебирать каждый индекс, и для каждого индекса i
, мы берем характер, вычислить новое положение j
, запомните символ в позиции j
, присвоить символ , i
чтобы j
, и повторите с символом с индексом j
. Поскольку для вычисления новой позиции нам нужна информация о пробелах, я кодирую старый пробел как заглавную версию новой буквы, а новый пробел - как @.