Potencial electrostático de un sistema simple.


21

En física, las cargas eléctricas repelen y, a diferencia, las cargas se atraen.

La energía potencial entre dos cargas unitarias separadas por una distancia des 1/dpara cargas similares y -1/dpara cargas diferentes. La energía potencial de un sistema de cargas es la suma de las energías potenciales entre todos los pares de cargas.

Reto

Determine la energía potencial de un sistema de cargas unitarias representadas por una cadena.

Este es el , por lo que gana la solución más corta en bytes.


Entrada

Una cadena no vacío de varias líneas, que consta de sólo +, -, y saltos de línea, con cada línea de una anchura constante. Los +y -representan cargos de +1 y -1 respectivamente. Por ejemplo, la siguiente cadena:

    + -
 +     

(considerando que la parte superior izquierda es el origen) representa un sistema con cargas positivas en (4,0) y (1, -1) y una carga negativa en (6,0).

Alternativamente, puede tomar la entrada como una lista de líneas.

Salida

Un número real firmado que representa la energía potencial del sistema de cargas. La salida debe ser correcta para cuatro cifras significativas o 10 -4 , lo que sea más flojo.

Casos de prueba:

   - 
     

Debería salir 0. No hay pares de cargas para repeler o atraer, y el espacio en blanco no cambia nada.

+  
  -

Solo hay dos cargos; están a 1 unidad de distancia en la dirección vertical y a 2 unidades de distancia en la dirección horizontal, por lo que su distancia es sqrt (5). La salida debe ser -1 / sqrt (5) = -0.447213595.

+       -
-       +

Debería dar -2.001930531.

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

Debería dar -22.030557890.

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

Debería dar 26.231088767.


1
Puntos positivos para implementar condiciones de contorno periódicas y calcular la energía de Madelung.
Andras Deak

1
@AndrasDeak Eso sería interesante.
lirtosiast

Respuestas:


3

Pyth, 34 bytes

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

Demostración

Primero, convertimos cada carácter a +1 para +, -1 para -y 0 para . Luego, cada número se anota con su posición en la matriz. En este punto, tenemos una matriz que se ve así:

[[[-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]]]

El código que llega a este punto es .e+RkCUBxL" +"b.z

Luego, aplanamos esta matriz en una lista y tomamos todos los pares posibles, con .cs ... 2.

Luego, encuentra la distancia entre el par con .atMdy el signo del potencial con *FhMd, divide y suma.


6

CJam, 51 caracteres

Contando todos los pares, filtrando Inf/NaNy dividiendo entre dos:

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

Alternativamente, filtrar las coordenadas primero para contar cada par una vez y no encontrarnos con Inf/NaN:

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

Explicación (antigua)

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.)

3
Entonces, ¿la explicación es TBA? : P
Rɪᴋᴇʀ

2
¿Escribiste esto mientras estaba en la caja de arena, o eres realmente rápido?
lirtosiast

Soy bastante rápido :) La primera versión fue "la cosa más simple que funcionó", lo que me tomó solo un par de minutos para escribir, así que inmediatamente publiqué eso, luego lo bajé durante la siguiente media hora.
Lynn

4

Haskell, 149 144 bytes

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

Ejemplo de uso:

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

fes una lista de todos los triples (x-coord, y-coord, unit charge). gcalcula la energía potencial para todas las combinaciones de dos triples que no son iguales, las suma y divide el resultado por 2.


3

Rubí, 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}

Mantiene una serie de cargos anteriores en forma de tuplas [charge, location(complex number)]y compara cada nuevo cargo con esta lista, antes de agregarlo a la lista.

Todos los espacios en la entrada se reemplazan con comas. Esto permite la siguiente asignación restando 44 de su código ASCII:

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

El hecho de que el programa considere +-1 y -+1 no hace ninguna diferencia en el resultado final. El hecho de que el programa se esfuerce por calcular la influencia de las cargas de 0 para los espacios no hace ninguna diferencia, aparte de ralentizarlo un poco :-)

Sin golf en el programa de prueba

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[
' - -- -+ - - -+-++-+
 +-- + +-- + ++-++ -
---++-+-+- -+- - +- 
-- - -++-+  --+  +  
-   + --+ ++-+  +-  
--  ++- + +  -+--+  
+ +++-+--+ +--+++ + 
-+- +-+-+-+  -+ +--+
- +-+- +      ---+  
-     - ++ -+- --+--'
]

3

MATL , 39 42 bytes

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

Funciona en la versión actual (5.1.0) . El compilador se ejecuta en Matlab u Octave.

Cada línea es una entrada separada. El final se señala ingresando una línea vacía.

Ejemplos

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

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

Explicación

`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)

3

Lua, 293 255 246 228 Bytes

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)

Ay, 228 bytes ... Probablemente pueda jugar golf significativamente, pero lo publicaré aquí por ahora. Probablemente lo actualice más tarde esta noche con algunas reflexiones más y (con suerte) algunas mejoras en la duración.

Sin 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)

Actualización de 255 bytes: se eliminaron los dos últimos inferiores para los bucles, el procesamiento ahora se realiza a medida que se agregan cadenas a la matriz de cadenas.

Actualización de 246 Bytes: Sustituido c=="+"or"-"==ccon c>" "según la sugerencia del Nombre del modelo. Gran idea, gracias!

Actualización de 228 bytes: si la declaración se puede eliminar por completo insertando en la tabla después del ciclo for, ahorrando bastantes bytes.


2

Mathematica 223 bytes

Todavía jugando al 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}]]

Último caso de prueba:

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

-22.030557890

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.