Obszar zamknięty pętlą obwodową

14

Znajdź obszar regionu komórek jednostkowych, biorąc pod uwagę jego obwodową pętlę jako sekwencję zwojów 90 stopni.

Na przykład weź region trzech komórek

XX
X

którego pętlę obwodową rysujemy

L<S<L
v   ^
S R>L
v ^
L>L

Każdy zakręt jest oznaczony jako lewy (L), prosty (S) lub prawy (R). Zaczynając od R, są tury RLLSLSLL. Tak więc, biorąc pod uwagę dane wejściowe RLLSLSLL, powinniśmy wyprowadzić 3 dla obszaru.

Sekwencja wejściowa gwarantuje prześledzenie pętli obejmującej pojedynczy region po lewej stronie.

  • Ścieżka kończy się w punkcie początkowym, twarzą do początkowego kierunku i tworzy pętlę.
  • Pętla nie przecina się ani nie dotyka.
  • Pętla biegnie w kierunku przeciwnym do ruchu wskazówek zegara wokół regionu.

I / O

Możesz przyjmować dane wejściowe jako listę lub ciąg znaków LSRlub jako liczby -1, 0, 1dla lewej, prostej, prawej. Wyjście jest dodatnią liczbą całkowitą. Pływaki są w porządku.

Przypadki testowe

Dane wejściowe są podawane w obu formatach, a następnie ich odpowiednie dane wyjściowe.

RLLSLSLL
LLLL
SLLSLL
LSRRSLLSSLSSLSSL
SSSSSLSSSSSLSSSSSLSSSSSL

[1, -1, -1, 0, -1, 0, -1, -1]
[-1, -1, -1, -1]
[0, -1, -1, 0, -1, -1]
[-1, 0, 1, 1, 0, -1, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1]
[0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1, 0, 0, 0, 0, 0, -1]

3
1
2
7
36
xnor
źródło

Odpowiedzi:

10

Brain-Flak , 112 bajtów

(([]){[{}]<{({}()){{}<>([{}]<([{}])>)(<>)}<>(({}[({})])[({}{})])<>}{}<>>({}<({}())>)<>([])}{})({()<({}()())>}{})

Wypróbuj online!

Ten program wykorzystuje twierdzenie Greena do obliczenia powierzchni

Bieżąca lokalizacja jest przechowywana na odpowiednim stosie, w formacie zależnym od zwróconego kierunku.

Direction  top  second
north       -x       y
west        -y      -x
south        x      -y
east         y       x

We wszystkich przypadkach druga wartość na stosie wzrośnie o 1, a całka linii dla obszaru zmniejszy się o połowę wartości na górze stosu. Aby to zrekompensować, koniec programu dzieli bieżącą sumę przez -2.

# For each number in input
(([]){[{}]

  # Evaluate turn-handling to zero
  <

    # If turn:
    {

      # If right turn:
      ({}()){{}

        # Negate both values on other stack (reverse direction)
        <>([{}]<([{}])>)

      (<>)}

      # Swap the two stack elements and negate the new top of stack
      # This performs a left turn.
      <>(({}[({})])[({}{})])<>

    }{}

  <>>

  # Evaluate as top of stack and...
  ({}<

    # increment the number below it
    ({}())

  >)<>

([])}{})

# Divide total by -2
({()<({}()())>}{})
Nitrodon
źródło
7

APL (Dyalog Classic) , 30 28 19 bajtów

-2 dzięki @ Adám

(+/9∘○×11○+\)0j1*+\

Wypróbuj online!

używa sztuczek o liczbach zespolonych do obliczenia współrzędnych

obszar wynosi ½Σ (x i -x i + 1 ) (y i + y i + 1 ) lub równoważnie Σ (x i -x i + 1 ) y i, ponieważ linie są tylko poziome lub pionowe

ngn
źródło
Zaoszczędź, konwertując na ciało tradfn.
Adám
@ Adám racja, miałem nadzieję na pociąg i jakoś zapomniałem to zrobić ...
ngn
@ Adám ah! Znalazłem pociąg :)
ngn
6

JavaScript (ES6), 52 50 bajtów

Zaoszczędź 2 bajty dzięki @Neil

Oczekuje drugiego formatu wejściowego.

a=>a.map(k=>r+=(2-(a=a+k&3))%2*(y+=~-a%2),r=y=0)|r

Wypróbuj online!

W jaki sposób?

Opis ten odnosi się do wersji poprzedniej : x i y od tego czasu zostały odwrócone.

Jest to oparte na formule już wspomnianej przez @ngn : A = Σ (x i - x i + 1 ) y i , którą można również zapisać jako Σdx i y i gdzie dx i wynosi -1, 0 lub 1.

Zaczynamy od r = y = 0 .

Mamy śledzić aktualny kierunek w :

          | a = 0 | a = 1 | a = 2 | a = 3
----------+-------+-------+-------+-------
direction | East  | South | West  | North
       dx |  +1   |   0   |  -1   |   0     <--  -(~-a % 2)
       dy |   0   |  +1   |   0   |  -1     <--  (2 - a) % 2

Jest aktualizowany o a = a + k & 3, gdzie k jest bieżącym elementem tablicy wejściowej.

Ponieważ początkowo zawiera tablicę wejściową, a + k jest zmuszany do NaN na pierwszej iteracji, a następnie do 0 , gdy jest stosowana bitowe AND. Oznacza to, że pierwsza zmiana kierunku jest faktycznie ignorowana i zawsze zaczynamy kierować się na wschód. To nie ma znaczenia, ponieważ obszar pozostaje taki sam, bez względu na orientację ostatecznego kształtu.

Następnie aktualizujemy y przy pomocy y += (2 - a) % 2.

Wreszcie, obliczyć -dx z ~-a % 2odjąć y * -dx z R , które - na zakończenie procesu - jest naszym wynik końcowy.

Arnauld
źródło
1
a=>a.map(k=>r+=(2-(a=a+k&3))%2*(y+=~-a%2),r=y=0)|roszczędza 2 bajty.
Neil
4

Python 2 , 64 bajty

f=lambda c,d=1,x=0:c>[]and f(c[1:],d*1j**c[0],x+d.real)-x*d.imag

Wypróbuj online!

Oblicza ∑xΔy przy użyciu liczb zespolonych.

Lynn
źródło
3

Haskell , 71 70 69 bajtów

a 0 0
a x d(t:r)|k<-t+d=x*g k+a(x+g(k-1))k r
a _ _ _=0
g a=sin$a*pi/2

Objaśnienie: Twierdzenie Greena daje wzór na obszar: A = ½∑ (x k + 1 + x k ) (y k + 1 -y k ), co upraszcza A = ½∑ Δx = 0 2x k Δy + ½∑ Δy = 0 (x k + 1 + x k ) * 0 = ∑xΔy, gdy skręty mają 90 stopni wzdłuż osi. Mamy następujący pseudokod dla rekurencyjnej funkcji globowania skrętu, która śledzi pozycję i kierunek x:

A x dir (turn:turns) = ΔA + A (xx) (dir+turn) turns

gdzie nowy kierunek, AA i Δx można zobaczyć w poniższych tabelach. Widzimy sinusoidalną cykliczność o długości cztery zarówno w andA, jak i Δx wzdłuż osi przekątnej dir+turn, która jest realizowana za pomocą sinzamiast modułowej arytmetyki.

  ↔|L S R ΔA| L  S  R  Δx| L  S  R 
         -x  0  x      0 -1  0  
          0  x  0     -1  0  1
          x  0 -x      0  1  0
          0 -x  0      1  0 -1

Wypróbuj online!

Angs
źródło
2

Wolfram Language (Mathematica) , 36 30 bajtów

Area@Polygon@AnglePath[.5Pi#]&

Jeśli masz starszą wersję Mathematica (~ v10), będziesz potrzebować Most@ przed nią, AnglePathaby uniknąć zamknięcia wielokąta. (Podziękowania dla @ user202729 za wskazówki).

oryginalny: Wypróbuj online!

zaktualizowano: Wypróbuj online!

Kelly Lowder
źródło
#.5Piwydaje się działać.
user202729,
Wygląda na to, że można też upuścić Most.
user202729,
2

Galaretka , 15 11 bajtów

Dzięki @xnor za wskazanie bezużytecznego kroku, oszczędzając 2 bajty
Dziękujemy @dylnan za zapisanie kolejnego bajtu

Oczekuje drugiego formatu wejściowego. Zwraca liczbę zmiennoprzecinkową.

+\ı*Ḟ_\×ƊĊS

Wypróbuj online! lub uruchom wszystkie przypadki testowe

Skomentował

+\ı*Ḟ_\×ƊĊS  - main link, taking the input list   e.g. [1, -1, -1, 0, -1, 0, -1, -1]
+\           - cumulative sum                     -->  [1, 0, -1, -1, -2, -2, -3, -4]
  ı*         - compute 1j ** d,                   -->  [(0+1j), (1+0j), (0-1j), (0-1j),
               which gives a list of (-dy + dx*j)       (-1+0j), (-1+0j), (0+1j), (1+0j)]
         Ċ   - isolate the imaginary part (dx)    -->  [1, 0, -1, -1, 0, 0, 1, 0] (floats)
        Ɗ    - invoke the last 3 links as a monad
    Ḟ        - isolate the real part (-dy)        -->  [0, 1, 0, 0, -1, -1, 0, 1] (floats)
     _\      - negated cumulative sum (gives y)   -->  [0, -1, -1, -1, 0, 1, 1, 0]
       ×     - compute dx * y                     -->  [0, 0, 1, 1, 0, 0, 1, 0]
          S  - sum                                -->  3
Arnauld
źródło
Czy zachowywanie tylko 2 znaczących bitów jest konieczne?
xnor
+\ı*Ḟ_\×ƊĊSzapisuje bajt
dylnan
@xnor i dylnan Dziękujemy za pomoc w grze w golfa. I dodatkowe podziękowania dla Xnor za nagrodę!
Arnauld
2

Python 2 , 62 bajty

f=lambda l,p=0,s=1:l>[]and(p/s).imag/2+f(l[1:],p+s,s*1j**l[0])

Wypróbuj online!

Podobne do rozwiązania Lynn , ale przy użyciu złożonej arytmetyki, aby wyodrębnić odpowiedni składnik liczby zespolonej za jednym razem.

xnor
źródło
0

Pyth , 14 bajtów

_smec^.j)sd2.:

Zestaw testowy

_smec^.j)sd2.:
              Q     implicit input
            .:      take all non-empty contiguous sublists
  m                map this operation onto each one:
   ec^.j)sd2
         s           the sum of the sublist
     ^.j)            raise it to the complex unit 1j to that power
    c      2         halve it
   e                take the imaginary part
_s                take the negated sum of the result

Wyraża to obszar jako sumę -1/2 * g(sum(l))wszystkich sąsiednich podlist lna wejściu, gdzie gindeksowane jest modułowo [0,1,0,-1]. Kod implementuje gjako g(x)=imag(1j**x). Może istnieć krótsza metoda z bezpośrednim indeksowaniem modułowym, użyciem sinlub funkcją arytmetyczną x%4.

xnor
źródło