Đặt một danh sách theo thứ tự


8

Với một cửa sổ tương tự như cửa sổ trong hình bên dưới, bạn sẽ được cung cấp một danh sách các chuỗi mà bạn muốn đặt theo thứ tự bảng chữ cái.

Hộp thoại sắp xếp thứ tự

Như được hiển thị, bạn có năm thao tác:

  • Di chuyển lên [U] - di chuyển chuỗi đã chọn lên một nơi
  • Di chuyển xuống [D] - di chuyển chuỗi đã chọn xuống một nơi
  • Di chuyển đầu tiên [F] - di chuyển chuỗi đã chọn lên đầu danh sách
  • Di chuyển cuối cùng [L] - di chuyển chuỗi đã chọn xuống cuối danh sách
  • Reverse [R] - đảo ngược thứ tự của danh sách

Sử dụng STDIN, chấp nhận một số (có bao nhiêu chuỗi), theo sau là danh sách các chuỗi không có thứ tự. Mỗi chuỗi bao gồm 2-99 chữ cái tiếng Anh viết thường. (Ví dụ trên sẽ không phải là một đầu vào hợp lệ.)

Sử dụng STDOUT, in cách để đưa danh sách theo thứ tự. Đầu tiên, đề cập đến một mục để chọn, và sau đó (các) thao tác để thực hiện trên đó để đặt danh sách theo thứ tự bảng chữ cái.

Ví dụ: February U December F May D D June D R D...

Giải thích: Nhấp vào Tháng Hai, di chuyển lên 1. Chọn Tháng 12, di chuyển lên trên cùng. Có thể, di chuyển nó xuống hai lần. Tháng Sáu, di chuyển xuống một lần, đảo ngược danh sách, di chuyển xuống lần nữa ...

Vì rõ ràng có nhiều giải pháp hợp lệ, bạn phải chọn ngắn nhất có thể. Nghĩa là chọn phương thức có số lượng thao tác ít nhất (7 trong ví dụ trên).

Nếu có sự ràng buộc giữa các đầu ra chính xác với đầu vào, hãy giải quyết nó theo thứ tự sau.

  1. Chọn một trong số các lựa chọn chuỗi ít nhất (4 trong ví dụ trên).

  2. Chọn một trong số các hoạt động ít nhất, tính các hoạt động giống hệt nhau liên tiếp (trên một chuỗi) là một (6 trong ví dụ trên).

  3. Chọn một cái có đầu ra ngắn nhất (số lượng ít nhất của tổng số ký tự, đếm khoảng trắng).

  4. Chọn một trong đó có đầu ra đầu tiên theo thứ tự abc.

Đây là môn đánh gôn; đệ trình ngắn nhất luôn tạo ra kết quả đầu ra chính xác.

Ví dụ

  • TRONG 2 zz abc
    • NGOÀI zz D
  • TRONG 3 cc bb aa
    • NGOÀI aa R
  • TRONG 4 abc def cd ccc
    • NGOÀI abc L R
  • TRONG 6 rr mm nn oo qq pp
    • NGOÀI pp U rr L

Ví dụ bổ sung (được cung cấp bởi Scott Leadley, bất kỳ lỗi nào là của tôi chứ không phải của ypnypn)

Một số trường hợp khó:

  • VÀO => NGOÀI
  • 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
    • ( không phải số lượng di chuyển tối thiểu, sẽ là cc F bb F aa F)

Hoán vị của 4 mục aa bb cc ddvới các đường dẫn sắp xếp có độ dài> 1:

  • VÀO => NGOÀI
  • 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

Biến thể về một chủ đề, 4 mục aaaaa bbbb ccc ddtrong đó độ dài chuỗi tạo sự khác biệt:

  • VÀO => NGOÀI
  • 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

Ví dụ của bạn dường như mâu thuẫn với thông số kỹ thuật về ít nhất hai phép tính: nó có các chuỗi không có chữ cái tiếng Anh chữ thường 2-99 và nó có một lệnh Akhông tồn tại.
Peter Taylor

1
Bạn có thể cung cấp một số đầu vào mẫu với đầu ra chính xác?
Claudiu

4
Để giải trí, các lệnh Vim cho tất cả các hành động này: U = ddkP, D = ddp, F = ddggP, L = ddGp, R = :g/^/m0. : P
Doorknob

2
Tôi đã hy vọng cho các ví dụ tinh vi hơn. Tôi đang gặp khó khăn trong việc tìm ra cách có thể tìm ra giải pháp ngắn nhất mà không cần tìm kiếm đầu tiên trên tất cả các khả năng, điều này nhanh chóng trở nên lố bịch
Claudiu

2
Tôi sẽ chỉ ra rằng nếu bạn muốn đảm bảo một tập hợp hoạt động tối thiểu, bạn đang ở trên mặt đất có thể tính toán được ... * ngay cả khi biết số lượng so sánh tối thiểu * cần thiết cho một loại hiện tại chỉ có tối đa 15 mục . Xem "Thuật toán sắp xếp ngoại cảm" .
HostileFork nói không tin tưởng SE

Câu trả lời:


2

Con trăn 2 - 593 521

Nó rất mạnh mẽ với một số hiệu quả nên nó thực sự sẽ kết thúc. Danh sách 6 mục tôi đang thử nghiệm mất khoảng 5 giây trên máy tính xách tay của tôi.

$ 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

Lưu ý rằng tôi đang bỏ qua số trong đầu vào. Tôi thấy nó vô dụng.

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, tôi chỉ nhận ra rằng tôi không xử lý nhiều thao tác trên cùng một giá trị. Tôi sẽ cố gắng khắc phục điều đó.


0

Ruby 2.0

Với toán tử được đặt [U, D, F, L], số chuỗi được chọn ít nhất để sắp xếp danh sách là số mục trong danh sách trừ đi chuỗi con dài nhất. Để thêm toán tử R, chỉ cần đảo ngược chuỗi và áp dụng quy tắc tương tự. Thật không may, tối thiểu hóa các lựa chọn chuỗi không giống như giảm thiểu số lượng hoạt động. Ví dụ, đối với đầu vào 8 dd ww aa bb cc xx yy zz, câu trả lời đúng là ww D D D dd D D D, nhưng số lượng thao tác ít nhất (đáp ứng các tiêu chí khác trong câu hỏi) sẽ là cc F bb F aa F. Điều này có nghĩa là một phần lớn hơn nhiều của tập hợp các đường dẫn sắp xếp có thể cần được khám phá.


Giải pháp này sử dụng chiến lược tìm kiếm theo chiều sâu và cắt tỉa alpha-beta. Điều quan trọng là nhanh chóng hạ thấp giá trị alpha để giảm thiểu độ sâu tìm kiếm, nếu không, cây tìm kiếm sẽ phát nổ theo cấp số nhân. Ví dụ: để xác định đường dẫn sắp xếp với số điểm tối thiểu cho ví dụ giới thiệu của OP, sắp xếp các tháng theo thứ tự lịch theo thứ tự từ vựng, có thể sẽ mất vài thập kỷ với phương pháp tính điểm hiện tại của chương trình này. Chương trình tìm thấy số chuỗi tối thiểu được chọn, 8, rất nhanh. Thật không may, điều đó vẫn để lại một cái cây khổng lồ để đi qua.

Tôi đang sử dụng gnome sort làm chức năng cho điểm của mình vì:

  1. thật đơn giản để hiểu và sửa đổi
  2. việc ghi điểm thường hội tụ đến alpha tối ưu một cách nhanh chóng
  3. việc thực hiện này nhanh hơn việc thực hiện chức năng LCS của tôi
  4. Nó sẽ chơi golf tốt hơn chức năng LCS

Số 4 là đủ. Mọi thứ khác là một phần thưởng.

Đối với tìm kiếm theo chiều sâu, thứ tự các thao tác được khám phá có tác động đáng kể đến thời gian tìm kiếm. Vì bất kỳ tập hợp N mục trống nào có thể được sắp xếp với các hoạt động ≤ N-1 F (irst) hoặc L (ast), các hoạt động đó được thử trước tiên.

# 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

Nó vượt qua bộ thử nghiệm TAP perl này:

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;
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.