Entrada ou saída sextavada?


8

uma grande história para contar sobre hexágonos comuns encontrados, por exemplo, em favos de mel. Mas essa abelha ocupada precisa de sua ajuda para dizer a ele que ponto está dentro ou fora de seu honeypot. Portanto, dado um hexágono regular, como mostrado na figura abaixo, centralizado na origem e com o tamanho da aresta l, determine se um conjunto de coordenadas (x, y) está dentro, exatamente na aresta ou fora do meu hexágono regular.

Hexágono com comprimento da aresta l, centrado na origem

Entrada, saída e regras

As regras são:

  • Os métodos de entrada e saída seguem as regras padrão .
  • Entrada consiste de três inteiros : x,y,l.
  • xe ysão de qualquer formato inteiro assinado e conveniente. lé positivo (nunca 0).
  • Seu programa deve gerar / retornar a 1se o ponto (x,y)estiver dentro do hexágono regular, -1se estiver fora ou 0se estiver exatamente no limite.
  • Este é um código de golfe, portanto o código mais curto vence. Em caso de empate, o primeiro post vence.
  • Para saída para stdout: são permitidos espaços à esquerda / à direita ou novas linhas na saída.
  • Aplicam-se brechas padrão.

Casos de teste

Aqui estão alguns casos de teste:

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

Presumo que este seja um hexágono regular, mas você deve explicitar isso.
Level River St

@LevelRiverSt sim. Um regular. Vou acrescentar isso em um momento.
agtoever

1
Podemos tomar x, y como um número complexo x + yi?
lirtosiast


@Lirtosiast, a pergunta é sobre um hexágono no plano euclidiano, não no plano complexo. Por causa dessa entrada complexa, não é permitido.
agtoever

Respostas:


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

Teste

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>


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}

Alterou a comparação tripla com um foguete.

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}

Remova o teste y igual ao apótema para pontos no hexágono, pois para números inteiros isso nunca pode ser verdade.

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}

O pôster sugeria não usar o epsilon, então substituiu o epsilon por zero e reorganizou, removeu um abdômen, 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 na definição de z e remova alguns parênteses.

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}

Termos reorganizados para evitar a necessidade de converter to_f. Use d (dobre o apótema) em vez de a (o apótema). Combine várias atribuições.

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}

Inline '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))))}

Isso funciona para números inteiros ou flutuantes! O teste epsilon é para que os pontos dentro do erro de arredondamento de estar na borda sejam corretamente identificados.

Os valores absolutos movem tudo para o quadrante um.

O valor 'a' é a distância do apótema (a interceptação em y do hexágono).

O valor 'c' é o valor x do canto superior direito do hexágono.

O valor 'z' é para ver se o ponto está acima ou abaixo da linha inclinada do canto até a interceptação x.

Ungolfed:

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
}

Teste

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!"

Isso pode ser mais curto, você não precisa do epsilon para inteiros
edc65

Ao introduzir a raiz quadrada de três, sou forçado a usar o ponto flutuante. Eu poderia arredondar os números antes da comparação ou usar cálculos epsilon. Como o epsilon permite que o código seja mais geral e funcione para carros alegóricos, deixei no epsilon. Estou apenas programando Ruby há um tempo, então não tenho certeza de como ele lida com erros de arredondamento.
Paul Chernoch 11/03/16

A inclinação do lado esquerdo e direito não é racional. O apotema não é racional. O são apenas dois pontos com coordenadas de número inteiro situados no perímetro: [l, 0] e [l, 0]
edc65

Você provavelmente está certo que, para entradas inteiras, não existem outros pontos inteiros possíveis que estejam "no" hexágono. Provar isso para mim foi mais difícil do que fazer o código não se importar, usando epsilon.
Paul Chernoch

sim! Acabei de passar a solução Python!
Paul Chernoch 11/03/16


0

Julia, 65 58 bytes

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

xé um vetor de linha [x y]. Chamada assim: f([0 0],1).


0

Python 2, 89 bytes

quase a mesma solução que a resposta de Julia, mas podemos usar a operação no vetor sem adormecer

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]


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 atribuir isso a uma variável para que você possa chamá-la, coloque f=depois de with(Math).

Eu usei l*le b*bno primeiro parâmetro para minevitar chamadas para abse sqrt, mas não consegui descobrir se eu poderia fazer um truque semelhante com o segundo parâmetro.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.