Rezystory o niezwykłej wartości

23

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ć 510omy. 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.):

  1. J - 70 znaków
  2. APL - 102 znak
  3. Mathematica - 122 znaków
  4. Ruby - 154 znak
  5. JavaScript - 156 znaków
  6. Julia - 163 char
  7. Perl - 185 znaków
  8. Python - 270 znaków
fosgen
źródło
3
@Claudiu Nie ma różnicy elektrycznej między 100 + 150 a 150 + 100; oba wytwarzają rezystancję 250 omów i zużywają rezystor 100 omów i rezystor 150 omów, więc nie możemy liczyć podwójnie. Należy je jednak odróżnić od 125 + 125, ponieważ chociaż daje to również 250 omów, zużywa różne rezystory (co może być lepsze, biorąc pod uwagę naszą liczbę części).
fosgen
3
510 jest w serii E24, więc nie jest to niezwykłe mieć pod ręką
gnibbler
3
Fosgen, a ROUV?
niepomyślnie
3
Nie sądzę, że istnieją.
fosgen
1
Zazwyczaj nie ustalamy terminów na pytania dotyczące kodu golfa, ponieważ może to zniechęcić niektóre osoby do publikowania postów. Zawsze możesz zmienić zaakceptowane odpowiedzi.
Nzall

Odpowiedzi:

6

J - 86 71 70 char

((]/:[|@<:@%~2{::"1])(;a:,<)"0,[:,/(<,.+`|,.+/;+&.%/)"1@;@((<@,.{:)\))

Nie 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ć:

   rouv =: ((]/:[|@<:@%~2{::"1])(;a:,<)"0,[:,/(<,.+`|,.+/;+&.%/)"1@;@((<@,.{:)\))
   # 510 rouv 100 150 220 330 470 680 1000 1500 2200 3300 4700      NB. how many?
143
   10 {. 510 rouv 100 150 220 330 470 680 1000 1500 2200 3300 4700  NB. view first 10
+---------+-+-------+
|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    |
+---------+-+-------+

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 blahw systemie Windows - upuść toCRLFna Linuksie - ale rouvjest 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))zamiast abs(Rapprox/Rtarget-1). Aby rozwiązać ten problem w moim golf, możemy zmienić |@<:@%się |@^.@%: <:jest Decrement natomiast ^.jest Logarytm.

algorytmshark
źródło
Choć twój kod wydaje się niezgłębiony, wciąż możemy docenić tajemnicę. Najlepszy wynik po jednym dniu - czy będzie ważny?
fosgen
1
Nie, nie chcę wysyłać wiadomości na
adres
12

Mathematica, 151 122 znaków

Oczekuje, że docelowa rezystancja zostanie zapisana, ra lista dostępnych rezystorów w l.

SortBy[Join[{#,#}&/@l,Join@@(#@@@Union[Sort/@N@l~Tuples~{2}]&/@{{"+",##,#+#2}&,{"|",##,#*#2/(#+#2)}&})],Abs[#[[-1]]/r-1]&]

Mniej golfa:

SortBy[Join[{#, #} & /@ l,
  Join @@ (# @@@ 
       Union[Sort /@ N@l~Tuples~{2}] & /@ {{"+", ##, # + #2} &, {"|", ##, 
        #*#2/(# + #2)} &})], Abs[#[[-1]]/r - 1] &]

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:

{R1, Total}
{"+", R1, R2, Total}
{"|", R1, R2, Total}

Tak więc pierwsze trzy elementy wyniku zostały odczytane

{{"|", 680., 2200., 519.444}, {"|", 1000., 1000., 500.}, {"+", 150., 330., 480.}, ...}

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 jako 4675/9zamiast 519.444.

Martin Ender
źródło
Dobra robota. Pobiłeś mnie do tego (i krótszym kodem).
DavidC
15
Didn '# your den # is # w @ rn you @ g @ ins # e @ # ing # h @ # much syn # @ c # ic sug sug @ r?
fosgen
2
@ N @ l Tuples? Czy to jakaś choroba programistów?
clabacchio
@clabacchio niesamowite, nawet tego nie widziałem. fosgen, musiał zapomnieć o tym wspomnieć ... a może po prostu lubi też grać w golfa ...
Martin Ender
10

APL (102)

{V←{⊃¨⍺{⍺,⍺⍺,⍵,'=',⍺⍵⍵⍵}⍺⍺/¨Z/⍨≤/¨Z←,∘.,⍨⍵}⋄K[⍋|¯1+⍺÷⍨0 4↓K←↑('|'{÷+/÷⍺⍵}V⍵),('+'+V⍵),{⍵,'  =',⍵}¨⍵;]}

To przyjmuje docelowy opór za lewy argument i listę dostępnych rezystorów jako prawy argument.

Wyjaśnienie:

  • V←{... }: Vjest 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 w Z,
      • Z/⍨≤/¨Z: wybierz jedną z Ztych 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 formatowania X [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żyj Vfunkcji, aby wykonać wszystkie konfiguracje szeregowe (znak jest '+'i funkcja jest +).
  • '|'{÷+/÷⍺⍵}V⍵: użyj Vfunkcji, 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 w K.
  • 0 4↓K: upuść 4 pierwsze kolumny z K, pozostawiając tylko wartości oporu.
  • |¯1+⍺÷⍨: oblicz odległość między każdą konfiguracją.
  • K[⍋... ;]: sortuj Kwedług odległości.
marinus
źródło
3
Uwierzę ci, że to działa. W mojej klawiaturze brakuje raczej wielu z tych znaków: D
fosgen
@phosgene: Jeśli chcesz to przetestować, możesz pobrać wersję próbną Dyalog APL ze strony dyalog.com. Następnie wklej wszystko, powinno działać. Argumenty idą na bok, więc na przykład:510 code_here 100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700
marinus
@ phosgene Możesz wypróbować ten internetowy tłumacz, chociaż nie zapewnia on pełnego wyniku, możesz sprawdzić, czy kilka początkowych wierszy i kilka ostatnich wierszy są takie same.
user12205
Zweryfikowano! APL to jakieś ezoteryczne rzeczy.
fosgen
1
@ace TryAPL jest bardzo ograniczony i zwykle nie działa. To, że akurat działa na tym, jest tylko zbiegiem okoliczności. Nie obsługuje eval ( ), I / O ( ) ani żadnych zmiennych systemowych (nawet ⎕UCSi ⎕Anie 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.
marinus
4

Python 3 - 250 247 270 bajtów

from itertools import*
import sys
r=sys.argv[1:]
t=int(r.pop())
p=set(map(tuple,map(sorted,product(r,r))))
a=[('+'.join(b),sum(map(int,b)))for b in p]+[('|'.join(b),1/sum(map(lambda n:1/int(n),b)))for b in p]
for s in sorted(a,key=lambda b:abs(float(b[1])/t-1)):print(s)

Uruchom tak:

python resistors.py 100 150 220 330 470 680 1000 1500 2200 3300 4700 510

(tzn. lista rezystorów rozdzielana spacjami, z wartością docelową na końcu)

Wydajność:

('2200|680', 519.4444444444445)
('1000|1000', 500.0)
('150+330', 480)
('220+330', 550)
('1500|680', 467.88990825688074)
('3300|680', 563.8190954773869)

[snip]

('2200+4700', 6900)
('3300+4700', 8000)
('4700+4700', 9400)

Powiedziałbym, że generowanie, powiedzmy 680|2200i 2200|680oddzielnie, 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.Nie do przyjęcia. Kosztował mnie bajtów. Teraz sortuję krotki przed wrzuceniem ich do zestawu, w przeciwnym razie rozwiązanie jest identyczne.

podziemny monorail
źródło
Jasne, wyniki wydają mi się jasne!
fosgen
Jednak liczysz podwójnie. 150 + 330 jest elektrycznie identyczny z 330 + 150, więc tylko jeden z nich powinien pojawić się w wyniku (143 konfiguracji ogółem na przykład).
fosgen
@ pho Dobra, naprawione. Kilka dodatkowych bajtów, ale rozwiązanie powinno być teraz prawidłowe.
metro
Myślę też, że twój program w ogóle nie szuka jednego opornika (a + = [(a, a) dla inr]). Możesz pominąć a = ..., ponieważ używasz dokładnie jednego razu. O tym import sys;r=sys.args[1:]użyj r=input().split()i powiedz, że musisz podać wartości standardowe. Nareszcie: używasz 1/sum(1/int(n)for n in b)zamiast 1/sum(map(lambda n:1/int(n),b). W sumie powinno to być 274 znaków
WorldSEnder
Właśnie grałem w golfa jeszcze 1 znak: Użyj print (* sorted (...), sep = '\ n')
WorldSEnder
3

Ruby 2.1, 156 154 bajty

s=->(a,z){c={};a.map{|e|a.map{|f|c[e]=e;c[e+f]="#{e}+#{f}";c[1/(1.0/f+1.0/e)]="#{e}|#{f}"}};c.sort_by{|k,|(k/z.to_f-1).abs}.map{|e|puts"#{e[1]}=#{e[0]}"}}

Nie golfowany:

s =->(a,z) {
  c={}
  a.map{|e|
    a.map{|f|
      c[e]=e
      c[e+f]="#{e}+#{f}"
      c[1/(1.0/f+1.0/e)]="#{e}|#{f}"
    }
  }
  c.sort_by{|k,|
    (k/z.to_f-1).abs
  }.map{|e|
    puts "#{e[1]}=#{e[0]}"
  }
}

Co to robi:

  • Dla każdej wartości ew a;
    • Iteruj przez a, obliczając wartości pojedyncze, szeregowe i równoległe jako klucze do drukowanych wartości w haszu c;
  • Określ odległość zdla każdego klucza w c; i,
  • Dla każdej wartości e[1]dla każdego klucza e[0]w cwydruku e[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:

2200|680=519.4444444444445
1000|1000=500.0
330+150=480
330+220=550
470=470
1500|680=467.88990825688074
3300|680=563.8190954773869
.
.
.
4700+1500=6200
3300+3300=6600
4700+2200=6900
4700+3300=8000
4700+4700=9400
josh
źródło
3

JavaScript (ECMAScript 6) - 186 znaków

f=(R,T)=>(D=x=>Math.abs(x[3]/T-1),r={p:(x,y)=>x*y/(x+y),s:(x,y)=>x+y},[...[[x,0,0,x]for(x of R)],...[[x,y,z,r[z](x,y)]for(x of R)for(y of R)for(z in r)if(x<=y)]].sort((a,b)=>D(a)-D(b)))

Wkład:

  • Szereg Rsił rezystora; i
  • T, docelowy opór.

Wydajność:

Tablica tablic (posortowana według odległości od T), z których każda zawiera:

  • mniejsza wartość rezystora;
  • wyższa wartość rezystora (lub 0, jeśli rezystor samotny);
  • p, sLub 0 rezystory są równoległe, szeregowe lub izolatce; i
  • opór netto.

Wyjaśnienie:

f=(R,T)=>(                               // Create a function f with arguments R & T
  D=x=>Math.abs(x[3]/T-1),               // A function D to calculate relative
                                         // distance from the target value
  r={p:(x,y)=>x*y/(x+y),s:(x,y)=>x+y},   // An object containing the formulae
                                         // to calculate resistance in serial and parallel
  solitary = [[x,0,0,x]for(x of R)],     // Create an array of solitary resistors
  pairs =                                // Use Array Comprehension to create the array of
   [[x,y,z,r[z](x,y)]                    // arrays
      for(x of R)                        // for each resistor value
      for(y of R)                        // for each resistor value (again)
      for(z in r)                        // for both serial & parallel
      if(x<=y)],                         // where the first resistor value is smaller than the second
  [
    ...solitary,                         // Use the spread ... operator to combine
    ...pairs                             // the two arrays
  ]
    .sort((a,b)=>D(a)-D(b))              // Sort the arrays by minimum distance
                                         // and return.
)
MT0
źródło
Brak pojedynczego rezystora (na przykład len wyjściowy to 132 zamiast 143). Chciałbym pożyczyć sztuczkę Array
Compictionion
Ach, zapomniałem samotnych rezystorów
MT0
3

Julia - 179 163 bajty

f(t,s)=(\ =repmat;m=endof(s);A=A[v=(A=s\m).>=(B=sort(A))];B=B[v];F=[s,C=A+B,A.*B./C];n=sum(v);print([[s P=[" "]\m P;A [+]\n B;A [|]\n B] F][sortperm(abs(F-t)),:]))

Dział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:

f(t,s)=(\ =repmat;m=endof(s);A=s\m;v=find(A.>=(B=sort(A)));A=A[v];B=B[v];F=[s,C=A+B,A.*B./C];n=endof(v);P=[" "]\m;print([[s,A,A] [P,[+]\n,[|]\n] [P,B,B] F][sortperm(abs(F-t)),:]))

W ramach funkcji oto, co robi:

\ =repmat            # Overloads \ operator to save lots of characters
m=endof(s)           # Length of input s ("Stock")
A=s\m                # Equivalent to repmat(s,m) (see first command)
B=sort(A)            # Same as A but sorted - rather than cycling through
                     # the resistors m times, it repeats each one m times
v=find(A.>=B)        # Identify which pairs for A,B have A>=B
A=A[v];B=B[v]        # Remove pairs where A<B (prevents duplicates)
F=[s,C=A+B,A.*B./C]  # Constructs vector containing results for single resistor,
                     # resistors in series, and resistors in parallel
n=endof(v)           # equivalent to n=(m+1)m/2, gets number of relevant pairs
P=[" "]\m            # Construct array of blank entries for use in constructing output
print([[s,A,A] [P,[+]\n,[|]\n] [P,B,B] F][sortperm(abs(F-t)),:]))
# The following are the components of the argument in the print statement:
[s,A,A]              # Set of resistor values for resistor 1
[P,[+]\n,[|]\n]      # Operator column, prints either nothing, +, or |
[P,B,B]              # Set of resistor values for resistor 2 (blank for single resistor)
F                    # Contains resulting equivalent resistance
[sortperm(abs(F-t)),:] # Determines permutation for sorting array by distance from Target t
                     # and applies it to array

Przykładowe dane wyjściowe:

julia> f(170,[100,220,300])
300  |  300  150
100  +  100  200
300  |  220  126.92307692307692
220          220
220  |  220  110
100          100
300  |  100  75
220  |  100  68.75
100  |  100  50
300          300
220  +  100  320
300  +  100  400
220  +  220  440
300  +  220  520
300  +  300  600
Glen O
źródło
Miły! Nie widzisz wielu zgłoszeń Julii - czy rośnie popularność?
fosgen
@ phosgene - mam nadzieję, że tak; Przeważnie je przesyłam, ponieważ dają mi dodatkowe doświadczenie z językiem.
Glen O
2

JavaScript (E6) 156 162 164 186

Ostatnia edycja Zakładając, że wszystkie wartości rezystorów> 0, możesz użyć ich jako warunku pętli

F=(t,s)=>{D=a=>Math.abs(a[1]/t-1);for(i=r=[];a=s[j=i++];r[l]=[a,a])for(;b=s[j--];)l=r.push([a+'+'+b,c=a+b],[a+'|'+b,a*b/c]);return r.sort((a,b)=>D(a)-D(b))}

Stosowanie : F(510, [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700])

Bez golfa

F = (t,s) => 
{
  D = a => Math.abs(a[1]/t-1);
  for (i=r=[]; a=s[j=i++]; r[l]=[a,a])
    for(; b=s[j--];)
      l = r.push([a+'+'+b, c=a+b], [a+'|'+b, a*b/c]);
   return r.sort((a,b) => D(a)-D(b))
}
edc65
źródło
1
Musisz naciskać (wynik, niższy)!
fosgen
Ostatnio sprawdziłem, że wszystkie moje rezystory zostały pozytywnie ocenione. Myślę, że to bezpieczne założenie.
fosgen
1

JavaScript, 248 bajtów

function r(T,L){R=[],O="";for(i in L){R.push([a=L[i],a]);for(j=i;j<L.length;)b=L[j++],s=a+b,R.push([a+"+"+b,s],[a+"|"+b,a*b/s])}R.sort(function(a,b){A=Math.abs;return A(a[1]/T-1)-A(b[1]/T-1)});for(i in R)q=R[i],O+=q[0]+"="+q[1]+"\n";console.log(O)}

Stosowanie : r(510, [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700]);

Wydajność

670|2200=519.4444444444445
1000|1000=500
150+330=480

(...such rows...)

2200+4700=6900
3300+4700=8000
4700+4700=9400
Przekąska
źródło
0

Perl, 213 199 185 bajtów

213 bajtów:

$t=pop;sub t{abs 1-(split/=/,pop)[1]/$t}sub S{$_[0]+$_[1]}sub P{$_[0]*$_[1]/&S}$"=',';@i=@ARGV;say for sort{t($a)<=>t($b)}grep s!(..\b(\d+)\b,?\b(\d+)?\b\))=\K(??{$2<$3})!$1!ee&&/\d$/,<{S,P}({@i},{@i})= S({@i})=>;

199 bajtów:

$t=pop;sub t{abs 1-(split/=/,pop)[1]/$t}sub S{$_[0]+$_[1]}sub P{$_[0]*$_[1]/&S}$"=',';@i=@ARGV;say for sort{t($a)<=>t($b)}grep/(..(\d+),?(\d+)?\))/&&$2>=$3&&($_.=eval$1),<{S,P}({@i},{@i})= S({@i})=>;

185 bajtów:

$t=pop;sub t{abs 1-$_[0]=~s!.*=!!r/$t}sub S{$_[0]+$_[1]}sub P{$_[0]*$_[1]/&S}$"=',';$i="{@ARGV}";say for sort{t($a)<=>t$b}grep{my($x,$y)=/\d+/g;$_.='='.eval,$x>=$y}<{S,P}($i,$i) S($i)>

Przekaż wszystkie dostępne rezystory jako argumenty. Docelowy opór powinien być ostatnim:

$ perl -E 'code' R1 R2 R3 ... Rn target

Jak to działa (stary kod)

  • Zdefiniuj podprogramy Si Poblicz sumę i wartości równoległe dwóch rezystorów.

  • Ustaw $"na „,”, aby interpolować @ARGVwewnątrz globoperatora

  • <{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///eez, grepaby ocenić równoważne rezystancje i odfiltrować niechciane powtórzenia (wykonywane przez (??{$2<$3})i/\d$/

  • sort według sprawności obliczonej w podprogramie t

Zmiany w nowym kodzie

  • Unikaj używania s///ee, używaj krótszego wyrażenia regularnego z kontrolą warunkową i evalwewnątrzgrep

  • Zamień powtórzenia "{@i}" with$ i`

  • Wprowadzenie $x, $yzamiast $2,$3

  • wymienić split/=/,popz$_[0]=~s!!!r

  • Nie ma potrzeby ciągnięcia ;

  • eval; jest równa eval $_;

  • Dodaj =wraz z evalodpowiedzią -ed zamiast deklarować ją z góry

Wydajność:

Preprezentuje rezystory równolegle, Sreprezentuje rezystory szeregowo.

P(2200,680)=519.444444444444
P(1000,1000)=500
S(330,150)=480
S(330,220)=550
S(470)=470
P(1500,680)=467.889908256881
P(3300,680)=563.819095477387
S(470,100)=570
S(220,220)=440
S(330,100)=430
P(4700,470)=427.272727272727
P(4700,680)=594.052044609665
P(1500,1000)=600
P(3300,470)=411.405835543767
P(1000,680)=404.761904761905
S(470,150)=620
P(2200,470)=387.265917602996
S(220,150)=370
S(330,330)=660
P(1500,470)=357.868020304569
S(680)=680
P(680,680)=340
P(2200,1000)=687.5
S(330)=330
S(470,220)=690
S(220,100)=320
P(1000,470)=319.727891156463
P(4700,330)=308.349900596421
S(150,150)=300
P(3300,330)=300
P(2200,330)=286.95652173913
P(680,470)=277.913043478261
P(1500,330)=270.491803278689
P(1500,1500)=750
P(3300,1000)=767.441860465116
S(150,100)=250
P(1000,330)=248.12030075188
S(680,100)=780
P(470,470)=235
P(680,330)=222.178217821782
S(470,330)=800
S(220)=220
P(4700,220)=210.162601626016
P(3300,220)=206.25
S(100,100)=200
P(2200,220)=200
P(4700,1000)=824.561403508772
P(470,330)=193.875
P(1500,220)=191.860465116279
S(680,150)=830
P(1000,220)=180.327868852459
P(680,220)=166.222222222222
P(330,330)=165
S(150)=150
P(470,220)=149.855072463768
P(4700,150)=145.360824742268
P(3300,150)=143.478260869565
P(2200,150)=140.425531914894
P(1500,150)=136.363636363636
P(330,220)=132
P(1000,150)=130.434782608696
P(2200,1500)=891.891891891892
P(680,150)=122.89156626506
S(680,220)=900
P(470,150)=113.709677419355
P(220,220)=110
P(330,150)=103.125
S(100)=100
P(4700,100)=97.9166666666667
P(3300,100)=97.0588235294118
P(2200,100)=95.6521739130435
P(1500,100)=93.75
P(1000,100)=90.9090909090909
P(220,150)=89.1891891891892
P(680,100)=87.1794871794872
P(470,100)=82.4561403508772
S(470,470)=940
P(330,100)=76.7441860465116
P(150,150)=75
P(220,100)=68.75
P(150,100)=60
P(100,100)=50
S(1000)=1000
S(680,330)=1010
P(3300,1500)=1031.25
S(1000,100)=1100
P(2200,2200)=1100
P(4700,1500)=1137.09677419355
S(680,470)=1150
S(1000,150)=1150
S(1000,220)=1220
P(3300,2200)=1320
S(1000,330)=1330
S(680,680)=1360
S(1000,470)=1470
P(4700,2200)=1498.55072463768
S(1500)=1500
S(1500,100)=1600
S(1500,150)=1650
P(3300,3300)=1650
S(1000,680)=1680
S(1500,220)=1720
S(1500,330)=1830
P(4700,3300)=1938.75
S(1500,470)=1970
S(1000,1000)=2000
S(1500,680)=2180
S(2200)=2200
S(2200,100)=2300
S(2200,150)=2350
P(4700,4700)=2350
S(2200,220)=2420
S(1500,1000)=2500
S(2200,330)=2530
S(2200,470)=2670
S(2200,680)=2880
S(1500,1500)=3000
S(2200,1000)=3200
S(3300)=3300
S(3300,100)=3400
S(3300,150)=3450
S(3300,220)=3520
S(3300,330)=3630
S(2200,1500)=3700
S(3300,470)=3770
S(3300,680)=3980
S(3300,1000)=4300
S(2200,2200)=4400
S(4700)=4700
S(3300,1500)=4800
S(4700,100)=4800
S(4700,150)=4850
S(4700,220)=4920
S(4700,330)=5030
S(4700,470)=5170
S(4700,680)=5380
S(3300,2200)=5500
S(4700,1000)=5700
S(4700,1500)=6200
S(3300,3300)=6600
S(4700,2200)=6900
S(4700,3300)=8000
S(4700,4700)=9400
Zaid
źródło
Brakujące dwie linie to S(100)=100i S(1000)=1000.
algorytmshark
@algorytmshark: Tak, rozumiem. Wyrażenie regularne je przypadkowo pochłonęło
Zaid
Ciekawe będzie, czy ktokolwiek może wymyślić krótsze rozwiązanie Perla.
Zaid