Area chiusa da anello perimetrale


14

Trova l'area di una regione di celle unitarie dato il suo ciclo perimetrale come una sequenza di curve di 90 gradi.

Ad esempio, prendi la regione a tre celle

XX
X

di cui disegniamo il perimetro

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

Ogni svolta è contrassegnata come sinistra (L), dritta (S) o destra (R). A partire dalla R, i giri sono RLLSLSLL. Quindi, dato l'input RLLSLSLL, dovremmo produrre 3 per l'area.

La sequenza di input è garantita per tracciare un loop che racchiude una singola regione alla sua sinistra.

  • Il percorso termina indietro nel punto iniziale, rivolto verso la direzione iniziale, formando un anello.
  • Il loop non si incrocia o si tocca.
  • Il loop va in senso antiorario attorno a una regione.

I / O

Puoi prendere l'input come un elenco o una stringa di caratteri LSRo come numeri -1, 0, 1per sinistra, dritto, destra. L'output è un numero intero positivo. I galleggianti sono OK.

Casi test

Gli ingressi sono forniti in entrambi i formati, seguiti dalle rispettive uscite.

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

Risposte:


10

Brain-Flak , 112 byte

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

Provalo online!

Questo programma utilizza il teorema di Green per calcolare l'area

La posizione corrente è memorizzata nello stack giusto, in un formato che dipende dalla direzione affrontata.

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

In tutti i casi, il secondo valore nella pila aumenterà di 1 e l'integrale di linea per l'area diminuisce della metà del valore nella parte superiore della pila. Per compensare, la fine del programma divide il totale parziale per -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 byte

-2 grazie a @ Adám

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

Provalo online!

usa trucchi con numeri complessi per calcolare le coordinate

l'area è ½Σ (x i -x i + 1 ) (y i + y i + 1 ) o equivalentemente Σ (x i -x i + 1 ) y i poiché le linee sono solo orizzontali o verticali


Risparmia convertendolo in body tradizionale.
Adám,

@Adám giusto, speravo in un treno e in qualche modo ho dimenticato di farlo ...
ngn

@ Adám ah! Ho trovato il treno :)
ngn

6

JavaScript (ES6), 52 50 byte

Salvato 2 byte grazie a @Neil

Si aspetta il secondo formato di input.

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

Provalo online!

Come?

Questa descrizione vale per la versione precedente : x ed y da allora sono stati invertiti.

Questo si basa sulla formula già menzionata da @ngn : A = Σ (x i - x i + 1 ) y i , che può anche essere scritta come Σdx i y i dove dx i è -1, 0 o 1.

Iniziamo con r = y = 0 .

Teniamo traccia della direzione corrente in un :

          | 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

Viene aggiornato con a = a + k & 3, dove k è l'elemento corrente dell'array di input.

Poiché un contiene inizialmente l'array di input, un + k è costretto a NaN alla prima iterazione e poi a 0 quando viene applicato AND bit a bit. Ciò significa che il primo cambio di direzione viene effettivamente ignorato e iniziamo sempre a dirigerci verso est. Non importa perché l'area rimane la stessa, indipendentemente dall'orientamento della forma finale.

Quindi, aggiorniamo y con y += (2 - a) % 2.

Infine, calcoliamo -dx con ~-a % 2e sottraiamo y * -dx da r , che - alla fine del processo - è il nostro risultato finale.


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


3

Haskell , 71 70 69 byte

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

Spiegazione: Il teorema di Green fornisce la formula per l'area: A = ½∑ (x k + 1 + x k ) (y k + 1 -y k ), che semplifica in A = ½∑ Δx = 0 2x k Δy + ½∑ Δy = 0 (x k + 1 + x k ) * 0 = ∑xΔy quando le svolte sono di 90 gradi lungo gli assi. Abbiamo il seguente pseudocodice per una funzione ricorsiva di turbolenza che tiene traccia della posizione e della direzione x:

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

dove la nuova direzione, ΔA e Δx è visibile dalle seguenti tabelle. Possiamo vedere una periodicità sinusoidale di lunghezza quattro in ΔA e Δx lungo l'asse diagonale dir+turn, che viene implementata usando sininvece l'aritmetica modulare.

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

Provalo online!



2

Jelly , 15 11 byte

Grazie a @xnor per aver segnalato un passaggio inutile, risparmiando 2 byte
Grazie a @dylnan per aver salvato un altro byte

Si aspetta il secondo formato di input. Restituisce un float.

+\ı*Ḟ_\×ƊĊS

Provalo online!o eseguire tutti i casi di test

Commentate

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

È necessario conservare solo i 2 bit significativi?
xnor

+\ı*Ḟ_\×ƊĊSsalva un byte
dylnan

@xnor e dylnan Grazie per avermi aiutato a giocare a golf con questa proposta. E grazie in più a xnor per la generosità!
Arnauld

2

Python 2 , 62 byte

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

Provalo online!

Simile alla soluzione di Lynn , ma usando una complessa aritmetica per estrarre il giusto componente del numero complesso in una volta sola.



0

Pyth , 14 byte

_smec^.j)sd2.:

Suite di test

_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

Questo esprime l'area come la somma di -1/2 * g(sum(l))tutte le liste secondarie contigue lsull'input, in cui gviene eseguita l' indicizzazione modulare [0,1,0,-1]. Il codice implementa gcome g(x)=imag(1j**x). Potrebbe esserci un metodo più breve con indicizzazione modulare diretta, utilizzo sino funzione aritmetica attiva x%4.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.