Introducción
Al construir un proyecto de electrónica, un esquema puede requerir una resistencia de un valor inusual (por ejemplo, 510 ohmios). Verifica su depósito de piezas y descubre que no tiene resistencias de 510 ohmios. Pero tiene muchos valores comunes por encima y por debajo de este valor. Al combinar resistencias en paralelo y en serie, debería poder aproximar la resistencia de 510 ohmios bastante bien.
Tarea
Debe escribir una función o programa que acepte una lista de valores de resistencia (resistencias que tenga) y un valor objetivo (que pretende aproximar). El programa debe considerar:
- Resistencias individuales
- Dos resistencias en serie.
- Dos resistencias en paralelo
El programa debe calcular todas las combinaciones posibles de 1 y 2 resistencias de la lista de existencias (incluidas dos copias del mismo valor de resistencia), calcular su resistencia en serie y en paralelo, luego clasificar las configuraciones de acuerdo a qué tan bien se aproximan al valor objetivo.
El formato de salida debe ser una configuración por línea, con una +
serie que |
denota y un paralelo que denota, y algo de espacio o un signo = antes de la resistencia neta.
Fórmulas
- La resistencia de una resistencia es
R1
- La resistencia neta de dos resistencias en serie es
R1 + R2
- La resistencia neta de dos resistencias en paralelo es
1 / (1/R1 + 1/R2)
- La distancia entre un valor de resistencia aproximado y el valor objetivo se puede calcular como la distancia pseudo-logarítmica, no lineal distancia:
dist = abs(Rapprox / Rtarget - 1)
. Por ejemplo, 200 está más cerca de 350 que de 100. - Una mejor medida de distancia es la verdadera distancia logarítmica
dist = abs(log(Rapprox/Rtarget))
, pero como no se especificó en la pregunta original, puede utilizar cualquiera de las dos medidas.
Tanteo
La puntuación se mide en caracteres de código, según las reglas de golf habituales. La puntuación más baja gana.
Ejemplo
Tenemos las siguientes resistencias en stock [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700]
y deseamos apuntar a 510
ohmios. El programa debe generar 143 configuraciones, aproximadamente como se muestra (puede cambiar el formato, pero asegúrese de que el significado se determine fácilmente):
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.
En este ejemplo, la mejor aproximación de 510 ohmios viene dada por resistencias de 680 y 2200 ohmios en paralelo.
Lo mejor de cada idioma hasta ahora (1 de junio de 2014):
- J - 70 char
- APL - 102 char
- Mathematica - 122 char
- Ruby - 154 char
- Javascript - 156 caracteres
- Julia - 163 char
- Perl - 185 char
- Python - 270 char
fuente
Respuestas:
J -
867170 charNo me voy a molestar en explicar cada pequeño detalle porque gran parte del código se gasta sincronizando los resultados de diferentes funciones, pero aquí está la esencia del golf:
;@((<@,.{:)\)
hace que todos los pares de resistencias posibles se conecten en paralelo o en serie.[:,/(<,.+`|,.+/;+&.%/)"1@
luego los conecta, en paralelo y en serie, haciendo una gran lista de posibles conexiones.(;a:,<)"0,
agrega la posibilidad de usar solo una resistencia por sí misma para aproximarse.(]/:[|@<:@%~2{::"1])
ordena la lista de combinaciones de resistencias por la distancia pseudológica (|@<:@%
) entre el objetivo y la resistencia resultante de cada combinación.Y así es como se usa:
No solo tiene que ver los primeros 10 como lo hice anteriormente, sino que esta es una función y J REPL trunca valores de retorno muy grandes, y la salida completa para este ejemplo tiene 287 líneas. Puede forzarlo a STDOUT con algo como
tmoutput toCRLF , LF ,.~ ": blah rouv blah
en Windows, soltarlotoCRLF
en Linux, perorouv
es una función e internamente, existen todas las filas.Nota:
La pregunta parece haber cambiado justo debajo de nuestras narices, y ahora la distancia logarítmica se define como en
abs(log(Rapprox/Rtarget))
lugar deabs(Rapprox/Rtarget-1)
. Para corregir esto en mi golf, podemos cambiar|@<:@%
a|@^.@%
:<:
es Decremento mientras^.
es Logaritmo.fuente
Mathematica,
151122 caracteresEspera que se almacene la resistencia objetivo
r
y la lista de resistencias disponibles enl
.Menos golf:
El formato de salida difiere del sugerido, pero las configuraciones son fácilmente determinables. El resultado es una lista de configuraciones. Cada configuración tiene una de las siguientes formas:
Entonces, los primeros tres elementos de la salida leen
Si estás de acuerdo con los números racionales, podría evitar que se omitan dos caracteres
N@
. Es decir, el primer elemento (por ejemplo) se devolvería como en4675/9
lugar de519.444
.fuente
APL (102)
Esto toma la resistencia objetivo como argumento izquierdo y una lista de resistencias disponibles como argumento correcto.
Explicación:
V←{
...}
:V
es una función que:Z/⍨≤/¨Z←,∘.,⍨⍵
: encuentra cada combinación única de dos valores en⍵
,Z←,∘.,⍨⍵
: une cada valor⍵
con cada valor en⍵
, almacenar enZ
,Z/⍨≤/¨Z
: seleccione deZ
aquellas combinaciones donde el primer valor es menor o igual que el segundo valor⍺{
...}⍺⍺/¨
: y luego aplica la siguiente función, vinculada con la función izquierda (⍺⍺
) a la derecha y el argumento izquierdo (⍺
) a la izquierda, a cada par:⍺,⍺⍺,⍵,'=',⍺⍵⍵⍵
, el argumento izquierdo, seguido del argumento de límite izquierdo, seguido del argumento derecho, seguido de=
, seguido de la función derecha (⍵⍵
) aplicada a ambos argumentos. (Esta es la función de formateo,.X [configuration] Y [equals] (X [fn] Y)
)⊃¨
: y luego desempaquetar cada elemento.{⍵,' =',⍵}¨⍵
: para cada elemento en⍵
, realice las configuraciones para las resistencias individuales. (⍵
, nada, nada=
,⍵
).('+'+V⍵)
: use laV
función para hacer todas las configuraciones en serie (el carácter es'+'
y la función es+
).'|'{÷+/÷⍺⍵}V⍵
: use laV
función para hacer todas las configuraciones paralelas (el carácter es'|'
y la función es{÷+/÷⍺⍵}
, inversa de la suma de la inversa de los argumentos).K←↑
: convierta esto en una matriz y guárdeloK
.0 4↓K
: suelta las 4 primeras columnasK
, dejando solo los valores de resistencia.|¯1+⍺÷⍨
: calcula la distancia entre⍺
y cada configuración.K[⍋
...;]
: ordenarK
por las distancias.fuente
510 code_here 100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700
⍎
), I / O (⎕
) ni ninguna variable del sistema (incluso⎕UCS
y⎕A
no funciona), por lo que la mayoría de los programas APL no se ejecutarán. Realmente dará un ERROR DE SINTAXIS si se usa una de las funciones deshabilitadas. El hecho de que este no utilice una de las muchas funciones que TryAPL no admite es una coincidencia.Python 3 -
250247270 bytesCorre así:
(es decir, una lista de resistencias delimitada por espacios, con el valor objetivo al final)
Salida:
Yo diría que la salida, digamos,No fue aceptable. Me costó bytes. Ahora clasifico las tuplas antes de arrojarlas al conjunto, de lo contrario la solución es idéntica.680|2200
y por2200|680
separado todavía es bastante clara. Si esto es inaceptable, puedo cambiarlo, pero me costará bytes.fuente
import sys;r=sys.args[1:]
, user=input().split()
y diga que tiene que dar los valores en stdin. Por fin: usas en1/sum(1/int(n)for n in b)
lugar de1/sum(map(lambda n:1/int(n),b)
. Con todo, eso debería ser 274 caracteresRuby 2.1,
156154 bytesSin golf:
Que hace:
e
ena
;a
, calcular valores únicos, en serie y paralelos como claves para valores impresos en hashc
;z
cada teclac
; y,e[1]
de cada teclae[0]
enc
, imprimire[1]=e[0]
.Uso de la muestra:
s[[100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700], 510]
Salida de muestra:
fuente
JavaScript (ECMAScript 6) - 186 caracteres
Entrada:
R
de resistencias de resistencia; yT
, la resistencia objetivo.Salida:
Una matriz de matrices (ordenadas por distancia desde
T
) cada una de las cuales contiene:p
,s
o 0 si las resistencias están en paralelo, en serie o en solitario; yExplicación:
fuente
Julia -
179163 bytesEsto funciona igual que la versión anterior, pero el argumento en la declaración de impresión se ha organizado de manera ligeramente diferente para reducir el número de corchetes necesarios. Ahorra 4 bytes. Absorber la creación del vector de espacios en el argumento de impresión ahorra 2 bytes adicionales. También ha cambiado de usar "buscar" para obtener los índices relevantes a usar la forma lógica. Ahorra 6 bytes. Absorber el cálculo del vector índice en el ajuste de A ahorró otros 2 bytes. Finalmente, reemplazar endof (v) con sum (v) ahorró 2 bytes más. Ahorro total: 16 bytes.
Versión antigua:
Dentro de la función, esto es lo que está haciendo:
Salida de muestra:
fuente
Javascript (E6)
156162164186Última edición Suponiendo todos los valores de resistencia> 0, puede usarlos para la condición de bucle
Uso:
F(510, [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700])
Sin golf
fuente
Javascript, 248 bytes
Uso:
r(510, [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700]);
Salida
fuente
Perl,
213199185 bytes213 bytes:
199 bytes:
185 bytes:
Pase todas las resistencias disponibles como argumentos. La resistencia objetivo debe ser la última:
Cómo funciona (código antiguo)
Definir subrutinas
S
yP
calcular la suma y los valores paralelos de dos resistencias.Establezca
$"
en "," para interpolar@ARGV
dentro delglob
operador<{S,P}({@i},{@i})= S({@i})=>
genera un cartesiano de todas las posibilidades:S (100,100), S (100,150), S (100,220), ... P (100,100), P (100,150) ... S (100), S (150) ...
Combine
s///ee
congrep
para evaluar las resistencias equivalentes y filtre las repeticiones no deseadas (realizadas por(??{$2<$3})
y/\d$/
sort
por aptitud calculada en subrutinat
Cambios en el nuevo código
Evite el uso de
s///ee
, use expresiones regulares más cortas con verificación condicional yeval
dentrogrep
Reemplazar repeticiones de
"{@i}" with
$ i`Introducir
$x
, en$y
lugar de$2
,$3
Reemplazar
split/=/,pop
con$_[0]=~s!!!r
No hay necesidad de seguir
;
eval;
es equivalente aeval $_;
Agregue
=
junto con laeval
respuesta -ed en lugar de declararlo por adelantadoSalida:
P
representa resistencias en paralelo,S
representa resistencias en serie.fuente
S(100)=100
yS(1000)=1000
.