Introdução
Ao construir um projeto de eletrônica, um esquema pode exigir um resistor de valor incomum (por exemplo, 510 ohms). Você verifica o compartimento de peças e descobre que não possui resistores de 510 ohm. Mas você tem muitos valores comuns acima e abaixo desse valor. Ao combinar resistores em paralelo e em série, você poderá aproximar o resistor de 510 ohm razoavelmente bem.
Tarefa
Você deve escrever uma função ou programa que aceite uma lista de valores de resistores (resistores que você armazena) e um valor alvo (que você pretende aproximar). O programa deve considerar:
- Resistores individuais
- Dois resistores em série
- Dois resistores em paralelo
O programa deve calcular todas as combinações possíveis de 1 e 2 resistores da lista de estoques (incluindo duas cópias do mesmo valor de resistor), calcular suas séries e resistências paralelas e, em seguida, classificar as configurações de acordo com a proximidade com o valor alvo.
O formato de saída deve ser uma configuração por linha, com uma +
série e |
paralelo, e algum espaço ou um sinal = antes da resistência líquida.
Fórmulas
- A resistência de um resistor é
R1
- A resistência líquida de dois resistores em série é
R1 + R2
- A resistência líquida de dois resistores em paralelo é
1 / (1/R1 + 1/R2)
- A distância entre um valor da resistência e o valor aproximado alvo pode ser calculada como a distância pseudo-logarítmica, não linear distância:
dist = abs(Rapprox / Rtarget - 1)
. Por exemplo, 200 está mais perto de 350 do que em 100. - Uma medida de distância melhor é a distância logarítmica verdadeira
dist = abs(log(Rapprox/Rtarget))
, mas como isso não foi especificado na pergunta original, você pode usar qualquer uma das medidas.
Pontuação
A pontuação é medida em caracteres de código, de acordo com as regras usuais de golfe. Menor pontuação ganha.
Exemplo
Temos os seguintes resistores em estoque [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700]
e queremos atingir 510
ohms. O programa deve produzir 143 configurações, aproximadamente como mostrado (você pode alterar o formato, mas verifique se o significado é facilmente determinado):
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.
Neste exemplo, a melhor aproximação de 510 ohms é dada pelos resistores de 680 e 2200 ohms em paralelo.
Melhor de cada idioma até agora (1 de junho de 2014):
- J - 70 char
- APL - 102 char
- Mathematica - 122 char
- Rubi - 154 caracteres
- Javascript - 156 caracteres
- Julia - 163 char
- Perl - 185 car
- Python - 270 caracteres
fonte
Respostas:
J -
867170 charNão vou me incomodar em explicar todos os detalhes, porque muito do código é gasto sincronizando os resultados de diferentes funções, mas aqui está a essência do golfe:
;@((<@,.{:)\)
faz com que todo par de resistores possível seja conectado em paralelo ou em série.[:,/(<,.+`|,.+/;+&.%/)"1@
depois os conecta, em paralelo e em série, fazendo uma grande lista de conexões possíveis.(;a:,<)"0,
acrescenta a possibilidade de usar apenas um resistor para se aproximar.(]/:[|@<:@%~2{::"1])
classifica a lista de combinações de resistores pela distância pseudológica (|@<:@%
) entre o alvo e a resistência resultante de cada combinação.E é assim que se usa:
Você não precisa visualizar apenas os 10 primeiros, como eu fiz acima, mas essa é uma função e o J REPL trunca valores de retorno muito grandes, e a saída completa para este exemplo tem 287 linhas. Você pode forçar tudo a STDOUT com algo como
tmoutput toCRLF , LF ,.~ ": blah rouv blah
no Windows - solte otoCRLF
Linux - masrouv
é uma função e, internamente, todas as linhas existem.Nota:
A questão parece ter sido alterada bem abaixo do nosso nariz, e agora a distância do log é definida como em
abs(log(Rapprox/Rtarget))
vez deabs(Rapprox/Rtarget-1)
. Para corrigir isso no meu golfe, podemos alterar|@<:@%
para|@^.@%
:<:
is Decrement e^.
Logarithm.fonte
Mathematica,
151122 caracteresEspera que a resistência alvo seja armazenada
r
e a lista de resistências disponíveis eml
.Menos golfe:
O formato de saída difere do sugerido, mas as configurações são facilmente determináveis. A saída é uma lista de configurações. Cada configuração é de uma das seguintes formas:
Então, os três primeiros elementos da saída leram
Se você estiver bem com números racionais, eu poderia salvar dois caracteres da omissão
N@
. Ou seja, o primeiro elemento (por exemplo) seria retornado como em4675/9
vez de519.444
.fonte
APL (102)
Isso leva a resistência ao alvo como argumento à esquerda e uma lista de resistores disponíveis como o argumento à direita.
Explicação:
V←{
...}
:V
é uma função que:Z/⍨≤/¨Z←,∘.,⍨⍵
: localiza todas as combinações únicas de dois valores em⍵
,Z←,∘.,⍨⍵
: junte cada valor⍵
a cada valor⍵
, armazeneZ
,Z/⍨≤/¨Z
: selecioneZ
as combinações em que o primeiro valor é menor ou igual ao segundo valor⍺{
...}⍺⍺/¨
: e aplica a seguinte função, vinculada à função esquerda (⍺⍺
) à direita e o argumento esquerdo (⍺
) à esquerda, a cada par:⍺,⍺⍺,⍵,'=',⍺⍵⍵⍵
, o argumento esquerdo, seguido pelo argumento ligado à esquerda, seguido pelo argumento à direita, seguido por=
, seguido pela função à direita (⍵⍵
) aplicada aos dois argumentos. (Esta é a função de formataçãoX [configuration] Y [equals] (X [fn] Y)
.)⊃¨
: e depois desmarque cada elemento.{⍵,' =',⍵}¨⍵
: para cada elemento⍵
, faça as configurações para os resistores individuais. (⍵
, nada, nada=
,⍵
).('+'+V⍵)
: use aV
função para fazer todas as configurações seriais (caractere é'+'
e função é+
).'|'{÷+/÷⍺⍵}V⍵
: use aV
função para fazer todas as configurações paralelas (caractere é'|'
e função é{÷+/÷⍺⍵}
, inverso da soma do inverso dos argumentos).K←↑
: faça isso em uma matriz e armazene-oK
.0 4↓K
: solte as 4 primeiras colunasK
, deixando apenas os valores de resistência.|¯1+⍺÷⍨
: calcula a distância entre⍺
e cada configuração.K[⍋
...;]
: classifiqueK
pelas distâncias.fonte
510 code_here 100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700
⍎
), E / S (⎕
) ou qualquer variável do sistema (uniforme⎕UCS
e⎕A
não funciona), portanto, a maioria dos programas APL não será executada. Na verdade, ele emitirá um erro de sintaxe se uma das funções desabilitadas for usada. O fato de este não usar uma das muitas funções que o TryAPL não suporta é uma coincidência.Python 3 -
250247270 bytesExecute assim:
(ou seja, uma lista de resistores delimitada por espaço, com o valor alvo no final)
Saída:
Eu diria que a saída, digamos,Não era aceitável. Custou-me bytes. Agora, ordeno as tuplas antes de jogá-las no conjunto, caso contrário, a solução é idêntica.680|2200
e2200|680
separadamente ainda é bastante clara. Se isso for inaceitável, eu posso alterá-lo, mas isso me custará bytes.fonte
import sys;r=sys.args[1:]
, user=input().split()
e diga que você deve fornecer os valores em stdin. Por fim: você usa em1/sum(1/int(n)for n in b)
vez de1/sum(map(lambda n:1/int(n),b)
. Ao todo, devem ser 274 caracteres.Ruby 2.1,
156154 bytesUngolfed:
O que faz:
e
ema
;a
, computando valores únicos, em série e paralelos como chaves para valores impressos em hashc
;z
cada chavec
; e,e[1]
para cada chavee[0]
emc
, imprimire[1]=e[0]
.Uso da amostra:
s[[100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700], 510]
Saída de amostra:
fonte
JavaScript (ECMAScript 6) - 186 caracteres
Entrada:
R
de resistências; eT
, a resistência ao alvo.Saída:
Uma matriz de matrizes (classificadas pela distância de
T
), cada uma contendo:p
,s
ou 0 se os resistores estiverem em paralelo, serial ou solitário; eExplicação:
fonte
Julia -
179163 bytesIsso funciona da mesma forma que na versão antiga, mas o argumento na instrução print foi organizado de maneira ligeiramente diferente para reduzir o número de colchetes necessário. Salva 4 bytes. A absorção da criação do vetor de espaços no argumento print economiza 2 bytes extras. Ele também passou de usar "localizar" para obter os índices relevantes para usar o formulário lógico. Salva 6 bytes. A absorção do cálculo do vetor de índice no ajuste de A salvou outros 2 bytes. Finalmente, a substituição de endof (v) pela soma (v) economizou mais 2 bytes. Economia total: 16 bytes.
Versão antiga:
Dentro da função, aqui está o que está fazendo:
Saída de amostra:
fonte
Javascript (E6) 156
162 164 186Última edição Assumindo todos os valores de resistores> 0, você pode usá-los para a condição de loop
Uso:
F(510, [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700])
Ungolfed
fonte
Javascript, 248 bytes
Uso:
r(510, [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700]);
Saída
fonte
Perl,
213199185 bytes213 bytes:
199 bytes:
185 bytes:
Passe todos os resistores disponíveis como argumentos. A resistência alvo deve ser a última:
Como funciona (código antigo)
Defina sub
S
- rotinas eP
calcule a soma e os valores paralelos de dois resistores.Defina
$"
como "," para interpolar@ARGV
dentro doglob
operador<{S,P}({@i},{@i})= S({@i})=>
gera um cartesiano de todas as possibilidades:S (100.100), S (100.150), S (100.220), ... P (100.100), P (100.150) ... S (100), S (150) ...
Combine
s///ee
comgrep
para avaliar as resistências equivalentes e filtrar repetições indesejadas (executadas por(??{$2<$3})
e/\d$/
sort
por aptidão computada na sub-rotinat
Mudanças no novo código
Evite usar
s///ee
, use regex mais curto com verificação condicional eeval
internagrep
Substitua repetições de
"{@i}" with
$ i`Introduzir
$x
, em$y
vez de$2
,$3
Substitua
split/=/,pop
por$_[0]=~s!!!r
Não há necessidade de arrastar
;
eval;
é equivalente aeval $_;
Adicione
=
junto com aeval
resposta -ed em vez de declará-la antecipadamenteSaída:
P
representa resistores em paralelo,S
representa resistores em série.fonte
S(100)=100
eS(1000)=1000
.