境界ループで囲まれた領域


14

周囲のループが90度の回転シーケンスとして与えられたユニットセルの領域の面積を見つけます。

たとえば、3セルの領域を取ります

XX
X

誰の境界ループを描くか

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

各ターンには、左(L)、直線(S)、ま​​たは右(R)のマークが付いています。Rから始まって、ターンはRLLSLSLLです。したがって、inputが与えられた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

Brain-Flak、112バイト

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

オンラインでお試しください!

このプログラムは、グリーンの定理を使用して面積を計算します

現在の場所は、直面している方向に応じた形式で、正しいスタックに保存されます。

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

すべてのインスタンスで、スタックの2番目の値は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線のみ水平または垂直であるように


tradfn本文に変換して保存します。
アダム

@Adám正しい、私は電車を望んでいて、どうにかしてそれをするのを忘れていました
...-ngn

@Adámああ!私は電車を見つけました:)
ngn

6

JavaScript(ES6)、52 50バイト

@Neilのおかげで2バイト節約

2番目の入力形式が必要です。

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

オンラインでお試しください!

どうやって?

この説明は以前のバージョンに適用されます。xyはそれ以降反転されています。

これに基づいて既に@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は入力配列の現在の要素です。

最初に入力配列が含まれているため、a + kは最初の反復でNaNに強制され、ビット単位のANDが適用されると0になります。これは、最初の方向変更が実際に無視され、常に東に向かうことを意味します。最終的な形状の向きに関係なく、面積は同じままであるため問題ではありません。

次に、yをで更新しy += (2 - a) % 2ます。

最後に、-dxを計算し~-a % 2rからy * -dxを減算します。これは、プロセスの最後で最終結果です。


1
a=>a.map(k=>r+=(2-(a=a+k&3))%2*(y+=~-a%2),r=y=0)|r2バイト節約します。
ニール


3

Haskell71 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 =ターンが軸に沿って90度の場合、∑xΔy。xの位置と方向を追跡する再帰的なターングローブ関数の擬似コードは次のとおりです。

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

ここで、新しい方向、ΔAおよびΔxは次の表から見ることができます。対角軸に沿ったΔAとΔxの両方で、長さ4の正弦波周期性を見ることができます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

Wolfram言語(Mathematica)36 30バイト

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

あなたはMathematicaの(〜V10)の旧バージョンをお持ちの場合は、必要がありますMost@の前にAnglePathポリゴンを閉じる避けるために。(ヒントを@ user202729に感謝します)。

オリジナル: オンラインでお試しください!

更新: オンラインでお試しください!


#.5Pi動作するようです。
-user202729

落とすことMostもできるようです。
user202729

2

ゼリー15 11バイト

無駄なステップを指摘して2バイトを保存してくれた@xnorに感謝します。
別のバイトを保存してくれた@dylnanに感謝します。

2番目の入力形式が必要です。フロートを返します。

+\ı*Ḟ_\×ƊĊ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バイトを保存します
-dylnan

@xnorとdylnanこの投稿のゴルフを手伝ってくれてありがとう。そして、賞金に感謝します!
アーナウルド



0

Pyth、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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.