Розв’яжіть задачу числа Арістотеля


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. Швидкість не має значення, але ви повинні показувати свої результати, тому код, на який потрібно 1000 років, не допоможе вам
  3. Знайдіть усі відповіді
  4. Розглядайте відповіді, які однакові під час обертання, як ідентичні
  5. Відрахуйте 5% від загальної кількості байтів, якщо ви отримаєте результати в привабливій стільниці
  6. Виграє найменше байт

Відмінне запитання, з нетерпінням чекаю налагодження його вирішення.
ПрограмістDan

Чи вважаєте ви ротаційні відповіді унікальними? Наприклад, припустимо, що a, b, c = 1, 18, 19 індексує конкретне рішення, якщо ми встановимо c, g, l = 1, 18, 19 і всі інші значення "повертаються" на відповідність, чи вважаєте ви це унікальним рішення?
ПрограмістDan

@ProgrammerDan Обернені відповіді ідентичні. Я уточню.
Майкл Стерн

1
У шестикутника більше симетрії, ніж просто обертання. Як щодо відповідей, які є однаковими при поєднанні обертання та відбиття?
Пітер Тейлор

Зацікавлені побачити рішення цього питання за допомогою карт, що самоорганізуються.
Мураха 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}]

Ще одна подібна відповідь, використовуючи арифметику для отримання проміжних шестигранників. На відміну від інших рішень, я не перевіряю, чи є суми> 0, перевіряючи, чи достатньо відсортованих шестигранників діапазону [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
Насправді я роблю те саме, що і у моїй відповіді С: прокляте, як я не бачив, що Haskell - ідеальний інструмент для роботи: P +1
Niklas B.

Я можу пропустити ваш x>0чек, оскільки я сортую список, включаючи мінуси, а не збільшуючи масив? З іншого боку, я повинен обмежити діапазони (мої y a b), щоб змусити Haskell виконати, що коштує мені в кілька символів. Але має бути ще одна мова, яка має вбудований сорт, який буде бити мене, працюючи таким же чином (дивлячись на вас, Mathematica).
bazzargh

Так, сортування в С, на жаль, не таке просте, як у Haskell. Проблема з Mathematica полягає в тому, що вона не складена і, таким чином, проклята повільно :(
Ніклас Б.

Я завжди роблю це в Haskell для практики, навіть якщо інша мова була б кращою.
bazzargh

Я насправді програмую Haskell як бічну роботу, тому мені натрапляє на те, що мені навіть не спало на думку використовувати його тут: D Це дійсно чудова мова, навіть у реальному / нечистому світі
Ніклас Б.

10

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

Це було весело.

Друкує всі унікальні рішення з дзеркальним відображенням та обертанням в приємному соті (отже, зменшення на 5%)

Час виконання: ~ 0,12 секунди (122 мілісекунди) на моєму 4-річному ноутбуці.

Код для гольфу ( редагування зрозуміло, що я тупо повторюю свої printfs, зменшив їх до одного 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();}}

Сила грубої дії є прохідною, але розумне використання того факту, що існує лише дуже малий набір рішень, призвело до відповіді на основі ітерації, де в межах кожного циклу ітерації я розглядаю лише цілі числа, які ще не були "призначені". Я використовую HashSet Java, щоб отримати O (1) пошуки номерів, які раніше використовувалися. Нарешті, існує рівно 12 рішень, але коли ви знижуєте і обертання, і дзеркальне відображення, це зводиться до лише одного унікального рішення, тому коли трапляється перше рішення, я роздруковую його та закінчую. Ознайомтеся з моїм менш гольф-кодом у github, щоб отримати чіткіше уявлення про те, як я підходжу до цього рішення.

Насолоджуйтесь!


Ну, ти лежиш у своєму спойлері, є більше різних рішень, тож відповідь твоя недійсна.
ST3

Сильна претензія, чи можете ви підкріпити її власною відповіддю, щоб довести це? Я, звичайно, не усвідомлюю жодної навмисної брехні в моєму спойлері.
ПрограмістDan

тому, коли трапляється перше рішення, я роздруковую його і скасовую правило ні. 3 розповідає говорить, щоб знайти всі відповіді. Там 19, як сказала ОП, не впевнений, чи справді це 19, але я вже зіткнувся з подібним завданням, тому знайте, що існує більше, ніж один.
ST3

Вам потрібно прочитати весь мій спойлер. Я знайшов 12 рішень. Тоді вам потрібно прочитати цілі коментарі, додані до питання. ОП каже, що відповіді, що мають рівний обертання wrt, рівнозначні, і їх слід пропустити. Інша людина запитала, чи потрібно пропустити відповіді на рівні дзеркальних дзеркал. Хоча до цього часу ОП не відповів на цей запит, і моє, і всі інші рішення на сьогоднішній день припускають, що відповідь "так". Отже, моє рішення цілком повне, повністю точне, і тут немає "брехні". Однак якщо ви хочете побачити всі 12 рішень, видаліть return;заяву.
ПрограмістDan

Нарешті, це код гольфу. Зважаючи на те, що додавання довільного return;твердження збільшує довжину мого коду на 7, для мене було б божевільним додавати його, якби правдива відповідь включала всі 12 рішень, які просто обертаються / відображаються дзеркальними версіями один одного. Хоча божевілля не можна виключити, але в цьому випадку додавання return;було навмисним, і, як я описав, на основі повного діалогу запитань та коментарів , який слід подбати про перегляд, перш ніж підкидати звинувачення. Спасибі!
ПрограмістДата

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 ^ 7 призначень для цих змінних. Тоді ми можемо обчислити всі інші клітини. Існує лише одне унікальне рішення обертання / дзеркального модульного рішення. Старішу, менш гольфну і приблизно в 20 разів швидшу (через обрізку) версію C ++ можна знайти на Github


Я дуже люблю тут арифметичний підхід. Браво! +1
Програміст,

1

Матлаб: 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.