Elektrostatisches Potential eines einfachen Systems

21

In der Physik stoßen sich elektrische Ladungen ab und ziehen sich anders als Ladungen an.

Die potentielle Energie zwischen zwei Einheitsladungen, die durch eine Entfernung voneinander getrennt sind, dgilt 1/dfür gleiche Ladungen und -1/dfür ungleiche Ladungen. Die potentielle Energie eines Ladungssystems ist die Summe der potentiellen Energien zwischen allen Ladungspaaren.

Herausforderung

Bestimmen Sie die potenzielle Energie eines Systems von Einheitsgebühren, die durch eine Zeichenfolge dargestellt werden.

Das ist , also gewinnt die kürzeste Lösung in Bytes.


Eingang

Ein nicht - leerer mehrzeilige Zeichenfolge, die nur aus +, -, und neue Zeilen, wobei jede Zeile mit einer konstanten Breite. Die +und -repräsentieren Ladungen von +1 bzw. -1. Zum Beispiel die folgende Zeichenfolge:

    + -
 +     

(unter Berücksichtigung des Ursprungs von links oben) repräsentiert ein System mit positiven Ladungen bei (4,0) und (1, -1) und einer negativen Ladung bei (6,0).

Alternativ können Sie Eingaben als Zeilenliste übernehmen.

Ausgabe

Eine vorzeichenbehaftete reelle Zahl, die die potenzielle Energie des Ladesystems darstellt. Die Ausgabe sollte auf vier signifikante Stellen oder 10 -4 (je nachdem, welcher Wert niedriger ist) korrekt sein .

Testfälle:

   - 
     

Sollte ausgeben 0. Es gibt keine Ladungspaare, die sich abstoßen oder anziehen lassen, und das Leerzeichen ändert nichts.

+  
  -

Es gibt nur zwei Gebühren; Sie sind 1 Einheit in vertikaler Richtung und 2 Einheiten in horizontaler Richtung entfernt, sodass ihr Abstand sqrt (5) beträgt. Die Ausgabe sollte -1 / sqrt (5) = sein -0.447213595.

+       -
-       +

Sollte geben -2.001930531.

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

Sollte geben -22.030557890.

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

Sollte geben 26.231088767.

Lirtosiast
quelle
1
Pluspunkte für die Implementierung periodischer Randbedingungen und die Berechnung der Madelung-Energie.
Andras Deak
1
@AndrasDeak Das wäre interessant.
Lirtosiast

Antworten:

3

Pyth, 34 Bytes

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

Demonstration

Zuerst konvertieren wir jedes Zeichen in +1 für +, -1 für -und 0 für . Dann wird jede Zahl mit ihrer Position in der Matrix beschriftet. An dieser Stelle haben wir eine Matrix, die so aussieht:

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

Der Code, der diesen Punkt erreicht, ist .e+RkCUBxL" +"b.z

Dann reduzieren wir diese Matrix in eine Liste und nehmen alle möglichen Paare mit .cs ... 2.

Dann findet er den Abstand zwischen dem Paar mit .atMdund dem Vorzeichen des Potentials mit *FhMd, dividieren und summieren.

isaacg
quelle
6

CJam, 51 Zeichen

Alle Paare zählen, Inf/NaNherausfiltern und durch zwei teilen:

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

Alternativ können Sie die Koordinaten zuerst filtern, damit wir jedes Paar einmal zählen und nicht auf Folgendes stoßen Inf/NaN:

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

Erklärung (alt)

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
quelle
3
Erklärung ist also TBA? : P
Rɪᴋᴇʀ
2
Hast du das geschrieben, während es in einer Sandkiste war, oder bist du nur sehr schnell?
Lirtosiast
Ich bin ziemlich schnell :) Die erste Version war "die einfachste, die funktioniert hat", und ich brauchte nur ein paar Minuten, um sie zu schreiben. Deshalb habe ich sie sofort gepostet und sie dann in der nächsten halben Stunde abgelegt.
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

Anwendungsbeispiel:

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

fist eine Liste aller Tripel (x-coord, y-coord, unit charge). gberechnet die potentielle Energie für alle Kombinationen von zwei solchen Dreifachen, die nicht gleich sind, summiert sie und dividiert das Ergebnis durch 2.

nimi
quelle
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}

Verwaltet eine Reihe früherer Gebühren in Form von Tupeln [charge, location(complex number)]und vergleicht jede neue Gebühr mit dieser Liste, bevor sie an die Liste angehängt wird.

Alle Leerzeichen in der Eingabe werden durch Kommas ersetzt. Dies ermöglicht die folgende Zuordnung durch Subtrahieren von 44 von ihrem ASCII-Code:

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

Die Tatsache, dass das Programm +-1 und -+1 betrachtet, hat keinen Einfluss auf das Endergebnis. Die Tatsache, dass das Programm sich bemüht, den Einfluss der Ladungen von 0 auf die Leerzeichen zu berechnen, macht keinen Unterschied, abgesehen davon, dass es etwas langsamer wird :-)

Ungolfed im Testprogramm

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
quelle
3

MATL , 39 42 Bytes

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

Funktioniert in der aktuellen Version (5.1.0) . Der Compiler läuft auf Matlab oder Octave.

Jede Zeile ist ein separater Eingang. Das Ende wird durch Eingabe einer Leerzeile signalisiert.

Beispiele

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

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

Erläuterung

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

Autsch, 228 Bytes ... Ich kann das wahrscheinlich bedeutend Golf spielen, aber ich werde es vorerst hier posten. Aktualisiere es wahrscheinlich später heute Abend mit ein paar weiteren Überlegungen und (hoffentlich) einigen Verbesserungen der Länge.

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)

Update 255 Bytes: Die alten unteren zwei für Schleifen wurden entfernt. Die Verarbeitung erfolgt nun, wenn Zeichenfolgen zum Zeichenfolgenarray hinzugefügt werden.

Update 246 Bytes: Ersetzt c=="+"or"-"==cdurch c>" "den Vorschlag von Nimi. Tolle Idee, danke!

Update 228 Bytes: Wenn die Anweisung durch Einfügen in die Tabelle nach der for-Schleife vollständig entfernt werden konnte, werden einige Bytes gespart.

Cyv
quelle
2

Mathematica 223 Bytes

Immer noch Golf zu spielen.

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

Letzter Testfall:

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

-22.030557890

DavidC
quelle