Grafici di spazio negativo


13

Compito

Ti verrà dato un numero intero positivo e devi generare un " grafico auto-complementare " con quel numero di nodi. Se non sai cosa sia un grafico auto-complementare l'articolo di Wikipedia non ti aiuterà molto, quindi di seguito sono riportate due spiegazioni, una tecnica e una non tecnica.

Non tecnico

Un grafico è un insieme di nodi collegati da linee. Ogni coppia di punti può essere collegata da una linea o nessuna. Il "complemento" di un grafico è il risultato della presa di un grafico e della connessione di tutti i nodi non connessi e della disconnessione di tutti i nodi che lo sono.

Un grafico auto-complementare è un grafico il cui complemento può essere riorganizzato nella forma dell'originale. Di seguito è riportato un esempio di un grafico auto-complementare e una dimostrazione di come.

Ecco un grafico con 5 nodi:

Grafico a 5 nodi

Evidenzieremo tutti i luoghi in cui le connessioni potrebbero andare con linee tratteggiate rosse:

Grafico evidenziato

Ora troveremo il complemento del grafico scambiando i bordi rosso e nero:

Complemento

Questo non sembra il grafico originale, ma se spostiamo i nodi in questo modo (ogni passaggio scambia due nodi):

Isomorfismo

Otteniamo il grafico originale! Il grafico e il suo complemento sono lo stesso grafico

Tecnico

Un grafico auto-complementare è un grafico isomorfo al suo complemento.

specificazioni

Riceverai un numero intero positivo tramite il metodo più adatto a te. E otterrai un grafico in qualunque metodo tu ritenga opportuno, questo include ma non è limitato a Modulo matrice adiacenza , Modulo elenco adiacenza e, naturalmente, immagini! Il grafico generato deve essere il proprio complemento e avere tanti nodi quanti l'input intero. Se tale grafico non esiste, è necessario generare un valore errato.

Questo è e dovresti mirare a ridurre al minimo il numero di byte.

Casi test

Di seguito sono riportate le immagini delle possibili uscite per diversi n

4

5

9


Un grafico auto-complementare può esistere solo dove il grafico completo ha un numero pari di bordi. Questo è garantito?
xnor

@xnor Ho dimenticato di includerlo. Riparato ora.
Post Rock Garf Hunter,

Dobbiamo gestire input negativi?
xnor

@xnor No. Risolverò la questione come congruente
Post Rock Garf Hunter,

3
Prima che qualcuno abbia l'idea di basare una risposta GraphData@{"SelfComplementary",{#,1}}&, credo che semplicemente carichi alcuni esempi di bassi ndal database di Wolfram, quindi questo non funzionerà per input arbitrariamente grandi.
Martin Ender,

Risposte:


9

Haskell , 77 byte

f n=[(a,b)|b<-[1..n],a<-[1..b-1],mod n 4<2,mod(a+(last$b:[a|odd n,n==b]))4<2]

Provalo online!

Questo utilizza un criterio esplicito facile da calcolare per decidere se un bordo (a,b)appartiene al grafico. Crea un'istanza di questo algoritmo , con il ciclo di permutazione tra i valori modulo 4

4*m -> 4*m+1 -> 4*m+2 -> 4*m+3 -> 4*m

Includiamo i bordi i cui due vertici dell'endpoint si aggiungono a 0 o 1 modulo 4. Si noti che i vertici ciclici secondo questa permutazione aggiungono 2 moduli 4 alla somma dei vertici su ciascuno di essi, quindi scambia bordi e non bordi. Questo dà una permutazione dei vertici che completa i bordi.

Se il grafico ha un nodo aggiuntivo oltre un multiplo di 4, viene inserito in un ciclo da solo. Includiamo i bordi con esso quando poi un altro vertice è pari. Permutare i vertici inverte la parità e quindi il grafico rimane auto-complementare.

Se il numero di vertici non è 0 o 1 modulo 4, non è possibile un grafico auto-complementare perché c'è un numero dispari di spigoli nel grafico completo

Nel complesso, ecco le condizioni:

  • Se l'ingresso n non è 0 o 1 modulo 4, genera un elenco vuoto
  • Altrimenti se n è pari, includere tutti i bordi (a,b)con a<be a+buguale a 0 o 1 modulo 4.
  • Altrimenti, se n è dispari, fai lo stesso, ma includi invece i bordi del modulo (a,n)quando a è pari.

Il codice combina il secondo e il terzo caso sostituendo la condizione mod(a+b)4<2con mod(a+a)4<2quando entrambi odd ne b==n.


5

Brachylog 2 , 24 byte

{⟦₁⊇Ċ}ᶠpḍ.(\\ᵐcdl?∨?<2)∧

Provalo online!

Questa è una funzione che restituisce una coppia composta da due elenchi di adiacenza: uno per il grafico, uno per il grafico del complemento. (Nell'interprete Brachylog su TIO, puoi chiedergli di valutare una funzione, piuttosto che un programma completo, tramite il dare Zcome argomento da riga di comando.) Ad esempio, l'output per l'input 5è:

[[[1,2],[1,3],[1,5],[3,5],[4,5]],[[2,5],[2,3],[2,4],[3,4],[1,4]]]

Ecco come appare un'immagine (mostrando i due grafici):

un grafico e il suo identico complemento su 5 elementi

Come è comune nei linguaggi basati su Prolog, la funzione supporta più di un modello di chiamata. In particolare, se provi a usarlo come generatore, produrrà tutti i possibili grafici auto-complementari con il numero dato di vertici (anche se non ho fatto alcuno sforzo per rendere utilizzabile questo caso, e in particolare produrrà ciascuno di i grafici più volte ciascuno).

Spiegazione

Questa è fondamentalmente solo una descrizione del problema, lasciando l'implementazione di Prolog per trovare il metodo migliore per risolverlo. (Tuttavia, dubito che utilizzerà un algoritmo migliore della forza bruta in questo caso particolare, quindi è probabilmente abbastanza inefficiente e i test sembrano confermarlo, mostrando che le prestazioni peggiorano tanto più grande è il grafico.)

{⟦₁⊇Ċ}ᶠpḍ.(\\ᵐcdl?∨?<2)∧
 ⟦₁                       The range [1, 2, …, ?], where ? is the input
   ⊇                      A subset of that range…
    Ċ                     …which has exactly two elements
{    }ᶠ                   A list of everything that fits the above description
{⟦₁⊇Ċ}ᶠ                   All edges that could exist in a ?-element graph
       p                  Find a permutation of these…
        ḍ                 …so that splitting it into two equal parts…
          (       ∨   )   …either:
               dl?          produces ? distinct elements
           \                after transposing it
            \ᵐ              and transposing its elements
              c             and flattening one level;
                          or:
                   ?<2      ? was less than 2
         .             ∧  Once you've found it, . specifies what to output

Per inciso, ho finito per dover spendere un totale di 6 byte (¼ del programma, i personaggi (∨?<2)) affrontando i casi speciali di 0 e 1. Frustrante, ma questa è la natura dei casi speciali.

La \\ᵐcdl?sezione è un po 'difficile da capire, quindi ecco un esempio funzionante. Il suo scopo è verificare se qualcosa è un grafico e il suo complemento, con i bordi corrispondenti nel grafico e il complemento nello stesso ordine all'interno degli elenchi. La coppia grafico / complemento diventa l'output finale del programma. Ecco un esempio:

[[[1,2],[1,3],[1,5],[3,5],[4,5]],[[2,5],[2,3],[2,4],[3,4],[1,4]]]

La trasposizione di questo ci dà un elenco di coppie di spigoli corrispondenti tra il grafico e il complemento:

[[[1,2],[2,5]],[[1,3],[2,3]],[[1,5],[2,4]],[[3,5],[3,4]],[[4,5],[1,4]]

Successivamente, trasponiamo all'interno degli elementi dell'elenco e appiattiamo un livello; che ci fornisce un elenco di coppie di elementi corrispondenti tra il grafico e il complemento:

[[1,2],[2,5],[1,2],[3,3],[1,2],[5,4],[3,3],[5,4],[4,1],[5,4]]

Chiaramente, ciò che vogliamo qui è che non ci sia più di 1 coppia a partire da ciascun elemento (dimostrando così che gli elementi del grafico e del complemento sono in corrispondenza 1: 1). Possiamo quasi verificarlo affermando che l'elenco ha ?elementi esattamente distinti (cioè un numero di elementi distinti pari al numero di vertici). In questo caso, il test ha esito positivo; gli elementi distinti sono:

[[1,2],[2,5],[3,3],[5,4],[4,1]]

Tuttavia, ciò lascia spazio a un potenziale problema; se un vertice è completamente disconnesso nel grafico originale, la sua corrispondenza non verrà menzionata, lasciando spazio a una corrispondenza duplicata da qualche altro vertice. Se questo è il caso, il grafico complemento deve avere un bordo tra cui vertice (senza perdita di generalità, diciamo che è 1), e ogni altro vertice, e così la lista delle corrispondenze conterrà [1,2], [1,3], ..., [1, ?]. Quando ?è grande, questo porterà a più corrispondenze totali di quante non avremmo altrimenti, quindi non c'è problema. L'unico problema si verifica quando ?è 3 o inferiore, nel qual caso finiamo per aggiungere solo una corrispondenza aggiuntiva (rimuovendone una da1non appare nell'input); tuttavia, questo non è un problema in pratica, perché ci sono 3 possibili bordi su un grafico a 3 elementi, che è un numero dispari (allo stesso modo, 1 possibile bordo su un grafico a 2 elementi è anche un numero dispari), e quindi il il test fallirà al \passaggio (non è possibile trasporre un elenco irregolare, ovvero quelli i cui elementi hanno lunghezze diverse).


La differenza tra zed \è che zè zip ciclico, il che significa che [[1,2,3],["a"]]finirà per essere [[1,"a"],[2,"a"],[3,"a"]]con z, mentre fallirà per \. \in questo momento funziona solo su matrici quadrate; l'implementazione futura lo farà funzionare come z, se non ciclicamente.
Fatalizza il

In realtà avevo capito la differenza da solo, ma solo dopo aver scritto la spiegazione. Questa particolare soluzione dipende da `` lavorare solo sui rettangoli (anche se ci vogliono solo 2 byte in più se non puoi trarre vantaggio da quel passaggio).

2

BBC BASIC, 161 byte

Dimensione dei file con token 140 byte

Scarica l'interprete su http://www.bbcbasic.co.uk/bbcwin/bbcwin.html

I.m:IF2ANDm ORm<4P.0:END
r=400n=-2A.m:t=2*PI/n:F.i=1TOn*n:a=i DIVn:b=i MODn:c=b:IFa+b A.2a*=t:b*=t:L.r+r*SINa,r+r*COSa,r+r*SINb,r+r*COSb:IF 1A.m A.c DRAWr*3,0
N.

Codice Ungolfed

  INPUTm                           :REM get input
  IF2ANDm ORm<4PRINT0:END          :REM if m=4x+2 or 4x+3 or less than 4, print 0 and exit
  r=400                            :REM radius of diagram
  n=-2ANDm                         :REM n = m truncated to an even number
  t=2*PI/n                         :REM t = 1/n turns
  FORi=1TOn*n                      :REM for each combination of vertices
    a=i DIVn                       :REM extract a and b
    b=i MODn                       :REM make a copy of c
    c=b                            :REM if a+b MOD 4 = 2 or 3, convert a and b to angles and draw edge.
    IFa+b AND2 a*=t:b*=t:LINEr+r*SINa,r+r*COSa,r+r*SINb,r+r*COSb:IF 1ANDm ANDc DRAWr*3,0
  NEXT                             :REM if m is odd and c is odd, draw a line to the additional vertex for m=4x+1 input.

Spiegazione

Questo utilizza lo stesso algoritmo di Xnor, ma produce un output schematico.

Dove si ntrova il modulo 4x+2o 4x+3non esiste una soluzione poiché il numero di spigoli è dispari.

Dove nè della forma 4x disponiamo tutti i vertici in un cerchio e disegniamo quei bordi dove (a+b) mod 4è 2 o 3 (non 0 o 1 come nel caso di Xnor, per ragioni di golf. Questo è quindi il complemento della soluzione data da Xnor.)

Per vederlo in un senso più pittorico, prendiamo ogni secondo vertice e disegniamo i bordi sui vertici 1 e 2 posti in senso antiorario. Questo definisce ndirezioni parallele, metà del totale. Quindi aggiungiamo tutti gli altri bordi paralleli a questi.

Il complemento può essere trovato aggiungendo 1 sia a che b in ciascuna specifica del bordo, oppure pittoricamente ruotando il diagramma di un 1/ngiro.

Dov'è ndella forma 4x + 1 aggiungiamo un altro vertice, che è collegato ad ogni secondo vertice del grafico 4x. Se fosse posizionato al centro, la simmetria del diagramma verrebbe preservata, ma ho scelto di posizionarlo al di fuori del cerchio principale di punti per maggiore chiarezza.

Produzione

Di seguito sono riportati i primi casi per 4x + 1. i casi 4x possono essere visti cancellando il vertice in basso a destra e i suoi bordi associati.

inserisci qui la descrizione dell'immagine


1

JavaScript (ES6), 191 byte

f=(n,a=[],v=n*~-n/4)=>v%1?0:eval(n>5?f(n-=4,a)&&'for(i=0;i<n;)a.push([i,n+1],[i++,n+2]);a.push([n,++n],[n,++n],[n,++n])-v':'for(l=x=0;x<n;x++)for(y=x;y<n;y++)l<v&y>>x&1?l=a.push([x,y]):a')||a

Questa funzione restituisce un elenco di adiacenza. Utilizza due algoritmi e differenzia tra grafici complementari vuoti e non output restituendo 0invece che []quando non esiste. Il primo algoritmo si basa sui grafici Rado costruiti utilizzando il predicato BIT e crea grafici complementari validi per 0, 1, 4 e 5 ordini. L'altro algoritmo, trovato dai nostri amici in matematica , costruisce un grafico complementare vertice V + 4 valido applicando un'aggiunta di 4 percorsi a un grafico complementare vertice V valido.

Inizia convalidando l'input per confermare l'esistenza di un grafico complementare valido (usando n*~-n/4%1) e, se fallisce, ritorna 0. Quindi controlla se n>5e fa ricorso al n-4caso per costruire una valida soluzione di ordine inferiore, quindi applica l'aggiunta 4 all'elenco di adiacenza restituito sulla via del backup della catena di ricorsione. Infine, se n>5non è vero, scorre da 0a n-1per xe ye controlla se (y>>x)&1è vero. In tal caso, tali nodi vengono accoppiati.

Ecco un formato più leggibile della funzione, con operatori ternari espansi in istruzioni if-else e in eval()linea:

// precalculate amount of required vertices in v
f = (n, a = [], v = n*~-n / 4) => {
  // if amount is non-integer
  if (v % 1) {
    // no valid complementary graph
    return 0;
  } else {
    if (n > 5) {
      // generate valid (n-4)-order complementary graph
      f(n -= 4, a);
      // apply 4-path addition
      for (i = 0; i < n;)
        a.push([i, n+1],[i++, n+2]);
      a.push([n, ++n], [n, ++n], [n, ++n]);
    } else {
      // construct Rado graph using BIT predicate
      for(l = x = 0; x < n; x++)
        for(y = x; y < n; y++)
          // if amount of pairs is less than required and xth bit of y is high
          if (l < v && (y>>x & 1))
            // vertices x and y should be paired
            a.push([x,y]);
    }
    return a;
  }
};

dimostrazione

f=(n,a=[],v=n*~-n/4)=>v%1?0:eval(n>5?f(n-=4,a)&&'for(i=0;i<n;)a.push([i,n+1],[i++,n+2]);a.push([n,++n],[n,++n],[n,++n])-v':'for(l=x=0;x<n;x++)for(y=x;y<n;y++)l<v&y>>x&1?l=a.push([x,y]):a')||a
<input type="number" onchange="o.textContent=JSON.stringify(f(this.value))"><pre id="o"></pre>

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.