Zone délimitée par une boucle périmétrique

14

Trouvez l'aire d'une région de cellules unitaires en fonction de sa boucle de périmètre sous la forme d'une séquence de virages à 90 degrés.

Par exemple, prenez la région à trois cellules

XX
X

dont on trace la boucle de périmètre

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

Chaque virage est marqué comme gauche (L), droit (S) ou droit (R). À partir du R, les virages sont RLLSLSLL. Donc, étant donné l'entrée RLLSLSLL, nous devrions sortir 3 pour la zone.

La séquence d'entrée est garantie pour tracer une boucle entourant une seule région sur sa gauche.

  • Le chemin se termine au point de départ, face à la direction initiale, formant une boucle.
  • La boucle ne se traverse pas et ne se touche pas.
  • La boucle va dans le sens antihoraire autour d'une région.

E / S

Vous pouvez prendre la saisie sous forme de liste ou de chaîne de caractères LSR, ou sous forme de chiffres -1, 0, 1pour gauche, droite, droite. La sortie est un entier positif. Les flotteurs sont OK.

Cas de test

Les entrées sont données dans les deux formats suivies de leurs sorties respectives.

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
la source

Réponses:

10

Brain-Flak , 112 octets

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

Essayez-le en ligne!

Ce programme utilise le théorème de Green pour calculer l'aire

L'emplacement actuel est stocké sur la pile de droite, dans un format qui dépend de la direction à laquelle vous faites face.

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

Dans tous les cas, la deuxième valeur de la pile augmentera de 1 et l'intégrale de la ligne pour la zone diminuera de moitié la valeur en haut de la pile. Pour compenser, la fin du programme divise le total cumulé par -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
la source
7

APL (Dyalog Classic) , 30 28 19 octets

-2 merci à @ Adám

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

Essayez-le en ligne!

utilise des astuces avec des nombres complexes pour calculer les coordonnées

l'aire est ½Σ (x i -x i + 1 ) (y i + y i + 1 ) ou de façon équivalente Σ (x i -x i + 1 ) y i car les lignes sont uniquement horizontales ou verticales

ngn
la source
Économisez en convertissant en corps tradfn.
2018
@ Adám à droite, j'espérais un train et j'ai oublié de le faire ...
ngn
@ Adám ah! J'ai trouvé le train :)
ngn
6

JavaScript (ES6), 52 50 octets

Sauvegardé 2 octets grâce à @Neil

Attend le deuxième format d'entrée.

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

Essayez-le en ligne!

Comment?

Cette description s'applique à la version précédente : x et y ont depuis été inversés.

Ceci est basé sur la formule déjà mentionnée par @ngn : A = Σ (x i - x i + 1 ) y i , qui peut également s'écrire Σdx i y idx i vaut -1, 0 ou 1.

Nous commençons par r = y = 0 .

Nous gardons une trace de la direction actuelle dans 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

Il est mis à jour avec a = a + k & 3, où k est l'élément actuel du tableau d'entrée.

Dans la mesure où a contient initialement le tableau d'entrée, a + k est contraint à NaN lors de la première itération, puis à 0 lorsque le AND au niveau du bit est appliqué. Cela signifie que le premier changement de direction est en fait ignoré et nous commençons toujours à nous diriger vers l'Est. Cela n'a pas d'importance car la zone reste la même, quelle que soit l'orientation de la forme finale.

Ensuite, nous mettons à jour y avec y += (2 - a) % 2.

Enfin, nous calculons -dx avec ~-a % 2et soustrayons y * -dx de r , qui - à la fin du processus - est notre résultat final.

Arnauld
la source
1
a=>a.map(k=>r+=(2-(a=a+k&3))%2*(y+=~-a%2),r=y=0)|renregistre 2 octets.
Neil
4

Python 2 , 64 octets

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

Essayez-le en ligne!

Calcule ∑xΔy en utilisant des nombres complexes.

Lynn
la source
3

Haskell , 71 70 69 octets

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

Explication: le théorème de Green donne la formule de l'aire: A = ½∑ (x k + 1 + x k ) (y k + 1 -y k ), ce qui simplifie en A = ½∑ Δx = 0 2x k Δy + ½∑ Δy = 0 (x k + 1 + x k ) * 0 = ∑xΔy lorsque les virages sont de 90 degrés le long des axes. Nous avons le pseudocode suivant pour une fonction récursive de tournage qui garde la position et la direction x:

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

où la nouvelle direction, ΔA et Δx peut être vue dans les tableaux suivants. Nous pouvons voir une périodicité sinusoïdale de longueur quatre à la fois dans ΔA et Δx le long de l'axe diagonal dir+turn, qui est mise en œuvre en utilisant sinau lieu de l'arithmétique modulaire.

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

Essayez-le en ligne!

Angs
la source
2

Wolfram Language (Mathematica) , 36 30 octets

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

Si vous avez une ancienne version de Mathematica (~ v10) dont vous aurez besoin Most@devant AnglePathpour éviter de fermer le polygone. (Merci à @ user202729 pour les conseils).

original: Essayez-le en ligne!

mis à jour: Essayez-le en ligne!

Kelly Lowder
la source
#.5Pisemble fonctionner.
user202729
On dirait qu'il est possible de laisser tomber Mostaussi.
user202729
2

Gelée , 15 11 octets

Merci à @xnor d'avoir signalé une étape inutile, économisant 2 octets
Merci à @dylnan d'avoir enregistré un autre octet

Attend le deuxième format d'entrée. Renvoie un flotteur.

+\ı*Ḟ_\×ƊĊS

Essayez-le en ligne!ou exécutez tous les cas de test

Commenté

+\ı*Ḟ_\×ƊĊ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
la source
Faut-il conserver uniquement les 2 bits les moins significatifs?
xnor
+\ı*Ḟ_\×ƊĊSenregistre un octet
dylnan
@xnor et dylnan Merci de m'avoir aidé à jouer cette soumission. Et merci à xnor pour la prime!
Arnauld
2

Python 2 , 62 octets

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

Essayez-le en ligne!

Similaire à la solution de Lynn , mais en utilisant une arithmétique complexe pour extraire la bonne composante du nombre complexe en une seule fois.

xnor
la source
0

Pyth , 14 octets

_smec^.j)sd2.:

Suite de tests

_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

Cela exprime la zone comme la somme de -1/2 * g(sum(l))toutes les sous-listes contiguës lsur l'entrée, d'où gl'indexation modulaire dans [0,1,0,-1]. Le code implémente gcomme g(x)=imag(1j**x). Il peut y avoir une méthode plus courte avec indexation modulaire directe, utilisation sinou fonction arithmétique activée x%4.

xnor
la source