แก้ปัญหาจำนวนของอริสโตเติล


21

ปริศนาตัวเลขของอริสโตเติลเป็นความท้าทายของการเติมแต่ละเซลล์ 19 เซลล์ในตารางหกเหลี่ยมที่มีจำนวนเต็มไม่ซ้ำกันระหว่าง 1 ถึง 19 ดังนั้นจำนวนทั้งหมดตามแกนคือ 38

คุณสามารถนึกภาพกระดานเกมที่มีลักษณะดังนี้:

ตารางอริสโตเติล

และในสาระสำคัญปริศนาคือคำตอบของสมการสิบห้าชุดดังต่อไปนี้:

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

{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}ที่ไหนตัวแปรแต่ละคนเป็นจำนวนที่ไม่ซ้ำกันในชุด

มีวิธีแก้ปัญหาที่เป็นไปได้หลายแบบและเป็น19!ไปได้ของการรวมจำนวนเต็มดังนั้นแรงเดรัจฉานไร้เดียงสาจึงไม่สามารถปฏิบัติได้

กฎ:

  1. ไม่มีการเข้ารหัสฮาร์ดโค้ดหรือค้นหาคำตอบที่อื่น รหัสของคุณจำเป็นต้องค้นหาด้วยตนเอง
  2. ความเร็วไม่สำคัญ แต่คุณต้องแสดงผลลัพธ์ของคุณดังนั้นรหัสที่ใช้เวลา 1,000 ปีจึงจะไม่ช่วยคุณ
  3. ค้นหาคำตอบทั้งหมด
  4. ปฏิบัติกับคำตอบที่เหมือนกันภายใต้การหมุนเหมือนกัน
  5. หัก 5% ของจำนวนไบต์ทั้งหมดหากคุณแสดงผลลัพธ์ในรังผึ้งที่น่าสนใจ
  6. ไบต์ที่น้อยที่สุดจะเป็นผู้ชนะ

คำถามที่ดีรอคอยที่จะทำงานแก้ปัญหาไป
ProgrammerDan

คุณพิจารณาคำตอบที่หมุนได้หรือไม่? เช่นสมมติว่า a, b, c = 1, 18, 19 ดัชนีวิธีแก้ปัญหาเฉพาะถ้าเราตั้งค่า c, g, l = 1, 18, 19 และค่าอื่น ๆ ทั้งหมดเป็น "หมุน" เพื่อให้ตรงกับที่คุณคิดว่ามันไม่ซ้ำกัน วิธีการแก้?
ProgrammerDan

@ProgrammerDan คำตอบที่หมุนเหมือนกัน ฉันจะชี้แจง
Michael Stern

1
รูปหกเหลี่ยมมีความสมมาตรมากกว่าการหมุน สิ่งที่เกี่ยวกับคำตอบที่เหมือนกันภายใต้การรวมกันของการหารและการสะท้อน?
Peter Taylor

สนใจที่จะดูวิธีการแก้ปัญหานี้โดยใช้แผนที่การจัดระเบียบตัวเอง
Ant P

คำตอบ:


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

อีกคำตอบที่คล้ายกันโดยใช้เลขคณิตเพื่อรับ hexes กลาง ต่างจากวิธีแก้ปัญหาอื่น ๆ ฉันไม่ได้ทดสอบผลรวมที่เป็น> 0 การทดสอบว่า hexes ที่เรียงนั้นมีค่าเท่ากับช่วง [1..19] ก็เพียงพอแล้ว a, c และ h ถูก จำกัด เพื่อให้อนุญาตเฉพาะโซลูชันแบบหมุน / มิเรอร์ที่ไม่ซ้ำกันเท่านั้น การแก้ปัญหาจะปรากฏขึ้นหลังจากผ่านไปสองสามวินาทีจากนั้นจะมีการรอประมาณหนึ่งนาทีหรือมากกว่านั้นในขณะที่การตัดสินใจไม่มีอีกต่อไป

การใช้งานใน ghci:

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

แก้ไขเพื่อโกนหนวดสองสามตัว 'y 0 t' สร้าง [1..19]


1
อันที่จริงฉันกำลังทำสิ่งเดียวกันในคำตอบ C ของฉัน :) เจ้ากรรมฉันจะไม่เห็นว่า Haskell เป็นเครื่องมือที่สมบูรณ์แบบสำหรับงาน: P +1
Niklas B.

ฉันจะพลาดx>0เช็คของคุณเพราะฉันเรียงลำดับรายการรวมถึงเชิงลบแทนการเพิ่มอาร์เรย์? ในทางกลับกันฉันต้อง จำกัด ช่วง (ของฉันy a b) เพื่อให้ Haskell แสดงซึ่งทำให้ฉันมีค่าใช้จ่ายไม่กี่ตัวอักษร แต่จะต้องมีภาษาอื่นที่มีอยู่แล้วภายในซึ่งจะทำให้ฉันทำงานเหมือนเดิม (มองมาที่คุณ Mathematica)
bazzargh

ใช่การเรียงลำดับใน C น่าเสียดายไม่ใช่เรื่องง่ายเหมือนใน Haskell ปัญหาของ Mathematica ก็คือมันไม่ได้ถูกรวบรวมและดังนั้นจึงช้ามาก :(
Niklas B.

ฉันมักจะทำสิ่งเหล่านี้ใน Haskell เพื่อฝึกฝนแม้ว่าภาษาอื่นจะดีกว่า
bazzargh

จริงๆแล้วฉันเขียนโปรแกรม Haskell เป็นงานด้านดังนั้นฉันจึงนิ่งงันว่ามันไม่ได้เกิดขึ้นกับฉันที่จะใช้ที่นี่: D มันเป็นภาษาที่ยอดเยี่ยมจริงๆแม้ในโลกที่แท้จริง / ไม่บริสุทธิ์
Niklas B.

10

Java (1517 - 75.85) = 1441.15 (1429 - 71.45) = 1357.55 (1325 - 66.25) = 1258.75

มันสนุกมาก

พิมพ์โซลูชั่นที่เป็นเอกลักษณ์ทั้งหมดสะท้อนการหมุนและการหมุนในรังผึ้งที่น่ารื่นรมย์ (ลด 5%)

Runtime: ~ 0.122s (122 มิลลิวินาที) บนแล็ปท็อปอายุ 4 ปีของฉัน

รหัส Golfed ( แก้ไขการรับรู้ฉันโง่ซ้ำของฉันพิมพ์ลดลงเป็น printf เดียวสำหรับกอล์ฟสูงสุด) ( แก้ไขใหม่ลดการเรียกไปที่การตั้งค่าฟังก์ชั่นฟังก์ชั่นที่มีขนาดเล็กที่ชาญฉลาดบางไมโครปรับประสิทธิภาพอื่น ๆ ):

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 คือ passe แต่การใช้งานอย่างชาญฉลาดของความจริงที่ว่ามีเพียงชุดเล็ก ๆ ของการแก้ปัญหาเท่านั้นที่นำฉันไปสู่คำตอบตามการวนซ้ำซึ่งภายในแต่ละลูปของการวนซ้ำฉันพิจารณาเฉพาะจำนวนเต็มที่ไม่ได้รับมอบหมาย ฉันใช้ประโยชน์จาก HashSet ของ Java เพื่อให้ได้การค้นหา O (1) สำหรับตัวเลขที่ใช้ก่อนหน้านี้ ในที่สุดมี 12 โซลูชั่นที่แน่นอน แต่เมื่อคุณลดทั้งการหมุนและการทำมิเรอร์สิ่งนี้จะลดให้เหลือเพียงหนึ่งโซลูชันที่ไม่ซ้ำกันดังนั้นเมื่อพบโซลูชันแรกฉันพิมพ์มันออกมาและยุติ ลองดูโค้ดที่ไม่ค่อยเล่นกอล์ฟของคุณที่ githubเพื่อรับมุมมองที่ชัดเจนยิ่งขึ้นว่าฉันกำลังเข้าใกล้โซลูชันนี้อย่างไร

สนุก!


คุณนอนในสปอยเลอร์มีวิธีแก้ไขปัญหาต่าง ๆ ดังนั้นคำตอบของคุณจึงไม่ถูกต้อง
ST3

คุณสามารถสำรองข้อมูลด้วยคำตอบของคุณเองเพื่อพิสูจน์มันได้หรือไม่? แน่นอนว่าฉันไม่ได้ตระหนักถึงความตั้งใจในการสปอยเลอร์ของฉัน
ProgrammerDan

ดังนั้นเมื่อพบวิธีแก้ปัญหาแรกฉันจะพิมพ์มันออกมาและยุติกฏหมายเลข 3 บอกให้บอกว่าจะหาคำตอบทั้งหมด มี 19 อย่างที่โอพีกล่าวว่าไม่แน่ใจว่าเป็น 19 จริงๆ แต่ฉันเคยทำงานที่คล้ายกันมาก่อนดังนั้นรู้ว่ามีมากกว่าหนึ่ง
ST3

คุณต้องอ่านสปอยเลอร์ทั้งหมดของฉัน ฉันพบวิธีแก้ไขปัญหา 12 ข้อ จากนั้นคุณต้องอ่านความคิดเห็นทั้งหมดที่แนบมากับคำถาม OP บอกว่าคำตอบที่มีการหมุน wrt เท่ากันนั้นเท่ากันและควรข้าม อีกคนถามว่าควรตอบข้ามการมิเรอร์ wrt เท่ากันหรือไม่ แม้ว่า OP มีวันที่ไม่ได้ตอบแบบสอบถามนี้ทั้งของฉันและโซลูชันอื่น ๆ ทั้งหมดจนถึงปัจจุบันถือว่าคำตอบคือ "ใช่" ดังนั้นทางออกของฉันสมบูรณ์ครบถ้วนถูกต้องครบถ้วนและไม่มี "การโกหก" ที่นี่ อย่างไรก็ตามหากคุณต้องการดูวิธีแก้ปัญหาทั้ง 12 ข้อให้ลบreturn;ข้อความนั้นออก
ProgrammerDan

ในที่สุดนี่คือรหัสกอล์ฟ เมื่อพิจารณาการเพิ่มreturn;คำสั่งโดยพลการจะเพิ่มความยาวโค้ดของฉันทีละ 7 มันจะบ้าถ้าฉันจะเพิ่มถ้าคำตอบที่แท้จริงนั้นรวมคำตอบทั้งหมด 12 ข้อซึ่งเป็นเวอร์ชั่นหมุน / มิเรอร์ของกันและกัน แม้ว่าจะไม่สามารถแยกแยะความวิกลจริตได้ แต่ในกรณีนี้การเพิ่มreturn;นั้นเป็นไปโดยเจตนาและตามที่ฉันอธิบายโดยใช้คำถามและความคิดเห็นแบบโต้ตอบเต็มรูปแบบซึ่งคุณควรตรวจสอบก่อนที่จะทำการกล่าวหา ขอบคุณ!
ProgrammerDan

8

C, 366 ไบต์ ( 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);}}

gcc -std=c99 -O3คอมไพล์ด้วย

พิมพ์โซลูชั่นที่เป็นเอกลักษณ์ทั้งหมดการหมุนแบบโมดูโลและการมิเรอร์ในรูปแบบa b c d ...หนึ่งรายการต่อบรรทัด

รันไทม์: 0.8 วินาทีบนคอมพิวเตอร์ของฉัน

เราแจกแจงเซลล์ตามลำดับ h -> c -> s -> a -> l -> q -> e เพื่อความสามารถในการตัดสูงสุด อันที่จริงแล้วเวอร์ชั่นด้านบนจะลองทำการมอบหมาย 20 20 ครั้งสำหรับตัวแปรเหล่านั้น จากนั้นเราสามารถคำนวณเซลล์อื่น ๆ ทั้งหมด มีวิธีการหมุน / การสะท้อนแบบโมดูโลที่ไม่ซ้ำกันเพียงวิธีเดียว เก่ากว่ากอล์ฟน้อยลงและเร็วขึ้น 20 เท่า (เนื่องจากการตัด) รุ่น C ++ สามารถพบได้ใน Github


ฉันชอบวิธีการทางคณิตศาสตร์ส่วนใหญ่ที่นี่ ไชโย! +1
ProgrammerDan

1

Matlab: 333 320 ตัวอักษร

นี่เป็นวิธีที่ใกล้เคียงกับสัตว์เดรัจฉานที่ไม่ได้ใช้การเรียกซ้ำ มันสร้างโซลูชันบางส่วนในzซึ่งพิมพ์ออกมาในตอนท้าย แต่ละคอลัมน์เป็นทางออก องค์ประกอบที่ระบุไว้ az จากบนลงล่าง รันไทม์คือ 1-2 ชั่วโมง

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

เรียกใช้จากภายใน Matlab:

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

ans =

    9
   11
   18
   14
    6
    1
   17
   15
    8
    5
    7
    3
   13
    4
    2
   19
   10
   12
   16
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.