Comprueba mis conjuntos de túneles

18

Imagine que tiene una matriz de enteros, cuyos valores no negativos son punteros a otras posiciones en la misma matriz, solo que esos valores representan túneles, por lo que si el valor en la posición A es positivo y apunta a la posición B, entonces el valor en la posición B también debe ser positivo y apuntar a la posición A para representar ambos extremos del túnel. Entonces:

Desafío

  • Dado un conjunto de enteros, verifique si el conjunto cumple con la restricción de ser un conjunto de túneles y devuelve dos valores distintos y coherentes para verdadero y falso.
  • Los valores en la matriz estarán por debajo de cero para las posiciones que no sean de túnel, y cero o más para las posiciones de túnel. Si su matriz está indexada en 1, entonces el valor cero representa una posición no túnel. Los valores que no son de túnel no necesitan ser verificados.
  • Si un valor positivo en una celda apunta a sí mismo, eso es falso. Si A apunta a B, B a C y C a A, eso es falso. Si un valor positivo apunta más allá de los límites de la matriz, eso es falso.

Ejemplos

Los siguientes ejemplos están indexados a 0:

[-1, -1, -1, 6, -1, -1, 3, -1, -1]  Truthy (position 3 points to position 6 and vice versa)
[1, 0]                              Truthy (position 0 points to position 1 and vice versa)
[0, 1]                              Falsey (positions 0 and 1 point to themselves)
[4, 2, 1, -1, 0, -1]                Truthy
[2, 3, 0, 1]                        Truthy
[1, 2, 0]                           Falsey (no circular tunnels allowed)
[-1, 2, -1]                         Falsey (tunnel without end)
[]                                  Truthy (no tunnels, that's OK)
[-1, -2, -3]                        Truthy (no tunnels, that's OK)
[1, 0, 3]                           Falsey (tunnel goes beyond limits)
[1]                                 Falsey (tunnel goes beyond limits)
[1, 0, 3, 7]                        Falsey (tunnel goes beyond limits)

Este es el , ¡así que puede ganar el código más corto para cada idioma!

Charlie
fuente
3
¿Para qué deberíamos regresar [0]?
ngn
1
Ampliando la pregunta de ngn, ¿se permiten túneles automáticos? ¿Cuáles serían los casos [0,1]y [0,-1,2]darían?
dylnan
1
@dylnan [0,1]está en los ejemplos. "Si un valor positivo en una celda apunta a sí mismo, eso es un error"
ngn
1
prueba sugerida:[2,3,0,1]
NGN
1
@JonathanAllan los valores del túnel son valores que indican posibles posiciones de la matriz. Si su matriz está indexada en 0, entonces cada valor por debajo de 0 no es un valor de túnel. Si está indexado en 1, cada valor por debajo de 1 no es un valor de túnel.
Charlie

Respuestas:

8

R , 47 bytes

function(v,a=v[v>0],b=sort(a))all(v[a]==b&a!=b)

Pruébalo en línea!


Código desenrollado y explicación:

f=
function(v){          # v vector of tunnel indexes (1-based) or values <= 0

  a = v[v>0]          # get the tunnel positions

  b = sort(a)         # sort the tunnel positions ascending

  c1 = v[a]==b        # get the values of 'v' at positions 'a'
                      # and check if they're equal to the sorted positions 'b'
                      # (element-wise, returns a vector of TRUE/FALSE)

  c2 = a != b         # check if positions 'a' are different from sorted positions 'b' 
                      # (to exclude tunnels pointing to themselves, element-wise,
                      #  returns a vector of TRUE/FALSE)

  all(c1 & c2)        # if all logical conditions 'c1' and 'c2' are TRUE then
                      # returns TRUE otherwise FALSE
}
digEmAll
fuente
Realmente agradecería una explicación para esta respuesta. :-)
Charlie
3
@Charlie: explicación agregada
digEmAll
5

APL (Dyalog Unicode) , 19 24 bytes

×/<∘≢⍨×≠∘⍳∘≢⍨×0∘>∨⊢=⊢⍳⍳⍨

Pruébalo en línea!

Prefijo lambda anónimo, devolviendo 1 para verdadero y 0 para falso. El enlace TIO contiene una versión "prettificada" de la salida para los casos de prueba.

Saludos a @ngn y @ Adám por guardar aproximadamente un bazillion de bytes.

Un agradecimiento adicional a @ngn por la ayuda con la solución de la respuesta para algunos casos de prueba y para convertirlo en un tren.

Los usos de respuestas actualizadas ⎕IO←0, preparando el I ndice O rigin a 0.

Cómo:

×/<∘≢⍨×≠∘⍳∘≢⍨×0∘>∨⊢=⊢⍳⍳⍨  Prefix lambda, argument   4 2 1 ¯1 0 ¯1.
                       ⍳⍨  Index of (⍳)  in ⍵. ⍵⍳⍵  0 1 2 3 4 3
                     ⊢⍳    Index of that in  (returns the vector length if not found). 
                           ⍵⍳⍵⍳⍵  4 2 1 6 0 6
                  ⊢=       Compare that with ⍵. ⍵=⍵⍳⍵⍳⍵  1 1 1 0 1 0
                           This checks if positive indices tunnel back and forth correctly.
                          Logical OR with
              0∘>          0>⍵  0 0 0 1 0 11 1 1 0 1 0  1 1 1 1 1 1
                           Removes the zeroes generated by negative indices
             ×             Multiply that vector with
                          (using  as both arguments)
         ⍳∘≢               Generate the range [0..length(⍵)-1]
       ≠∘                  And do ⍵≠range; this checks if any          
                           element in  is tunneling to itself.
                           ⍵≠⍳≢⍵  4 2 1 ¯1 0 ¯10 1 2 3 4 5  1 1 1 1 1 1  
      ×                    Multiply that vector with
                          (using  as both arguments)
  <∘≢                       < length(⍵)  4 2 1 ¯1 0 ¯1 < 6  1 1 1 1 1 1
                           This checks if any index is out of bounds
×/                         Finally, multiply and reduce.
                           ×/1 1 1 1 1 1  1 (truthy)
J. Sallé
fuente
Creo que esto no funciona para (1), (3 2 1), (5 4 3 2 1).
nwellnhof
0<×Creo
Uriel
4

JavaScript (ES6), 35 bytes

Guardado 1 byte gracias a @Shaggy

a=>a.every((v,i)=>v<0|v!=i&a[v]==i)

Pruébalo en línea!

Comentado

a =>                // a[] = input array
  a.every((v, i) => // for each value v at position i in a[]:
    v < 0 |         //   force the test to succeed if v is negative (non-tunnel position)
    v != i &        //   make sure that this cell is not pointing to itself
    a[v] == i       //   check the other end of the tunnel
  )                 // end of every()
Arnauld
fuente
Lo bueno es que verifiqué las soluciones antes de publicar un puerto de mi solución Japt, que es casi idéntico a esto. Puede guardar un byte con a=>a.every((v,i)=>v<0|v!=i&a[v]==i).
Shaggy
3

Perl 6 , 36 bytes

{!.grep:{2-set $++,$^v,.[$v]xx$v+1}}

Pruébalo en línea!

La idea básica es comprobar si el conjunto { i, a[i], a[a[i]] }contiene exactamente dos elementos distintos para cada índice icon a[i] >= 0. Si un elemento se señala a sí mismo, el conjunto contiene solo un único elemento distinto. Si el otro extremo no apunta hacia atrás i, el conjunto contiene tres elementos distintos. Si a[i] < 0, el xxfactor es cero o negativo, entonces el conjunto es { i, a[i] }, también con dos elementos distintos.

nwellnhof
fuente
3

MATL , 19 18 Bytes

-1 Byte gracias a Luis

n:G=GGG0>f))7M-|hs

Pruébalo en línea! , solo para el primero, ¡porque no sé cómo hacerlos todos!

Da 0si es verdadero, un número entero distinto de cero si es falso, por ejemplo. para el caso de prueba 6 da 4.

¡Recuerde que, al igual que MATLAB, MATL está indexado en 1, por lo que debe agregarse 1 a los casos de prueba!

Nunca jugué golf en un Esolang antes, ¡así que los consejos fueron muy bien recibidos!

Explicado:

n:G=GGG0>f))7M-|hs
                        Implicit - input array
n                       Number of values in array
 :                      Make array 1:n
  G                     Push input
   =                    Equality
n:G=                    Makes non-zero array if any of the tunnels lead to themselves
    GGG                 Push input 3x
       0                Push literal 0
        >               Greater than
      G0>               Makes array of ones where input > 0
         f              Find - returns indeces of non-zero values
                        Implicit - copy this matrix to clipboard
          )             Indeces - returns array of positive integers in order from input
           )            Ditto - Note, implicit non-zero any above maximum
            7M          Paste from clipboard
              -         Subtract
    GGG0>f))7M-         Makes array of zeros if only two-ended tunnels evident
               |        Absolute value (otherwise eg. [3,4,2,1] -> '0')
                h       Horizontal concat (ie. joins check for self tunnels and wrong tunnels)
                 s      Sum; = 0 if truthy, integer otherwise                 
Lui
fuente
¿Mi explicación es demasiado prolija? Quiero hacerlo obvio sin ir por la borda.
Lui
3

05AB1E , 16 15 14 bytes

εèNQyNÊ*y0‹~}P

-1 byte gracias a @Dorian .

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

ε               # Map each value `y` of the (implicit) input-list to:
 è              #   If the current value indexed into the (implicit) input-list
  NQ            #   is equal to the index
       *        #   And
    yNÊ         #   If the current value is not equal to the current index
           ~    #  Or if:
        y0     #   The current value is negative
            }P  # After the map: check if everything is truthy
                # (after which the result is output implicitly)
Kevin Cruijssen
fuente
Mi intento fue el mismo, excepto con filtro. No veo una manera de mejorar esto.
Emigna
1
14 bytes . Puede empujar el valor actual de εcon y. Así que no hay necesidad de ©, y cada uno ®reemplazado pory
Dorian
@Dorian Ah, por supuesto ... Eso no fue posible en el legado cuando publiqué esta respuesta, pero debería haberlo pensado cuando hice mi golf el día de hoy. ¡Gracias! :)
Kevin Cruijssen
2

Python, 112 97 96 86 bytes

f=lambda l:sum(i==l[i]or len(l)<=l[i]or 0<=l[i]and i!=l[l[i]]for i in range(len(l)))<1

Pruébalo en línea!

Devoluciones Trueo False.

-10 bytes gracias a @Rod y @TFeld.

DimChtz
fuente
2

Haskell , 48 bytes

(all=<< \u(x,y)->y<0||x/=y&&elem(y,x)u).zip[0..]

¡Verifique todos los casos de prueba!

Explicación

Primero eliminemos un poco el código. Como f =<< ges lo mismo \x -> f (g x) x, el código es equivalente a

(\u->all(\(x,y)->y<0||x/=y&&elem(y,x)u)u).zip[0..]

que es un poco más claro

(\u ->                                  -- given u, return
    all (\(x, y) ->                     -- whether for all elements (x, y) of u
            y < 0 ||                    -- either y < 0, or
            x /= y && elem (y, x) u     -- (x /= y) and ((y, x) is in u)
        )
    u
) . zip [0..]                           -- given the array a (implicitly via point-free style),
                                        -- return the array augmented with indices (it's the u above)

Esta solución se basa en una observación simple: deje que asea ​​la matriz de entrada y ula lista de pares (i, a[i])donde ihay un índice. Entonces aes una matriz válida si y sólo si para cada (x, y)en ucon y >= 0, el par (y, x)pertenece a utambién.

Delfad0r
fuente
2

Java (JDK) , 89 bytes

a->{int l=a.length,i=l;for(;i-->0;)i=a[i]<1||a[i]<l&&a[i]!=i&a[a[i]]==i?i:-2;return-2<i;}

Pruébalo en línea!

Créditos

Olivier Grégoire
fuente
Podría haber sido 87 bytes si no fuera por esa molesta IndexOutOfBoundsException. ¿Quizás ves algo para arreglarlo fácilmente?
Kevin Cruijssen
@KevinCruijssen Puedo ver cómo arreglar eso para 102 bytes . Nada más corto todavía :(
Olivier Grégoire
1
-3 bytes - omitir ry salir del bucle análogo a aquí
AlexRacer
1

Carbón , 22 bytes

¬Φθ∨⁼ικ¬∨‹ι⁰∧‹ιLθ⁼κ§θι

Pruébalo en línea! El enlace es a la versión detallada del código. Salidas -para la verdad y nada para la falsedad. Nota: Ingresar una matriz vacía parece bloquear el carbón, pero por ahora puede ingresar un espacio, que está lo suficientemente cerca. Explicación:

  θ                     Input array
 Φ                      Filter elements
     ι                  Current value
    ⁼                   Equals
      κ                 Current index
   ∨                    Or
       ¬                Not
          ι             Current value
         ‹ ⁰            Is less than zero
        ∨               Or
              ι         Current value
             ‹          Is less than
               L        Length of
                θ       Input array
            ∧           And
                  κ     Current index
                 ⁼      Equals
                   §θι  Indexed value
¬                       Logical Not (i.e. is result empty)
                        Implicitly print
Neil
fuente
Esto no parece ser un desafío muy recargable ... :-)
Charlie
1

Pascal (FPC) , 165 155 153 bytes

function f(a:array of int32):byte;var i:int32;begin f:=1;for i:=0to length(a)-1do if a[i]>-1then if(a[i]=i)or(a[i]>length(a))or(a[a[i]]<>i)then f:=0;end;

Pruébalo en línea!

Funcionó esta vez porque la entrada es matriz. Vuelve 1por veracidad y 0por falsey.

AlexRacer
fuente
1

Limpio , 60 bytes

import StdEnv
@l=and[v<0||l%(v,v)==[i]&&v<>i\\v<-l&i<-[0..]]

Pruébalo en línea!

Limpio , 142 bytes

Versión monstruosa extremadamente complicada:

import StdEnv,Data.List,Data.Maybe
$l=and[?i(mapMaybe((!?)l)j)j\\i<-l&j<-map((!?)l)l|i>=0]with?a(Just(Just c))(Just b)=a==c&&b<>c;?_ _ _=False

Pruébalo en línea!

Explicado:

$ l                           // function $ of `l` is
 = and [                      // true when all elements are true
  ?                           // apply ? to
   i                          // the element `i` of `l`
   (mapMaybe                  // and the result of attempting to
    ((!?)l)                   // try gettting an element from `l`
    j)                        // at the potentially invalid index `j`
   j                          // and `j` itself, which may not exist
  \\ i <- l                   // for every element `i` in `l`
  & j <- map                  // and every potential `j` in
    ((!?)l)                   // `l` trying to be indexed by
    l                         // every element in `l`
  | i >= 0                    // where `i` is greater than zero
 ]
with
 ? a (Just (Just c)) (Just b) // function ? when all the arguments exist
  = a==c && b<>c              // `a` equals `c` and not `b`
  ;
 ? _ _ _ = False              // for all other arguments, ? is false
Οurous
fuente
1

Pyth , 17 16 bytes

.A.e|>0b&nbkq@Qb

Pruébelo en línea aquí , o verifique todos los casos de prueba a la vez aquí .

.A.e|>0b&nbkq@QbkQ   Implicit: Q=eval(input())
                     Trailing k, Q inferred
  .e             Q   Map the input with b=element, k=index, using:
     >0b               0>b
    |                  OR (
         nbk           b != k
        &              AND
            q@Qbk      Q[b] == k)
.A                   Check if all elements are truthy

Editar: me di cuenta de que el k al final también era innecesario

Sok
fuente
0

Mathematica, 42 bytes

#=={}||(a=0@@#)[[#]]=!=a&&a[[#]][[#]]===a&

Pura función. Toma una lista de números indexados en 1 como entrada y devuelve Trueo Falsecomo salida. Simplemente sigue los túneles, asegurando que los 0mapas a 0, no existen 1 ciclos, y todos los ciclos son 2 ciclos. (No estoy completamente seguro de si esto falla en algún caso extremo, pero da los resultados correctos para los ejemplos).

LegionMammal978
fuente
0

Esta respuesta no funciona. Aquí solo con fines ilustrativos.

Esta respuesta pasa todos los casos de prueba (actualmente) publicados. Sin embargo, falla (genera un error) en otra entrada válida, como [1, 2]o [1, 0, 3, 7].

¿Cómo podría pasar [1, 0, 3]y fallar [1, 0, 3, 7]? Bueno, avanza por la lista, como era de esperar. Cuando lee un elemento xde la lista a, primero comprueba si xes menor len(a)e inmediatamente devuelve False, si es así. De modo que devuelve correctamente Falseen[1, 0, 3] , porque 3no es menos len(a).

Pero suponiendo que xpase esa verificación, el código pasará a hacer otras verificaciones y, en cierto momento, se evaluará a[a[x]]. Ya hemos garantizado que la evaluación a[x]estará bien ... pero no a[a[x]], lo que resuelve a[7]cuándo xestá 3en el[1, 0, 3, 7] ejemplo. En este punto, Python plantea un IndexError, en lugar de regresarFalse .

Para completar, aquí está la respuesta.

Python 2 , 59 bytes

lambda a:all(x<len(a)>-1<a[x]!=x==a[a[x]]for x in a if-1<x)

Pruébalo en línea!

Quería hacerlo x<len(a)and-1<a[x]..., pero por supuesto len(a)es siempre >-1, por lo que lo anterior es equivalente. Esta comprobación es un total de 5 relaciones encadenados ( <, >, <, !=, y ==), además de un cheque por separado -1<xen el ifestado.

Python (convenientemente) cortocircuita relaciones encadenadas como esta, por ejemplo, si x>=len(a)la verificación regresa Falseantes de llegar a[x](lo que de otro modo generaría un IndexError).

Mathmandan
fuente