Kiểm tra xem một chuỗi có phải là một cặp song sinh không


10

Giải trình

Hai chuỗi có thể được xáo trộn bằng cách xen kẽ các chữ cái của chúng để tạo thành một chuỗi mới, giống như hai đống thẻ có thể được xáo trộn để tạo thành một đống.

Ví dụ, các chuỗi HELLOWORLDcó thể được xáo trộn để tạo thành HWEOLRLLOD, hoặc HEWORLLLDO, hoặc có lẽ đơn giản HELLOWORLD.

không phải là một sự xáo trộn nếu thứ tự ban đầu của các chữ cái không được giữ nguyên. Ví dụ, Dtrong WORLDkhông thể bao giờ xuất hiện trước Rsau khi bị xáo trộn. Điều này có nghĩa là EHLLOWRDLO, chẳng hạn, không phải là sự xáo trộn HELLOWORLD, mặc dù nó chứa tất cả các chữ cái gốc.

Một chuỗi là sự xáo trộn của cặp song sinh nếu nó có thể được hình thành bằng cách xáo trộn hai chuỗi giống hệt nhau. Ví dụ, ABACBDECDElà một sự xáo trộn của cặp song sinh vì nó có thể được hình thành bằng cách xáo trộn ABCDEABCDE. DBEACBCADEkhông phải là sự xáo trộn của cặp song sinh vì nó không thể được hình thành bằng cách xáo trộn hai chuỗi giống hệt nhau.

Chi tiết chương trình

Đưa ra một chuỗi đầu vào, đầu ra 0nếu nó không phải là một cặp song sinh và xuất ra một trong các chuỗi sinh đôi nếu đó là một chuỗi các cặp song sinh.

Bạn có thể giả sử rằng chuỗi đầu vào có độ dài bao gồm từ bốn đến hai mươi ký tự và được cấu tạo hoàn toàn bằng các ký tự chữ cái in hoa. Nó sẽ có thể chạy trong một khoảng thời gian hợp lý, giả sử, dưới 10 phút.

Đây là mã golf, vì vậy giải pháp ngắn nhất sẽ thắng.

Ví dụ I / O

> ABACBDECDE
ABCDE

> DBEACBCADE
0

> FFFFFF
FFF

> FFGGG
0

> ABBA
0

> AABB
AB

> AABAAB
AAB

Tôi có một ví dụ (không chơi gôn) .


Chuỗi ví dụ FGG vi phạm khẳng định that the input string has a length inclusively between four and twenty charactersvà đừng nói với tôi "không bao giờ tin vào đầu vào của người dùng!", "Không bao giờ tin vào thông số kỹ thuật!"
người dùng không xác định

@userunknown Thật là xấu hổ! Tôi chỉnh sửa nó FFGGGđể làm cho nó phù hợp.
Peter Olson

1
Vì tò mò, bất cứ ai cũng có thể đưa ra một giải pháp với độ phức tạp của trường hợp xấu nhất theo cấp số nhân, hoặc chứng minh rằng không có gì cả?
Ilmari Karonen

Câu trả lời:


4

Haskell, 114

main=getLine>>=putStrLn.f.p;f x=head$[a|(a,b)<-x,a==b]++["0"]
p[]=[([],[])];p(x:y)=do(a,b)<-p y;[(x:a,b),(a,x:b)]

Ung dung:

main :: IO ()
main = getLine >>= putStrLn . findMatch . partitions

-- | Find the first partition where the two subsequences are
-- equal. If none are, return "0".
findMatch :: [(String, String)] -> String
findMatch ps = head $ [a | (a,b) <- ps, a == b] ++ ["0"]

-- | Return all possible partitions of the input into two
-- subsequences. Preserves the order of each subsequence.
--
-- Example:
-- partitions "AB" == [("AB",""),("B","A"),("A","B"),("","AB")]
partitions :: [a] -> [([a], [a])]
partitions []     = [([], [])]
partitions (x:xs) = do (a, b) <- partitions xs
                       [(x:a, b), (a, x:b)]

Giải trình:

Hầu hết các công việc đang được thực hiện trong partitionschức năng. Nó hoạt động bằng cách tạo đệ quy tất cả các phân vùng (a, b)của đuôi danh sách, sau đó sử dụng danh sách đơn nguyên để thêm phần tử ban đầu xcho mỗi phần tử và thu thập tất cả các kết quả.

findMatchhoạt động bằng cách lọc danh sách này để chỉ các phân vùng trong đó các chuỗi con vẫn bằng nhau. Sau đó, nó trả về lần đầu tiên trong phân vùng đầu tiên. Nếu không còn lại, danh sách trống, vì vậy phần "0"bổ sung ở cuối sẽ được trả lại.

main chỉ cần đọc đầu vào, đưa nó qua hai chức năng này và in nó.


Đối với những người trong chúng ta không thể đọc Haskell, bạn sẽ đưa ra lời giải thích chứ?
Mr.Wizard

1
@ Mr.Wizard: Xem chỉnh sửa.
hammar

Tôi nghĩ rằng tôi đã nghĩ ra một cái gì đó khá giống nhau, mặc dù không ngắn, nhưng tôi đã ném một cách ngu ngốc khiến nó thất bại hoàn toàn. Bạn có phiền nếu tôi thực hiện thuật toán này trong Mathematica không?
Mr.Wizard

4

R, 113 ký tự

l=length(x<-charToRaw(scan(,'')));max(apply(combn(l,l/2),2,function(i)if(all(x[i]==x[-i]))rawToChar(x[i])else 0))

Ungolfed (và thay vào đó là một hàm lấy chuỗi):

untwin <- function(x) {
  x <- charToRaw(x)
  indMtx <- combn(length(x),length(x)/2)
  res <- apply(indMtx, 2, function(i) {
    if (all(x[i]==x[-i]))
      rawToChar(x[i])
    else
      0
  })
  max(res)
}

untwin("ABACBDECDE") # "ABCDE"
untwin("DBEACBCADE") # 0

Giải pháp dựa vào combnhàm tạo ra tất cả các kết hợp chỉ mục dưới dạng cột trong ma trận. applysau đó áp dụng một hàm cho mỗi cột (thứ nguyên 2) trong ma trận và trả về một vectơ của chuỗi hoặc số không. maxsau đó tìm chuỗi lớn nhất (mà bỏ qua 0).

Một tính năng thú vị trong R là khả năng chọn một tập hợp con của một vectơ được cung cấp một vectơ chỉ mục và sau đó chọn phần của tập hợp con đó bằng cách phủ định các chỉ mục:x[i] == x[-i]


Đã làm một số cải tiến gia tăng và giảm số lượng char.
Tommy

3

Toán học, 87

Điều này trực tiếp dựa trên bài đăng của hammar, nhưng hy vọng nó đủ khác biệt để đăng bài.

<<Combinatorica`

f=Catch[Cases[Characters@#~KSetPartitions~2,{x_,x_}:>Throw[""<>x]];0]&

Kiểm tra:

f /@ {"ABACBDECDE", "DBEACBCADE", "FFFFFF", "FGG", "ABBA", "AABB", "AABAAB"}
{"ABCDE", 0, "FFF", 0, 0, "AB", "AAB"}

1

D

string c(string in,string a=[],string b=[]){
    if(in.length==0)return a==b?a;"0";
    auto r=c(in[1..$],a~in[0],b);
    return r=="0"?c(in[1..$],a,b~in[0]):r;
}
void main(){writeln(c(readline));}

sử dụng tìm kiếm đệ quy sâu đầu tiên

Tôi có thể làm cho nó nhanh hơn với một int i = min(a.length,b.length);if(a[0..i]!=b[0..i])return "0";điều khoản bảo vệ


Trên IDEONE, tôi đã thất bại khi thử khởi động chương trình với void main(){writeln(c("ABCADABCAD"));}- chỉ là một phiên bản khác của D, lỗi của tôi, còn gì nữa không? Thế còn "ABCABCA"?
người dùng không xác định

bạn sẽ cần nhập std.stdio; cho IO
ratchet freak

1

Ruby, 89 ký tự

s=->a,x,y{a=="\n"?x==y ?x:?0:[s[b=a[1..-1],x+c=a[0],y],s[b,x,y+c]].max}
$><<s[gets,'','']

Mã này thực hiện một thuật toán tìm kiếm đệ quy đơn giản. Đầu vào phải được đưa ra trên STDIN.


1

Perl, 68 ký tự

/^((.+)(?{local($x,$,)=($,,$x.$^N)}))+$(?(?{$o=$,eq$x&&$,})|x)/?$o:0

Chuỗi đầu vào được giả định là trong $_biến, đầu ra là giá trị của biểu thức. Trailing dòng mới trong đầu vào được bỏ qua. Bạn có thể chạy nó từ dòng lệnh như thế này:

perl -lne 'print /^((.+)(?{local($x,$,)=($,,$x.$^N)}))+$(?(?{$o=$,eq$x&&$,})|x)/?$o:0'

Mã này sử dụng công cụ regrec của Perl (và cụ thể là tính năng thực thi mã nhúng của nó ) để thực hiện quay lui. Về cơ bản, nó phù hợp với chuỗi đầu vào dựa trên regexp ^((.+))+$, theo dõi các submatches odd- và số chẵn trong $x$,, và từ chối trận đấu cuối cùng nếu hai bên không bằng nhau.


Điều này có kết quả chính xác cho AABAAB?
Peter Olson

Có nó làm. (Trên thực tế, đây AABAABlà một trường hợp dễ dàng cho giải pháp này, vì nhóm bên ngoài chỉ cần khớp hai lần. Tôi mất nhiều thời gian hơn để xử lý AABBđúng.)
Ilmari Karonen

1

Con trăn, 168 ký tự

def f(s):
 c=s[0]
 d=i=r=0
 if s==c+c:r=c
 while i+1 and i<=len(s)/2 and not r:
  if i:d=f(s[1:i]+s[i+1:])
  if d:r=c+d
  i=s.find(c,i+1)
 return r
print f(raw_input())
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.