Obliczanie oporu (Nerd Sniping)

10

Dzień dobry golfiści,

Nasze dzisiejsze wyzwanie jest inspirowane komiksami XKCD 356 i 370 . Napiszemy program do obliczania rezystancji grupy rezystorów. Ostrzeżenie, że jest to prawie wystarczająco trudne, aby uzasadnić wyzwanie kodowe, myślę jednak, że istnieje pewna sztuka pisania nieco bardziej złożonych programów w formacie golfowym. Najniższa liczba znaków wygrywa.

Obliczanie oporu opiera się na dwóch następujących wzorach:

  • Jeśli rezystory są szeregowo, rezystancja jest sumą rezystancji każdego rezystora
  • Jeśli rezystory są równoległe, rezystancja jest odwrotnością sumy odwrotności rezystancji każdego rezystora

Więc - na przykład:

Przykład obliczania oporu

Twoim zadaniem jest, w jak najmniejszej liczbie znaków, obliczyć opór grupy do 64 rezystorów. Przepraszam za złożoność, szczególnie zasad wprowadzania danych. Próbowałem zdefiniować je w taki sposób, aby każdy język był użyteczny.

  • Każdy rezystor zostanie podłączony do 2 lub więcej innych rezystorów.

  • Dane wejściowe są gwarantowane, z jednym wejściem i jednym punktem wyjścia, które się połączą

  • Sieć będzie szeregowo równoległa, aby nie wymagać więcej matematyki niż to, co jest prezentowane

  • Dane wejściowe będą dokonywane za pomocą pliku, argumentu lub standardowego wejścia, w zależności od tego, co jest odpowiednie dla twojego języka.

  • Dane wejściowe będą składały się z szeregu oddzielnych instrukcji nowej linii lub przecinanych do przodu, zawierających liczbę całkowitą rezystancji rezystora oraz spacje oddzielające identyfikatory rezystorów, do których podłączona jest jedna strona rezystora.

  • Identyfikator pierwszego rezystora będzie wynosił 1, zwiększając się o jeden dla każdego kolejnego rezystora

  • Początek zawsze będzie miał identyfikator 0

  • Rezystor końcowy zawsze będzie miał rezystancję 0 omów, a połączenia będą mieć tylko zdefiniowane na swojej linii

Na przykład:

Przykład 2

Może być reprezentowany jako

3 0
6 1
1 0
5 0
0 2 3 4
  • Wyjściem może być wyjście standardowe lub plik. Może być reprezentowany na jeden z następujących sposobów:
    • Liczba z minimum 2 miejscami po przecinku, po której następuje nowa linia
    • Ułamek składający się z liczby całkowitej (licznika), ukośnika i innej liczby całkowitej (mianownika), po której następuje nowa linia. Frakcja nie musi być w najniższej formie - na przykład dopuszczalne są 4/4 lub 10/8. Ułamek musi być dokładny w granicach 1/100. Nie ma żadnej premii za bycie idealnie dokładnym - jest to podstawa umożliwiająca konkurowanie językach bez operacji stałych lub zmiennoprzecinkowych.

Mam nadzieję, że obejmuje to wszystkie punkty. Powodzenia!

Lochok
źródło
/nie jest odwrotnym ukośnikiem. Miałeś na myśli `\ 'lub ukośnik?
John Dvorak,
Czy wolno nam wytwarzać nieprawidłowe wyniki, jeśli dane wejściowe nie są siecią szeregowo-równoległą?
John Dvorak
1
mostek Wheatstone'a nie jest szeregowo-równoległy, jeśli wymienić środkową woltomierz z rezystorem
John Dvorak
1
czy rezystory zawsze będą łączyć się z tymi o niższym ID, czy mogą być wprowadzane w dowolnej kolejności? Jest 1 2/1 0/0 1ważny?
John Dvorak,
9
Podobny przykład jest zły. Powinien to być 15/23, a nie 15/8.
Peter Taylor

Odpowiedzi:

6

APL 190

Indeks początku 1. Pierwsza pętla (pętle) łączy wszystkie rezystory połączone szeregowo, druga (p) połączona równolegle i powtórzenie do pierwszej pętli, aby połączyć wszystkie równoległe rezystory połączone szeregowo. Specyfikacja końcowego rezystora zerowego wydaje się zbędna.

r←¯1↓⍎¨(c≠'/')⊂c        
o←⊃↑¨r                  
r←⊃1↓¨r                 
s:→(0=+/n←1=+/×r)/p     
n←↑n/i←⍳↑⍴r             
o[n-1]←+/o[n-0 1]       
o←(i←n≠i)/o             
r←i⌿r                   
r←r-r≥n                 
→s                      
p:n←1⍪2≠/r[;1]          
r←((⍴r),1)⍴r←¯1++\n~0   
o←∊1÷¨+/¨1÷¨n⎕penclose o
→(1<⍴o)/s               
3⍕o                     
' '  

Przetestowano na przykładach w pytaniu plus nieco bardziej skomplikowany:

      Input: '5 0/3 1/1 2/0 2'
 9.000

      Input: '3 0/1 0/5 0/0 1 2 3'
 0.652

      Input: '3 0/6 1/1 0/5 0/0 2 3 4'
 0.763

      Input: '2 0/2 1/2 0/2 0/2 4/2 5/2 2 3 6/2 7/2 2 3 6/0 8 9'
 2.424
Graham
źródło
Zawsze zadziwione odpowiedziami APL - wyglądają absolutnie szalone. Ostateczny rezystor miał po prostu dać coś, z czym mogli się połączyć pozostałe rezystory - ślepy łącznik końcowy. Dobra robota!
lochok
Myślę, że możesz uratować kilka postaci. Zamień dwa pierwsze wiersze na o←⊃↑¨r←¯1↓⍎¨(c≠'/')⊂c. Ten wzór ma zastosowanie w kilku miejscach.
FUZxxl,
5

Python, 329 znaków

import sys
N=[[1]]+[map(int,x.split())for x in sys.stdin]
N[-1][0]=1
n=len(N)
S=[set([i])for i in range(2*n)]
for x in range(n):
 C=S[2*x]
 for y in N[x][1:]:C|=S[2*y+1]
 for x in C:S[x]|=C
V=[0]*(2*n-1)+[1]
for k in range(999):
 for i in range(1,2*n-1):V[i]+=sum((V[j^1]-V[i])/N[j/2][0]for j in S[i])/9./len(S[i])
print 1/V[1]-2

Oblicza rezystancję, wykonując relaksację napięcia w obwodzie. Najpierw mocuje opornik 1 omów do początku i zmienia ostatni opornik z 0 omów na 1 omów. Następnie ustawia napięcie wejściowe na 0, a napięcie wyjściowe na 1 wolt. Po symulacji przepływu prądu przez sieć rezystancję sieci oblicza się na podstawie spadku napięcia na pierwszym rezystorze 1 om.

Każdemu opornikowi przypisane są dwie liczby: numer lewego zacisku i numer prawego zacisku. Lewy zacisk rezystora r ma wartość 2 * r, a prawy zacisk 2 * r + 1. Dane wejściowe służą do obliczania Szestawów zacisków, które są ze sobą połączone. Każdy zacisk otrzymuje napięcie, V[t]a relaksacja odbywa się poprzez podniesienie napięcia, jeśli prąd płynie do zestawu zacisków, i obniżenie napięcia, jeśli prąd wypływa z sieci.

Keith Randall
źródło
2

(To jest komentarz, ale nie mogę robić sztuki ascii w prawdziwym komentarzu ...)

Jak wprowadzono coś takiego?

    --1--     --3--
   /     \   /     \
---       ---       --0--
   \     /   \     /
    --2--     --4--

W szczególności z czym są połączone 3 i 4? 1 lub 2, czy zarówno 1, jak i 2?

Keith Randall
źródło
Zarówno jeden, jak i drugi
lochok