Sargı numarasını hesaplayın


15

Sarım sayısı bir gözlemci verilen bir kapalı yolu izlemeyi yapılmış olmalı, net yönünün tersine devrimlerin tamsayı sayısıdır. Saat yönünde dönüşlerin sargı sayısına negatif sayıldığına dikkat edin. Yolun kendi kendine kesişmesine izin verilir.

Bazı örnekler (utanmadan Wikipedia'dan alınmıştır) aşağıda verilmiştir:

resim açıklamasını buraya girin

Amacınız belirli bir yolun sargı numarasını hesaplamaktır.

Giriş

Gözlemcinin başlangıçta olduğu varsayılır (0,0).

Giriş, parça bazında lineer yolu tarif eden herhangi bir istenen giriş kaynağından sınırlı bir nokta dizisidir (tamsayı sayılarının çifti benzeri). İsterseniz bunu 1D tamsayılar dizisine yassılaştırabilir ve ayrıca y koordinatlarından / tam tersinden önce tüm x koordinatlarını almak için girdiyi çevirebilirsiniz. Girdiyi karmaşık bir sayı olarak da alabilirsiniza+b i . Yol kendiliğinden kesişebilir ve sıfır uzunlukta segmentler içerebilir. İlk nokta, yolun başlangıcıdır ve pozitif x ekseninde bir yerde olduğu varsayılır.

Yolun hiçbir kısmı başlangıç ​​noktasıyla kesişmeyecektir. Yol her zaman kapalı olacaktır (yani ilk ve kayıp nokta aynıdır). Kodunuz ya son noktayı ima edebilir ya da dahil edilmesini gerektirebilir.

Örneğin, tercihinize bağlı olarak her iki giriş de aynı kareyi belirtir:

zımni bitiş noktası

1,0
1,1
-1,1
-1,-1
1,-1

açık bitiş noktası

1,0
1,1
-1,1
-1,-1
1,-1
1,0

Çıktı

Çıkış, sargı numarası için tek bir tamsayıdır. Bu herhangi bir kaynağa (dönüş değeri, stdout, dosya vb.) Ait olabilir.

Örnekler

Tüm örneklerde bitiş noktası açıkça tanımlanmıştır ve x, y çiftleri olarak verilmiştir. Bu arada, bu örnekleri dolaylı olarak tanımlanmış bitiş noktaları varsayarak çıktılara aynı olması gerektiği gibi doğrudan herhangi bir koda da aktarabilmelisiniz.

1. Temel test

1,0
1,1
-1,1
-1,-1
1,-1
1,0

Çıktı

1

2. Tekrarlanan nokta testi

1,0
1,0
1,1
1,1
-1,1
-1,1
-1,-1
-1,-1
1,-1
1,-1
1,0

Çıktı

1

3. Saat yönünde test

1,0
1,-1
-1,-1
-1,1
1,1
1,0

Çıktı

-1

4. Dış test

1,0
1,1
2,1
1,0

Çıktı

0

5. Karışık sargı

1,0
1,1
-1,1
-1,-1
1,-1
1,0
1,-1
-1,-1
-1,1
1,1
1,0
1,1
-1,1
-1,-1
1,-1
1,0
1,1
-1,1
-1,-1
1,-1
1,0

Çıktı

2

puanlama

Bu kod golf; en kısa kod kazanır. Standart boşluklar geçerlidir. Sargı numarasını hesaplamak için özel olarak tasarlanmadığı sürece yerleşik işlevleri kullanabilirsiniz.


2
Girdi karmaşık sayılar olarak alınabilir mi (ya da bunların dize olarak temsil edilmesi, "1-i"ya da gibi "1-1i"?)
Level River St

evet, her türlü çift kabul edilebilir.
helloworld922

Yanıtlar:


10

ES6, 83 bayt

a=>a.map(([x,y])=>r+=Math.atan2(y*b-x*c,y*c+x*b,b=x,c=y),b=c=r=0)&&r/Math.PI/2

Girdi olarak karmaşık sayılar olarak yorumlanan bir dizi nokta alır. Her noktayı bir açıya dönüştürmek yerine, noktalar önceki noktaya bölünür; Math.atan2 daha sonra -π ve π arasında bir açıya dönüşür, böylece yolun hangi yönde sarıldığını otomatik olarak belirler. Açıların toplamı, sargı sayısının 2π katıdır.

Math.atan2 argümanlarının ölçeğini umursamadığı için tam bölünmeyi tam olarak gerçekleştirmiyorum, z / w = (z * w*) / (w * w*)bunun yerine her noktayı bir önceki noktanın karmaşık eşleniği ile çarpıyorum .

Düzenleme: @ edc65 sayesinde 4 bayt kaydedildi.


Güzel ve hızlı. Ve ben senin matematiğini anlamıyorum. Ancak reduceneredeyse her zaman kötü bir seçimdir.
edc65

a=>a.map(([x,y])=>r+=Math.atan2(y*b-x*c,y*c+x*b,b=x,c=y),b=c=r=0)&&r/Math.PI/2harita kullanmak veya azaltmak. Yine de benim
oyum

@ edc65 Teşekkürler; Kullandım reduceçünkü Math.atan2'nin (0,0) 0 olduğunu fark etmedim. (Eh, 0'larınızdan birinin gerçekten -0 olup olmadığına bağlıdır.) Matematik normalde şu şekilde hesaplanan karmaşık bölünmeye dayanır. z / w = z * w* / |w|², ama büyüklük umurumda değil, bu yüzden sadece karmaşık eşlenik ile çarpma. Ayrıca biraz kafa karıştırıcı bir şekilde Math.atan2 (y, x) argümanlarını kabul eder.
Neil

Kodu anlamadığımı itiraf ediyorum, ancak açıklamanız doğru ise, cevabınızın yanlış olduğuna inanıyorum. Gerçekten de, bu yoldan puan girdiyseniz (daha fazla netlik için bir resim veriyorum), sarım numarası 1'dir, sorununuz 2
çıkardı

@Wojowu Üzgünüm, poligonun dış açılarından ziyade, başlangıç ​​noktasından ölçülen noktalar arasındaki açıyı kastediyorum, bu yüzden resminiz için kodum gerçekten yanıtı 1 olarak hesaplamalıdır.
Neil

3

MATL , 11 bayt

X/Z/0)2/YP/

Giriş, bitiş noktası dahil karmaşık sayıların bir dizisidir.

Çevrimiçi deneyin!

açıklama

İşin çoğu, pi'den daha büyük veya eşit olan mutlak sıçramaları 2 * pi tamamlayıcılarına değiştirerek radyanlardaki açıları açan Z/fonksiyon ( unwrap) tarafından yapılır .

X/       % compute angle of each complex number
Z/       % unwrap angles
0)       % pick last value. Total change of angle will be a multiple of 2*pi because 
         % the path is closed. Total change of angle coincides with last unwrapped
         % angle because the first angle is always 0
2/       % divide by 2
YP/      % divide by pi

1
MATL ve Jelly son zamanlarda pek çok mathy sorununu birbirine bağlıyor. Etkilendim, neredeyse meta-golfe uğramış Dennis'in dili ...
ETHproductions

@ETHproductions Güzel sözleriniz için teşekkürler! Evet, bazı yeni zorluklarla bağlantılılar. Öte yandan, Jelly'in bayt sayısının MATL kadar yarıya düştüğü birkaç problem gördüm:
Luis Mendo

2

Jöle, 11 bayt

æAI÷ØPæ%1SH

Bu, girdiyi y koordinatları listesi ve x koordinatları listesi olarak alır.

Burada deneyin .


1

Python, 111

Şimdiye kadarki en uzun cevap. Benim motivasyonlarım 1) python öğrenmek ve 2) muhtemelen bunu pire taşıyor.

from cmath import *
q=input()
print reduce(lambda x,y:x+y,map(lambda (x,y):phase(x/y)/pi/2,zip(q[1:]+q[:1],q)))

Girdi karmaşık sayıların bir listesi olarak verilir.

Ideone.

Bence yaklaşım ES6 cevabına benziyor.

2 karmaşık sayı çarpıldığında, ürünün argümanı veya fazı iki sayının argümanının veya fazının toplamıdır. Böylece, karmaşık bir sayı bir başkasına bölündüğünde, bölümün fazı, pay ve payda aşamaları arasındaki farktır. Böylece her nokta ve bir sonraki nokta için geçilen açıyı hesaplayabiliriz. Bu açıları toplayın ve 2π'ye bölün, gerekli sargı numarasını verir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.