Disegna una rete di nodi


24

C'è una rete di fino a 26 nodi (chiamati Aa Zo aal zsecondo il vostro desiderio). Ogni coppia di nodi può essere connessa o disconnessa. Un nodo può essere collegato al massimo a 4 altri nodi. Il tuo compito è disegnare la rete in un diagramma 2D. Verrà fornito un input in modo che questa attività sia possibile (vedere più vincoli nella sezione output).


Formato

Ingresso

  • Coppie di lettere ( Ada Zo averso zsecondo il tuo desiderio). Non sono ordinati in alcun ordine.
  • Opzionale - numero di coppie

Produzione

  • Un disegno ASCII che mostra i collegamenti effettivi tra i nodi. I nodi sono dati da aa zo Aa Z. Utilizzare -per collegamenti orizzontali e |per collegamenti verticali. I collegamenti possono avere qualsiasi lunghezza (diversa da zero) ma devono essere linee orizzontali / verticali diritte che non si piegano . Gli spazi possono essere aggiunti purché non sfigurino l'immagine.

Non è possibile utilizzare i componenti integrati che aiutano nel layout del grafico. Possono essere consentiti altri built-in relativi ai grafici (sebbene le soluzioni senza built-in sarebbero più apprezzate). Il codice più corto vince.


Dati di esempio

Ingresso

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

Produzione

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

Ingresso

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

Produzione

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

1
Ritengo che le mie precedenti domande abbiano avuto una risposta sufficiente, ma noto che il nuovo caso di test è errato perché la prima riga è H Ae quel bordo non è nell'output dato. Modifica: problema identificato e risolto.
Peter Taylor,

2
Forse cambiarlo in "Il primo (funzionante) codice vince"? ;-) Scherzi a parte, questo è impegnativo da solo, anche senza golf ...
Marco13,

@ Marco13 Molto probabilmente chiuderebbe la sfida come fuori tema.
Dennis,

@ghosts_in_the_code Non utilizzare le bandiere per porre domande ai moderatori. Se hai bisogno di feedback su qualcosa, c'è sempre The Nineteenth Byte .
Dennis,

@Dennis ok, scusa. Non sono mai stato in chat prima, quindi non so come funzioni.
ghosts_in_the_code

Risposte:


3

CJam, 142

Non hai chiesto una soluzione ottimale, deterministica o veloce, quindi eccoti qui:

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*

Provalo online

Questo genera coordinate casuali per ogni lettera e verifica se il layout è accettabile (lettere di bordo allineate e senza intersezioni), fino a quando non lo è. Diventa incredibilmente lento mentre aggiungi più spigoli.

Le due Dlettere nel codice specificano le coordinate massime xey; Ho scelto D(= 13) perché penso che dovrebbe essere sufficiente per tutti i casi, sentiti libero di dimostrarmi che ho torto. Ma puoi cambiarli in altri valori per accelerare il programma, ad esempio il secondo esempio dovrebbe finire entro un minuto o due se usi 3 e 4 invece.


Non ho chiesto una soluzione rapida, ma forse avrei dovuto chiederne una deterministica. Ma ora che la domanda è rimasta così a lungo, non la cambierò.
ghosts_in_the_code

@ghosts_in_the_code non dovrebbe essere troppo difficile renderlo deterministico: prova tutte le combinazioni di coordinate. Ma sarebbe probabilmente più lungo e molto più lento, e consumerebbe anche molta memoria.
aditsu,

3

C, 813 byte

#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();}

Accetta input come argomenti della riga di comando, ad esempio:

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

In nessun luogo vicino alla concorrenza con la risposta di aditsu per dimensione, ma molto più efficiente!

Ciò forzerà tutte le possibili soluzioni, ma riconoscerà rapidamente il fallimento man mano che procede. Per i due casi di test, termina quasi immediatamente e sembra richiedere solo pochi secondi per input più scomodi. Inoltre non ha limiti ai nomi dei nodi accettati (anche se non puoi nominare uno spazio, |o- ) e non ha limiti al numero di nodi (purché tutti i nomi si adattino a un byte, quindi il limite pratico è 252 nodi, e rallenterà molto prima di raggiungere così tanti).

C'è un sacco di spazio per accelerare questo; molte uscite di cortocircuito sono andate perse a causa del golf, e ci sono parti che potrebbero essere spostate da circuiti a caldo. Anche alcune osservazioni di simmetria possono ridurre drasticamente il posizionamento dei primi 2 nodi, tra le altre cose.


Abbattersi:

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

Finalmente! Sono passati 2 mesi. Personalmente non sono favorevole al golf come una risposta, mi è stato richiesto solo dalle persone di questo sito.
ghosts_in_the_code il

@ghosts_in_the_code se non vuoi il golf del codice ci sono molti altri criteri vincenti oggettivi che puoi usare (anche se ovviamente non puoi cambiare questa sfida ora che è stata pubblicata). Gli esempi basati sul tempo sarebbero: il più veloce per generare risultati su hardware specifico (ad es. Particolare istanza EC2 / raspberry pi / ecc.), Output più compatto per una batteria di test entro un limite di tempo, la rete più grande supportata da una batteria di test all'interno di un limite di tempo (ad es. un giorno, che consente flessibilità sull'hardware specifico). Prova a usare la sandbox la prossima volta; le persone possono aiutarti a scegliere un obiettivo.
Dave,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.