แก้ปัญหาผู้บงการในการเคลื่อนไหว 6 ครั้งหรือน้อยกว่า


24

เป้าหมายของคุณคือการเขียนโปรแกรมที่จะแก้ปริศนาบงการใด ๆ ในการเคลื่อนไหว 6 หรือน้อยกว่า

พื้นหลัง

บงการเป็นเกมกระดาน เป้าหมายของเกมคือการเดาการรวมกัน (สีและลำดับ) ของหมุดสี 4 อันที่ซ่อนโดยผู้เล่นคนอื่น เมื่อทำการเดาผู้เล่นคนอื่นจะตอบสนองด้วยหมุดสีขาวและหมุดสีแดงระหว่าง 0 ถึง 4 หมุดสีแดงคือตำแหน่งที่สีและตำแหน่งถูกต้อง หมุดสีขาวคือสีที่แสดงในชิ้นส่วนที่เหลือ แต่อยู่ในตำแหน่งที่ไม่ถูกต้อง หากมีสีที่ซ้ำกันในการเดาจะมีเพียงหมุดเดียวที่ได้รับต่อสีที่ตรงกันในความลับ (ดังนั้น - ถ้าความลับมี 1 Blue และการเดามี 2 blues กับหนึ่งในตำแหน่งที่ถูกต้องจะมีหมุดสีแดงหนึ่งอัน) มี 6 สีที่แตกต่างกันและอาจใช้ซ้ำ

ตัวอย่างเช่นเกมอาจไปดังนี้: (สมมติว่าการแก้ปัญหาคือสีแดงสีเขียวสีเขียวสีน้ำเงิน)

1:  Blue Purple Black Green - 2 white pegs
2:  Green Red Black Blue    - 2 white pegs, 1 red peg
3:  Green Green Green Blue  - 3 red pegs
4:  Red Green Green Blue    - 4 red pegs

กฎมีการขยายตัวในWikipedia

ความต้องการ

  • โปรแกรมต้องอ่านจาก stdin และเขียนไปยัง stdout
  • ฉันจะใช้ตัวเลขเพื่อความเรียบง่ายแทนสี ชุดค่าผสมที่คาดเดาจะเป็นตัวเลข 4 ตัวระหว่าง 1 ถึง 6
  • พวกเขาจะต้องส่งออกการคาดเดาของพวกเขาเป็นชุดของ 4 ช่องว่างคั่นตัวเลขจาก 1 ถึง 6 สรุปด้วยบรรทัดใหม่ ตัวอย่างเช่น

    1 5 2 2 \ n

  • โปรแกรมจะได้รับเป็นอินพุตหลังจากเดาจำนวนเต็ม 2 ตัวระหว่าง 0 ถึง 4 โดยคั่นด้วยช่องว่างและสรุปด้วยบรรทัดใหม่ ครั้งแรกจะเป็นจำนวนหมุดสีขาวที่สองจำนวนหมุดสีแดง

  • ในอินพุตของ "0 4" (หมุดสีแดง 4 อัน) โปรแกรมจะต้องยุติการทำงาน
  • โปรแกรมจะต้องสามารถไขปริศนาใด ๆ ในเวลาน้อยกว่า 6 ตาร์ (โปรแกรมของคุณให้เอาต์พุตแล้วตามด้วยอินพุตตอบกลับคือ 1 เทิร์น) ไม่มีโบนัส (เนื่องจากความซับซ้อนของการพิสูจน์) สำหรับความสามารถในการแก้ปัญหาในน้อย
  • โซลูชันต้องอยู่ภายในอย่างสมบูรณ์และรวมอยู่ในแหล่ง อนุญาตให้ใช้ไลบรารีมาตรฐานเท่านั้น การแก้ปัญหาจึงอาจไม่พึ่งพาไฟล์อื่น ๆ (เช่นพจนานุกรม) หรืออินเทอร์เน็ต

ตัวอย่างอินพุต / เอาท์พุต

> is your programs output
< is the responding input
Solution is 1 5 6 6

> 1 2 3 4
< 0 1
> 4 1 6 6
< 1 2
> 1 6 5 6
< 2 2
> 1 5 6 6
< 0 4 

เกณฑ์การให้คะแนน

  • นี่คือบริสุทธิ์และเรียบง่ายรหัสกอล์ฟ ทางออกที่สั้นที่สุดในหน่วยไบต์ชนะ

นี่คือคำถามรหัสกอล์ฟครั้งแรกของฉัน ฉันขอโทษถ้าฉันทำอะไรผิด แต่ฉันพยายามเท่าที่จะทำได้เพื่อให้แน่ใจว่าไม่มีความคลุมเครือและป้องกันไม่ให้มีการออกกฎหมายมากที่สุด หากฉันไม่ชัดเจนหรือไม่ชัดเจนโปรดถามคำถาม


1
ในตัวอย่างอินพุต / เอาท์พุตไม่ควร1 2 3 4กลับมา0 1?
Gaffi

1
และในข้อความตัวอย่างไม่ควร "Green Green Green Blue" ให้หมุดสีขาวเช่นกัน (สำหรับ Green แรก)? แก้ไข - วิกิพีเดียชี้แจงว่าไม่ควรให้สีขาวตามที่คุณเขียน แต่ฉันคิดว่าควรระบุกฎขาว / ดำอย่างชัดเจนในคำถาม
ugoren

การอนุญาตให้ทำงานช้าแค่ไหน
หยุดหมุนทวนเข็มนาฬิกา

@Gaffi - ถูกต้องแน่นอน - คงที่
lochok

1
กฎสำหรับหมุดขาวไม่ได้ระบุไว้ที่นี่ สมมติว่าคุณเลือก 1234 และฉันเดา 5611 ทั้งคู่ของฉันเป็นสีที่ถูกต้องในที่ที่ผิดดังนั้นจากวิธีที่คุณระบุกฎฉันจะบอกว่าฉันได้ผ้าขาว 2 อัน แต่ไม่ - Wikipedia บอกว่ามันคือ 1 สีขาว วิธีที่ไม่ถูกต้องนั้นง่ายกว่าในการเขียนโปรแกรม (แต่ Steven Rumbalski ใช้กฎของ Wikipedia อย่างถูกต้อง)
ugoren

คำตอบ:


8

Python 2 Python 3, 359 365 338 ตัวอักษร

from itertools import*
from collections import*
m=h=set(product(*['123456']*4))
def f(g,k):b=sum(x==y for x,y in zip(g,k));return'%s %s'%(sum(min(g.count(c),k.count(c))for c in set(g))-b,b)
while len(m)>1:g=min(h,key=lambda g:max(Counter(f(g,k)for k in m).values()));print(*g);s=input();m=set(x for x in m if s==f(g,x))
print(*(m.pop()))

ตลกฉันต้องใช้การแก้ไขหลายอย่างเพื่อรู้ว่าฉันมีชื่อตัวแปรห้าตัว

ฉันไม่ชอบการนำเข้าที่ยาวนาน รู้สึกเหมือนฉันควรจะสามารถนำมาใช้แทนcollections.Counterที่จะประหยัดการนำเข้า

ฉันยังไม่ชอบprint(*(m.pop()))ในตอนท้าย รู้สึกเหมือนว่ามันควรจะหายไปในขณะที่ลูป แต่ฉันไม่สามารถหาวิธีที่จะทำได้โดยไม่ทำให้มันอีกต่อไป


TypeError: join() takes exactly one argument (2 given)return j(sum(min(g.count(c),k.count(c))for c in set(g))-b,b)บน และ sum () จะคืนค่า int ในขณะที่ j (str.join) ควรทำซ้ำได้
Blazer

โครงสร้างลูปของฉันกำจัดขั้นสุดท้ายprintและฉันคิดว่ามันสั้นกว่าเล็กน้อย นอกจากนี้ยังตรงกับพฤติกรรมที่ร้องขอได้ดีกว่า (หยุดที่ "4 0" มากกว่าเมื่อคุณรู้คำตอบ) และ==len(m)>1 m[1:]การนำเข้านั้นน่ารำคาญแน่นอน - น่าfrom a,b import *จะดี
ugoren

โปรแกรมนี้ดูเหมือนว่าจะออกเมื่อใดก็ตามที่รู้สึกว่าถูกต้อง มีอยู่ครั้งหนึ่งที่ฉันวิ่งมันและมันหยุดลงที่การเดา 5 ครั้งมันไม่ถูกต้อง ครั้งต่อไปที่มันหยุดที่ 4 การเดาและมันก็ถูกต้อง แต่ฉันยังไม่ได้ป้อนข้อมูล4 0ซึ่งอยู่ในเกณฑ์วัตถุประสงค์และเวลาอื่นมันจะออกโดยมีข้อยกเว้น:print(*(m.pop())) KeyError: 'pop from an empty set'
Blazer

@Blazer กรณีทดสอบอะไรที่ทำให้เกิดผลลัพธ์นี้
Steven Rumbalski

@Blazer: 4 0เป็นหมุดสีขาวสี่อัน ฉันคิดว่าคุณมีการให้คะแนนย้อนกลับ
Steven Rumbalski

7

Haskell, 317 304

q[0,4]_=error""
q[n,m]l=(\s->all(==4-m)[g s,n+g(u(foldr((u((.drop 1).(++)).).break.(==)))$unzip s)]).c(u(/=)).zip l
u=uncurry;m=map;g=length;c=filter
f a=[head.c(($(zipWith q(take n a)$f a)).all.flip($)).sequence$replicate 4[1..6]|n<-[0..]]
main=interact$unlines.m(unwords.m show).f.m(m read.words).lines

ฉันชอบเขียนโปรแกรมแบบโต้ตอบที่ใช้งานได้จริง! แต่แน่นอนว่ารูปแบบนี้มีข้อ จำกัด บางประการ: มันสิ้นสุดลงในขณะนี้ด้วยข้อผิดพลาด แต่คุณไม่ได้ระบุว่านี่ไม่เป็นไร ฉันจำเป็นต้องปรับโครงสร้างทั้งหมดในIOmonad เพื่อให้ได้ทางออกที่ไม่ใช่ข้อผิดพลาด


รับประกันการเดาที่ถูกต้องในการเคลื่อนไหว 6 ครั้งหรือไม่?
ugoren

เอ่อ ฉันคิดว่ามันเป็น (ใช้งานได้กับตัวอย่างของ OP และวิธีแก้ปัญหาอื่น ๆ ) แต่การทดสอบที่ละเอียดแสดงให้เห็นว่าบางครั้งมันต้องการการเดา 7 ครั้ง ฉันจะต้องทำงานเกี่ยวกับเรื่องนี้!
หยุดหมุนทวนเข็มนาฬิกา

5

Python 385 357 ตัวอักษร, แก้ปัญหาใน 5 การเคลื่อนไหว

ยิ่งฉันเปลี่ยนมันมันจะเติบโตขึ้นเรื่อย ๆ เหมือนของ Steven Rumbalski ... ความแตกต่างที่สำคัญคือเขาทำงานกับสตริงมากกว่าจำนวนเต็ม
ใช้อัลกอริทึมของ Knuth (อย่างถูกต้องตอนนี้ฉันหวังว่า)
ยืมฟังก์ชันการให้คะแนนจาก Steven Rumbalski
ใช้เวลานานในการสร้างการคาดเดาครั้งแรกดีขึ้นในภายหลัง
การเข้ารหัสแบบฮาร์ด ( g=len(A)==1296 and [1,1,2,2] or ...) ทำให้ชีวิตง่ายขึ้นหากคุณต้องการทดสอบ
ฉันไม่นับคู่ขึ้นบรรทัดใหม่ + คู่แท็บซึ่งสามารถแทนที่ด้วยเครื่องหมายอัฒภาค

from collections import*
from itertools import*
a=B=A=list(product(*[range(1,7)]*4))
r=lambda g,k:(sum(x==y for x,y in zip(g,k)),sum(min(g.count(c),k.count(c))for c in set(g)))
while a!=4:
    g=A[1:]and min(B,key=lambda x:max(Counter(r(x,i)for i in A).values()))or A[0]
    print"%d "*4%tuple(g)
    b,a=map(int,raw_input().split())
    A=[x for x in A if r(g,x)==(a,a+b)]

"%d "*4%tuple(g)
gnibbler

from collections import*
gnibbler

a,b=map(int,raw_input())
gnibbler

product(*[range(1,7)]*4)
gnibbler

Counter(r(x,i)for i in A).values()
gnibbler
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.