Площа, огороджена петлею по периметру


14

Знайдіть площу області одиничних комірок, задану її периметровою петлею, як послідовність 90-градусних витків.

Наприклад, візьміть триклітинні області

XX
X

чию петлю по периметру ми намалюємо

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

Кожен поворот позначений як лівий (L), прямий (S) або правий (R). Починаючи з R, повороти є RLLSLSLL. Отже, з урахуванням введення RLLSLSLL, нам слід вивести 3 для області.

Гарантована послідовність введення відстежує цикл, що охоплює одну область зліва.

  • Шлях закінчується назад у початковій точці, зверненою до початкового напрямку, утворюючи петлю.
  • Петля не перетинається і не торкається себе.
  • Петля проходить проти годинникової стрілки навколо регіону.

I / O

Ви можете приймати введення як список або рядок символів LSR, або як цифри -1, 0, 1для лівого, прямого, правого. Вихід - це натуральне число. Поплавки в порядку.

Тестові справи

Введення подаються в обох форматах, а за ними - відповідні виходи.

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

Відповіді:


10

Мозок-Флак , 112 байт

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

Спробуйте в Інтернеті!

Ця програма використовує теорему Гріна для обчислення площі

Поточне місцезнаходження зберігається у правій стеці у форматі, який залежить від напрямку, з яким стикається.

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

У всіх випадках друге значення стека збільшиться на 1, а інтеграл рядка для області зменшиться на половину значення у верхній частині стека. Для компенсації кінець програми ділить загальну кількість на -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
({()<({}()())>}{})

7

APL (Dyalog Classic) , 30 28 19 байт

-2 завдяки @ Adám

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

Спробуйте в Інтернеті!

використовує трюки зі складними числами для обчислення координат

площа дорівнює ½Σ (x i -x i + 1 ) (y i + y i + 1 ) або еквівалентно Σ (x i -x i + 1 ) y i, оскільки лінії є лише горизонтальними або вертикальними


Збережіть, перетворивши на body tradfn.
Адам

@ Adám вірно, я сподівався на поїзд і якось забув це зробити ...
ngn

@ Adám ах! Я знайшов поїзд :)
пн

6

JavaScript (ES6), 52 50 байт

Збережено 2 байти завдяки @Neil

Очікує другий формат введення.

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

Спробуйте в Інтернеті!

Як?

Цей опис стосується попередньої версії : x і y з тих пір перевернуті.

Це ґрунтується на формулі, яку вже згадував @ngn : A = Σ (x i - x i + 1 ) y i , яку також можна записати як Σdx i y i, де dx i - або -1, 0 або 1.

Почнемо з r = y = 0 .

Ми продовжуємо відстежувати напрямки струму в :

          | 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

Він оновлюється a = a + k & 3, де k - поточний елемент вхідного масиву.

Оскільки спочатку містить масив введення, а + до принуждается до NaN на першій ітерації , а потім в 0 , коли побітовое І застосовується. Це означає, що перша зміна напрямку насправді ігнорується, і ми завжди починаємо прямувати на Схід. Не має значення, тому що площа залишається такою ж, незалежно від орієнтації остаточної форми.

Потім ми оновлюємо y с y += (2 - a) % 2.

Нарешті, ми обчислюємо -dx з ~-a % 2і віднімаємо y * -dx від r , що - в кінці процесу - наш кінцевий результат.


1
a=>a.map(k=>r+=(2-(a=a+k&3))%2*(y+=~-a%2),r=y=0)|rекономить 2 байти.
Ніл


3

Haskell , 71 70 69 байт

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

Пояснення: Теорема Гріна дає формулу для площі: A = ½∑ (x k + 1 + x k ) (y k + 1 -y k ), яка спрощує до A = ½∑ Δx = 0 2x k Δy + ½∑ Δy = 0 (x k + 1 + x k ) * 0 = ∑xΔy, коли повороти по осях 90 градусів. У нас є наступний псевдокод для рекурсивної функції повороту, яка відстежує положення х і напрямок:

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

де новий напрямок ΔA та Δx видно з наступних таблиць. Ми можемо побачити синусоїдальну періодичність довжиною чотири як ΔA, так і Δx уздовж діагональної осі dir+turn, яка реалізується з використанням sinзамість модульної арифметики.

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

Спробуйте в Інтернеті!


2

Мова Вольфрама (Mathematica) , 36 30 байт

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

Якщо у вас є старша версія Mathematica (~ v10), вам знадобиться Most@перед, AnglePathщоб уникнути закриття багатокутника. (Дякуємо @ user202729 за поради).

оригінал: Спробуйте в Інтернеті!

оновлено: Спробуйте онлайн!


#.5Piздається, працює.
користувач202729,

Схоже, що теж можна скинути Most.
користувач202729

2

Желе , 15 11 байт

Дякуємо @xnor за те, що вказав на марний крок, економив 2 байти.
Дякував @dylnan за збереження ще одного байта

Очікує другий формат введення. Повертає поплавок.

+\ı*Ḟ_\×ƊĊS

Спробуйте в Інтернеті!або запустити всі тестові приклади

Прокоментував

+\ı*Ḟ_\×ƊĊ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

Чи потрібно зберігати лише найменші 2 значущі біти?
xnor

+\ı*Ḟ_\×ƊĊSзберігає байт
дилнан

@xnor та dylnan Дякую за те, що ти допомагаєш мені грати у цій програмі. І додаткова подяка xnor за щедрість!
Арнольд



0

Піт , 14 байт

_smec^.j)sd2.:

Тестовий набір

_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

Це виражає область як суму -1/2 * g(sum(l))над усіма суміжними списками lнад входом, де gвідбувається модульне індексування [0,1,0,-1]. Код реалізується gяк g(x)=imag(1j**x). Можливо, існує коротший метод із sinвключеним прямим модульним індексуванням, використанням або арифметичною функцією x%4.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.