Wprowadzenie
Podczas budowy projektu elektronicznego schemat może wymagać rezystora o nietypowej wartości (powiedzmy 510 omów). Sprawdzasz pojemnik na części i okazuje się, że nie masz rezystorów 510 omów. Ale masz wiele wspólnych wartości powyżej i poniżej tej wartości. Łącząc rezystory równolegle i szeregowo, powinieneś być w stanie dość dobrze przybliżyć rezystor 510 Ω.
Zadanie
Musisz napisać funkcję lub program, który akceptuje listę wartości rezystorów (zapas rezystorów) i wartość docelową (którą chcesz przybliżyć). Program musi uwzględniać:
- Indywidualne rezystory
- Dwa rezystory w szeregu
- Dwa oporniki równolegle
Program powinien obliczyć wszystkie możliwe kombinacje rezystorów 1 i 2 z listy zapasów (w tym dwie kopie tej samej wartości rezystora), obliczyć ich szeregową i równoległą rezystancję, a następnie posortować konfiguracje według tego, jak dobrze przybliżają wartość docelową.
Format wyjściowy powinien mieć jedną konfigurację na linię, z +
szeregiem |
oznaczającym i oznaczającym równolegle oraz pewną spacją lub znakiem = przed oporem netto.
Formuły
- Rezystancja jednego opornika wynosi
R1
- Rezystancja netto dwóch rezystorów szeregowych wynosi
R1 + R2
- Rezystancja netto dwóch równoległych rezystorów wynosi
1 / (1/R1 + 1/R2)
- Odległość między aproksymacją wartości oporu oraz wartości zadanej może być obliczona jako pseudo-odległości logarytmicznym nie liniowa odległość:
dist = abs(Rapprox / Rtarget - 1)
. Na przykład 200 jest bliższe 350 niż 100. - Lepszą miarą odległości jest prawdziwa odległość logarytmiczna
dist = abs(log(Rapprox/Rtarget))
, ale ponieważ nie zostało to określone w pierwotnym pytaniu, możesz dowolnie stosować dowolny pomiar.
Punktacja
Wynik mierzony jest znakami kodu, zgodnie ze zwykłymi zasadami golfa. Najniższy wynik wygrywa.
Przykład
W magazynie mamy następujące rezystory [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700]
i chcemy kierować 510
omy. Program powinien wypisać 143 konfiguracje, w przybliżeniu jak pokazano (możesz zmienić format, ale upewnij się, że znaczenie jest łatwe do ustalenia):
680 | 2200 519.444
1000 | 1000 500.
150 + 330 480.
220 + 330 550.
470 470
680 | 1500 467.89
680 | 3300 563.819
100 + 470 570.
220 + 220 440.
100 + 330 430.
470 | 4700 427.273
680 | 4700 594.052
1000 | 1500 600.
470 | 3300 411.406
680 | 1000 404.762
150 + 470 620.
...
many more rows
...
2200 + 4700 6900.
3300 + 4700 8000.
4700 + 4700 9400.
W tym przykładzie najlepsze przybliżenie 510 omów podane jest równolegle przez rezystory 680 i 2200 omów.
Najlepsze z dotychczasowych języków (1 czerwca 2014 r.):
- J - 70 znaków
- APL - 102 znak
- Mathematica - 122 znaków
- Ruby - 154 znak
- JavaScript - 156 znaków
- Julia - 163 char
- Perl - 185 znaków
- Python - 270 znaków
Odpowiedzi:
J -
867170 charNie zamierzam zawracać sobie głowy wyjaśnianiem każdego najmniejszego szczegółu, ponieważ dużo kodu spędza się na synchronizowaniu wyników różnych funkcji, ale oto sedno gry w golfa:
;@((<@,.{:)\)
sprawia, że każda możliwa para rezystorów może być połączona równolegle lub szeregowo.[:,/(<,.+`|,.+/;+&.%/)"1@
następnie łączy je równolegle i szeregowo, tworząc dużą listę możliwych połączeń.(;a:,<)"0,
dodaje możliwość zastosowania tylko jednego rezystora jako przybliżenia.(]/:[|@<:@%~2{::"1])
sortuje listę kombinacji rezystorów według odległości pseudologicznej (|@<:@%
) między celem a rezystancją wynikową z każdej kombinacji.A oto jak go użyć:
Nie musisz tylko wyświetlać pierwszych 10, jak ja powyżej, ale jest to funkcja i J REPL obcina bardzo duże zwracane wartości, a pełne wyjście dla tego przykładu ma 287 linii. Możesz wymusić to wszystko do STDOUT za pomocą czegoś takiego jak
tmoutput toCRLF , LF ,.~ ": blah rouv blah
w systemie Windows - upuśćtoCRLF
na Linuksie - alerouv
jest funkcją i wewnętrznie wszystkie wiersze istnieją.Uwaga:
Wydaje się, że pytanie zostało zmienione tuż pod naszymi nosami, a teraz odległość kłody jest zdefiniowana jako
abs(log(Rapprox/Rtarget))
zamiastabs(Rapprox/Rtarget-1)
. Aby rozwiązać ten problem w moim golf, możemy zmienić|@<:@%
się|@^.@%
:<:
jest Decrement natomiast^.
jest Logarytm.źródło
Mathematica,
151122 znakówOczekuje, że docelowa rezystancja zostanie zapisana,
r
a lista dostępnych rezystorów wl
.Mniej golfa:
Format wyjściowy różni się od sugerowanego, ale konfiguracje można łatwo określić. Dane wyjściowe to lista konfiguracji. Każda konfiguracja ma jedną z następujących postaci:
Tak więc pierwsze trzy elementy wyniku zostały odczytane
Jeśli nie masz racjonalnych liczb, mogę uratować dwie postacie przed pominięciem
N@
. Oznacza to, że pierwszy element (na przykład) zostałby zwrócony jako4675/9
zamiast519.444
.źródło
APL (102)
To przyjmuje docelowy opór za lewy argument i listę dostępnych rezystorów jako prawy argument.
Wyjaśnienie:
V←{
...}
:V
jest funkcją, która:Z/⍨≤/¨Z←,∘.,⍨⍵
: znajduje każdą unikalną kombinację dwóch wartości w⍵
,Z←,∘.,⍨⍵
: połącz każdą wartość⍵
z każdą wartością w⍵
, zapisz wZ
,Z/⍨≤/¨Z
: wybierz jedną zZ
tych kombinacji, w których pierwsza wartość jest mniejsza lub równa drugiej wartości⍺{
...}⍺⍺/¨
: a następnie stosuje następującą funkcję, związaną z lewą funkcją (⍺⍺
) po prawej stronie i lewym argumentem (⍺
) po lewej stronie, do każdej pary:⍺,⍺⍺,⍵,'=',⍺⍵⍵⍵
, lewy argument, po nim lewostronny argument, następnie prawy argument, a po nim=
, a po nim prawa funkcja (⍵⍵
) zastosowana do obu argumentów. (To jest funkcja formatowaniaX [configuration] Y [equals] (X [fn] Y)
.)⊃¨
: a następnie rozpakuj każdy element.{⍵,' =',⍵}¨⍵
: dla każdego elementu⍵
weź konfiguracje dla poszczególnych rezystorów. (⍵
nic, nic=
,⍵
).('+'+V⍵)
: użyjV
funkcji, aby wykonać wszystkie konfiguracje szeregowe (znak jest'+'
i funkcja jest+
).'|'{÷+/÷⍺⍵}V⍵
: użyjV
funkcji, aby wykonać wszystkie konfiguracje równoległe (znak jest'|'
i funkcja jest{÷+/÷⍺⍵}
odwrotnością sumy odwrotności argumentów).K←↑
: przekształć to w macierz i zapisz wK
.0 4↓K
: upuść 4 pierwsze kolumny zK
, pozostawiając tylko wartości oporu.|¯1+⍺÷⍨
: oblicz odległość między⍺
każdą konfiguracją.K[⍋
...;]
: sortujK
według odległości.źródło
510 code_here 100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700
⍎
), I / O (⎕
) ani żadnych zmiennych systemowych (nawet⎕UCS
i⎕A
nie działa), więc większość programów APL nie będzie działać. Faktycznie da BŁĄD SYNTAXU, jeśli zostanie użyta jedna z wyłączonych funkcji. Fakt, że ta nie korzysta z jednej z wielu funkcji, których TryAPL nie obsługuje, jest zbiegiem okoliczności.Python 3 -
250247270 bajtówUruchom tak:
(tzn. lista rezystorów rozdzielana spacjami, z wartością docelową na końcu)
Wydajność:
Powiedziałbym, że generowanie, powiedzmyNie do przyjęcia. Kosztował mnie bajtów. Teraz sortuję krotki przed wrzuceniem ich do zestawu, w przeciwnym razie rozwiązanie jest identyczne.680|2200
i2200|680
oddzielnie, jest nadal całkiem jasne. Jeśli jest to nie do przyjęcia, mogę to zmienić, ale będzie mnie to kosztowało bajtów.źródło
import sys;r=sys.args[1:]
użyjr=input().split()
i powiedz, że musisz podać wartości standardowe. Nareszcie: używasz1/sum(1/int(n)for n in b)
zamiast1/sum(map(lambda n:1/int(n),b)
. W sumie powinno to być 274 znakówRuby 2.1,
156154 bajtyNie golfowany:
Co to robi:
e
wa
;a
, obliczając wartości pojedyncze, szeregowe i równoległe jako klucze do drukowanych wartości w haszuc
;z
dla każdego klucza wc
; i,e[1]
dla każdego kluczae[0]
wc
wydrukue[1]=e[0]
.Przykładowe użycie:
s[[100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700], 510]
Przykładowe dane wyjściowe:
źródło
JavaScript (ECMAScript 6) - 186 znaków
Wkład:
R
sił rezystora; iT
, docelowy opór.Wydajność:
Tablica tablic (posortowana według odległości od
T
), z których każda zawiera:p
,s
Lub 0 rezystory są równoległe, szeregowe lub izolatce; iWyjaśnienie:
źródło
Julia -
179163 bajtyDziała to tak samo jak stara wersja, ale argument w instrukcji print został nieco inaczej zorganizowany, aby zmniejszyć liczbę niezbędnych nawiasów kwadratowych. Oszczędza 4 bajty. Absorbowanie tworzenia wektora spacji do argumentu print pozwala zaoszczędzić dodatkowe 2 bajty. Zmienił także używanie „znajdź”, aby uzyskać odpowiednie indeksy, na używanie logicznej postaci. Oszczędza 6 bajtów. Absorbując obliczenia wektora indeksu do korekty A zaoszczędzono kolejne 2 bajty. Wreszcie, zastąpienie endof (v) sumą (v) pozwoliło zaoszczędzić 2 kolejne bajty. Całkowita oszczędność: 16 bajtów.
Stara wersja:
W ramach funkcji oto, co robi:
Przykładowe dane wyjściowe:
źródło
JavaScript (E6) 156
162 164 186Ostatnia edycja Zakładając, że wszystkie wartości rezystorów> 0, możesz użyć ich jako warunku pętli
Stosowanie :
F(510, [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700])
Bez golfa
źródło
JavaScript, 248 bajtów
Stosowanie :
r(510, [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700]);
Wydajność
źródło
Perl,
213199185 bajtów213 bajtów:
199 bajtów:
185 bajtów:
Przekaż wszystkie dostępne rezystory jako argumenty. Docelowy opór powinien być ostatnim:
Jak to działa (stary kod)
Zdefiniuj podprogramy
S
iP
oblicz sumę i wartości równoległe dwóch rezystorów.Ustaw
$"
na „,”, aby interpolować@ARGV
wewnątrzglob
operatora<{S,P}({@i},{@i})= S({@i})=>
generuje kartezjański wszystkich możliwości:S (100,100), S (100,150), S (100,220), ... P (100,100), P (100,150) ... S (100), S (150) ...
Połącz
s///ee
z,grep
aby ocenić równoważne rezystancje i odfiltrować niechciane powtórzenia (wykonywane przez(??{$2<$3})
i/\d$/
sort
według sprawności obliczonej w podprogramiet
Zmiany w nowym kodzie
Unikaj używania
s///ee
, używaj krótszego wyrażenia regularnego z kontrolą warunkową ieval
wewnątrzgrep
Zamień powtórzenia
"{@i}" with
$ i`Wprowadzenie
$x
,$y
zamiast$2
,$3
wymienić
split/=/,pop
z$_[0]=~s!!!r
Nie ma potrzeby ciągnięcia
;
eval;
jest równaeval $_;
Dodaj
=
wraz zeval
odpowiedzią -ed zamiast deklarować ją z góryWydajność:
P
reprezentuje rezystory równolegle,S
reprezentuje rezystory szeregowo.źródło
S(100)=100
iS(1000)=1000
.