Identificare insiemi di punti soddisfatti per via arborale


14

Un set di punti soddisfatto arboralmente è un set di punti 2D tale che, per qualsiasi rettangolo allineato all'asse che può essere formato usando due punti nel set come angoli opposti, quel rettangolo contiene o tocca almeno un altro punto. Ecco una definizione equivalente da Wikipedia:

Si dice che un insieme di punti sia soddisfatto arboralmente se vale la seguente proprietà: per qualsiasi coppia di punti che non si trovano entrambi sulla stessa linea orizzontale o verticale, esiste un terzo punto che si trova nel rettangolo attraversato dai primi due punti ( all'interno o al limite).

L'immagine seguente mostra come si formano i rettangoli. Questo set di punti NON è soddisfatto arboralmente perché questo rettangolo deve contenere almeno un altro punto.

inserisci qui la descrizione dell'immagine

Nell'arte ASCII, questo set di punti può essere rappresentato come:

......
....O.
......
.O....
......

Una leggera modifica può rendere questo arboralmente soddisfatto:

......
....O.
......
.O..O.
......

Sopra, puoi vedere che tutti i rettangoli (di cui ce n'è solo uno) contengono almeno tre punti.

Ecco un altro esempio di un insieme di punti più complesso che è soddisfatto arboralmente:

inserisci qui la descrizione dell'immagine

Per qualsiasi rettangolo che può essere disegnato su due punti, quel rettangolo contiene almeno un altro punto.

La sfida

Data una griglia rettangolare di punti (con cui rappresento O) e uno spazio vuoto (con cui rappresento .), genera un valore di verità se è soddisfatto arboralmente o un valore di falsa se non lo è. Questo è code-golf.

Regole aggiuntive:

  • Puoi scegliere di avere i personaggi Oe .scambiarli con qualsiasi altra coppia di caratteri ASCII stampabili. Basta specificare quale mappatura dei caratteri viene utilizzata dal programma.
  • La griglia sarà sempre rettangolare. È consentita una nuova riga finale.

Altri esempi

Arboralmente soddisfatto:

.OOO.
OO...
.O.OO
.O..O
....O

..O..
OOOO.
...O.
.O.O.
...OO

O.O.
..O.
OOOO
.O.O
OO..

...
...
...

...
..O
...

O.....
O.O..O
.....O

OOO.OO

Non soddisfatto dell'arboricamente:

..O..
O....
...O.
.O...
....O

..O..
O.OO.
...O.
.O.O.
...OO

O.....
..O...
.....O

1
Quindi non siamo autorizzati a prendere l'input come un elenco di coordinate anziché ASCII? In caso contrario, posso prendere l'input come un elenco 2D di numeri interi (0 e 1) per rappresentare i punti?
Denker,

La griglia può avere un'area 0?
feersum

Risposte:


7

Lumache , 29 30 39 byte

!{t\Oo\.+c\.,\O!{t\O{w!(.,~}2

Funziona tracciando 2 lati del rettangolo e quindi controllando se esiste un quadrato contenente una O tale che viaggiare su una linea retta dal quadrato in 2 delle direzioni cardinali comporterebbe di colpire un lato del rettangolo.

Stampa il massimo di 1 e l'area della griglia se l'ingresso è "soddisfatto per via arborale"; altrimenti 0.


3

Oracle SQL 11.2, 364 344 byte

WITH v AS(SELECT MOD(LEVEL-1,:w)x,FLOOR((LEVEL-1)/:w)y FROM DUAL WHERE'O'=SUBSTR(:g,LEVEL,1)CONNECT BY LEVEL<=LENGTH(:g))SELECT a.*,b.*FROM v a,v b WHERE b.x>a.x AND b.y>a.y MINUS SELECT a.*,b.*FROM v a,v b,v c WHERE((c.x IN(a.x,b.x)AND c.y>=a.y AND c.y<=b.y)OR(c.y IN(a.y,b.y)AND c.x>=a.x AND c.x<=b.x))AND(c.x,c.y)NOT IN((a.x,a.y),(b.x,b.y));

: g è la griglia come una stringa
: w è la larghezza della griglia

Restituisce nessuna riga come verità, restituisce i rettangoli che non corrispondono ai criteri come falsi

Un-golfed

WITH v AS
(
  SELECT MOD(LEVEL-1,:w)x,FLOOR((LEVEL-1)/:w)y,SUBSTR(:g,LEVEL,1)p 
  FROM   DUAL 
  WHERE  'O'=SUBSTR(:g,LEVEL,1)
  CONNECT BY LEVEL<=LENGTH(:g)
)
SELECT a.*,b.*FROM v a,v b
WHERE b.x>a.x AND b.y>a.y
MINUS
SELECT a.*,b.*FROM v a,v b,v c
WHERE((c.x IN(a.x,b.x) AND c.y>=a.y AND c.y<=b.y) OR (c.y IN(a.y,b.y) AND c.x>=a.x AND c.x<=b.x))
  AND(c.x,c.y)NOT IN((a.x,a.y),(b.x,b.y));

La vista v calcola le coordinate di ciascun punto O.
La prima parte del meno restituisce tutti i rettangoli, la clausola where assicura che un punto non possa essere accoppiato con se stesso.
La seconda parte cerca un terzo punto in ogni rettangolo. Quel punto deve avere una coordinata, x o y, uguale a quella coordinata per uno dei due punti che definiscono il rettangolo. L'altra coordinata di quel terzo punto deve trovarsi nell'intervallo delimitato da quella coordinata per ciascuno dei punti che definiscono il rettangolo.
L'ultima parte della clausola where assicura che il terzo punto non sia uno dei due punti che definiscono il rettangolo.
Se tutti i rettangoli hanno almeno un terzo punto, la prima parte del meno è uguale alla seconda parte e la query non restituisce nulla.


2

MATL , 38 byte

Ti2\2#fh!XJ"J@-XKtAZ)"@K-@/Eq|1>~As2>*

Questo utilizza un array di caratteri 2D come input, con le righe separate da ;. Quindi il primo esempio è

['......';'....O.';'......';'.O..O.';'......']

Il resto dei casi di test in questo formato sono i seguenti.

  • Arboralmente soddisfatto:

    ['.OOO.';'OO...';'.O.OO';'.O..O';'....O']
    ['..O..';'OOOO.';'...O.';'.O.O.';'...OO']
    ['O.O.';'..O.';'OOOO';'.O.O';'OO..']
    ['...';'...';'...']
    ['...';'..O';'...']
    ['O.....';'O.O..O';'.....O']
    ['OOO.OO']
    
  • Non soddisfatto arboralmente:

    ['..O..';'O....','...O.';'.O...';'....O']
    ['..O..';'O.OO.';'...O.';'.O.O.';'...OO']
    ['O.....';'..O...';'.....O']
    

Provalo online! Puoi anche verificare tutti i casi di test contemporaneamente .

Spiegazione

Il codice ottiene innanzitutto le coordinate dei caratteri Onell'input. Quindi utilizza due loop nidificati. Il ciclo esterno prende ciascun punto P (2-tupla delle sue coordinate), confronta con tutti i punti e mantiene i punti che differiscono da P nelle due coordinate. Questi sono i punti che possono formare un rettangolo con P. Chiamali set R.

L'anello interno preleva ciascun punto T da R e verifica se il rettangolo definito da P e T comprende almeno 3 punti. Per fare ciò, sottrae P da tutti i punti; cioè sposta l'origine delle coordinate su P. Un punto è nel rettangolo se ciascuna delle sue coordinate divisa per la coordinata corrispondente di T è nell'intervallo chiuso [0, 1].

T          % push "true"
i          % take input 2D array
2\         % modulo 2: gives 1 for 'O', 0 for '.'
2#f        % row and column coordinates of ones. Gives two column arrays
h!         % concatenate horizontally. Transpose. Each point is a column
XJ         % copy to clipboard J
"          % for each column
  J        %   push all points
  @-       %   subtract current point (move to origin)
  XK       %   copy to clipboard K
  tA       %   logical index of points whose two coordinates are non-zero
  Z)       %   keep only those points. Each is a column
  "        %   for each column (point)
    @K-    %     push that point. Subtract all others
    @/     %     divide by current point
    Eq|1>~ %     true if in the interval [0,1]
    A      %     true if that happens for the two coordinates
    s      %     sum: find out how many points fulfill that
    2>     %     true if that number is at least 3
    *      %     multiply (logical and). (There's an initial true value at the bottom)
           %   end
           % end
           % implicit display

Mi piaceva di più Don Muesli, perché l'hai cambiato? :(
Denker

@DenkerAffe :-) Bene, sono tornato al mio vero nome. L'altro era divertente, ma era inteso come temporaneo
Luis Mendo il

1
Questo non è un vero uomo di vita, qui abbiamo bisogno di più divertimento! :)
Denker

@DenkerAffe Potrei tornare a quel nome, o ad un altro, in futuro. Che ne dici di Denim Soul? MrGreen
Luis Mendo il

1
... e devi aspettare anche 30 giorni (credo)
Stewie Griffin

2

PHP, 1123 byte , 851 byte , 657 byte

(novizio php)

<?php
$B=array_map("str_split",array_map("trim",file('F')));$a=[];$b=-1;foreach($B as $c=>$C){foreach($C as $d=>$Z){if($Z=='O'){$a[++$b][]=$c;$a[$b][]=$d;}}}$e=array();foreach($a as $f=>$l){foreach($a as $g=>$m){$h=$l[0];$i=$l[1];$j=$m[0];$k=$m[1];if($h!=$j&&$i!=$k&&!(in_array([$g,$f],$e,1)))$e[]=[$f,$g];}}$A=array();foreach($e as $E){$n=$E[0];$o=$E[1];$q=$a[$n][0];$s=$a[$n][1];$r=$a[$o][0];$t=$a[$o][1];$u=($q<$r)?$q:$r;$v=($s<$t)?$s:$t;$w=($q>$r)?$q:$r;$X=($s>$t)?$s:$t;$Y=0;foreach($a as $p){$x=$p[0];$y=$p[1];if($x>=$u&&$x<=$w&&$y>=$v&&$y<=$X){$Y=($x==$q&&$y==$s)||($x==$r&&$y==$t)?0:1;}if($Y==1)break;}if($Y==1)$A[]=1;}echo count($A)==count($e)?1:0;

spiegazione (codice commentato):

<?php
//read the file
$lines=array_map("str_split",array_map("trim",file('F'))); // grid in file 'F'

//saving coords
$coords=[]; // new array
$iCoord=-1;
foreach($lines as $rowIndex=>$line) {
    foreach($line as $colIndex=>$value) {
        if ($value=='O'){
            $coords[++$iCoord][]=$rowIndex;//0 is x
            $coords[$iCoord][]=$colIndex;  //1 is y
        }
    }
}

/* for each point, draw as many rectangles as other points
 * without creating 'mirror' rectangles
 */ 
$rectangles=array();

foreach ($coords as $point1Index=>$point1) {
     //draw
     foreach ($coords as $point2Index=>$point2) {
            $point1X=$point1[0];
            $point1Y=$point1[1];
            $point2X=$point2[0];
            $point2Y=$point2[1];
            //if not on the same line or on the same column, ...
            if ($point1X!=$point2X &&   // same line
                $point1Y!=$point2Y &&   // same column
                !(in_array([$point2Index,$point1Index],$rectangles,true)) //... and if no 'mirror one' already
             ) $rectangles[]=[$point1Index,$point2Index]; //create a new rectangle
     }
 }

//now that we have rectangles and coords
//try and put a third point into each
$tests=array();
foreach ($rectangles as $rectangle) {
    $pointA=$rectangle[0];    // points of the rectangle
    $pointB=$rectangle[1];    // __________"____________
    $xA=$coords[$pointA][0];
    $yA=$coords[$pointA][1];
    $xB=$coords[$pointB][0];
    $yB=$coords[$pointB][1];
    $minX=($xA<$xB)?$xA:$xB;
    $minY=($yA<$yB)?$yA:$yB;
    $maxX=($xA>$xB)?$xA:$xB;
    $maxY=($yA>$yB)?$yA:$yB;

    $arborally=false;
    foreach ($coords as $point) {
        $x=$point[0];
        $y=$point[1];
        if ($x>=$minX &&
            $x<=$maxX &&
            $y>=$minY &&
            $y<=$maxY) {
                $arborally=($x==$xA&&$y==$yA) || ($x==$xB&&$y==$yB)?0:1; //same point (pointA or pointB)
        }     
        if ($arborally==true) break;//1 found, check next rectangle
    }
    if ($arborally==true) $tests[]=1;//array of successes

}

echo count($tests)==count($rectangles)?1:0; //if as many successes than rectangles...

?>

1

C, 289 byte

a[99][99],x,X,y,Y,z,Z,i,c;main(k){for(;x=getchar(),x+1;x-10||(y=0,i++))a[y++][i]=x;for(;X<i;X++)for(x=0;a[x][X]-10;x++)for(Y=X+1;Y<i;Y++)for(y=0;a[y][Y]-10;y++)if(x-y&&!(a[x][X]-79||a[y][Y]-79)){c=0;for(Z=X;Z<=Y;Z++)for(z=x<y?x:y;z<=(x>y?x:y);)a[z++][Z]-79||c++;c-2||(k=0);}putchar(k+48);}

Richiede newline finale, che è consentito (senza la nuova riga, il codice sarebbe più grande di due byte). Output 0 (non soddisfatto arboralmente) o 1 (soddisfatto arboralmente).

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.