Hexagon-In atau Hexagon-Out?

8

Ada kisah hebat untuk diceritakan tentang segi enam reguler yang ditemukan misalnya di sarang madu. Tetapi lebah yang sibuk ini membutuhkan bantuan Anda untuk memberi tahu dia titik mana di dalam atau di luar honeypot-nya. Jadi, diberi segi enam biasa seperti gambar di bawah, berpusat di titik asal dan dengan ukuran tepi l, tentukan apakah satu set koordinat (x, y) ada di dalam, tepatnya di tepi atau di luar segi enam biasa.

Hexagon dengan panjang tepi l, berpusat di titik asal

Input, output, dan aturan

Aturannya adalah:

  • Metode input dan output mengikuti aturan default .
  • Masukan terdiri dari tiga bilangan bulat : x,y,l.
  • xdan ymerupakan format integer bertanda tangan yang nyaman. lpositif (tidak pernah 0).
  • Program Anda harus menampilkan / mengembalikan a 1jika titik (x,y)tersebut berada di dalam segi enam biasa, -1jika di luar atau 0jika tepat di tepi.
  • Ini adalah kode-golf, sehingga kode terpendek menang. Dalam hal seri, pos paling awal menang.
  • Untuk output ke stdout: diizinkan spasi / spasi tambahan atau baris baru dalam output diizinkan.
  • Celah standar berlaku.

Uji kasus

Berikut ini beberapa kasus uji:

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
agtoever
sumber
Saya berasumsi ini adalah segi enam biasa, tetapi Anda harus membuatnya eksplisit.
Level River St
@LevelRiverSt ya. Biasa. Saya akan menambahkan itu sebentar lagi.
agtoever
1
Bisakah kita menganggap x, y sebagai bilangan kompleks x + yi?
lirtosiast
Terkait
xnor
@ lirtosiast pertanyaannya adalah tentang segi enam di bidang euclidian, bukan di bidang kompleks. Karena itu input yang rumit tidak diperbolehkan.
agtoever

Jawaban:

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

Uji

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
sumber
2

Ruby, 150 145 137 127 125 106 88 76 byte

76 byte

->(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}

Mengubah perbandingan tiga kali lipat dengan roket.

88 byte

->(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}

Hapus y sama dengan tes apothem untuk poin pada segi enam, karena untuk bilangan bulat, itu tidak pernah benar.

106 byte:

->(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}

Poster menyarankan agar tidak menggunakan epsilon, jadi ganti epsilon dengan nol dan atur ulang, lepaskan perut, dll.

125 byte:

->(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}

Masukkan y ke dalam definisi z dan hapus beberapa tanda kurung.

127 byte:

->(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}

Menyusun ulang persyaratan untuk menghindari keharusan pelemparan to_f. Gunakan d (gandakan apotema) alih-alih a (apotema). Gabungkan beberapa tugas.

137 byte:

->(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}

Sebaris 'c'.

150 byte:

->(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))))}

Ini berfungsi untuk bilangan bulat atau mengapung! Tes epsilon adalah agar titik-titik dalam kesalahan pembulatan berada di tepi diidentifikasi dengan benar.

Nilai absolut memindahkan semuanya ke kuadran.

Nilai 'a' adalah jarak apotem (y-intersep hexagon).

Nilai 'c' adalah nilai-x dari sudut kanan atas segi enam.

Nilai 'z' adalah untuk melihat apakah titik di atas atau di bawah garis miring dari sudut ke intersep x.

Tidak Disatukan:

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
}

Uji

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
sumber
Ini bisa lebih pendek, Anda tidak perlu epsilon untuk bilangan bulat
edc65
Dengan memperkenalkan akar kuadrat dari tiga, saya terpaksa menggunakan floating point. Saya bisa membulatkan angka sebelum perbandingan, atau menggunakan perhitungan epsilon. Karena epsilon memungkinkan kode menjadi lebih umum dan berfungsi untuk mengapung, saya pergi di epsilon. Saya hanya memprogram Ruby sebentar, jadi saya tidak yakin bagaimana ini berhubungan dengan kesalahan pembulatan.
Paul Chernoch
Kemiringan sisi kiri dan kanan tidak rasional. Apotanya tidak rasional. Hanya ada 2 poin dengan koordinat bilangan bulat yang terletak di perimeter: [l, 0] dan [-l, 0]
edc65
Anda mungkin benar bahwa untuk input integer tidak ada poin integer lain yang mungkin "pada" segi enam. Membuktikan itu pada diri saya lebih sulit daripada membuat kode tidak peduli, menggunakan epsilon.
Paul Chernoch
Ya! Baru saja melewati solusi Python!
Paul Chernoch
0

Julia, 65 58 byte

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

xadalah vektor baris [x y]. Sebut seperti ini: f([0 0],1).

Rainer P.
sumber
0

Python 2, 89 byte

solusi yang hampir sama dengan jawaban Julia tetapi kita dapat menggunakan operasi pada vektor tanpa 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.]]]))

Hasil

>>> 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
sumber
0

Pyth, 41 byte

?<=d.5K+?>ZJ-c.ahQeQdZJ.acchtQeQ^3d_1s>dK

Uji di sini

Cameron McCluskie
sumber
0

JavaScript (ES6), 67 byte

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

Catatan: Untuk menetapkan ini ke variabel sehingga Anda dapat memanggilnya, masukkan f=setelahwith(Math) .

Saya menggunakan l*ldan b*bpada parameter pertama minuntuk menghindari panggilan ke absdan sqrttetapi saya tidak bisa mengetahui apakah saya bisa melakukan trik yang sama dengan parameter kedua.

Neil
sumber