Thứ tự đảo ngược của các từ trong một chuỗi tại chỗ


17

Nhiệm vụ

  • Bạn được cung cấp một chuỗi có thể thay đổi phù hợp [a-z]+( [a-z]+)*.
  • Bạn phải biến nó thành chuỗi chứa các từ giống nhau, nhưng theo thứ tự ngược lại, để "xin chào mọi người" trở thành "mọi người ở đó xin chào".
  • Bạn không được phép sử dụng nhiều hơn một lượng bộ nhớ bổ sung không đổi (vì vậy không sao chép toàn bộ chuỗi hoặc bất kỳ từ nào vào bộ đệm bạn vừa phân bổ).
  • Không có hạn chế về thời gian. Vô vọng không hiệu quả sẽ không làm hại điểm số của bạn.
  • Nếu ngôn ngữ bạn chọn không cho phép đột biến chuỗi, mảng ký tự là một thay thế chấp nhận được.

Số điểm của bạn

  • Điểm của bạn được tính hoàn toàn vào số lần đánh giá bạn thực hiện đối với các yếu tố chuỗi (điểm nhỏ là tốt nhất). Nếu bạn sử dụng hàm thư viện ghi vào chuỗi, thì ghi của nó cũng được tính.
  • Giả sử số lượng bài tập bạn cần cho s đầu vào là n (s) . Sau đó, điểm của bạn là tối đa (theo phương pháp giáo dục, tối cao) trên tất cả các đầu vào s (khớp với biểu thức chính quy định ở trên) của n (s) / length (s) . Nếu bạn không thể tính toán chính xác điều này, bạn có thể sử dụng giới hạn trên thấp nhất mà bạn có thể chứng minh.
  • Bạn có thể phá vỡ một mối ràng buộc nếu bạn có thể chứng minh rằng thuật toán của bạn sử dụng các bài tập ít bất thường hơn (điều này có thể xảy ra ngay cả khi bạn có cùng số điểm, xem bên dưới). Nếu bạn không thể làm điều này, bạn có thể phá vỡ một cà vạt bằng cách hiển thị rằng bạn sử dụng ít bộ nhớ bổ sung. Tuy nhiên, điều kiện tie-break đầu tiên luôn được ưu tiên.
  • Đối với một số đầu vào, mỗi ký tự cần thay đổi, vì vậy không thể ghi ít hơn 1.
  • Tôi có thể nghĩ về một thuật toán đơn giản với điểm 2 (nhưng tôi không nhập nó).

Ghi chú về suprema và quan hệ

  • Một tối cao của một tập hợp các số là số nhỏ nhất không nhỏ hơn bất kỳ số nào trong số chúng. Điều này giống như mức tối đa của một tập hợp, ngoại trừ một số tập hợp vô hạn như {2/3, 3/4, 4/5, 5/6, ...} không có phần tử tối đa duy nhất, nhưng vẫn sẽ có một phần tối cao, trong trường hợp này 1.
  • Nếu bạn quản lý để "chỉ" lưu một số lượng bài tập không đổi so với thuật toán điểm 2 của tôi (điểm), điểm của bạn sẽ vẫn là 2, bởi vì bạn sẽ tự ý tiến gần đến 2 lần nhập lớn hơn. Tuy nhiên, bạn giành chiến thắng trong tie-break nếu nói đến điều đó.

1
Tôi sẽ hơi buồn một chút nếu tất cả điều này xảy ra với các bài nộp điểm số 2 liên quan đến việc sử dụng bộ nhớ của họ. Tôi chủ yếu đăng câu hỏi này tự hỏi liệu có ai có thể đạt được ít hơn 2.
Ben Millwood

1
Tôi không có bằng chứng chính thức, nhưng trực giác của tôi nói với tôi rằng với giới hạn không gian liên tục, không thể làm tốt hơn 2. Nếu bạn chỉ tính khai báo biến cho không gian, tôi có thể gian lận và thực hiện chức năng đệ quy. nhưng điều đó chỉ ngụy trang little-omega(1)không gian bằng cách đặt nó lên ngăn xếp.
sai

2
@bacchusbeale có, nhưng đó là bộ nhớ thêm không đổi.
Martin Ender

4
Nếu bạn thực thi nghiêm túc các quy tắc thì không thể viết một chương trình như vậy. Chuỗi có thể có độ dài tùy ý và bạn sẽ cần ít nhất một số loại biến lưu trữ một chỉ mục. Vì vậy, tôi chỉ cần làm cho chuỗi đủ dài để vượt quá giới hạn của biến của bạn. Để lưu trữ thành công ít nhất một chỉ mục, bộ nhớ cần thiết của bạn sẽ tăng theo chiều dài chuỗi.
IchBinKeinBaum

3
@IchBinKeinBaum là đúng, không thể thực hiện nhiệm vụ này với O(1)không gian bổ sung. Bạn cần O(log n)không gian để lưu trữ một vị trí chỉ mục, vì một số nguyên k-bit chỉ có thể lưu trữ trong chúng cho các chuỗi có độ dài lên đến 2^k. Giới hạn độ dài của chuỗi làm cho thách thức trở nên vô nghĩa, vì mọi thuật toán sẽ yêu cầu O(1)không gian theo cách này.
Dennis

Câu trả lời:


4

Python, Điểm: 2 1,5 1,25

Đây là sự kết hợp trực tiếp giữa câu trả lời của primo và câu trả lời của tôi. Vì vậy, tín dụng cho anh ta cũng!

Bằng chứng vẫn đang được tiến hành, nhưng đây là mã để chơi! Nếu bạn có thể tìm thấy một ví dụ về số điểm lớn hơn 1,25 (hoặc nếu có lỗi), hãy cho tôi biết!

Hiện tại trường hợp xấu nhất là:

aa ... aa dcb ... cbd

trong đó có chính xác n của mỗi chữ cái "a", "b", "c" và "" (dấu cách) và chính xác là hai "d" s. Độ dài của chuỗi là 4n + 2 và số lượng bài tập là 5n + 2 , cho số điểm 5/4 = 1,25 .

Thuật toán hoạt động theo hai bước:

  1. Tìm knhư vậy string[k]string[n-1-k]là ranh giới từ
  2. Chạy bất kỳ thuật toán đảo ngược từ nào string[:k]+string[n-1-k:](nghĩa là ghép các ký tự đầu tiên kvà cuối cùng k) với sửa đổi nhỏ.

trong đó nđộ dài của chuỗi.

Sự cải tiến mà thuật toán này mang lại đến từ "sửa đổi nhỏ" trong Bước 2. Về cơ bản, kiến ​​thức trong chuỗi được nối, các ký tự ở vị trí kk+1là các ranh giới từ (có nghĩa là chúng là khoảng trắng hoặc ký tự đầu tiên / cuối cùng trong một từ), và vì vậy chúng ta có thể thay thế trực tiếp các ký tự ở vị trí kk+1bằng ký tự tương ứng trong chuỗi cuối cùng, lưu một vài bài tập. Điều này loại bỏ trường hợp xấu nhất khỏi thuật toán đảo ngược từ máy chủ

Có những trường hợp chúng tôi thực sự không thể tìm thấy như vậy k, trong trường hợp đó, chúng tôi chỉ chạy "thuật toán đảo ngược bất kỳ từ nào" trên toàn bộ chuỗi.

Mã này dài để xử lý bốn trường hợp này khi chạy thuật toán đảo ngược từ trên chuỗi "nối":

  1. Khi kkhông tìm thấy ( f_long = -2)
  2. Khi string[k] != ' ' and string[n-1-k] != ' '( f_long = 0)
  3. Khi string[k] != ' ' and string[n-1-k] == ' '( f_long = 1)
  4. Khi string[k] == ' ' and string[n-1-k] != ' '( f_long = -1)

Tôi chắc chắn rằng mã có thể được rút ngắn. Hiện tại nó đã dài bởi vì tôi không có hình ảnh rõ ràng về toàn bộ thuật toán lúc ban đầu. Tôi chắc chắn người ta có thể thiết kế nó để được trình bày trong một mã ngắn hơn =)

Chạy mẫu (thứ nhất là của tôi, thứ hai là primo):

Nhập chuỗi: a bc def ghij
"ghij def bc a": 9, 13, 0.692
"ghij def bc a": 9, 13, 0.692
Nhập chuỗi: ab cdefghijklmnopqrstuvw xyz
"zyxwvutsrqponmlkjihgf edc ab": 50, 50, 1.000
"zyxwvutsrqponmlkjihgf edc ab": 51, 50, 1.020
Nhập chuỗi: abcdefg Hijklmnopqrstuvwx
"Hijklmnopqrstuvwx gfedcb a": 38, 31, 1.226
"Hijklmnopqrstuvwx gfedcb a": 38, 31, 1.226
Nhập chuỗi: a 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
Nhập chuỗi: aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaa dcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbd
"Dcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbd aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaa một": 502, 402, 1,249
"Dcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbd aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaa một": 502, 402, 1,249

Bạn có thể thấy rằng điểm số gần như giống nhau, ngoại trừ trường hợp xấu nhất của thuật toán đảo ngược từ máy chủ trong ví dụ thứ ba, trong đó cách tiếp cận của tôi mang lại điểm dưới 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, Điểm: 1,5

Số lượng bài tập chính xác có thể được xấp xỉ theo công thức:

n <= 1,5 * chiều dài (chuỗi)

với trường hợp xấu nhất là:

abcdefghi jklmnopqrstuvwxyzzz

với 55 bài tập trên chuỗi có độ dài 37.

Ý tưởng tương tự như trước đây của tôi, chỉ là trong phiên bản này, tôi đã cố gắng tìm tiền tố và hậu tố ở ranh giới từ với độ dài khác nhau nhiều nhất 1. Sau đó, tôi chạy thuật toán trước đó của mình trên tiền tố đó và hậu tố (hãy tưởng tượng chúng là được nối) . Sau đó tiếp tục vào phần chưa xử lý.

Ví dụ: đối với trường hợp xấu nhất trước đó:

ab | ab | c

đầu tiên chúng ta sẽ thực hiện đảo ngược từ trên "ab" và "c" (4 bài tập) thành:

c | ab | ab

Chúng tôi biết rằng tại ranh giới trước đây là không gian (có nhiều trường hợp được xử lý, nhưng bạn có thể làm điều đó), vì vậy chúng tôi không cần mã hóa không gian ở ranh giới, đây là cải tiến chính từ thuật toán trước .

Sau đó, cuối cùng chúng tôi chạy trên bốn nhân vật ở giữa để có được:

cba ab

trong tổng số 8 bài tập, tối ưu cho trường hợp này, vì tất cả 8 ký tự đã thay đổi.

Điều này giúp loại bỏ trường hợp xấu nhất trong thuật toán trước vì trường hợp xấu nhất trong thuật toán trước được loại bỏ.

Xem một số mẫu chạy (và so sánh với câu trả lời của @ primo - đây là dòng thứ hai):

Nhập chuỗi: tôi có thể làm bất cứ điều gì
"bất cứ điều gì tôi có thể": 20, 17
"bất cứ điều gì tôi có thể": 17, 17
Nhập chuỗi: abcdef ghijklmnopqrs
"ghijklmnopqrs fedcb a": 37, 25
"ghijklmnopqrs fedcb a": 31, 25
Nhập chuỗi: abcdef ghijklmnopqrst
"ghijklmnopqrst fedcb a": 38, 26
"ghijklmnopqrst fedcb a": 32, 26
Nhập chuỗi: abcdefghi jklmnozzzzzzzzzzzzzzzzzzz
"jklmnozzzzzzzzzzzzzzzzz ihgfedcb a": 59, 41
"jklmnozzzzzzzzzzzzzzzzz ihgfedcb a": 45, 41
Nhập chuỗi: abcdefghi jklmnopqrstuvwxyzzz
"jklmnopqrstuvwxyzzz ihgfedcb a": 55, 37
"jklmnopqrstuvwxyzzz ihgfedcb a": 45, 37
Nhập chuỗi: ab ababababababac
"Cababababababa ab": 30, 30
"Cababababababa ab": 31, 30
Nhập chuỗi: ab abababababababc
"Cbababababababa ab": 32, 32
"Cbababababababa ab": 33, 32
Nhập chuỗi: abc d abc
"abc d abc": 0, 9
"abc d abc": 0, 9
Nhập chuỗi: abc dca
"acd abc": 6, 9
"acd abc": 4, 9
Nhập chuỗi: abc ababababababc
"cbabababababa abc": 7, 29
"cbabababababa abc": 5, 29

câu trả lời của Primo nói chung là tốt hơn, mặc dù trong một số trường hợp tôi có thể có lợi thế 1 điểm =)

Ngoài ra mã của anh ấy ngắn hơn tôi nhiều, 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, Điểm: không có triệu chứng 2, trong trường hợp bình thường ít hơn nhiều

mã cũ bị xóa do hạn chế về không gian

Ý tưởng là để lặp qua từng chỉ số, và cho mỗi chỉ số i, chúng ta lấy nhân vật, tính toán vị trí mới j, học thuộc lòng các nhân vật ở vị trí j, phân công các nhân vật tại iđể j, và lặp lại với nhân vật ở index j. Vì chúng tôi cần thông tin không gian để tính toán vị trí mới, tôi mã hóa không gian cũ dưới dạng phiên bản chữ hoa của chữ cái mới và không gian mới là '@'.


Nếu bạn có thể giảm số lượng từ trong trường hợp xấu hơn về độ dài của chuỗi (giả sử length(string)/3bằng cách buộc mỗi từ trong trường hợp xấu nhất ít nhất là độ dài 2 bằng cách nào đó), thì điểm sẽ nhỏ hơn 2 (trong ví dụ ở trên sẽ là 1,67)
cần

1
Tôi đã thêm một bộ đếm trao đổi với tôi; của bạn thực sự đánh bại tôi trong trường hợp xấu nhất (nhưng không phải là trường hợp chung). Cần tìm cách khắc phục điều đó;)
primo

Dòng 127: Các if any(process_loop(...) for j in range(...))bài tập từ các vòng lặp quy trình này có cần được tính không?
primo

Điều đó không làm bất kỳ nhiệm vụ. Nếu bạn thấy, dry_runtham số được đặt thành khác không (giá trị thành i). Bên trong process_loop, nếu dry_runkhác không, nó sẽ không thực hiện bất kỳ nhiệm vụ nào.
justhalf

1
Tôi nghĩ rằng tôi có một hình ảnh tốt hơn bây giờ. Trong essense, hai phương pháp riêng biệt với hành vi trường hợp xấu nhất khác nhau được kết hợp, để loại bỏ trường hợp xấu nhất cho cả hai. Tôi thích nó. Tôi nghĩ nói chung, đây có thể là cách tiếp cận tốt nhất để thực hiện, mặc dù có vẻ như hai (hoặc nhiều hơn) các phương pháp hoàn toàn khác nhau có thể được kết hợp để giảm trường hợp xấu nhất hơn nữa.
primo

14

Perl, điểm 1,3̅

Đối với mỗi ký tự không phải khoảng trắng, một phép gán được thực hiện và đối với mỗi ký tự khoảng trắng, hai phép gán. Vì các ký tự không gian không thể chiếm hơn một nửa tổng số ký tự, nên trường hợp xấu nhất là 1,5 .

Thuật toán đã không thay đổi, nhưng tôi có thể chứng minh giới hạn trên dưới. Chúng ta hãy thực hiện hai quan sát:

  1. Không gian trực tiếp trên không gian không cần phải hoán đổi.
  2. Các từ ký tự đơn trực tiếp từ các khoảng trắng không được hoán đổi trong giai đoạn chính, mà chỉ một lần ở cuối.

Sau đó có thể thấy rằng 'trường hợp xấu nhất' về mặt lý thuyết với 1/2 không gian không có triệu chứng hoàn toàn không phải là trường hợp xấu nhất: ab c d e f g h i ...

$ echo ab c d e f g h i j k l m n o p q r s t u v w x y z|perl reverse-inplace.pl
z y x w v u t s r q p o n m l k j i h g f e d c ab
swaps: 51; len: 50
ratio: 1.02

Trong thực tế, đó là một trường hợp khá tốt.

Để ngăn việc quan sát một và hai ở trên, mỗi từ một ký tự sẽ cần phải được định vị lại ở giữa một từ dài ba ký tự trở lên. Điều này sẽ gợi ý một trường hợp xấu nhất có chứa khoảng trống 1/3 không triệu chứng:a bcd a bcd a ... bc

$ echo a bcd a bcd a bcd a bcd a bcd a bc|perl reverse-inplace.pl
bc a bcd a bcd a bcd a bcd a bcd a
swaps: 45; len: 34
ratio: 1.32352941176471

Hoặc tương đương, chỉ có hai từ có hai ký tự: a bc de fg hi jk ...

$ echo a bc de fg hi jk lm no pq rs tu vx xy|perl reverse-inplace.pl
xy vx tu rs pq no lm jk hi fg de bc a
swaps: 49; len: 37
ratio: 1.32432432432432

Bởi vì trường hợp xấu nhất chứa 1/3 khoảng cách không có triệu chứng, điểm trường hợp xấu nhất trở thành 1,3̅ .

#!perl -l
use warnings;

$words = <>;
chomp($words);
$len = length($words);
$words .= ' ';
$spaces = 0;
# iterate over the string, count the spaces
$spaces++ while $words =~ m/ /g;

$origin = 0;
$o = vec($words, $origin, 8);
$cycle_begin = $origin;
$swaps = 0;

# this possibly terinates one iteration early,
# if the last char is a one-cycle (i.e. moves to its current location)
# one-cycles previous to the last are iterated, but not swapped.
while ($i++ < $len - $spaces || !$was_cycle) {
  $w_start = rindex($words, ' ', $origin);
  $w_end = index($words, ' ', $origin);
  $pos = ($origin - $w_start) - 1;
  $target = $len - ($w_end - $pos);
  $t = vec($words, $target, 8);

  if ($t == 32) {
    $target = $len - $target - 1;
    $t = vec($words, $target, 8);
  }

  # char is already correct, possibly a one-cycle
  if ($t != $o) {
    $swaps += 1;
    vec($words, $target, 8) = $o;
  }

  $origin = $target;
  $o = $t;
  if ($origin == $cycle_begin) {
    if ($i < $len - $spaces) {
      # backtrack through everything we've done up to this point
      # to find the next unswapped char ...seriously.
      $origin += 1;
      if (vec($words, $origin, 8) == 32) {
        $origin += 1;
      }
      $bt_origin = 0;
      $bt_cycle_begin = 0;
      while ($bt_cycle_begin < $origin) {
        $w_start = rindex($words, ' ', $bt_origin);
        $w_end = index($words, ' ', $bt_origin);
        $pos = ($bt_origin - $w_start) - 1;
        $target = $len - ($w_end - $pos);
        $t = vec($words, $target, 8);

        if ($t == 32) {
          $target = $len - $target - 1;
          $t = vec($words, $target, 8);
        }

        if ($target == $bt_cycle_begin) {
          $bt_origin = ++$bt_cycle_begin;
          if (vec($words, $bt_origin, 8) == 32) {
            $bt_origin = ++$bt_cycle_begin;
          }
        } else {
          $bt_origin = $target;
        }

        if ($target == $origin) {
          $origin += 1;
          if (vec($words, $origin, 8) == 32) {
            $origin += 1;
          }
          $bt_origin = $bt_cycle_begin = 0;
        }
      }
    }

    $cycle_begin = $origin;
    $o = vec($words, $origin, 8);
    $was_cycle = 1;
  } else {
    $was_cycle = 0;
  }
}

for $i (0..$len/2-1) {
  $mirror = $len - $i - 1;
  $o = vec($words, $i, 8);
  $m = vec($words, $mirror, 8);
  # if exactly one is a space...
  if (($o == 32) ^ ($m == 32)) {
    $swaps += 2;
    vec($words, $mirror, 8) = $o;
    vec($words, $i, 8) = $m;
  }
}

chop($words);
print $words;
print "swaps: $swaps; len: $len";
print 'ratio: ', $swaps/$len;

Chỉnh sửa: Đã thêm bộ đếm trao đổi và tỷ lệ.

Đầu vào được lấy từ stdin. Sử dụng mẫu:

$ echo where in the world is carmen sandiego|perl reverse-inplace.pl
sandiego carmen is world the in where
swaps: 35; len: 37
ratio: 0.945945945945946

phương pháp

Để bắt đầu, ký tự đầu tiên của chuỗi được di chuyển đến đích cuối cùng của nó. Ký tự vừa được thay thế sau đó được chuyển đến đích, v.v ... Điều này tiếp tục cho đến khi một trong hai điều kiện được đáp ứng:

  1. Các nhân vật nên được hoán đổi với một không gian.
    Khi điều này xảy ra, nhân vật không được hoán đổi với không gian, mà là vào vị trí gương của không gian. Thuật toán tiếp tục từ vị trí đó.
  2. Một chu kỳ đã đạt được.
    Khi mục tiêu trở về vị trí bắt đầu ban đầu của chu kỳ hiện tại, cần tìm thấy ký tự không được đánh dấu tiếp theo (hay đúng hơn là bất kỳ ký tự không được mã hóa nào). Để thực hiện điều này trong các ràng buộc bộ nhớ liên tục, tất cả các giao dịch hoán đổi được thực hiện cho đến thời điểm này đều được theo dõi ngược.

Sau giai đoạn này, mỗi nhân vật không phải không gian đã được di chuyển nhiều nhất một lần. Để kết thúc, tất cả các ký tự không gian được hoán đổi với các ký tự ở vị trí gương của chúng, yêu cầu hai thao tác gán cho mỗi khoảng trắng.


Wow nó thật tuyệt. Bạn có thể giải thích tại sao đặt nhân vật vào vị trí gương của không gian cho câu trả lời đúng không?
justhalf

1
@Niklas, tôi không nghĩ điều đó là có thể. Bởi vì để thực hiện quay lui bạn cần thông tin vị trí không gian. Nếu bạn ghi đè thông tin đó, bạn không thể thực hiện quay lại.
justhalf

1
Tôi thực hiện một so sánh với thuật toán của mình trong câu trả lời của tôi ở đây: codegolf.stackexchange.com/a/26952/16337
justhalf

1
@justhalf Trong chuỗi cuối cùng, tất cả các khoảng trắng sẽ ở vị trí được nhân đôi. Do đó, chúng ta có thể sử dụng vị trí này một cách an toàn để lưu trữ ký tự thay thế khoảng trắng và chuyển đổi chúng ở cuối.
primo

1
Làm tốt. Tôi có một ý tưởng tương tự nhưng không nghĩ đến việc chỉ chừa chỗ trống và sau đó phản chiếu chúng.
IchBinKeinBaum

7

Ruby, điểm 2

Là một khởi đầu một thuật toán rất cơ bản. Đầu tiên, nó đảo ngược toàn bộ chuỗi và sau đó đảo ngược từng từ trong chuỗi một lần nữa. Trong trường hợp xấu nhất (một từ, số chẵn của các ký tự), điểm sẽ trở thành 2.

def revstring(s, a, b)
  while a<b
    h = s[a]
    s[a] = s[b]
    s[b] = h
    a += 1
    b -= 1
  end
  s
end

def revwords(s)
  revstring(s, 0, s.length-1)
  a = 0
  while a<s.length
    b = a+1
    b += 1 while b<s.length and s[b]!=" "
    revstring(s, a, b-1)
    a = b+1
  end
  s
end

Sử dụng:

> revwords("hello there everyone")
"everyone there hello"

Tại sao bạn không sử dụng hàm tích hợp Ruby để đảo ngược chuỗi? Nó sẽ thay đổi điểm số?
AL

sử dụng, s [a], s [b] = s [b], s [a]
Thaha kp

5

C ++: Điểm 2

#include<iostream>
#include<algorithm>

void rev(std::string& s)
{
    std::reverse(s.begin(),s.end());
    std::string::iterator i=s.begin(),j=s.begin();
    while(i!=s.end())
    {
        while(i!=s.end()&&(*i)==' ')
            i++;
        j=i;
        while(i!=s.end()&&(*i)!=' ')
            i++;
        std::reverse(j,i);
    }
}

int main()
{
    std::string s;
    getline(std::cin,s);
    rev(s);
    std::cout<<s;
}

2
Tôi đã thử nó. Hoạt động tốt!
bacchusbeale

2

Nổi loạn

reverse-words: function [
    "Reverse the order of words. Modifies and returns string (series)"
    series [string!] "At position (modified)"
  ][
    first-time: on
    until [
        reverse/part series f: any [
            if first-time [tail series]
            find series space
            tail series
        ]
        unless first-time [series: next f]
        first-time: off
        tail? series
    ]

    series: head series
]

Tôi không rõ về điểm số cho điều này. Không có sự gán chuỗi trực tiếp trong mã này. Tất cả mọi thứ được xử lý bởi một trong reverse/partđó đảo ngược tại chỗ trong và ban đầu trên toàn bộ chuỗi.

Một số chi tiết về mã:

  • Lặp qua chuỗi ( series) cho đến khi đạt đếntail?

  • Lần đầu tiên trong vòng lặp thực hiện đảo ngược hoàn toàn chuỗi - reverse/part series tail series(giống như reverse series)

  • Sau đó đảo ngược mọi từ được tìm thấy trên các lần lặp tiếp theo - reverse/part series find series space

  • Khi từ cạn kiệt tìm thấy rồi quay lại tail seriesđể nó sẽ đảo ngược từ cuối cùng trong chuỗi -reverse/part series tail series

Rebol cho phép truyền qua một chuỗi thông qua một con trỏ bên trong . Bạn có thể thấy điều này tại series: next f(di chuyển con trỏ đến sau khoảng trắng để bắt đầu từ tiếp theo) và series: head series(đặt lại con trỏ trở lại đầu).

Xem Series để biết thêm.

Ví dụ sử dụng trong bảng điều khiển Rebol:

>> reverse-words "everyone there hello"
== "hello there everyone"

>> x: "world hello"
== "world hello"

>> reverse-words x
== "hello world"

>> x
== "hello world"

>> reverse-words "hello"
== "hello"

Trên đường chuyền đầu tiên, mỗi ký tự được định vị lại một lần và trên đường chuyền thứ hai, mỗi ký tự không phải khoảng trắng được định vị lại một lần nữa. Đối với một đầu vào tùy tiện lớn với tương đối ít không gian, điểm số các phương pháp tiếp cận 2.
primo

2

C: Điểm 2

Điều này chỉ lật toàn bộ chuỗi một lần sau đó đảo ngược từng từ.

#include <stdio.h>
#include <string.h>

void reverse(char *s,unsigned n){
    char c;
    unsigned i=0,r=1;
    while(i < n){ //no swap function in C 
        c=s[i];
        s[i++]=s[n];
        s[n--]=c;
    }
}

unsigned wordlen(char *s){
    unsigned i=0;
    while (s[i] != ' ' && s[i]) ++i;
    return i;
}

int main(int argc, char **argv) {
    char buf[]="reverse this also";
    char *s=buf;
    unsigned wlen=0,len=strlen(s)-1;
    reverse(s,len);  //reverse entire string
    while(wlen<len){  // iterate over each word till end of string
      wlen=wordlen(s);
      reverse(s,wlen-1);
      s+=wlen+1;
      len-=wlen;
    }
    printf("%s\n",buf);
    return 0;
}

3
Đây là một câu trả lời chỉ có mã. Xem xét thêm một lời giải thích về những gì diễn ra trong mã của bạn.
Justin

1

Con trăn: điểm 2

Gần giống với thuật toán của Howard, nhưng thực hiện các bước đảo ngược (lần đầu tiên lật các từ sau đó lật toàn bộ chuỗi). Bổ sung bộ nhớ được sử dụng là 3 biến byte-size: i, j, và t. Về mặt kỹ thuật, findlenđang sử dụng một số biến nội bộ, nhưng chúng có thể dễ dàng sử dụng lại ihoặc jkhông bị mất chức năng.

chỉnh sửa nhanh: lưu vào các bài tập chuỗi bằng cách chỉ hoán đổi khi các ký tự khác nhau, vì vậy tôi có thể lấy thêm một số điểm từ ghi chú # 2.

from sys import stdin

def word_reverse(string):
    # reverse each word
    i=0
    j=string.find(' ')-1
    if j == -2: j=len(string)-1
    while True:
        while i<j:
            if string[i] != string[j]:
                t = string[i]
                string[i] = string[j]
                string[j] = t
            i,j = i+1,j-1
        i=string.find(' ', i)+1
        if i==0: break
        j=string.find(' ', i)-1
        if j == -2: j=len(string)-1
    # reverse the entire string
    i=0
    j=len(string)-1
    while i<j:
        if string[i] != string[j]:
            t = string[i]
            string[i] = string[j]
            string[j] = t
        i,j = i+1,j-1
    return string

for line in stdin.readlines():
    # http://stackoverflow.com/a/3463789/1935085
    line = line.strip() # no trailing newlines ore spaces to ensure it conforms to '[a-z]+( [a-z]+)*'
    print word_reverse(bytearray(line))

1

Lô hàng

Tôi sẽ thừa nhận là không hiểu đầy đủ về điểm số (tôi nghĩ đó là hai) .. nhưng tôi sẽ nói - nó làm được điều đó .

@echo off

setLocal enableDelayedExpansion
set c=
set s=

for %%a in (%~1) do set /a c+=1 & echo %%a >> f!c!

for /L %%a in (!c!, -1, 1) do (
    set /p t=<f%%a
    set s=!s!!t!
    del f%%a
)

echo !s!

Đầu vào được lấy làm giá trị đầu vào tiêu chuẩn đầu tiên, và do đó cần được bao quanh bởi dấu ngoặc kép -
gọi: script.bat "hello there everyone"
out : everyone there hello.

Có lẽ ai đó khác có thể chấm điểm cho tôi (giả sử tôi không, theo một cách nào đó, không đủ tư cách).


-2

Javascript

function reverseWords(input) {
    if (input.match(/^[a-z]+( [a-z]+)*$/g)) {
        return input.split(' ').reverse().join(' ');
    }
}

Sử dụng:

> reverseWords('hello there everyone');
'everyone there hello'

Tôi có cảm giác kỳ lạ tôi đã bỏ lỡ điều gì đó ...


3
Có, điều này không đúng chỗ, vì bạn không sửa đổi chuỗi đầu vào. Vì JavaScript không thể thực hiện được, bạn cần mô phỏng các chuỗi với một mảng các ký tự (ví dụ: số nguyên điểm mã hoặc chuỗi ký tự đơn).
Martin Ender

Hơn nữa, nó sử dụng rất nhiều không gian bổ sung.
Ben Millwood
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.