Potentiel électrostatique d'un système simple

21

En physique, comme les charges électriques repoussent, et contrairement aux charges s'attirent.

L'énergie potentielle entre deux charges unitaires séparées par une distance dest 1/dpour des charges similaires et -1/dpour des charges différentes. L'énergie potentielle d'un système de charges est la somme des énergies potentielles entre toutes les paires de charges.

Défi

Déterminez l'énergie potentielle d'un système de charges unitaires représenté par une chaîne.

C'est le , donc la solution la plus courte en octets l'emporte.


Contribution

Une chaîne non vide multiligne, constitué de seulement +, -, et les sauts de lignes, chaque ligne d'une largeur constante. Les +et -représentent des frais de +1 et -1 respectivement. Par exemple, la chaîne suivante:

    + -
 +     

(considérant que le coin supérieur gauche est l'origine) représente un système avec des charges positives à (4,0) et (1, -1) et une charge négative à (6,0).

Alternativement, vous pouvez prendre la saisie comme une liste de lignes.

Production

Un nombre réel signé représentant l'énergie potentielle du système de charges. La sortie doit être correcte à quatre chiffres significatifs ou 10 -4 , selon le plus lâche.

Cas de test:

   - 
     

Devrait sortir 0. Il n'y a pas de paires de charges à repousser ou à attirer, et l'espace blanc ne change rien.

+  
  -

Il n'y a que deux charges; ils sont à 1 unité dans le sens vertical et à 2 unités dans le sens horizontal, leur distance est donc sqrt (5). La sortie doit être -1 / sqrt (5) = -0.447213595.

+       -
-       +

Devrait donner -2.001930531.

 - -- -+ - - -+-++-+
 +-- + +-- + ++-++ -
---++-+-+- -+- - +- 
-- - -++-+  --+  +  
-   + --+ ++-+  +-  
--  ++- + +  -+--+  
+ +++-+--+ +--+++ + 
-+- +-+-+-+  -+ +--+
- +-+- +      ---+  
-     - ++ -+- --+--

Devrait donner -22.030557890.

---+--- ++-+++- -+ +
-+ ---+++-+- +- +  +
---+-+ - ----  +-- -
 -   + +--+ -++- - -
--+ - --- - -+---+ -
+---+----++ -   +  +
-+ - ++-- ++-  -+++ 
 +----+-   ++-+-+  -
++- -+ -+---+  -- -+
+-+++ ++-+-+ -+- +- 

Devrait donner 26.231088767.

lirtosiast
la source
1
Points positifs pour la mise en œuvre de conditions aux limites périodiques et le calcul de l'énergie de Madelung.
Andras Deak
1
@AndrasDeak Ce serait intéressant.
lirtosiast

Réponses:

3

Pyth, 34 octets

smc*FhMd.atMd.cs.e+RkCUBxL" +"b.z2

Manifestation

Tout d'abord, nous convertissons chaque caractère en +1 pour +, -1 pour -et 0 pour . Ensuite, chaque nombre est annoté avec sa position dans la matrice. À ce stade, nous avons une matrice qui ressemble à:

[[[-1, 0, 0], [-1, 1, 0], [-1, 2, 0], [1, 3, 0], [-1, 4, 0], [-1, 5, 0], [-1, 6, 0]],
 [[1, 0, 1], [1, 1, 1], [-1, 2, 1], [-1, 3, 1], [0, 4, 1], [1, 5, 1], [0, 6, 1]]]

Le code qui atteint ce point est .e+RkCUBxL" +"b.z

Ensuite, nous aplatissons cette matrice dans une liste et prenons toutes les paires possibles, avec .cs ... 2.

Ensuite, il trouve la distance entre la paire avec .atMdet le signe du potentiel avec *FhMd, divise et additionne.

isaacg
la source
6

CJam, 51 caractères

Compter toutes les paires, filtrer Inf/NaNet diviser par deux:

q_N#:L;N-" +"f#ee2m*{z~:*\Lfmd2/:.-:mh/}%{zL<},:+2/

Alternativement, en filtrant les coordonnées en premier, nous comptons chaque paire une fois et ne rencontrons pas Inf/NaN:

q_N#:L;N-" +"f#ee2m*{0f=:<},{z~:*\Lfmd2/:.-:mh/}%:+

Explication (ancienne)

q                        Get all input.
 _N#:L;                  Store the line width in L.
       N-                Flatten it into one long line.
         :i              Get all ASCII values.
           :(3f%:(       Map space to 0, + to 1, - to -1.
                  ee     Enumerate: list of [index, sign] pairs.
                    2m*  Get all possible pairs.

{                        }%     For each pair:
 e_~                              i1 s1 i2 s2
    @*                            i1 i2 s        (multiply signs)
      \aa@aa+                     s [[i2] [i1]]  (put indices in nested list)
             Lffmd                s [[x2 y2] [x1 y1]]  (divmod by L)
                  :.-             s [xD yD]      (point diff)
                     :mh          s d            (Euclidean dist.)
                        /         s/d            (divide)

{zL<},                   Filter out infinite results.
      :+2/               Sum all charges, and divide by two.
                           (We counted each pair twice.)
Lynn
la source
3
Alors l'explication est TBA? : P
Rɪᴋᴇʀ
2
Avez-vous écrit ceci alors qu'il était en bac à sable, ou êtes-vous vraiment très rapide?
lirtosiast
Je suis assez rapide :) La première version était "la chose la plus simple qui ait fonctionné", ce qui ne m'a pris que quelques minutes pour l'écrire, alors j'ai immédiatement posté cela, puis je l'ai étudiée pendant la demi-heure suivante.
Lynn
4

Haskell, 149 144 octets

z=zip[0..]
g n|f<-[(x,y,c)|(y,r)<-z$lines n,(x,c)<-z r,c>' ']=sum[c%d/sqrt((x-i)^2+(y-j)^2)|a@(x,y,c)<-f,b@(i,j,d)<-f,a/=b]/2
c%d|c==d=1|1<2= -1

Exemple d'utilisation:

*Main> g " - -- -+ - - -+-++-+\n +-- + +-- + ++-++ -\n---++-+-+- -+- - +- \n-- - -++-+  --+  +  \n-   + --+ ++-+  +-  \n--  ++- + +  -+--+  \n+ +++-+--+ +--+++ + \n-+- +-+-+-+  -+ +--+\n- +-+- +      ---+  \n-     - ++ -+- --+--"
-22.030557889699853

fest une liste de tous les triplets (x-coord, y-coord, unit charge). gcalcule l'énergie potentielle pour toutes les combinaisons de deux de ces triplets qui ne sont pas égaux, les additionne et divise le résultat par 2.

nimi
la source
3

Rubis, 133

->n{t=i=j=0.0
c=[]
n.tr(' ',?,).bytes{|e|e-=44
z="#{j}+#{i}i".to_c
i+=1
e<-1?i=0*j+=1:(c.map{|d|t+=d[0]*e/(d[1]-z).abs};c<<[e,z])}
t}

Conserve un tableau des charges précédentes sous forme de tuples [charge, location(complex number)]et compare chaque nouvelle charge avec cette liste, avant de l'ajouter à la liste.

Tous les espaces dans l'entrée sont remplacés par des virgules. Cela permet l'affectation suivante en soustrayant 44 de leur code ascii:

symbol  charge (internal representation)
+        -1
,         0
-        +1

Le fait que le programme considère +comme -1 et -comme +1 ne fait aucune différence pour le résultat final. Le fait que le programme fasse l'effort de calculer l'influence des charges de 0 pour les espaces ne fait aucune différence, à part le ralentir un peu :-)

Non testé dans le programme de test

g=->n{
  t=i=j=0.0                           #t=total potential; i and j are coordinates of charge.
  c=[]                                #array to store tuples: charge + location (complex number).
  n.tr(' ',?,).bytes{|e|              #replace all spaces with commas, then iterate through characters.
    e-=44                             #subtract 44 from ascii code: + -> -1; comma -> 0; - -> 1
    z="#{j}+#{i}i".to_c               #position of current character as complex number
    i+=1                              #advance x coordinate to next character.
    e<-1?i=0*j+=1:                    #if current character is newline, set i to zero and advance j instead,
    (c.map{|d|t+=d[0]*e/(d[1]-z).abs};#else add up the contribution for interaction of the current charge with all previous charges, 
    c<<[e,z])}                        #and append the current charge to the list of previous charges.
t}                                    #return t

p g[
'+       -
-       +'
]

p g[
' - -- -+ - - -+-++-+
 +-- + +-- + ++-++ -
---++-+-+- -+- - +- 
-- - -++-+  --+  +  
-   + --+ ++-+  +-  
--  ++- + +  -+--+  
+ +++-+--+ +--+++ + 
-+- +-+-+-+  -+ +--+
- +-+- +      ---+  
-     - ++ -+- --+--'
]
Level River St
la source
3

MATL , 39 42 octets

`jt]N$v'- +'FT#m2-I#fbbhtZPwt!**1w/XRss

Fonctionne dans la version actuelle (5.1.0) . Le compilateur fonctionne sur Matlab ou Octave.

Chaque ligne est une entrée distincte. La fin est signalée en entrant une ligne vide.

Exemples

>> matl
 > `jt]N$v'- +'FT#m2-I#fbbhtZPwt!**1w/XRss
 > 
> +       -
> -       +
> 
-2.001930530821583

>> matl
 > `jt]N$v'- +'FT#m2-I#fbbhtZPwt!**1w/XRss
 > 
>  - -- -+ - - -+-++-+
>  +-- + +-- + ++-++ -
> ---++-+-+- -+- - +- 
> -- - -++-+  --+  +  
> -   + --+ ++-+  +-  
> --  ++- + +  -+--+  
> + +++-+--+ +--+++ + 
> -+- +-+-+-+  -+ +--+
> - +-+- +      ---+  
> -     - ++ -+- --+--
> 
-22.03055788969994

Explication

`jt]           % keep inputting lines until an empty one is found
N$v            % concatenate all inputs vertically. This removes the last empty line
'- +'FT#m      % replace '-', ' ', '+'  by numbers 1, 2, 3
2-             % transform into -1, 0, 1 for '-', ' ', '+'
I#f            % find rows, columnss and values of nonzeros
bbh            % concatenate rows and columns into 2-col matrix or coordinates
tZP            % compute pair-wise distances for those coordinates
wt!*           % generate matrix of signs depending on signs of charges
*              % multiply distances by signs, element-wise
1w/            % invert element-wise
XR             % keep part over the diagonal
ss             % sum along colums, then rows
               % (output is implicitly printed)
Luis Mendo
la source
3

Lua, 293 255 246 228 octets

e=0l={}p={}i=1while l[i-1]~=""do l[i]=io.read()for k=1,#l[i]do c=l[i]:sub(k,k)if(c>" ")then for h,v in ipairs(p)do e=e+(v.s==c and 1 or-1)/math.sqrt((v.y-i)^2+(v.x-k)^2)end table.insert(p,{s=c,x=k,y=i})end end i=i+1 end print(e)

Aïe, 228 octets ... Je peux probablement jouer au golf de manière significative, mais je vais le poster ici pour l'instant. Mettez-le probablement à jour plus tard ce soir avec quelques réflexions supplémentaires et (espérons-le) quelques améliorations de la longueur.

Non golfé

e=0l={}p={}i=1
while l[i-1]~=""do 
    l[i]=io.read()
    for k=1,#l[i]do
        c=l[i]:sub(k,k)
        if(c>" ")then
            for h,v in ipairs(p) do
                e=e+(v.s==c and 1 or-1)/math.sqrt((v.y-i)^2+(v.x-k)^2)
            end
            table.insert(p,{s=c,x=k,y=i})
        end
    end
    i=i+1 
end

print(e)

Mise à jour 255 octets: Suppression des deux derniers bas pour les boucles, le traitement est désormais effectué lorsque des chaînes sont ajoutées au tableau de chaînes.

Mise à jour 246 octets: remplacé c=="+"or"-"==cpar c>" "selon la suggestion de nimi. Excellente idée, merci!

Mise à jour 228 octets: si l'instruction peut être supprimée complètement en insérant dans le tableau après la boucle for, en économisant pas mal d'octets.

Cyv
la source
2

Mathematica 223 octets

Toujours jouer au golf.

f[{{c1_,p1_},{c2_,p2_}}]:=N[(c1 c2)/EuclideanDistance[p1,p2],13];
h[charges_]:=Tr[f/@Subsets[DeleteCases[Flatten[Array[{r[[#,#2]],{#,#2}}&,Dimensions[r=Replace[Characters[charges],{"+"-> 1,"-"->-1," "->0},2]]],1],{0,_}],{2}]]

Dernier cas de test:

h[{" - -- -+ - - -+-++-+", " +-- + +-- + ++-++ -", 
  "---++-+-+- -+- - +- ", "-- - -++-+  --+  +  ", 
  "-   + --+ ++-+  +-  ", "--  ++- + +  -+--+  ", 
  "+ +++-+--+ +--+++ + ", "-+- +-+-+-+  -+ +--+", 
  "- +-+- +      ---+  ", "-     - ++ -+- --+--"}]

-22.030557890

DavidC
la source