Potenziale elettrostatico di un sistema semplice


21

In fisica, come le cariche elettriche si respingono e diversamente dalle cariche si attraggono.

L'energia potenziale tra due cariche unitarie separate da una distanza dè 1/dper cariche simili e -1/dper cariche diverse. L'energia potenziale di un sistema di cariche è la somma delle energie potenziali tra tutte le coppie di cariche.

Sfida

Determina l'energia potenziale di un sistema di cariche unitarie rappresentato da una stringa.

Questo è , quindi vince la soluzione più breve in byte.


Ingresso

Una stringa non vuota multilinea, composto da soli +, -, e nuove righe, con ogni riga una larghezza costante. La +e -rappresentano accuse di +1 e -1 rispettivamente. Ad esempio, la seguente stringa:

    + -
 +     

(considerando l'origine in alto a sinistra) rappresenta un sistema con cariche positive a (4,0) e (1, -1) e una carica negativa a (6,0).

In alternativa, puoi inserire input come un elenco di righe.

Produzione

Un numero reale firmato che rappresenta l'energia potenziale del sistema di cariche. L'output dovrebbe essere corretto su quattro cifre significative o 10 -4 , a seconda di quale sia più flessibile.

Casi test:

   - 
     

Dovrebbe produrre 0. Non ci sono coppie di cariche da respingere o attrarre, e lo spazio bianco non cambia nulla.

+  
  -

Ci sono solo due cariche; sono 1 unità di distanza in direzione verticale e 2 unità di distanza in direzione orizzontale, quindi la loro distanza è sqrt (5). L'output dovrebbe essere -1 / sqrt (5) = -0.447213595.

+       -
-       +

Dovrebbe dare -2.001930531.

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

Dovrebbe dare -22.030557890.

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

Dovrebbe dare 26.231088767.


1
Punti positivi per l'implementazione di condizioni al contorno periodiche e il calcolo dell'energia di Madelung.
Andras Deak,

1
@AndrasDeak Sarebbe interessante.
lirtosiast,

Risposte:


3

Pyth, 34 byte

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

Dimostrazione

Innanzitutto, convertiamo ogni personaggio in +1 per +, -1 per -e 0 per . Quindi, ogni numero viene annotato con la sua posizione nella matrice. A questo punto, abbiamo una matrice che assomiglia a:

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

Il codice che raggiunge questo punto è .e+RkCUBxL" +"b.z

Quindi, appiattiamo questa matrice in un elenco e prendiamo tutte le coppie possibili, con .cs ... 2.

Quindi, trova la distanza tra la coppia con .atMde il segno del potenziale con *FhMd, divide e somma.


6

CJam, 51 caratteri

Contando tutte le coppie, filtrando Inf/NaNe dividendo per due:

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

In alternativa, filtrando prima le coordinate, contiamo ogni coppia una volta e non ci imbattiamo in Inf/NaN:

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

Spiegazione (vecchia)

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
Quindi la spiegazione è TBA? : P
Rɪᴋᴇʀ

2
Hai scritto questo mentre era in modalità sandbox o sei davvero veloce?
lirtosiast

Sono abbastanza veloce :) La prima versione è stata "la cosa più semplice che ha funzionato", che mi ha richiesto solo un paio di minuti per scrivere, quindi l'ho immediatamente postato, poi l'ho buttato giù nella mezz'ora successiva.
Lynn,

4

Haskell, 149 144 byte

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

Esempio di utilizzo:

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

fè un elenco di tutte le triple (x-coord, y-coord, unit charge). gcalcola l'energia potenziale per tutte le combinazioni di due di queste triple che non sono uguali, le somma e divide il risultato per 2.


3

Ruby, 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 di addebiti precedenti sotto forma di tuple [charge, location(complex number)]e confronta ogni nuovo addebito con questo elenco, prima di aggiungerlo all'elenco.

Tutti gli spazi nell'input sono sostituiti da virgole. Ciò consente la seguente assegnazione sottraendo 44 dal loro codice ASCII:

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

Il fatto che il programma consideri +-1 e -sia +1 non fa differenza per il risultato finale. Il fatto che il programma faccia lo sforzo di calcolare l'influenza delle cariche di 0 per gli spazi non fa alcuna differenza, oltre a rallentarlo un po ':-)

Non registrato nel programma di 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[
' - -- -+ - - -+-++-+
 +-- + +-- + ++-++ -
---++-+-+- -+- - +- 
-- - -++-+  --+  +  
-   + --+ ++-+  +-  
--  ++- + +  -+--+  
+ +++-+--+ +--+++ + 
-+- +-+-+-+  -+ +--+
- +-+- +      ---+  
-     - ++ -+- --+--'
]

3

MATL , 39 42 byte

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

Funziona nella versione corrente (5.1.0) . Il compilatore funziona su Matlab o Octave.

Ogni riga è un input separato. L'estremità viene segnalata inserendo una riga vuota.

Esempi

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

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

Spiegazione

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

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)

Ahi, 228 byte ... Probabilmente posso giocare a golf in modo significativo, ma lo pubblicherò qui per ora. Probabilmente lo aggiornerò più tardi stasera con qualche altra riflessione e (si spera) alcuni miglioramenti alla lunghezza.

Ungolfed

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)

Aggiornamento 255 byte: rimossi i vecchi due inferiori per i loop, l'elaborazione ora viene eseguita mentre le stringhe vengono aggiunte all'array di stringhe.

Aggiornamento 246 byte: sostituito c=="+"or"-"==ccon c>" "il suggerimento di nimi. Ottima idea, grazie!

Aggiornamento 228 byte: se l'istruzione può essere rimossa completamente inserendola nella tabella dopo il ciclo for, risparmiando parecchi byte.


2

Mathematica 223 byte

Giocare ancora a 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}]]

Ultimo caso di test:

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

-22,030557890

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.