ตรวจสอบว่าสตริงเป็นการสลับแบบแฝดหรือไม่


10

คำอธิบาย

สองสายสามารถสับโดยการกระจายตัวอักษรของพวกเขาเพื่อสร้างสายใหม่เช่นเดียวกับไพ่สองกองสามารถสับเพื่อสร้างกองเดียว

ยกตัวอย่างเช่นสตริงHELLOและWORLDสามารถสับในรูปแบบHWEOLRLLODหรือหรือบางทีอาจจะเพียงแค่HEWORLLLDOHELLOWORLD

มันเป็นไม่ได้สับเปลี่ยนถ้าคำสั่งเดิมของตัวอักษรไม่ได้เก็บรักษาไว้ ยกตัวอย่างเช่นDในWORLDไม่เคยปรากฏมาก่อนRหลังจากที่ถูกสับ ซึ่งหมายความว่าEHLLOWRDLOยกตัวอย่างเช่นไม่ใช่การสับเปลี่ยนHELLOและWORLDแม้ว่าจะมีตัวอักษรต้นฉบับทั้งหมด

สตริงคือการสลับของแฝดถ้ามันสามารถเกิดขึ้นได้โดยการสับสองสายเหมือนกัน ยกตัวอย่างเช่นABACBDECDEเป็นสับเปลี่ยนของฝาแฝดเพราะมันสามารถเกิดขึ้นโดยการสับและABCDE ไม่ใช่การสับเปลี่ยนของฝาแฝดเนื่องจากไม่สามารถขึ้นรูปได้โดยการสลับสองสายเหมือนกันABCDEDBEACBCADE

รายละเอียดโปรแกรม

รับสตริงอินพุตเอาต์พุต0ถ้าไม่ใช่การสลับแบบแฝดและส่งเอาต์พุตหนึ่งในสตริงแฝดหากเป็นสับเปลี่ยนของฝาแฝด

คุณอาจคิดว่าสายป้อนมีความยาวรวมระหว่างสี่ถึงยี่สิบอักขระและประกอบด้วยตัวอักษรตัวพิมพ์ใหญ่ทั้งหมด มันควรจะสามารถทำงานในเวลาที่เหมาะสมพูดภายใต้ 10 นาที

นี่คือรหัสกอล์ฟดังนั้นทางออกที่สั้นที่สุดชนะ

ตัวอย่าง I / O

> ABACBDECDE
ABCDE

> DBEACBCADE
0

> FFFFFF
FFF

> FFGGG
0

> ABBA
0

> AABB
AB

> AABAAB
AAB

ผมมีตัวอย่าง (ที่ไม่แข็งแรงเล่นกอล์ฟ) การดำเนินงาน


ตัวอย่างสตริง FGG ละเมิดการยืนยันthat the input string has a length inclusively between four and twenty charactersและอย่าบอกฉันว่า "อย่าไว้ใจอินพุตของผู้ใช้!", "อย่าเชื่อใจ specs!"
ผู้ใช้ที่ไม่รู้จัก

@userunknown น่าอายมาก! ฉันแก้ไขมันFFGGGเพื่อให้สอดคล้องกัน
Peter Olson

1
เพียงแค่อยากรู้อยากเห็นใครสามารถแก้ปัญหาด้วยความซับซ้อนของเวลากรณีเลวร้ายที่สุดชี้แจงหรือพิสูจน์ว่าไม่มีอะไรเลย?
Ilmari Karonen

คำตอบ:


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)]

Ungolfed:

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)]

คำอธิบาย:

งานส่วนใหญ่จะทำในpartitionsหน้าที่ มันทำงานโดยการสร้างพาร์ติชันทั้งหมดซ้ำ(a, b)ของรายการแล้วใช้list monadเพื่อเพิ่มองค์ประกอบเริ่มต้นxให้กับแต่ละองค์ประกอบและรวบรวมผลลัพธ์ทั้งหมด

findMatchทำงานโดยการกรองรายการนี้เพื่อให้พาร์ติชันเท่านั้นที่ยังคงมีส่วนประกอบที่เท่ากัน จากนั้นจะส่งคืนองค์ประกอบแรกในพาร์ติชันแรก หากไม่มีสิ่งใดเหลืออยู่รายการจะว่างเปล่าดังนั้นส่วน"0"ท้ายที่ได้รับจะถูกส่งคืนแทน

main เพียงอ่านอินพุตป้อนข้อมูลผ่านฟังก์ชั่นทั้งสองนี้แล้วพิมพ์ออกมา


สำหรับพวกเราที่ไม่สามารถอ่าน Haskell ได้คุณจะให้คำอธิบายไหม?
Mr.Wizard

1
@ Mr.Wizard: ดูการแก้ไข
hammar

ฉันคิดว่าฉันเกิดสิ่งที่คล้ายกันขึ้นมาแม้ว่าจะไม่สั้น แต่ฉันก็คิดแบบโง่ ๆ ที่ทำให้มันล้มเหลวโดยสิ้นเชิง คุณรังเกียจไหมถ้าฉันใช้อัลกอริทึมนี้ใน Mathematica
Mr.Wizard

4

R, 113 ตัวอักษร

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 (และแทนที่จะใช้ฟังก์ชันที่รับสตริง):

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

การแก้ปัญหาขึ้นอยู่กับcombnฟังก์ชั่นที่สร้างการรวมกันของดัชนีทั้งหมดเป็นคอลัมน์ในเมทริกซ์ applyจากนั้นใช้ฟังก์ชันกับแต่ละคอลัมน์ (มิติ2) ในเมทริกซ์และส่งกลับเวกเตอร์ของสตริงหรือศูนย์ maxจากนั้นหาสตริงที่ใหญ่ที่สุด (ซึ่งสำคัญกว่า 0)

คุณลักษณะที่ยอดเยี่ยมใน R คือความสามารถในการเลือกชุดย่อยของเวกเตอร์ที่กำหนดเวกเตอร์ของดัชนีและจากนั้นเลือกส่วนประกอบของชุดย่อยนั้นโดยลบดัชนี:x[i] == x[-i]


ทำการปรับปรุงส่วนเพิ่มและลดจำนวนถ่าน
Tommy

3

Mathematica, 87

นี่เป็นพื้นฐานโดยตรงจากการโพสต์ของ hammar แต่หวังว่ามันจะแตกต่างกันพอที่จะทำบุญการโพสต์

<<Combinatorica`

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

ทดสอบ:

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));}

ใช้การค้นหาเชิงลึกแบบเรียกซ้ำครั้งแรก

ฉันสามารถทำให้เร็วขึ้นด้วยint i = min(a.length,b.length);if(a[0..i]!=b[0..i])return "0";ประโยคป้องกัน


ใน IDEONE ฉันล้มเหลวในการพยายามเริ่มโปรแกรมด้วยvoid main(){writeln(c("ABCADABCAD"));}- เป็นรุ่นอื่นของ D ความผิดของฉันอย่างอื่นใช่ไหม เกี่ยวกับ "ABCABCA" คืออะไร
ผู้ใช้ไม่ทราบ

คุณจะต้องนำเข้า std.stdio; สำหรับ IO
ratchet freak

1

Ruby, 89 ตัวอักษร

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,'','']

รหัสนี้ใช้อัลกอริทึมการค้นหาแบบเรียกซ้ำแบบธรรมดา อินพุตต้องถูกกำหนดบน STDIN


1

Perl, 68 ตัวอักษร

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

สตริงอินพุตที่สมมติว่าอยู่ใน$_ตัวแปรเอาต์พุตคือค่าของนิพจน์ ขึ้นบรรทัดใหม่ในอินพุตจะถูกละเว้น คุณสามารถเรียกใช้จากบรรทัดคำสั่งดังนี้:

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

รหัสนี้ใช้ประโยชน์จากโปรแกรม regexp ของ Perl (และโดยเฉพาะคุณสมบัติการประมวลผลโค้ดแบบฝังตัว ) เพื่อทำการย้อนรอย โดยพื้นฐานแล้วจะจับคู่สตริงอินพุตกับ regexp ^((.+))+$ติดตามการส่งคำคี่และเลขคู่ใน$xและ$,และปฏิเสธการแข่งขันในตอนท้ายหากทั้งสองไม่เท่ากัน


สิ่งนี้มีผลลัพธ์ที่ถูกต้องAABAABใช่หรือไม่
Peter Olson

ใช่. (อันที่จริงแล้วAABAABเป็นกรณีที่ง่ายสำหรับโซลูชันนี้เนื่องจากกลุ่มนอกต้องจับคู่สองครั้งเท่านั้นฉันใช้เวลานานกว่านั้นในการจัดการให้AABBถูกต้อง)
Ilmari Karonen

1

Python 168 ตัวอักษร

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())
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.