Намалюйте мережу вузлів


24

Існує мережа до 26 вузлів (званих Aв Zабо aна zза вашим бажанням). Кожна пара вузлів може бути підключена або відключена. Вузол може бути підключений щонайбільше до 4 інших вузлів. Ваше завдання - намалювати мережу на 2D-схемі. Введення буде надано таким чином, що це завдання можливо (див. Більше обмежень у розділі виводу).


Формат

Вхідні дані

  • Пари листів ( Aдо Zабо aдо zвашого бажання). Вони не сортуються в будь-якому порядку.
  • Необов’язково - кількість пар

Вихідні дані

  • Креслення ASCII, яке показує фактичні зв’язки між вузлами. Вузли даються aв zабо Aна Z. Використовувати як -для горизонтальних, так і |для вертикальних. Посилання можуть бути будь-якої (ненульової) довжини, але вони повинні бути прямими горизонтальними / вертикальними лініями , які не згинаються . Пробіли можна додати за умови, що вони не спотворюють зображення.

Ви не можете використовувати вбудовані модулі, які допомагають у компонуванні графіка. Можуть бути дозволені інші вбудовані графіки (хоча рішення без вбудованих програм були б більш вдячні). Найкоротший код виграє.


Зразок даних

Вхідні дані

A B
B F
B L
F K
L K
K R
K S
R P
S J
S P
J A
T V
V N

Вихідні дані

A - B - F   T - V
|   |   |       |
|   L - K - R   N
|       |   |
J ----- S - P

Вхідні дані

H C
G H
A B
B F
B C
F G
C D
D A

Вихідні дані

A - B ----- F
|   |       |
D - C - H - G

1
Я вважаю, що на мої попередні запитання було достатньо відповідей, але зауважте, що новий тестовий випадок невірний, оскільки перший рядок є, H Aа цей край не в даному висновку. Редагувати: проблема виявлена ​​та виправлена.
Пітер Тейлор

2
Може змінити його на "Перший (робочий) код виграє"? ;-) Серйозно, це складне завдання самостійно, навіть без гольфу ...
Marco13

@ Marco13 Це, швидше за все, закриє виклик як поза темою.
Денніс

@ghosts_in_the_code Будь ласка, не використовуйте прапори, щоб задавати питання модераторам. Якщо вам потрібні відгуки про щось, завжди знайдеться дев'ятнадцятий байт .
Денніс

@Денніс добре, вибач. Я ніколи раніше не спілкувався, тому не знаю, як це працює.
ghosts_in_the_code

Відповіді:


3

CJam, 142

Ви не просили оптимального, детермінованого чи швидкого рішення, тож ось вам:

qN%Sf%::c_s_&:Aff#:E;{A{;[DmrDmr]2f*}%:C;E{Cf=~.-:*}%0m1{E{Cf=$~1$.-_:g:T\:+,1>\ff*\f.+T0="-|"=f+~}%CA.++:L2f<__&=!}?}gS25*a25*L{~2$4$=\tt}/N*

Спробуйте в Інтернеті

Це генерує випадкові координати для кожної літери і тестує, чи макет прийнятний (крайові літери, що вишикуються, і немає перетинів), поки це не стане. Це стає розумно повільно, коли ви додаєте більше ребер.

Два D букви в коді задають максимальні координати x і y; Я вибрав D(= 13), тому що я вважаю, що цього має бути достатньо для всіх випадків, сміливо докажіть мене неправильно. Але ви можете змінити їх на інші значення, щоб пришвидшити програму, наприклад, другий приклад повинен закінчитися через хвилину-дві, якщо ви замість цього використовуєте 3 та 4.


Я не просив швидкого рішення, але, можливо, я мав би попросити детермінованого. Але тепер, коли питання стоїть так довго, я його не зміню.
ghosts_in_the_code

@ghosts_in_the_code це не повинно бути занадто важким, щоб зробити його детермінованим - спробуйте всі комбінації координат. Але це, мабуть, буде довше і набагато повільніше, і їсти багато пам’яті теж.
aditsu

3

C, 813 байт

#include<map>
#include<set>
#include<cstdlib>
typedef int I;typedef char*C;I a,t,s,h;struct p{I x,y;}j,k;std::map<I,std::set<I>>l;std::map<I,p>g;C m,M="  |-";I L(I n,C q,C Q){j=g[n],h=1;for(I o:l[n])if(g.find(o)!=g.end())if(!(a=(k=g[o]).y==j.y)&&k.x^j.x)h=0;else for(I x=j.x,y=j.y,e=k.y*s+k.x,b,d=(k.x<j.x||k.y<j.y)?-1:1;a?x+=d:y+=d,(b=y*s+x)^e;m[b]=q[a])if(m[b]^Q[a]){h=0;break;}}I N(){for(auto i:g)for(I n:l[i.first])if(g.find(n)==g.end())return n;for(auto i:l)if(g.find(a=i.first)==g.end())return a;exit(puts(m));}I f(){for(I n=N(),x,y=0,b;y<s;y+=2)for(x=0;x<s;x+=2)m[b=y*s+x]==*M?g[n]={x,y},m[b]=n,L(n,M+2,M),h&&f(),L(n,M,M+2),m[b]=*M,g.erase(n):0;}I main(I c,C*v){for(;--c;l[a].insert(s),l[s].insert(a))a=v[c][0],s=v[c][1];t=l.size(),s=t|1;memset(m=(C)calloc(s,s),*M,s*s-1);for(a=1;a<s;++a)m[a*s-1]=10;f();}

Вводиться як аргументи командного рядка, наприклад:

./network AB BF BL FK LK KR KS RP SJ SP JA TV VN

Ніде не конкуруючи з відповіддю за розміром відповіді aditsu, але набагато ефективніше!

Це призведе до грубого змушення всіх можливих рішень, але швидко визнає невдачу, як вона піде. Для двох тестових випадків він закінчується майже відразу, і, здається, потрібно лише кілька секунд на більш незручних введеннях. Він також не обмежує прийнятих імен вузлів (хоча ви не можете назвати один пробіл, |або -) і не має обмеження щодо кількості вузлів (доки всі імена вміщуються в байт, тому практичне обмеження становить 252 вузли, і це стане повільним задовго до досягнення багатьох).

Існує достатньо можливостей для прискорення цього процесу; в гольфі було втрачено багато короткого замикання, і там є частини, які можна було перемістити з гарячих циклів. Також деякі спостереження симетрії можуть, крім іншого, різко зменшити позиціонування перших 2 вузлів.


Зламатися:

#include<map>
#include<set>
#include<cstdlib>
typedef int I;
typedef char*C;
I a,t,s,h;                // Variables shared between functions
struct p{I x,y;}          // Coord datatype
j,k;                      // Temporary coord references
std::map<I,std::set<I>>l; // Bidirectional multimap of node links
std::map<I,p>g;           // Map of nodes to positions
C m,                      // Rendered grid
M="  |-";                 // Lookup table for output characters

// Line rendering function
// Sets h to 1 if all lines are drawn successfully, or 0 if there is a blocker
I L(I n,C q,C Q){
  j=g[n],h=1;
  for(I o:l[n])                  // For each connection to the current node
    if(g.find(o)!=g.end())       // If the target node has been positioned
      if(!(a=(k=g[o]).y==j.y)&&k.x^j.x)h=0; // Fail if the nodes are not aligned
      else
        for(I x=j.x,y=j.y,             // Loop from node to target
          e=k.y*s+k.x,
          b,d=(k.x<j.x||k.y<j.y)?-1:1;
          a?x+=d:y+=d,(b=y*s+x)^e;
          m[b]=q[a])                   // Render character (| or -)
          if(m[b]^Q[a]){h=0;break;}    // Abort if cell is not blank
}

// Next node selection: finds the next connected node to try,
// or the next unconnected node if the current connected set is complete.
// Displays the result and exits if the entire graph has been rendered.
I N(){
  for(auto i:g)for(I n:l[i.first])  // Search for a connected node...
    if(g.find(n)==g.end())return n; // ...and return the first available
  for(auto i:l)                     // Else search for an unconnected node...
    if(g.find(a=i.first)==g.end())
      return a;                     // ...and return the first available
  exit(puts(m));                    // Else draw the grid to screen and stop
}

// Recursive brute-force implementation
I f(){
  for(I n=N(),x,y=0,b;y<s;y+=2) // Loop through all grid positions
    for(x=0;x<s;x+=2)
      m[b=y*s+x]==*M            // If the current position is available
       ?g[n]={x,y},             // Record the location for this node
        m[b]=n,                 // Render the node
        L(n,M+2,M),             // Render lines to connected nodes
        h&&f(),                 // If line rendering succeeded, recurse
        L(n,M,M+2),             // Un-render lines
        m[b]=*M,g.erase(n)      // Un-render node
       :0;
}

// Input parsing and grid setup
I main(I c,C*v){
  // Parse all inputs into a bidirectional multi-map
  for(;--c;l[a].insert(s),l[s].insert(a))a=v[c][0],s=v[c][1];
  t=l.size(),s=t|1; // Calculate a grid size
  // Allocate memory for the grid and render newlines
  memset(m=(C)calloc(s,s),*M,s*s-1);
  for(a=1;a<s;++a)m[a*s-1]=10;
  f(); // Begin recursive solving
}

Нарешті! Минуло 2 місяці. Я особисто не є прихильником того, щоб грати в таку відповідь, як мене вимагали лише люди цього сайту.
ghosts_in_the_code

@ghosts_in_the_code, якщо ви не хочете коду для гольфу, існує безліч інших об'єктивних критеріїв виграшу, які ви можете використовувати (хоча очевидно, ви не можете змінити цю проблему зараз, коли вона була розміщена). Приклади, засновані на часі, будуть: найшвидший для отримання результатів на конкретному апаратному забезпеченні (наприклад, конкретний екземпляр EC2 / малиновий пі / тощо), найбільш компактний висновок для батареї тестів протягом обмеженого періоду, найбільша мережа, що підтримується за допомогою батареї тестів обмеження часу (наприклад, день, що забезпечує гнучкість для конкретного обладнання). Спробуйте використати пісочницю наступного разу; люди можуть допомогти вам вибрати мету.
Дейв
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.