Letakkan daftar secara berurutan

8

Dengan jendela yang mirip dengan yang digambarkan di bawah ini, Anda diberikan daftar string, yang ingin Anda masukkan dalam urutan abjad.

Urutkan dialog pesanan

Seperti yang ditunjukkan, Anda memiliki lima operasi:

  • Move up [U] - memindahkan string yang dipilih ke atas satu tempat
  • Move down [D] - memindahkan string yang dipilih ke satu tempat
  • Pindahkan dulu [F] - pindahkan string yang dipilih ke atas daftar
  • Pindahkan [L] terakhir - memindahkan string yang dipilih ke bagian bawah daftar
  • Reverse [R] - membalik urutan daftar

Dengan menggunakan STDIN, terima nomor (berapa banyak string), diikuti oleh daftar string yang tidak diurutkan. Setiap string terdiri dari 2-99 huruf bahasa Inggris huruf kecil. (Contoh di atas tidak akan menjadi input yang valid.)

Dengan menggunakan STDOUT, cetak cara untuk mengatur daftar. Pertama, sebutkan item untuk dipilih, dan kemudian operasi untuk dilakukan untuk menempatkan daftar dalam urutan abjad.

Sebagai contoh: February U December F May D D June D R D...

Penjelasan: Klik Februari, naikkan 1. Pilih Desember, pindah ke atas. Mungkin, gerakkan ke bawah dua kali. June, mundur satu kali, balik daftar, turun lagi ...

Karena jelas ada banyak solusi yang valid, Anda harus memilih yang sesingkat mungkin. Yaitu, pilih metode dengan jumlah operasi paling sedikit (7 pada contoh di atas).

Jika ada kaitan antara output yang benar dengan input, atasi dalam urutan berikut.

  1. Pilih satu dengan pilihan string paling sedikit (4 pada contoh di atas).

  2. Pilih satu dengan operasi paling sedikit, hitung operasi identik berurutan (pada satu string) sebagai satu (6 dalam contoh di atas).

  3. Pilih satu dengan output terpendek (paling sedikit jumlah karakter, penghitungan spasi).

  4. Pilih satu dengan output yang muncul lebih dulu menurut abjad.

Ini adalah kode-golf; pengajuan terpendek yang selalu menghasilkan output yang benar akan menang.

Contohnya

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

Contoh tambahan (disediakan oleh Scott Leadley, setiap kesalahan adalah milik saya dan bukan milik ypnypn)

Beberapa kasus sulit:

  • 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
    • ( bukan jumlah minimum gerakan, yang akan menjadi cc F bb F aa F)

Permutasi 4 item aa bb cc dddengan panjang jalur sortir> 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

Variasi pada tema, 4 item di aaaaa bbbb ccc ddmana panjang string membuat perbedaan:

  • 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
sumber
Contoh Anda tampaknya bertentangan dengan spesifikasi pada setidaknya dua hal: ia memiliki string yang bukan 2-99 huruf Inggris dengan huruf kecil, dan memiliki perintah Ayang tidak ada.
Peter Taylor
1
Bisakah Anda memberikan beberapa input sampel dengan output yang benar?
Claudiu
4
Hanya untuk bersenang-senang, perintah Vim untuk semua tindakan ini: U = ddkP, D = ddp, F = ddggP, L = ddGp, R = :g/^/m0. : P
Gagang Pintu
2
Saya berharap untuk contoh yang lebih canggih. Saya mengalami kesulitan mencari tahu bagaimana menemukan solusi terpendek tanpa pencarian pertama yang luas atas semua kemungkinan, yang dengan cepat menjadi konyol
Claudiu
2
Saya akan menunjukkan bahwa jika Anda ingin menjamin serangkaian operasi minimal, Anda berada di tanah yang sulit dikomputasi ... * bahkan mengetahui jumlah minimal perbandingan * yang diperlukan untuk jenis hanya diketahui hingga 15 item saat ini. Lihat "Algoritma Penyortiran Psikis" .
HostileFork mengatakan jangan percaya

Jawaban:

2

Python 2 - 593 521

Ini sangat kasar dengan beberapa efisiensi sehingga benar-benar akan selesai. Daftar 6 item yang saya uji dengan mengambil sekitar 5 detik di laptop saya.

$ 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

Perhatikan bahwa saya mengabaikan nomor di input. Saya merasa itu tidak berguna.

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, saya baru sadar saya tidak menangani banyak operasi dengan nilai yang sama dengan benar. Saya akan mencoba memperbaikinya.

Aneh
sumber
0

Ruby 2.0

Dengan set operator [U, D, F, L], jumlah string yang paling sedikit dipilih untuk mengurutkan daftar adalah jumlah item dalam daftar dikurangi urutan umum terpanjang. Untuk menambahkan operator R, balikkan string dan terapkan aturan yang sama. Sayangnya, meminimalkan string yang dipilih tidak sama dengan meminimalkan jumlah operasi. Misalnya, untuk input 8 dd ww aa bb cc xx yy zz, jawaban yang benar adalah ww D D D dd D D D, tetapi jumlah operasi paling sedikit (yang memenuhi kriteria lain dalam pertanyaan) adalah cc F bb F aa F. Ini berarti bahwa bagian yang jauh lebih besar dari set jalur pengurutan yang mungkin perlu dieksplorasi.


Solusi ini menggunakan strategi pencarian mendalam-pertama dan pemangkasan alpha-beta. Sangat penting untuk menurunkan nilai alpha dengan cepat untuk meminimalkan kedalaman pencarian, jika tidak pohon pencarian akan meledak secara eksponensial. Misalnya untuk menentukan jalur pengurutan dengan skor minimum untuk contoh pengantar OP, mengurutkan bulan dalam urutan kalender ke urutan leksikal, mungkin akan memakan waktu beberapa dekade dengan metode penilaian saat ini dalam program ini. Program ini menemukan jumlah minimum string yang dipilih, 8, sangat cepat. Sayangnya, itu masih menyisakan pohon besar untuk dilalui.

Saya menggunakan gnome sort sebagai fungsi penilaian saya karena:

  1. mudah dimengerti dan dimodifikasi
  2. skor biasanya menyatu dengan alpha optimal dengan cepat
  3. implementasi ini lebih cepat dari implementasi fungsi LCS saya
  4. itu akan golf lebih baik daripada fungsi LCS

Angka 4 sudah cukup. Yang lainnya adalah bonus.

Untuk pencarian mendalam-pertama, urutan operasi dieksplorasi memiliki dampak signifikan pada waktu pencarian. Karena setiap set item N yang tidak kosong dapat diurutkan dengan operasi ≤ N-1 F (pertama) atau L (ast), operasi tersebut dicoba terlebih dahulu.

# 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

Itu melewati perl test TAP ini :

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
sumber