Giải quyết Mastermind trong 6 hoặc ít hơn


24

Mục tiêu của bạn là viết một chương trình sẽ giải bất kỳ câu đố Mastermind nào trong 6 lần di chuyển trở xuống.

Lý lịch

Mastermind là một trò chơi hội đồng quản trị. Mục tiêu của trò chơi là đoán chính xác sự kết hợp (màu sắc và thứ tự) của 4 chốt màu được ẩn bởi người chơi khác. Khi đoán được thực hiện, người chơi khác trả lời từ 0 đến 4 chốt trắng và đỏ. Một chốt màu đỏ là nơi màu sắc và vị trí chính xác. Một chốt màu trắng là nơi màu được thể hiện trong các phần còn lại, nhưng ở vị trí không chính xác. Nếu có các màu trùng lặp trong dự đoán, sẽ chỉ có một chốt được trao cho mỗi màu tương ứng trong bí mật. (Vì vậy - nếu bí mật chứa 1 Blue và đoán có 2 màu xanh với một vị trí chính xác, sẽ có một chốt màu đỏ được đưa ra). Có 6 màu khác nhau và có thể sử dụng các bản sao.

Vì vậy, ví dụ, một trò chơi có thể diễn ra như sau: (Giả sử giải pháp là Red Green Green Blue)

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

Các quy tắc được mở rộng trên Wikipedia

Yêu cầu

  • Chương trình phải đọc từ stdin và viết vào stdout
  • Tôi sẽ sử dụng số cho đơn giản thay vì màu sắc. Sự kết hợp để đoán sẽ là 4 số từ 1 đến 6
  • Họ phải đưa ra dự đoán của mình dưới dạng một chuỗi gồm 4 số cách nhau từ 1 đến 6 kết thúc bằng một dòng mới. Ví dụ:

    1 5 2 2 \ n

  • Chương trình sau đó sẽ nhận làm đầu vào sau khi đoán 2 số nguyên nằm trong khoảng từ 0 đến 4 cách nhau bởi một khoảng trắng và kết thúc bằng một dòng mới. Đầu tiên sẽ là số lượng chốt màu trắng, thứ hai là số lượng chốt màu đỏ.

  • Trên đầu vào "0 4" (4 chốt màu đỏ), chương trình phải chấm dứt
  • Chương trình phải có khả năng giải bất kỳ câu đố nào sau ít hơn 6 lượt (chương trình của bạn cho đầu ra, tiếp theo là đầu vào phản hồi là 1 lượt). Không có tiền thưởng (do sự phức tạp của bằng chứng) cho việc có thể giải quyết nó ít hơn.
  • Các giải pháp phải hoàn toàn nội bộ và bao gồm trong nguồn. Thư viện tiêu chuẩn chỉ được phép. Do đó, giải pháp có thể không dựa vào bất kỳ tệp nào khác (như từ điển) hoặc internet.

Ví dụ đầu vào / đầu ra

> 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 

Chấm điểm

  • Đây là Code Golf đơn giản và đơn giản . Giải pháp ngắn nhất trong byte thắng.

Đây là câu hỏi Code Golf đầu tiên của tôi. Tôi xin lỗi nếu tôi đã làm điều gì đó sai, nhưng tôi đã cố gắng hết sức có thể để đảm bảo rằng hoàn toàn không có sự mơ hồ, và ngăn chặn càng nhiều quy tắc lập pháp càng tốt. Nếu tôi đã mơ hồ hoặc không rõ ràng, xin vui lòng đặt câu hỏi.


1
Trong ví dụ đầu vào / đầu ra của bạn không nên 1 2 3 4trả về 0 1?
Gaffi

1
Và trong văn bản ví dụ, không nên "Green Green Green Blue" cũng cung cấp một chốt màu trắng (cho Green đầu tiên)? EDIT - Wikipedia làm rõ rằng không nên đưa ra màu trắng, như bạn đã viết. Nhưng tôi nghĩ rằng các quy tắc trắng / đen nên được nêu rõ ràng trong câu hỏi.
ugoren

Làm thế nào chậm nó sẽ được phép làm việc?
đã ngừng quay ngược chiều

@Gaffi - Hoàn toàn đúng - cố định
lochok

1
Các quy tắc cho chốt trắng không được nêu ở đây. Giả sử bạn đã chọn 1234 và tôi đoán 5611. Cả hai số 1 của tôi đều sai màu, do đó, từ cách bạn nêu các quy tắc tôi sẽ nói tôi nhận được 2 lòng trắng. Nhưng không - Wikipedia nói đó là 1 màu trắng. Phương pháp không chính xác cũng dễ lập trình hơn (nhưng Steven Rumbalski đã thực hiện đúng các quy tắc của Wikipedia).
ugoren

Câu trả lời:


8

Python 2 Python 3, 359 365 338 ký tự

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

Thật buồn cười, tôi đã phải chỉnh sửa nhiều lần để nhận ra tôi có một tên biến gồm năm ký tự.

Tôi không thích hàng nhập khẩu dài. Có vẻ như tôi sẽ có thể thực hiện thay thế để collections.Countertiết kiệm nhập khẩu.

Tôi cũng không thích print(*(m.pop()))ở cuối. Cảm giác như nó sẽ biến mất trong vòng lặp while, nhưng tôi không thể tìm ra cách để làm điều đó mà không làm cho nó dài hơn.


TypeError: join() takes exactly one argument (2 given)trên return j(sum(min(g.count(c),k.count(c))for c in set(g))-b,b). Ngoài ra, sum () trả về một int, trong khi j (str.join) sẽ có một lần lặp
Blazer

Cấu trúc vòng lặp của tôi bị loại khỏi trận chung kết printvà tôi nghĩ nó ngắn hơn một chút. Nó cũng phù hợp với hành vi được yêu cầu tốt hơn (dừng lại ở "4 0" thay vì khi bạn biết câu trả lời). Và len(m)>1== m[1:]. Nhập khẩu thực sự gây phiền nhiễu - from a,b import *sẽ rất tốt.
ugoren

chương trình này dường như thoát ra bất cứ khi nào nó cảm thấy đúng. một lần tôi chạy nó và nó dừng lại ở 5 lần đoán, nó không đúng. lần tiếp theo, nó dừng lại ở 4 lần đoán và nó đã đúng, nhưng tôi thậm chí còn 4 0chưa nhập , đó là trong tiêu chí khách quan, và lần khác nó sẽ thoát với một ngoại lệ:print(*(m.pop())) KeyError: 'pop from an empty set'
Blazer

@ Áo lót. Các trường hợp thử nghiệm gây ra đầu ra này là gì?
Steven Rumbalski

@Blazer: 4 0là bốn chốt màu trắng. Tôi nghĩ rằng bạn có điểm đảo ngược.
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

Tôi thích viết các chương trình tương tác chức năng hoàn toàn! Nhưng tất nhiên phong cách này có một số hạn chế nhất định: hiện tại đã chấm dứt với một lỗi, nhưng bạn đã không xác định rằng điều này không ổn. Tôi cần phải cấu trúc lại toàn bộ mọi thứ vào IOđơn nguyên để có được lối thoát không có lỗi.


Liệu nó có đảm bảo đoán đúng trong 6 lần di chuyển không?
ugoren

Ừm Tôi nghĩ rằng nó là (hoạt động cho ví dụ của OP và các giải pháp khác), nhưng thử nghiệm toàn diện cho thấy rằng đôi khi nó cần 7 lần đoán. Tôi sẽ phải làm việc này chưa!
đã ngừng quay ngược chiều

5

Python, 385 357 ký tự, Giải quyết trong 5 lần di chuyển

Tôi càng thay đổi nó, nó càng phát triển giống như của Steven Rumbalski ... Sự khác biệt chính là anh ta làm việc với các chuỗi chứ không phải là số nguyên.
Đã thực hiện thuật toán của Knuth (chính xác là bây giờ, tôi hy vọng).
Mượn chức năng ghi bàn từ Steven Rumbalski.
Phải mất một thời gian dài để tạo ra dự đoán đầu tiên, trở nên tốt hơn sau này.
Mã hóa cứng nó ( g=len(A)==1296 and [1,1,2,2] or ...) làm cho cuộc sống dễ dàng hơn nếu bạn muốn kiểm tra nó.
Tôi không đếm 4 dòng mới + cặp tab, có thể được thay thế bằng dấu chấm phẩy.

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