¿Hexágono de entrada o hexágono de salida?

8

Hay una gran historia que contar sobre los hexágonos regulares que se encuentran, por ejemplo, en los panales. Pero esta abeja ocupada necesita tu ayuda para decirle qué punto está dentro o fuera de su honeypot. Entonces, dado un hexágono regular como se muestra a continuación, centrado en el origen y con el tamaño de borde l, determine si hay un conjunto de coordenadas (x, y) dentro, exactamente en el borde o fuera de mi hexágono regular.

Hexágono con longitud de borde l, centrado en el origen

Entrada, salida y reglas.

Las reglas son:

  • Los métodos de entrada y salida siguen las reglas predeterminadas .
  • La entrada consiste en tres números enteros : x,y,l.
  • xy yson de cualquier formato entero con signo conveniente. les positivo (nunca 0).
  • Su programa debe generar / devolver a 1si el punto (x,y)está dentro del hexágono regular, -1si está afuera o 0si está exactamente en el borde.
  • Este es un código de golf, por lo que gana el código más corto. En caso de empate, el primer puesto gana.
  • Para salida a stdout: se permiten espacios iniciales / finales o nuevas líneas en la salida.
  • Se aplican lagunas estándar.

Casos de prueba

Aquí hay algunos casos de prueba:

0,0,1        --> 1
0,1,1        --> -1
0,-1,1       --> -1
1,0,1        --> 0
-1,0,1       --> 0
-1,-1,1      --> -1
1,1,1        --> -1
-2,-3,4      --> 1
32,45,58     --> 1
99,97,155    --> -1
123,135,201  --> 1
en cualquier lugar
fuente
Supongo que este es un hexágono regular, pero debes hacerlo explícito.
Level River St
@LevelRiverSt sí. Un habitual. Agregaré eso en un momento.
agtoever
1
¿Podemos tomar x, y como un número complejo x + yi?
lirtosiast
@lirtosiast la pregunta es sobre un hexágono en el plano euclidiano, no en el plano complejo. Debido a que la entrada compleja no está permitida.
agtoever

Respuestas:

2

JavaScript (ES6) 77 83

(a,b,l,h=Math.sqrt(3)*l,x=a<0?-a:a,y=b<0?-b:b)=>y|x!=l?2*y<h&x/l+y/h<1?1:-1:0

Prueba

f=(a,b,l,h=Math.sqrt(3)*l,x=a<0?-a:a,y=b<0?-b:b)=>y|x!=l?2*y<h&x/l+y/h<1?1:-1:0

// TEST

function go() {
  C.width=400;C.height=300;
  var l=+I.value, x,y, cols={0:'#ff0',1:'#0f0','-1':'#888'},
  ctx = C.getContext("2d")
  ctx.translate(200,150)
  ctx.strokeStyle='#000'
  ctx.lineWidth=1;
  ctx.beginPath();
  ctx.moveTo(0,-150);ctx.lineTo(0,150);ctx.moveTo(-200,0);ctx.lineTo(200,0);
  ctx.stroke();
  ctx.strokeStyle='#f00'
  ctx.beginPath();
  ctx.moveTo(l*10,0);ctx.lineTo(l*5,l*Math.sqrt(3)*5);ctx.lineTo(-l*5,l*Math.sqrt(3)*5)
  ctx.lineTo(-l*10,0);ctx.lineTo(-l*5,-l*Math.sqrt(3)*5);ctx.lineTo(l*5,-l*Math.sqrt(3)*5)
  ctx.closePath();
  ctx.stroke();

  for(y=-14;y<15;y++)
    for(x=-19;x<20;x++) {
      ctx.beginPath();
      ctx.moveTo(x*10,y*10-3);ctx.lineTo(x*10,y*10+3);
      ctx.moveTo(x*10-3,y*10);ctx.lineTo(x*10+3,y*10);
      ctx.strokeStyle=cols[f(x,y,l)]
      ctx.stroke()
    }
}

go()
#C {
  border: 1px solid #000
}
<b>L</b> <input id=I value=15><button onclick="go()">GO</button><br>
<canvas id=C width=400 height=300></canvas>

edc65
fuente
2

Ruby, 150 145 137 127 125 106 88 76 bytes

76 bytes

->(x,y,l){x,y,t=x.abs,y.abs,3**0.5;d=t*l;z=d-t*x-y;2*y>d ?-1:2*x<l ?1:z<=>0}

Se cambió la triple comparación a un cohete.

88 bytes

->(x,y,l){x,y,t=x.abs,y.abs,3**0.5;d=t*l;z=d-t*x-y;2*y>d ?-1:2*x<l ?1:z==0 ?0:0<z ?1:-1}

Elimine la prueba y igual a apotema para puntos en el hexágono, porque para enteros, eso nunca puede ser cierto.

106 bytes:

->(x,y,l){x,y,t=x.abs,y.abs,3**0.5;d=t*l;z=d-t*x-y;2*y==d&&2*x<=l ?0:2*y>d ?-1:2*x<l ?1:z==0 ?0:0<z ?1:-1}

El póster sugirió no usar epsilon, por lo que reemplazó epsilon con cero y se reorganizó, eliminó un abs, etc.

125 bytes:

->(x,y,l){x,y,t,e=x.abs,y.abs,3**0.5,1e-9;d=t*l;z=d-t*x-y;(2*y-d).abs<=e&&2*x<=l ?0:2*y>d ?-1:2*x<l ?1:z.abs<=e ?0:0<z ?1:-1}

Incorpore y en la definición de z y elimine algunos paréntesis.

127 bytes:

->(x,y,l){x,y,t,e=x.abs,y.abs,3**0.5,1e-9;d=t*l;z=d-t*x;(2*y-d).abs<=e&&2*x<=l ?0:2*y>d ?-1:2*x<l ?1:(z-y).abs<=e ?0:y<z ?1:-1}

Términos reordenados para evitar la necesidad de to_f cast. Use d (doble apotema) en lugar de a (la apotema). Combina múltiples tareas.

137 bytes:

->(x,y,l){x=x.abs.to_f;y=y.abs.to_f;a=3**0.5*l/2;e=1e-9;z=2*a*(1-x/l);(y-a).abs<=e&&2*x<=l ?0:y>a ?-1:2*x<l ?1:(z-y).abs<=e ?0:y<z ?1:-1}

En línea 'c'.

150 bytes:

->(x,y,l){c=l/2.0;x=x.abs.to_f;y=y.abs.to_f;a=3**0.5*l/2;e=1e-10;z=2*a*(1-x/l);(y-a).abs<=e&&x<=c ?0:(y>a ?-1:(x<c ?1:((z-y).abs<=e ?0:(y<z ?1:-1))))}

¡Esto funciona para enteros o flotadores! La prueba epsilon es para identificar correctamente los puntos dentro del error de redondeo de estar en el borde.

Los valores absolutos mueven todo al cuadrante uno.

El valor 'a' es la distancia apotema (la intersección en y del hexágono).

El valor 'c' es el valor x de la esquina superior derecha del hexágono.

El valor 'z' es para ver si el punto está por encima o por debajo de la línea inclinada desde la esquina hasta la intersección con el eje x.

Sin golf:

hex = ->(x,y,l){ 
    c = l/2.0;
    x = x.abs.to_f;
    y = y.abs.to_f;
    a = 3**0.5 * l / 2;
    e = 1e-10;
    z = 2*a*(1 - x/l);
    if (y-a).abs <= e && x <= c then 0
    elsif (y>a) then -1
    elsif (x<c) then 1
    elsif (z-y).abs <= e then 0
    elsif y < z then 1
    else -1
    end
}

Prueba

hex = ->(x,y,l){x,y,t=x.abs,y.abs,3**0.5;d=t*l;z=d-t*x-y;2*y>d ?-1:2*x<l ?1:z<=>0}

cases = [
    [0,0,1,1],
    [0,1,1,-1],
    [0,-1,1,-1],
    [1,0,1,0],
    [-1,0,1,0],
    [-1,-1,1,-1],
    [1,1,1,-1],
    [-2,-3,4,1],
    [32,45,58,1],
    [99,97,155,-1],
    [123,135,201,1]
]

cases.each { |test| 
  expected = test[3]
  actual = hex.call(test[0],test[1],test[2])
  status = expected == actual ? "PASS" : "FAIL";
  p "#{status}. #(x,y) L = (#{test[0]},#{test[1]}) #{test[2]} Expects #{expected}. Actual #{actual}"
}
"Done!"
Paul Chernoch
fuente
Esto podría ser más corto, no necesita el épsilon para enteros
edc65
Al introducir la raíz cuadrada de tres, me veo obligado a usar coma flotante. Podría redondear los números antes de la comparación, o usar cálculos epsilon. Como epsilon permite que el código sea más general y funcione para flotadores, lo dejé en epsilon. Solo he estado programando Ruby por un tiempo breve, así que no estoy seguro de cómo lidiar con los errores de redondeo.
Paul Chernoch
La pendiente del lado izquierdo y derecho no es racional. El apotema no es racional. Son solo 2 puntos con coordenadas enteras en el perímetro: [l, 0] y [-l, 0]
edc65
Probablemente tenga razón en que para entradas enteras no hay otros posibles puntos enteros que estén "en" el hexágono. Probar eso para mí fue más difícil que hacer que el código no me importara, usando epsilon.
Paul Chernoch
¡Si! ¡Acabo de pasar la solución Python!
Paul Chernoch
0

Julia, 65 58 bytes

f(x,l)=(t=maxabs(x/l*[[0 1 1];[2 1 -1]/3^.5]);(t<1)-(t>1))

xes un vector fila [x y]. Llamar así: f([0 0],1).

Rainer P.
fuente
0

Python 2, 89 bytes

casi la misma solución que la respuesta de Julia, pero podemos usar la operación en vector sin numpy

lambda x,y,L,K=3**0.5/2.:cmp(K*L,max([abs(x*i+y*j)for i,j in[[K,1/2.],[0,1],[-K,1/2.]]]))

Resultados

>>> f(0,0,1)
1
>>> f(32,45,58)
1
>>> f(99,97,155)
-1
>>> f(-1,0,1)
0
>>> [f(0,0,1)== 1,f(0,1,1)== -1,f(0,-1,1)== -1,f(1,0,1)== 0,f(-1,0,1)== 0,f(-1,-1,1)== -1,f(1,1,1)== -1,f(-2,-3,4)== 1,f(32,45,58)== 1,f(99,97,155)== -1,f(123,135,201)== 1,f(0,0,1)== 1,f(0,1,1)== -1,f(0,-1,1)== -1,f(1,0,1)== 0,f(-1,0,1)== 0,f(-1,-1,1)== -1,f(1,1,1)== -1,f(-2,-3,4)== 1,f(32,45,58)== 1,f(99,97,155)== -1,f(123,135,201)== 1]
[True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True, True]
Erwan
fuente
0

JavaScript (ES6), 67 bytes

with(Math)(a,b,l)=>sign(min(l*l*3-b*b*4,(l-abs(a))*sqrt(3)-abs(b)))

Nota: Para asignar esto a una variable para que pueda llamarla, coloque f=después de with(Math).

Utilicé l*ly b*ben el primer parámetro para minevitar llamadas a absy sqrtpero no pude determinar si podría hacer un truco similar con el segundo parámetro.

Neil
fuente