Ordnen Sie eine Liste an

8

Mit einem Fenster ähnlich dem unten abgebildeten erhalten Sie eine Liste von Zeichenfolgen, die Sie in alphabetischer Reihenfolge einfügen möchten.

Dialogfeld "Sortierreihenfolge"

Wie gezeigt, haben Sie fünf Operationen:

  • Nach oben bewegen [U] - Verschiebt die ausgewählte Zeichenfolge um eine Stelle nach oben
  • Nach unten bewegen [D] - Verschiebt die ausgewählte Zeichenfolge um eine Stelle nach unten
  • Zuerst verschieben [F] - Verschiebt die ausgewählte Zeichenfolge an den Anfang der Liste
  • Letzte verschieben [L] - Verschiebt die ausgewählte Zeichenfolge an den unteren Rand der Liste
  • Umkehren [R] - Kehrt die Reihenfolge der Liste um

Akzeptieren Sie mit STDIN eine Zahl (wie viele Zeichenfolgen), gefolgt von der ungeordneten Liste der Zeichenfolgen. Jede Zeichenfolge besteht aus 2-99 englischen Kleinbuchstaben. (Das obige Beispiel wäre keine gültige Eingabe.)

Drucken Sie mit STDOUT die Reihenfolge der Liste. Erwähnen Sie zuerst ein Element, das Sie auswählen möchten, und dann die Operationen, die Sie ausführen müssen, um die Liste in alphabetischer Reihenfolge zu platzieren.

Zum Beispiel: February U December F May D D June D R D...

Erläuterung: Klicken Sie auf Februar und verschieben Sie es nach oben. 1. Wählen Sie Dezember und verschieben Sie es nach oben. Mai, bewege es zweimal nach unten. Juni, einmal nach unten gehen, die Liste umkehren, wieder nach unten gehen ...

Da es offensichtlich viele gültige Lösungen gibt, müssen Sie die kürzestmögliche auswählen. Wählen Sie also die Methode mit der geringsten Anzahl von Operationen (7 im obigen Beispiel).

Wenn die korrekten Ausgaben mit der Eingabe verknüpft sind, lösen Sie sie in der folgenden Reihenfolge.

  1. Wählen Sie diejenige mit der geringsten Auswahl an Zeichenfolgen (4 im obigen Beispiel).

  2. Wählen Sie die Operation mit den wenigsten Operationen aus und zählen Sie aufeinanderfolgende identische Operationen (an einer Zeichenfolge) als eine (6 im obigen Beispiel).

  3. Wählen Sie die mit der kürzesten Ausgabe (geringste Anzahl von Zeichen insgesamt, Leerzeichen zählen).

  4. Wählen Sie die mit der Ausgabe, die zuerst alphabetisch angezeigt wird.

Das ist Code-Golf; Die kürzeste Einreichung, die immer die richtige Ausgabe liefert, gewinnt.

Beispiele

  • IM 2 zz abc
    • AUS zz D
  • IM 3 cc bb aa
    • AUS aa R
  • IM 4 abc def cd ccc
    • AUS abc L R
  • IM 6 rr mm nn oo qq pp
    • AUS pp U rr L

Zusätzliche Beispiele (bereitgestellt von Scott Leadley, alle Fehler sind meine und nicht die von ypnypn)

Einige schwierige Fälle:

  • IN => OUT
  • 6 xx aa dd bb ee cc => dd L ee L xx L
  • 7 aa bb ee cc dd ff gg => ee D D
  • 8 dd ww aa bb cc xx yy zz => ww D D D dd D D D
    • ( nicht die minimale Anzahl von Zügen, die wäre cc F bb F aa F)

Permutationen von 4 Elementen aa bb cc ddmit Sortierpfaden der Länge> 1:

  • IN => OUT
  • 4 aa cc dd bb => bb F D
  • 4 aa dd cc bb => aa L R
  • 4 bb aa dd cc => aa F cc U
  • 4 bb dd aa cc => aa F cc U
  • 4 bb dd cc aa => bb D D R
  • 4 cc aa bb dd => cc D D
  • 4 cc aa dd bb => bb F aa F
  • 4 cc bb aa dd => dd F R
  • 4 cc bb dd aa => dd F R
  • 4 cc dd aa bb => bb F aa F
  • 4 cc dd bb aa => cc D R
  • 4 dd aa cc bb => aa L R
  • 4 dd bb aa cc => cc F D R
  • 4 dd bb cc aa => bb D R
  • 4 dd cc aa bb => aa D R

Variationen über ein Thema, 4 Elemente, bei aaaaa bbbb ccc dddenen die Länge der Zeichenfolge einen Unterschied macht:

  • IN => OUT
  • 4 ccc dd aaaaa bbbb => ccc L dd L
  • 4 bbbb aaaaa dd ccc => bbbb D dd D
  • 4 bbbb dd aaaaa ccc => dd L bbbb D
  • 4 ccc aaaaa dd bbbb => ccc L dd L
  • 4 ccc dd bbbb aaaaa => dd F R
  • 4 dd bbbb ccc aaaaa => ccc R D
  • 4 dd ccc aaaaa bbbb => bbbb R D
Ypnypn
quelle
Ihr Beispiel scheint der Spezifikation in mindestens zwei Punkten zu widersprechen: Es enthält Zeichenfolgen, die keine 2-99 englischen Kleinbuchstaben sind, und einen Befehl, Ader nicht vorhanden ist.
Peter Taylor
1
Könnten Sie einige Beispieleingänge mit den richtigen Ausgängen versehen?
Claudiu
4
Nur zum Spaß befiehlt Vim für alle diese Aktionen: U = ddkP, D = ddp, F = ddggP, L = ddGp, R = :g/^/m0. : P
Türknauf
2
Ich hatte auf anspruchsvollere Beispiele gehofft. Ich habe Probleme herauszufinden, wie ich nachweislich die kürzeste Lösung finden kann, ohne zuerst alle Möglichkeiten zu durchsuchen, was schnell lächerlich wird
Claudiu
2
Ich möchte darauf hinweisen, dass Sie, wenn Sie eine minimale Anzahl von Operationen garantieren möchten, sich auf einem rechnerisch unlösbaren Boden befinden ... * Selbst wenn Sie die minimale Anzahl von Vergleichen kennen *, die für eine Sortierung erforderlich sind, sind derzeit nur bis zu 15 Elemente bekannt . Siehe "Psychische Sortieralgorithmen" .
HostileFork sagt, vertraue SE

Antworten:

2

Python 2 - 593 521

Es ist sehr brutal mit einigen Effizienzen, so dass es tatsächlich zu Ende geht. Die Liste mit 6 Elementen, mit der ich teste, dauert auf meinem Laptop ungefähr 5 Sekunden.

$ time echo 5 xx aa dd bb ee cc | python order.py
dd L ee L xx L

real    0m4.444s
user    0m4.388s
sys 0m0.051s

Beachten Sie, dass ich die Nummer in der Eingabe ignoriere. Ich finde es nutzlos.

import sys
def d(l,s,o,f):
 p=len(o)
 tl=tuple(l)
 if tl in s and p>=len(s[tl]) or f and p>=len(f):
  return
 if l==sorted(l):
  return o if not f or p<len(f) else None
 s[tl]=o
 x=d(l[::-1],s,o+[l[-1]+' R'],f)or f
 for n,i in enumerate(l):
  for j,k in ([(l[:n]+[l[n+1],l[n]]+l[n+2:],'D'),(l[:n]+l[n+1:]+[l[n]],'L')]if(n!=len(l)-1)else[])+([(l[:n-1]+[l[n-1],l[n]]+l[n+1:],'U'),([l[n]]+l[:n]+l[n+1:],'F')]if(n!=0)else[]):
   x=d(j,s,(o+[i+' '+k]),x)or x
 return x
print ' '.join(d(sys.stdin.read().split()[1:],{},[],[]))

Ugh, ich habe gerade festgestellt, dass ich nicht mehrere Operationen mit demselben Wert richtig verarbeite. Ich werde versuchen, das zu beheben.

Bizangles
quelle
0

Ruby 2.0

Wenn der Operator [U, D, F, L] eingestellt ist, ist die Anzahl der Elemente in der Liste abzüglich der längsten gemeinsamen Teilsequenz die geringste Anzahl von Zeichenfolgen, die zum Sortieren der Liste ausgewählt werden. Um den R-Operator hinzuzufügen, kehren Sie einfach die Zeichenfolge um und wenden dieselbe Regel an. Leider ist das Minimieren der Auswahl von Zeichenfolgen nicht dasselbe wie das Minimieren der Anzahl von Operationen. Für eine Eingabe von 8 dd ww aa bb cc xx yy zzlautet beispielsweise die richtige Antwort ww D D D dd D D D, aber die geringste Anzahl von Operationen (die die anderen Kriterien in der Frage erfüllen) wäre cc F bb F aa F. Dies bedeutet, dass ein viel größerer Teil des Satzes möglicher Sortierpfade untersucht werden muss.


Diese Lösung verwendet eine Tiefensuchstrategie und Alpha-Beta-Bereinigung. Es ist wichtig, den Alpha-Wert schnell zu senken, um die Suchtiefe zu minimieren. Andernfalls explodiert der Suchbaum exponentiell. Das Bestimmen des Sortierpfads mit der Mindestpunktzahl für das Einführungsbeispiel von OP, das Sortieren von Monaten in Kalenderreihenfolge nach lexikalischer Reihenfolge, wird mit der aktuellen Bewertungsmethode dieses Programms wahrscheinlich einige Jahrzehnte dauern. Das Programm findet sehr schnell die minimale Anzahl von String-Auswahlen (8). Leider bleibt immer noch ein riesiger Baum übrig, durch den man laufen kann.

Ich verwende die Gnomensortierung als Bewertungsfunktion, weil:

  1. Es ist einfach zu verstehen und zu ändern
  2. Die Wertung konvergiert normalerweise schnell zum optimalen Alpha
  3. Diese Implementierung ist schneller als meine Implementierung der LCS-Funktion
  4. Es wird besser Golf spielen als die LCS-Funktion

Nummer 4 wäre ausreichend. Alles andere ist ein Bonus.

Bei einer Tiefensuche hat die Reihenfolge, in der Operationen untersucht werden, einen erheblichen Einfluss auf die Suchzeit. Da jeder nicht leere Satz von N Elementen mit ≤ N-1 F (erste) oder L (ast) Operationen sortiert werden kann, werden diese Operationen zuerst versucht.

# gnome sort
def gnomeSort(a)
    selects = 0
    previous = nil
    i = 1
    while i < a.size
        if a[i-1] <= a[i]
            # the array a[0..i] is sorted
            i += 1      # take another bite
        else
            if a[i] != previous
                previous = a[i]
                selects += 1
            end
            a[i], a[i-1] = a[i-1], a[i]
            if (i > 1)
                i -= 1
            end
        end
    end
    return selects
end
def score(a)
    return gnomeSort(a.dup)
end

# squeeze out unnecessary operands
def consolidate(a)
    # separate operands and operators
    x = []                      # operands
    f = []                      # operators
    a.each_slice(2) { |a,b|
        x << a
        f << b
    }
    n = x.size                  # number of (operand operator) pairs
    if n>=2
        # replace all R operands with the lexically lower operand
        #   from the right or left
        f.each_with_index{|v,i|
            if v=='R'
                leftOperand = x[i-1]
                rightOperand = x[i+1]
                # handle left & right edge cases
                leftOperand = rightOperand.succ  if i==0
                rightOperand = leftOperand.succ  if i>=n-1
                x[i] = [leftOperand, rightOperand].min
            end
        }

        # replace repeated operands with <nil>
        x = x.chunk{|e|e}.map{|v|v[1].fill(nil,1)}.flatten
    end
    return [x, f]
end

@solutions = []
@operation = []
@operation[3] = ->(a, i) {
        # swap a[i] and a[i-1]
        return nil  if i<1 || i>=a.size
        v = a[i]
        a[i-1], a[i] = a[i], a[i-1]
        return [ v, 'U' ]
    }
@operation[0] = ->(a, i) {
        # move a[i] after a.last
        return nil  if i+1>=a.size
        a.push(v=a.delete_at(i))
        return [ v, 'L' ]
    }
@operation[4] = ->(a, i) {
        # reverse the whole array
        v = a[i]
        a.reverse!
        return [ v, 'R' ]
    }
@operation[1] = ->(a, i) {
        # move a[i] before a.first
        return nil  if i<=0
        a.unshift(v=a.delete_at(i))
        return [ v, 'F' ]
    }
@operation[2] = ->(a, i) {
        # swap a[i] and a[i+1]
        return nil  if i<0 || i+1>=a.size
        v = a[i]
        a[i], a[i+1] = a[i+1], a[i]
        return [ v, 'D' ]
    }

def alphaSort(depth, a, selected, selects, sortPath)
  depth += 1
  return  if selects > @alpha
  return  if selects>@alpha || selects+depth>a.size+1
  if a.each_cons(2).all?{ |x, y| x <= y }
    # found a sort path
    @alpha = selects
    @solutions << sortPath.flatten.compact
  else
    selectsFromHere = score(a)
    if @alpha > selects+selectsFromHere
      @alpha = selects+selectsFromHere
    else
    end
    @operation.each do |op|
      a.each_index do |i|
        b = a.dup
        branch = sortPath.dup << op[b,i]
        alphaSort(depth, b, a[i], selects+(selected==a[i] ? 0 : 1), branch)
      end
    end
  end
end


#       input
a = ARGF.read.scan(/\w+/m)      # alternative, $*[0].scan(/\w+/m)
a.shift                         # ignore the item count

#       depth-first search of sort operations
@alpha = [a.size-1, score(a), score(a.reverse)+1].min + 1
alphaSort(0, a, nil, 0, [])

#       winnow the set of solutions
# determine the minimum number of string selects to solve
# short-circuit if selects to solve is 0 (already sorted)
@solutions.map!{|v|consolidate v}
minSelects = @solutions.map{|v|v[0].compact.size}.min
if !minSelects
    puts
    exit
end
# keep only solutions with the minimum number of string selects
@solutions.reject!{ |v| v[0].compact.size > minSelects }

# determine the minimum number of moves in the remaining solutions
minMoves = @solutions.map{|v|v[1].size}.min
# keep only solutions with the minimum number of moves
@solutions.reject!{ |v| v[1].size > minMoves }

#       beauty contest
# turn into strings
solutions = @solutions.map{|v|v[0].zip(v[1]).flatten.compact*' '}
# keep the shortest strings
minLength = solutions.map{|v|v.size}.min
solutions.reject!{ |v| v.size > minLength }
# print the string that "that comes first alphabetically"
puts solutions.sort.first

Es besteht diese Perl-TAP -Testsuite:

use strict;
use warnings;

use Test::More qw(no_plan);
#use Test::More tests => 61;

#       solution executable
my $solver = 'ruby2.0 sortshort.rb';
my $nonTrivial = 1;


#       "happy" path

#       examples from OP
is( `echo 2 zz abc | $solver 2>&1`, "zz D\n", 'OP example #1');
is( `echo 3 cc bb aa | $solver 2>&1`, "aa R\n", 'OP example #2');
is( `echo 4 abc def cd ccc | $solver 2>&1`, "abc L R\n", 'OP example #3');
is( `echo 6 rr mm nn oo qq pp | $solver 2>&1`, "pp U rr L\n", 'OP example #4');

# example from bizangles
is( `echo 6 xx aa dd bb ee cc | $solver 2>&1`, "dd L ee L xx L\n", 'wascally wabbit, challenges deep diver (from bizangles)');

SKIP: {
  skip('non-trivial tests', 2)  unless $nonTrivial;

  # 7 item example; bizangles' python solution (circa 2014-08-22) requires higher sys.setrecursionlimit() and takes about 5 minutes
  is( `echo 7 aa bb ee cc dd ff gg | $solver 2>&1`, "ee D D\n", 'shallow');

  # minimizing the number of selects scores better than minimizing moves
  # minimizing moves                =>  cc F bb F aa F
  # minimizing selects              =>  dd D D D D ww D D D D,  ww D D D dd D D D,  ww L U U U dd D D D,  etc.
  # minimizing selects, then moves  =>  ww D D D dd D D D
  is( `echo 8 dd ww aa bb cc xx yy zz | $solver 2>&1`, "ww D D D dd D D D\n", 'joker, minimize selects before moves');
}

#       exhaustive variations on a theme with 1 item ["aa"]
is( `echo 1 aa | $solver 2>&1`, "\n", 'permutations of 1, #1');

#       exhaustive variations on a theme with 2 items ["ab", "c"]
is( `echo 2 ab c | $solver 2>&1`, "\n", 'permutations of 2, #1');
# test OP's requirement that a string be selected before reverse operation
is( `echo 2 c ab | $solver 2>&1`, "c D\n", 'permutations of 2, #2');

#       exhaustive variations on a theme with 3 items ["five", "four", "three"]
is( `echo 3 five four three | $solver 2>&1`, "\n", 'permutations of 3, #1');
is( `echo 3 five three four | $solver 2>&1`, "four U\n", 'permutations of 3, #2');
is( `echo 3 four five three | $solver 2>&1`, "five F\n", 'permutations of 3, #3');
is( `echo 3 four three five | $solver 2>&1`, "five F\n", 'permutations of 3, #4');
is( `echo 3 three five four | $solver 2>&1`, "three L\n", 'permutations of 3, #5');
is( `echo 3 three four five | $solver 2>&1`, "five R\n", 'permutations of 3, #6');

#       selected variations on a theme with 5 items ["aa", "bb", "cc", "dd", "ee"]
is( `echo 5 aa bb cc dd ee | $solver 2>&1`, "\n", 'permutations of 5, #1, already sorted');
# two sort paths of length 1
is( `echo 5 aa bb cc ee dd | $solver 2>&1`, "dd U\n", 'permutations of 5, #2, single U or D');
is( `echo 5 aa bb ee cc dd | $solver 2>&1`, "ee L\n", 'permutations of 5, #4, single L');
is( `echo 5 bb cc aa dd ee | $solver 2>&1`, "aa F\n", 'permutations of 5, #31, single F');
is( `echo 5 ee dd cc bb aa | $solver 2>&1`, "aa R\n", 'permutations of 5, #120, reverse sorted');

#       exhaustive variations on a theme with 4 items ["aa", "bb", "cc", "dd"]
# sort paths of length 0
is( `echo 4 aa bb cc dd | $solver 2>&1`, "\n", 'permutations of 4, #1');
# sort paths of length 1
is( `echo 4 aa bb dd cc | $solver 2>&1`, "cc U\n", 'permutations of 4, #2');
is( `echo 4 aa cc bb dd | $solver 2>&1`, "bb U\n", 'permutations of 4, #3');
is( `echo 4 aa dd bb cc | $solver 2>&1`, "dd L\n", 'permutations of 4, #5');
is( `echo 4 bb aa cc dd | $solver 2>&1`, "aa F\n", 'permutations of 4, #7');
is( `echo 4 bb cc aa dd | $solver 2>&1`, "aa F\n", 'permutations of 4, #9');
is( `echo 4 bb cc dd aa | $solver 2>&1`, "aa F\n", 'permutations of 4, #10');
is( `echo 4 dd aa bb cc | $solver 2>&1`, "dd L\n", 'permutations of 4, #19');
is( `echo 4 dd cc bb aa | $solver 2>&1`, "aa R\n", 'permutations of 4, #24');

# sort paths of length 2
is( `echo 4 aa cc dd bb | $solver 2>&1`, "bb F D\n", 'permutations of 4, #4');
is( `echo 4 aa dd cc bb | $solver 2>&1`, "aa L R\n", 'permutations of 4, #6');
is( `echo 4 bb aa dd cc | $solver 2>&1`, "aa F cc U\n", 'permutations of 4, #8');
is( `echo 4 bb dd aa cc | $solver 2>&1`, "aa F cc U\n", 'permutations of 4, #11');
is( `echo 4 bb dd cc aa | $solver 2>&1`, "bb D D R\n", 'permutations of 4, #12');
is( `echo 4 cc aa bb dd | $solver 2>&1`, "cc D D\n", 'permutations of 4, #13');
is( `echo 4 cc aa dd bb | $solver 2>&1`, "bb F aa F\n", 'permutations of 4, #14');
is( `echo 4 cc bb aa dd | $solver 2>&1`, "dd F R\n", 'permutations of 4, #15');
is( `echo 4 cc bb dd aa | $solver 2>&1`, "dd F R\n", 'permutations of 4, #16');
is( `echo 4 cc dd aa bb | $solver 2>&1`, "bb F aa F\n", 'permutations of 4, #17');
is( `echo 4 cc dd bb aa | $solver 2>&1`, "cc D R\n", 'permutations of 4, #18');
is( `echo 4 dd aa cc bb | $solver 2>&1`, "aa L R\n", 'permutations of 4, #20');
is( `echo 4 dd bb aa cc | $solver 2>&1`, "cc F D R\n", 'permutations of 4, #21');
is( `echo 4 dd bb cc aa | $solver 2>&1`, "bb D R\n", 'permutations of 4, #22');
is( `echo 4 dd cc aa bb | $solver 2>&1`, "aa D R\n", 'permutations of 4, #23');

#       variations on a theme with 4 items ["aaaaa", "bbbb", "ccc", "dd"]
# force choice by string length
is( `echo 4 ccc dd aaaaa bbbb | $solver 2>&1`, "ccc L dd L\n", 'permutations of 4, #17');
is( `echo 4 dd bbbb aaaaa ccc | $solver 2>&1`, "ccc F D R\n", 'permutations of 4, #21');
is( `echo 4 bbbb aaaaa dd ccc | $solver 2>&1`, "bbbb D dd D\n", 'permutations of 4, #8');
is( `echo 4 bbbb dd aaaaa ccc | $solver 2>&1`, "dd L bbbb D\n", 'permutations of 4, #11');
is( `echo 4 ccc aaaaa dd bbbb | $solver 2>&1`, "ccc L dd L\n", 'permutations of 4, #14');
is( `echo 4 ccc dd bbbb aaaaa | $solver 2>&1`, "dd F R\n", 'permutations of 4, #18');
is( `echo 4 dd aaaaa ccc bbbb | $solver 2>&1`, "aaaaa L R\n", 'permutations of 4, #20');
is( `echo 4 dd bbbb ccc aaaaa | $solver 2>&1`, "ccc R D\n", 'permutations of 4, #22');
is( `echo 4 dd ccc aaaaa bbbb | $solver 2>&1`, "bbbb R D\n", 'permutations of 4, #23');

# identical items in list
is( `echo 2 aa aa | $solver 2>&1`, "\n", '1 repeat #1');
is( `echo 3 aa aa bb | $solver 2>&1`, "\n", '1 repeat #2');
is( `echo 3 aa bb aa | $solver 2>&1`, "aa F\n", '1 repeat #3');
is( `echo 3 bb aa aa | $solver 2>&1`, "aa R\n", '1 repeat #4');
is( `echo 4 aa cc bb aa| $solver 2>&1`, "aa L R\n", '1 repeat #5');
is( `echo 5 cc bb aa bb cc | $solver 2>&1`, "aa F cc L\n", '2 repeats');

#       "sad" path

# not explicitly excluded, so cover this case
#       exhaustive variations on a theme with 0 items []
is( `echo 0 | $solver 2>&1`, "\n", 'permutations of 0, #1');


#       "bad" path
# none!


exit 0;
Scott Leadley
quelle