Umgekehrte Reihenfolge der Wörter in einer Zeichenfolge

17

Die Aufgabe

  • Sie erhalten eine veränderbare Zeichenfolge, die übereinstimmt [a-z]+( [a-z]+)*.
  • Sie müssen es in die Zeichenfolge umwandeln, die die gleichen Wörter enthält, jedoch in umgekehrter Reihenfolge, so dass "Hallo, da sind alle" zu "Hallo, da sind alle" wird.
  • Sie dürfen nicht mehr als eine konstante Menge zusätzlichen Speichers verwenden (also nicht die gesamte Zeichenfolge oder ein ganzes Wort in einen Puffer kopieren, den Sie gerade zugewiesen haben).
  • Es gibt keine zeitlichen Einschränkungen. Hoffnungslos ineffizient zu sein, schadet Ihrer Punktzahl nicht.
  • Wenn Ihre Sprache die Mutation von Zeichenfolgen nicht zulässt, sind Arrays von Zeichen ein akzeptabler Ersatz.

Ihre Punktzahl

  • Ihre Punktzahl wird nur anhand der Anzahl der Zuordnungen gezählt, die Sie zu Zeichenfolgenelementen vornehmen (kleine Punktzahlen sind am besten). Wenn Sie eine Bibliotheksfunktion verwenden, die in die Zeichenfolge schreibt, zählen auch deren Schreibvorgänge.
  • Angenommen, die Anzahl der Zuweisungen, die Sie für die Eingabe von s benötigen, ist n (s) . Dann ist Ihre Punktzahl das Maximum (pedantisch, supremum) über alle Eingaben s (passend zur oben angegebenen Regex) von n (s) / Länge (n) . Wenn Sie dies nicht genau berechnen können, können Sie die niedrigste Obergrenze verwenden, die Sie nachweisen können.
  • Sie können einen Gleichstand beenden, wenn Sie nachweisen können, dass Ihr Algorithmus asymptotisch weniger Zuweisungen verwendet (dies kann auch bei gleichem Ergebnis der Fall sein, siehe unten). Wenn Sie dies nicht tun können, können Sie ein Band durchbrechen, indem Sie zeigen, dass Sie weniger zusätzlichen Speicher verwenden. Die erste Unterbrechungsbedingung hat jedoch immer Vorrang.
  • Bei einigen Eingaben muss sich jedes Zeichen ändern, daher ist es nicht möglich, weniger als 1 zu erzielen.
  • Ich kann mir einen einfachen Algorithmus mit Punktzahl 2 vorstellen (aber ich gebe ihn nicht ein).

Hinweise zu Suprema und Krawatten

  • Ein Supremum einer Reihe von Zahlen ist die kleinste Zahl, die nicht kleiner als eine von ihnen ist. Dies entspricht in etwa dem Maximum einer Menge, mit der Ausnahme, dass einige unendliche Mengen wie {2/3, 3/4, 4/5, 5/6, ...} kein einzelnes maximales Element haben, aber immer noch ein Supremum haben. in diesem Fall 1.
  • Wenn es Ihnen gelingt, nur eine konstante Anzahl von Zuweisungen über meinen Algorithmus mit Punktzahl 2 (z. B.) zu "speichern", beträgt Ihre Punktzahl immer noch 2, da Sie mit zunehmender Eingabe beliebig nahe an 2 kommen. Allerdings gewinnt man im Tie-Break, wenn es dazu kommt.
Ben Millwood
quelle
1
Ich wäre ein bisschen traurig, wenn das alles auf bahnbrechende Score-2-Einsendungen zur Speichernutzung hinauslaufen würde. Ich habe diese Frage meistens gestellt und mich gefragt, ob es jemandem gelingen würde, weniger als 2 Punkte zu erzielen.
Ben Millwood,
1
Ich habe keinen formalen Beweis, aber meine Intuition sagt mir, dass es mit der Beschränkung auf konstante Leerzeichen unmöglich ist, bessere Ergebnisse als 2 zu erzielen. Wenn Sie nur Variablendeklarationen für Leerzeichen zählen, könnte ich schummeln und eine rekursive Funktion erstellen. aber das verschleiert den little-omega(1)Raum nur, indem es auf den Stapel gelegt wird.
Falsch
2
@bacchusbeale ja, aber es ist ständig zusätzlicher Speicher.
Martin Ender
4
Wenn Sie die Regeln strikt durchsetzen, ist es unmöglich, ein solches Programm zu schreiben. Die Zeichenfolge kann beliebig lang sein, und Sie benötigen mindestens eine Variable, in der ein Index gespeichert ist. Also muss ich die Zeichenfolge nur lang genug machen, um die Grenzen Ihrer Variablen zu überschreiten. Um mindestens einen Index erfolgreich zu speichern, wächst der benötigte Speicherplatz mit der Länge der Zeichenfolge.
IchBinKeinBaum
3
@IchBinKeinBaum ist richtig, es ist unmöglich, diese Aufgabe mit O(1)zusätzlichem Platz durchzuführen . Sie benötigen O(log n)Platz zum Speichern einer Indexposition, da eine k-Bit-Ganzzahl nur Zeichenfolgen mit einer Länge von bis zu darin speichern kann 2^k. Das Begrenzen der Länge der Zeichenketten macht die Herausforderung ziemlich sinnlos, da jeder Algorithmus auf O(1)diese Weise Platz beanspruchen würde .
Dennis

Antworten:

4

Python, Score: 2 1,5 1,25

Dies ist die direkte Kombination zwischen der Antwort von primo und meiner Antwort. Also auch ihm zu verdanken!

Der Beweis ist noch in Bearbeitung, aber hier ist der Code zum Spielen! Wenn Sie ein Gegenbeispiel für eine Punktzahl größer als 1,25 finden (oder wenn es einen Fehler gibt), lassen Sie es mich wissen!

Derzeit ist der schlimmste Fall:

aa ... aa dcb ... cbd

Dabei gibt es genau n der Buchstaben "a", "b", "c" und "" (Leerzeichen) und genau zwei "d". Die Länge der Zeichenfolge beträgt 4n + 2 und die Anzahl der Zuweisungen beträgt 5n + 2 , was eine Punktzahl von 5/4 = 1,25 ergibt .

Der Algorithmus arbeitet in zwei Schritten:

  1. Finden Sie ksolche string[k]und string[n-1-k]sind Wortgrenzen
  2. Führen Sie einen beliebigen Wortumkehralgorithmus mit kleinen Änderungen aus string[:k]+string[n-1-k:](dh Verkettung der ersten kund letzten kZeichen).

Wo nist die Länge der Zeichenfolge.

Die Verbesserung, die dieser Algorithmus bietet, ergibt sich aus der "kleinen Änderung" in Schritt 2. Es ist im Grunde das Wissen, dass in der verketteten Zeichenfolge die Zeichen an der Position kund k+1Wortgrenzen sind (dh sie sind Leerzeichen oder das erste / letzte Zeichen in einem Wort). und so können wir die Zeichen in Position kund k+1mit dem entsprechenden Zeichen in der letzten Zeichenfolge direkt ersetzen und einige Zuweisungen speichern. Dies entfernt den ungünstigsten Fall aus dem Host-Wortumkehralgorithmus

Es gibt Fälle, in denen wir solche nicht finden kkönnen. In diesem Fall führen wir einfach den "Any Word Reversal Algorithmus" für die gesamte Zeichenfolge aus.

Der Code ist lang, um diese vier Fälle beim Ausführen des Wortumkehralgorithmus für die "verkettete" Zeichenfolge zu behandeln:

  1. Wann kwird nicht gefunden ( f_long = -2)
  2. Wann string[k] != ' ' and string[n-1-k] != ' '( f_long = 0)
  3. Wann string[k] != ' ' and string[n-1-k] == ' '( f_long = 1)
  4. Wann string[k] == ' ' and string[n-1-k] != ' '( f_long = -1)

Ich bin sicher, dass der Code gekürzt werden kann. Momentan ist es lange her, weil ich am Anfang kein klares Bild des gesamten Algorithmus hatte. Ich bin sicher, man kann es so gestalten, dass es in einem kürzeren Code dargestellt wird =)

Probelauf (der erste ist meiner, der zweite ist der Primo):

Zeichenfolge eingeben: a bc def ghij
"ghij def bc a": 9, 13, 0,692
"ghij def bc a": 9, 13, 0,692
Zeichenfolge eingeben: ab cdefghijklmnopqrstuvw xyz
"zyxwvutsrqponmlkjihgf edc ab": 50, 50, 1.000
"zyxwvutsrqponmlkjihgf edc ab": 51, 50, 1,020
Zeichenfolge eingeben: abcdefg hijklmnopqrstuvwx
"hijklmnopqrstuvwx gfedcb a": 38, 31, 1,226
"hijklmnopqrstuvwx gfedcb a": 38, 31, 1,226
Zeichenfolge eingeben: 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
Geben Sie 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

Sie können sehen, dass die Punktzahl fast gleich ist, mit Ausnahme des schlechtesten Falls des Host-Wortumkehralgorithmus im dritten Beispiel, für den mein Ansatz eine Punktzahl von weniger als 1,25 ergibt

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, Score: 1,5

Die genaue Anzahl der Zuordnungen kann durch die Formel angenähert werden:

n <= 1,5 * Länge (String)

mit dem schlimmsten Fall ist:

abcdefghi jklmnopqrstuvwxyzzz

mit 55 Aufgaben an einer Saite mit der Länge 37.

Die Idee ähnelt meiner vorherigen, es ist nur so, dass ich in dieser Version versucht habe, Präfix und Suffix an Wortgrenzen mit einem Längenunterschied von höchstens 1 zu finden. Dann führe ich meinen vorherigen Algorithmus mit diesem Präfix und Suffix aus (stelle sie mir als verkettet vor). . Fahren Sie dann mit dem unbearbeiteten Teil fort.

Zum Beispiel für den vorigen schlimmsten Fall:

ab | ab | c

Wir werden zuerst das Wort "ab" und "c" (4 Zuordnungen) umkehren, um zu sein:

c | ab | ab

Wir wissen, dass es sich an der Grenze früher um Leerzeichen handelte (es gibt viele Fälle, die behandelt werden müssen, aber Sie können dies tun), sodass wir das Leerzeichen an der Grenze nicht codieren müssen. Dies ist die Hauptverbesserung gegenüber dem vorherigen Algorithmus .

Dann laufen wir endlich auf die mittleren vier Zeichen, um zu bekommen:

cba ab

Insgesamt 8 Zuordnungen, die für diesen Fall optimal sind, da sich alle 8 Zeichen geändert haben.

Dies beseitigt den schlechtesten Fall im vorherigen Algorithmus, da der schlechteste Fall im vorherigen Algorithmus beseitigt ist.

Sehen Sie sich einen Probelauf an (und vergleichen Sie ihn mit @primos Antwort - dies ist die zweite Zeile):

Zeichenfolge eingeben: Ich kann alles
"alles kann ich tun": 20, 17
"alles kann ich tun": 17, 17
Zeichenfolge eingeben: abcdef ghijklmnopqrs
"ghijklmnopqrs fedcb a": 37, 25
"ghijklmnopqrs fedcb a": 31, 25
Zeichenfolge eingeben: abcdef ghijklmnopqrst
"ghijklmnopqrst fedcb a": 38, 26
"ghijklmnopqrst fedcb a": 32, 26
Zeichenfolge eingeben: abcdefghi jklmnozzzzzzzzzzzzzzz
"jklmnozzzzzzzzzzzzzzzzz ihgfedcb a": 59, 41
"jklmnozzzzzzzzzzzzzzzzz ihgfedcb a": 45, 41
Zeichenfolge eingeben: abcdefghi jklmnopqrstuvwxyzzz
"jklmnopqrstuvwxyzzz ihgfedcb a": 55, 37
"jklmnopqrstuvwxyzzz ihgfedcb a": 45, 37
Zeichenfolge eingeben: ab abababababac
"cababababababa ab": 30, 30
"cababababababa ab": 31, 30
Zeichenfolge eingeben: ab abababababababc
"cbababababababa ab": 32, 32
"cbababababababa ab": 33, 32
Zeichenfolge eingeben: abc d abc
"abc d abc": 0, 9
"abc d abc": 0, 9
Zeichenfolge eingeben: abc dca
"acd abc": 6, 9
"acd abc": 4, 9
Zeichenfolge eingeben: abc ababababababc
"cbabababababa abc": 7, 29
"cbabababababa abc": 5, 29

Die Antwort von primo ist im Allgemeinen besser, obwohl ich in einigen Fällen 1 Punkt Vorteil haben kann =)

Auch sein Code ist viel kürzer als meiner, 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: asymptotisch 2, im Normalfall viel weniger

alter Code aus Platzgründen entfernt

Die Idee ist , zu durchlaufen jeden Index, und für jeden Index i, wir den Charakter nehmen, berechnen die neue Position j, merken an Position den Charakter j, weisen das Zeichen an izu j, und wiederholen Sie mit Charakter am Index j. Da wir die Leerzeicheninformationen benötigen, um die neue Position zu berechnen, codiere ich das alte Leerzeichen als Großbuchstaben des neuen Buchstabens und das neue Leerzeichen als '@'.

nur zur Hälfte
quelle
Wenn Sie die Anzahl der Wörter im length(string)/3schlimmsten Fall auf die Länge der Zeichenfolge reduzieren können (z. B. indem Sie jedes Wort im schlimmsten Fall zwingen, mindestens die Länge 2 zu haben), ist die Punktzahl geringer als 2 (im obigen Beispiel ist es 1,67)
halbe
1
Ich fügte meiner einen Wechselschalter hinzu; deines schlägt meins für den schlimmsten Fall (aber nicht für den allgemeinen Fall). Müssen einen Weg finden, um das zu beheben;)
Primo
Zeile 127: if any(process_loop(...) for j in range(...))Müssten die Zuordnungen aus diesen Prozessschleifen nicht gezählt werden?
Primo
Das macht keine Aufgabe. Wenn Sie sehen, wird der dry_runParameter auf einen Wert ungleich Null gesetzt (der Wert auf i). Innerhalb der process_loop, wenn dry_runnicht Null ist, wird es jede Zuordnung nicht.
Nur die Hälfte des
1
Ich denke, ich habe jetzt ein besseres Bild. Im Wesentlichen werden zwei unterschiedliche Methoden mit unterschiedlichem Worst-Case-Verhalten kombiniert, um den Worst-Case für beide zu eliminieren. Ich mag das. Ich denke im Allgemeinen, dass dies der beste Ansatz ist, obwohl es wahrscheinlich ist, dass zwei (oder mehr) völlig unterschiedliche Methoden kombiniert werden könnten, um den Worst-Case noch weiter zu reduzieren.
Primo
14

Perl, Score 1.3̅

Für jedes Nicht-Leerzeichen wird eine Zuweisung ausgeführt und für jedes Leerzeichen zwei Zuweisungen. Da Leerzeichen nicht mehr als die Hälfte der Gesamtzahl der Zeichen betragen dürfen, beträgt die schlechteste Punktzahl 1,5 .

Der Algorithmus hat sich nicht geändert, aber ich kann eine untere Obergrenze nachweisen. Lassen Sie uns zwei Beobachtungen machen:

  1. Leerzeichen direkt gegenüber müssen nicht getauscht werden.
  2. Einzelworte direkt gegenüber von Leerzeichen werden in der Hauptphase nicht getauscht, sondern nur einmal am Ende.

Es ist dann zu sehen, dass der theoretische 'worst case' mit asymptotisch 1/2 Leerzeichen überhaupt nicht worst case ist: 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

In der Tat ist es ein ziemlich guter Fall.

Um die obigen Beobachtungen eins und zwei zu vermeiden, müsste jedes Wort mit einem Zeichen in die Mitte eines drei oder mehr Zeichen langen Wortes verschoben werden. Dies würde den schlimmsten Fall nahe legen, der asymptotisch 1/3 Leerzeichen enthält: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

Oder gleichbedeutend nur zweistellige Wörter: 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

Da der schlechteste Fall asymptotisch 1/3 Leerzeichen enthält, wird der schlechteste Fall bewertet beträgt 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;

Bearbeiten: Es wurden ein Swap-Zähler und das Verhältnis hinzugefügt.

Die Eingabe erfolgt aus stdin. Beispielnutzung:

$ 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

Methode

Zu Beginn wird das erste Zeichen der Zeichenfolge an das endgültige Ziel verschoben. Das gerade ersetzte Zeichen wird dann an sein Ziel usw. verschoben. Dies wird fortgesetzt, bis eine der beiden Bedingungen erfüllt ist:

  1. Der Charakter sollte mit einem Leerzeichen getauscht werden.
    In diesem Fall ist das Zeichen nicht mit dem Leerzeichen vertauscht, sondern in die Spiegelposition des Leerzeichens. Der Algorithmus fährt von dieser Position fort.
  2. Ein Zyklus wurde erreicht.
    Wenn das Ziel zur anfänglichen Startposition des aktuellen Zyklus zurückkehrt, muss das nächste nicht vertauschte Zeichen (oder vielmehr jedes nicht vertauschte Zeichen) gefunden werden. Um dies unter konstanten Speicherbeschränkungen zu tun, werden alle bis zu diesem Zeitpunkt vorgenommenen Auslagerungen zurückverfolgt.

Nach dieser Phase wurde jedes Nicht-Leerzeichen höchstens einmal verschoben. Zum Abschluss werden alle Leerzeichen mit den Zeichen an ihren Spiegelpositionen vertauscht, was zwei Zuweisungsoperationen pro Leerzeichen erfordert.

primo
quelle
Wow, das ist cool. Können Sie erklären, warum das Setzen des Zeichens an die Spiegelposition des Raums die richtige Antwort gibt?
Nur die Hälfte des
1
@ Niklas, ich glaube nicht, dass das möglich ist. Denn für das Backtracking benötigen Sie die Raumpositionsinformationen. Wenn Sie diese Informationen überschreiben, können Sie die Rückverfolgung nicht durchführen.
Nur die Hälfte des
1
Ich vergleiche meinen Algorithmus in meiner Antwort hier: codegolf.stackexchange.com/a/26952/16337
Hälfte des
1
@justhalf In der letzten Zeichenfolge befinden sich alle Leerzeichen in ihrer gespiegelten Position. Daher können wir diese Position sicher verwenden, um das Zeichen, das das Leerzeichen ersetzt, zu speichern und am Ende zu wechseln.
Primo
1
Gut gemacht. Ich hatte eine ähnliche Idee, dachte aber nicht daran, die Räume an Ort und Stelle zu lassen und sie dann zu spiegeln.
IchBinKeinBaum
7

Ruby, Punktzahl 2

Als Starter ein sehr grundlegender Algorithmus. Es kehrt zuerst die gesamte Zeichenfolge um und kehrt dann jedes Wort in der Zeichenfolge erneut um. Im schlimmsten Fall (ein Wort, gerade Anzahl von Zeichen) wird die Punktzahl 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

Verwendung:

> revwords("hello there everyone")
"everyone there hello"
Howard
quelle
Warum haben Sie keine in Ruby integrierte Funktion verwendet, um eine Zeichenfolge umzukehren? Würde es die Punktzahl ändern?
AL
benutze, s [a], s [b] = s [b], s [a]
Thaha kp
5

C ++: Score 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;
}
Anmol Singh Jaggi
quelle
2
Ich habe es getestet. Funktioniert gut!
Bacchusbeale
2

Rebol

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
]

Ich bin mir nicht sicher, wie es ausgeht. In diesem Code gibt es keine direkte Zeichenfolgenzuweisung. Alles wird von dem einen erledigtreverse/part erledigt, der an Ort und Stelle innerhalb der Saite und zunächst insgesamt die Saite umkehrt.

Einige Details zum Code:

  • Durchlaufe string ( series) bis zumtail?

  • Das erste Mal in der Schleife mache die vollständige Umkehrung des Strings - reverse/part series tail series(das ist dasselbe wie reverse series)

  • Kehren Sie dann jedes Wort um, das Sie bei weiteren Iterationen gefunden haben - reverse/part series find series space

  • Sobald ein erschöpftes Wort gefunden wurde, kehre zurück, tail seriesdamit es das letzte Wort in der Zeichenfolge umkehrt.reverse/part series tail series

Mit Rebol kann ein String über einen internen Zeiger durchlaufen werden . Sie können dies sehen bei series: next f(Zeiger nach Leerzeichen bewegen, so Beginn des nächsten Wortes) undseries: head series (Zeiger auf den Kopf zurücksetzen).

Siehe SerieWeitere Informationen finden .

Anwendungsbeispiel in der Rebol-Konsole:

>> 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"
draegtun
quelle
Beim ersten Durchgang wird jedes Zeichen einmal neu positioniert, und beim zweiten Durchgang wird jedes Nicht-Leerzeichen erneut positioniert. Für eine beliebig große Eingabe mit relativ wenigen Leerzeichen nähert sich die Punktzahl 2.
Primo
2

C: Punktzahl 2

Dadurch wird die gesamte Zeichenfolge nur einmal umgedreht und dann jedes Wort umgekehrt.

#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;
}
Technosaurus
quelle
3
Dies ist eine reine Code-Antwort. Erwägen Sie, eine Erklärung für den Code hinzuzufügen.
Justin
1

Python: Punktzahl 2

Fast identisch mit Howards Algorithmus, jedoch werden die Umkehrschritte in umgekehrter Reihenfolge ausgeführt (zuerst werden Wörter umgedreht, dann wird die gesamte Zeichenfolge umgedreht). Zusätzlicher Speicher 3 verwendet wird Byte-Größe Variablen: i, j, und t. Technisch findund lenmit einigen internen Variablen, aber sie könnten genauso einfach wiederverwendet werden ioderj ohne Funktionsverlust.

Schnelle Bearbeitung: Speichern von Zeichenfolgen, indem nur bei unterschiedlichen Zeichen getauscht wird, damit ich einige zusätzliche Punkte aus Note 2 herausholen kann.

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))
wrongu
quelle
1

Stapel

Ich gebe zu, dass ich die Wertung nicht ganz verstehe (ich glaube, es sind zwei). Aber ich werde sagen - es macht das Ding .

@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!

Die Eingabe wird als erster Standardeingabewert genommen, und so Bedürfnisse von Anführungszeichen umgeben sein -
Aufruf: script.bat "hello there everyone"
out: everyone there hello.

Vielleicht kann mich jemand anderes bewerten (vorausgesetzt, ich habe mich nicht auf andere Weise disqualifiziert).

unclemeat
quelle
-2

Javascript

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

Verwendung:

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

Ich habe das komische Gefühl, etwas verpasst zu haben ...

Vorwärts
quelle
3
Ja, dies ist nicht vorhanden, da Sie die Eingabezeichenfolge nicht ändern. Da dies in JavaScript nicht möglich ist, müssen Sie Zeichenfolgen mit einem Array von Zeichen emulieren (z. B. Codepunkt-Ganzzahlen oder Zeichenfolgen mit nur einem Zeichen).
Martin Ender
Um es auf den Punkt zu bringen, benötigt es sehr viel zusätzlichen Platz.
Ben Millwood