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

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


@ 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>


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

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).


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]


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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.