Giải bài toán số Aristotle


21

Câu đố số của Aristotle là thử thách đưa vào mỗi 19 ô trong một lưới hình lục giác có số nguyên duy nhất trong khoảng từ 1 đến 19 sao cho tổng số dọc theo mỗi trục là 38.

Bạn có thể hình dung bảng trò chơi trông như thế này:

lưới aristotle

Và câu đố, về bản chất, là lời giải cho bộ mười phương trình sau:

((a + b + c) == 38 && (d + e + f + g) == 38 && (h + i + j + k + l) == 
   38 && (m + n + o + p) == 38 && (q + r + s) == 38 && (a + d + h) == 
   38 && (b + e + i + m) == 38 && (c + f + j + n + q) == 
   38 && (g + k + o + r) == 38 && (l + p + s) == 38 && (c + g + l) == 
   38 && (b + f + k + p) == 38 && (a + e + j + o + s) == 
   38 && (d + i + n + r) == 38 && (h + m + q) == 38)

Trong đó mỗi biến là một số duy nhất trong tập hợp {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}.

Có nhiều giải pháp khả thi, và là 19!sự kết hợp có thể của các số nguyên, vì vậy lực lượng vũ phu ngây thơ sẽ không thực tế.

Quy tắc:

  1. Không mã hóa câu trả lời hoặc tìm kiếm câu trả lời ở nơi khác; mã của bạn cần phải tự tìm nó
  2. Tốc độ không thành vấn đề, nhưng bạn phải hiển thị kết quả của mình, vì vậy mã phải mất 1000 năm để chạy sẽ không giúp bạn
  3. Tìm tất cả các câu trả lời
  4. Coi các câu trả lời giống hệt nhau khi quay
  5. Khấu trừ 5% tổng số byte của bạn nếu bạn đưa ra kết quả trong một tổ ong hấp dẫn
  6. Ít byte nhất sẽ thắng

Câu hỏi tuyệt vời, mong muốn làm việc một giải pháp cho nó.
Lập trình viên

Bạn có coi câu trả lời xoay là duy nhất? Ví dụ: giả sử a, b, c = 1, 18, 19 lập chỉ mục một giải pháp cụ thể, nếu chúng ta đặt c, g, l = 1, 18, 19 và tất cả các giá trị khác được "xoay" để khớp, bạn có coi đây là một duy nhất dung dịch?
Lập trình viên

@ProgrammerDan Xoay câu trả lời là giống hệt nhau. Tôi sẽ làm rõ.
Michael Stern

1
Một hình lục giác có nhiều đối xứng hơn là chỉ xoay. Điều gì về câu trả lời giống hệt nhau dưới sự kết hợp của giới hạn và phản ánh?
Peter Taylor

Quan tâm để xem một giải pháp cho vấn đề này bằng cách sử dụng bản đồ tự tổ chức.
Ant P

Câu trả lời:


3

Haskell 295 289

import Data.List
t=38
y a b=[max(19-b)(a+1)..19]
w=y 0 t
x=filter((==w).sort)$[[a,b,c,d,e,f,g,h,i,t-a-e-o-s,k,l,m,t-d-i-r,o,p,q,r,s]|a<-[1..14],c<-y a a,l<-y a c,s<-y a l,q<-y a s,h<-y c q,e<-w,let{f=t-g-e-d;i=t-b-e-m;o=t-r-k-g;k=t-p-f-b;b=t-a-c;g=t-l-c;p=t-l-s;r=t-q-s;m=t-q-h;d=t-a-h}]

Một câu trả lời tương tự khác, sử dụng số học để có được các hình lục giác trung gian. Không giống như các giải pháp khác, tôi không kiểm tra các khoản tiền đó> 0, kiểm tra xem các hình lục giác được sắp xếp có bằng với phạm vi [1..19] là đủ. a, c và h bị hạn chế để chỉ cho phép các giải pháp xoay / nhân đôi duy nhất. Giải pháp xuất hiện sau vài giây, sau đó chờ khoảng một phút hoặc lâu hơn trong khi nó quyết định không còn nữa.

Cách sử dụng trong ghci:

ghci> x
[[3,19,16,17,7,2,12,18,1,5,4,10,11,6,8,13,9,14,15]]

Chỉnh sửa để cạo một vài ký tự. 'y 0 t' tạo ra [1..19].


1
Trên thực tế tôi đang làm điều tương tự trong câu trả lời C của mình :) chết tiệt làm sao tôi không thấy Haskell là công cụ hoàn hảo cho công việc: P +1
Niklas B.

Tôi có thể bỏ lỡ x>0kiểm tra của bạn , bởi vì tôi sắp xếp danh sách bao gồm cả phủ định thay vì tăng một mảng? Mặt khác, tôi phải hạn chế các phạm vi (của tôi y a b) để Haskell thực hiện, điều này khiến tôi mất một vài ký tự. Nhưng chắc chắn sẽ có một ngôn ngữ khác được tích hợp sẵn sẽ đánh bại tôi làm việc theo cách tương tự (nhìn vào bạn, Mathicala).
bazzargh

Có, sắp xếp trong C không may là không đơn giản như trong Haskell. Vấn đề với Mathematica là nó không được biên dịch và do đó rất chậm :(
Niklas B.

Tôi luôn luôn làm những điều này trong Haskell để thực hành, ngay cả khi một ngôn ngữ khác sẽ tốt hơn.
bazzargh

Tôi thực sự lập trình Haskell như một công việc phụ, vì vậy tôi đã bối rối rằng tôi thậm chí không sử dụng nó ở đây: D Đó là một ngôn ngữ thực sự tuyệt vời, ngay cả trong thế giới thực / không trong sạch
Niklas B.

10

Java (1517 - 75,85) = 1441,15 (1429 - 71,45) = 1357,55 (1325 - 66,25) = 1258,75

Đây là niềm vui

In tất cả các giải pháp độc đáo, phản chiếu và xoay, trong một tổ ong dễ chịu (do đó giảm 5%)

Thời gian chạy: ~ 0.122 giây (122 mili giây) trên máy tính xách tay 4 tuổi của tôi.

Mã đánh gôn ( chỉnh sửa golf nhận ra tôi đã lặp lại một cách ngu ngốc các bản in của mình, giảm chúng thành một bản in duy nhất cho golf tối đa) ( chỉnh sửa mới Giảm các cuộc gọi để Đặt chức năng thành các chức năng nhỏ hơn thông minh, một số tối ưu hóa vi mô khác):

import java.util.*;class A{boolean c(Set<Integer>u,int z){return!u.contains(z);}Set<Integer>b(Set<Integer>c,int...v){Set<Integer>q=new HashSet<Integer>(c);for(int x:v)q.add(x);return q;}void w(){Set<Integer>U,t,u,v,w,y,z;int a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,X,Z;X=20;Z=38;for(a=1;a<X;a++)for(b=1;b<X;b++)if(b!=a)for(c=1;c<X;c++)if(c!=a&&c!=b&&a+b+c==Z){U=b(new HashSet<Integer>(),a,b,c);for(d=1;d<X;d++)if(c(U,d))for(h=1;h<X;h++)if(h!=d&&c(U,h)&&a+d+h==Z){t=b(U,a,b,c,d,h);for(m=1;m<X;m++)if(c(t,m))for(q=1;q<X;q++)if(q!=m&&c(t,q)&&h+m+q==Z){u=b(t,m,q);for(r=1;r<X;r++)if(c(u,r))for(s=1;s<X;s++)if(s!=r&&c(u,s)&&q+r+s==Z){v=b(u,r,s);for(p=1;p<X;p++)if(c(v,p))for(l=1;l<X;l++)if(l!=p&&c(v,l)&&s+p+l==Z){w=b(v,p,l);for(g=1;g<X;g++)if(c(w,g)&&l+g+c==Z)for(e=1;e<X;e++)if(e!=g&&c(w,e))for(f=1;f<X;f++)if(f!=e&&f!=g&&c(w,f)&&d+e+f+g==Z){y=b(w,g,e,f);for(i=1;i<X;i++)if(c(y,i))for(n=1;n<X;n++)if(n!=i&&c(y,n)&&d+i+n+r==Z&&b+e+i+m==Z){z=b(y,i,n);for(o=1;o<X;o++)if(c(z,o))for(k=1;k<X;k++)if(k!=o&&c(z,k)&&m+n+o+p==Z&&r+o+k+g==Z&&b+f+k+p==Z)for(j=1;j<X;j++)if(c(z,j)&&j!=o&&j!=k&&a+e+j+o+s==Z&&c+f+j+n+q==Z&&h+i+j+k+l==Z){System.out.printf("%6d%4d%4d\n\n%4d%4d%4d%4d\n\n%2d%4d%4d%4d%4d\n\n%4d%4d%4d%4d\n\n%6d%4d%4d\n\n",a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s);return;}}}}}}}}}public static void main(String[]a){(new A()).w();}}

Brute force là passe, nhưng việc sử dụng thông minh thực tế là chỉ có một bộ giải pháp rất nhỏ tồn tại đã đưa tôi đến một câu trả lời dựa trên phép lặp, trong đó trong mỗi vòng lặp, tôi chỉ xem xét các số nguyên chưa được "gán". Tôi sử dụng Hashset của Java để có được tra cứu O (1) cho các số đã được sử dụng trước đó. Cuối cùng, có chính xác 12 giải pháp, nhưng khi bạn giảm giá cả xoay và phản chiếu thì điều này giảm xuống chỉ còn một giải pháp duy nhất, vì vậy khi gặp giải pháp đầu tiên, tôi in nó ra và chấm dứt. Kiểm tra mã ít chơi gôn của tôi tại github để có một cái nhìn rõ ràng hơn về cách tôi tiếp cận giải pháp này.

Thưởng thức!


Vâng, bạn nằm trong spoiler của bạn, có nhiều giải pháp khác nhau, vì vậy câu trả lời của bạn là không hợp lệ.
ST3

Yêu cầu mạnh mẽ, bạn có thể sao lưu nó bằng một câu trả lời của riêng bạn để chứng minh điều đó không? Tôi chắc chắn không nhận thức được bất kỳ lời nói dối có chủ ý trong spoiler của tôi.
Lập trình viên

Vì vậy, khi gặp giải pháp đầu tiên, tôi in nó ra và chấm dứt quy tắc không. 3 nói để tìm tất cả các câu trả lời. Có 19 như OP đã nói, không chắc nó có thực sự là 19 không, nhưng tôi đã từng làm nhiệm vụ tương tự trước đây, vì vậy hãy biết rằng có nhiều hơn một.
ST3

Bạn cần phải đọc toàn bộ spoiler của tôi . Tôi tìm thấy 12 giải pháp. Sau đó, bạn cần phải đọc toàn bộ ý kiến ​​kèm theo câu hỏi. OP nói rằng các câu trả lời là xoay vòng bằng nhau là tương đương và nên được bỏ qua. Một người khác hỏi nếu câu trả lời phản ánh wrt bằng nhau nên được bỏ qua. Mặc dù OP đến nay chưa trả lời câu hỏi này, cả tôi và tất cả các giải pháp khác cho đến nay đều cho rằng câu trả lời là "có". Do đó, giải pháp của tôi hoàn toàn đầy đủ, hoàn toàn chính xác và không có "lời nói dối" nào ở đây. Tuy nhiên, nếu bạn muốn xem tất cả 12 giải pháp, hãy xóa return;câu lệnh.
Lập trình viên

Cuối cùng, đây là mã golf. Xem xét việc thêm một return;câu lệnh tùy ý làm tăng độ dài mã của tôi lên 7, tôi sẽ thêm điên rồ nếu câu trả lời đúng bao gồm tất cả 12 giải pháp chỉ là các phiên bản được xoay / nhân đôi của nhau. Mặc dù sự điên rồ không thể loại trừ, trong trường hợp này, việc bổ sung return;là có chủ ý, và như tôi đã mô tả, dựa trên hộp thoại câu hỏi và bình luận đầy đủ , bạn nên cẩn thận xem xét trước khi đưa ra lời buộc tội. Cảm ơn!
Lập trình viên

8

C, 366 byte ( C ++ 541 450 )

#define R(i)for(int i=19;i;--i)
#define X(x)if(x>0&&!V[x]++)
#define K(X)X(a)X(b)X(c)X(d)X(e)X(f)X(g)X(h)X(i)X(j)X(k)X(l)X(m)X(n)X(o)X(p)X(q)X(r)X(s)
Q(x){printf("%d ",x);}
T=38,V[99];main(){R(h)R(c)R(s)R(a)R(l)R(q)R(e){int d=T-a-h,b=T-a-c,g=T-c-l,p=T-l-s,r=T-q-s,m=T-h-q,f=T-g-e-d,i=T-b-e-m,n=T-d-i-r,o=T-p-n-m,k=T-g-o-r,j=T-h-i-k-l;R(C)V[C]=0;K(X)K(+Q),exit(0);}}

Biên dịch với gcc -std=c99 -O3.

In tất cả các giải pháp xoay và phản chiếu modulo độc đáo, ở định dạng a b c d ... , mỗi dòng trên một dòng.

Thời gian chạy: 0,8 giây trên máy tính của tôi.

Chúng tôi liệt kê các ô theo thứ tự h -> c -> s -> a -> l -> q -> e để có thể dễ dàng tối đa. Trong thực tế, phiên bản trên chỉ thử mỗi 20 ^ 7 bài tập cho các biến đó. Sau đó chúng ta có thể tính toán tất cả các ô khác. Chỉ có một giải pháp xoay / phản chiếu modulo duy nhất. Phiên bản C ++ cũ hơn, ít chơi gôn hơn và nhanh hơn ~ 20 lần (do cắt tỉa) có thể được tìm thấy trên Github


Tôi thích cách tiếp cận số học phần lớn ở đây. Bravo! +1
Lập trình viên

1

Matlab: 333 320 ký tự

Đây là một cách tiếp cận gần như ngu ngốc, không sử dụng đệ quy. Nó xây dựng các giải pháp một phần z, được in ra ở cuối. Mỗi cột là một giải pháp; các yếu tố được liệt kê az từ trên xuống dưới. Thời gian chạy là 1-2 giờ.

z=[];
a='abc adh hmq qrs spl lgc defg beim mnop dinr rokg pkfb hijkl aejos cfjnq';while a[k,a]=strtok(a);n=length(k);x=nchoosek(1:19,n)';s=[];for t=x(:,sum(x)==38)s=[s,perms(t)'];end
m=0.*s;m(19,:)=0;m(k(1:n)-96,:)=s(1:n,:);y=[];for p=m for w=z m=[];l=w.*p~=0;if p(l)==w(l) y(:,end+1)=w+p.*(~l);end
end
end
z=[m,y];end
z

Chạy từ bên trong Matlab:

>> aristotle;
>> z(:,1)

ans =

    9
   11
   18
   14
    6
    1
   17
   15
    8
    5
    7
    3
   13
    4
    2
   19
   10
   12
   16
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.