introduction
Lors de la construction d'un projet électronique, un schéma peut nécessiter une résistance d'une valeur inhabituelle (disons, 510 ohms). Vous vérifiez votre bac de pièces et constatez que vous n'avez pas de résistances de 510 ohms. Mais vous avez de nombreuses valeurs communes au-dessus et en dessous de cette valeur. En combinant des résistances en parallèle et en série, vous devriez être en mesure d'approximer assez bien la résistance de 510 ohms.
Tâche
Vous devez écrire une fonction ou un programme qui accepte une liste de valeurs de résistance (résistances que vous stockez) et une valeur cible (que vous souhaitez approximer). Le programme doit considérer:
- Résistances individuelles
- Deux résistances en série
- Deux résistances en parallèle
Le programme doit calculer toutes les combinaisons possibles de 1 et 2 résistances à partir de la liste de stock (y compris deux copies de la même valeur de résistance), calculer leur série et leur résistance parallèle, puis trier les configurations en fonction de leur approximation de la valeur cible.
Le format de sortie doit être une configuration par ligne, avec une +
série |
dénotant et dénotant parallèle, et un peu d'espace ou un signe = avant la résistance nette.
Formules
- La résistance d'une résistance est
R1
- La résistance nette de deux résistances en série est
R1 + R2
- La résistance nette de deux résistances en parallèle est
1 / (1/R1 + 1/R2)
- La distance entre une valeur approchée de la résistance et de la valeur cible peut être calculée comme distance de pseudo-logarithmique, non linéaire distance:
dist = abs(Rapprox / Rtarget - 1)
. Par exemple, 200 est plus proche de 350 que de 100. - Une meilleure mesure de distance est la vraie distance logarithmique
dist = abs(log(Rapprox/Rtarget))
, mais comme cela n'était pas spécifié dans la question d'origine, vous êtes libre d'utiliser l'une ou l'autre mesure.
Notation
Le score est mesuré en caractères de code, selon les règles de golf habituelles. Le score le plus bas l'emporte.
Exemple
Nous avons les résistances suivantes en stock [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700]
et souhaitons cibler les 510
ohms. Le programme devrait produire 143 configurations, approximativement comme indiqué (vous pouvez changer le format, mais assurez-vous que la signification est facilement déterminée):
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.
Dans cet exemple, la meilleure approximation de 510 ohms est donnée par des résistances de 680 et 2200 ohms en parallèle.
Le meilleur de chaque langue jusqu'à présent (1er juin 2014):
- J - 70 car
- APL - 102 car.
- Mathematica - 122 caractères
- Rubis - 154 car.
- Javascript - 156 caractères
- Julia - 163 caractères
- Perl - 185 caractères
- Python - 270 caractères
la source
Réponses:
J -
867170 charJe ne vais pas prendre la peine d'expliquer chaque petit détail car une grande partie du code est consacrée à la synchronisation des résultats de différentes fonctions, mais voici l'essentiel du golf:
;@((<@,.{:)\)
fabrique toutes les paires de résistances possibles, à connecter en parallèle ou en série.[:,/(<,.+`|,.+/;+&.%/)"1@
puis les connecte, en parallèle et en série, faisant une grande liste de connexions possibles.(;a:,<)"0,
ajoute la possibilité d'utiliser une seule résistance par elle-même pour l'approximation.(]/:[|@<:@%~2{::"1])
trie la liste des combinaisons de résistances en fonction de la distance pseudologique (|@<:@%
) entre la cible et la résistance résultante de chaque combinaison.Et voici comment l'utiliser:
Vous n'avez pas seulement à visualiser les 10 premiers comme je l'ai fait ci-dessus, mais c'est une fonction et le J REPL tronque de très grandes valeurs de retour, et la sortie complète de cet exemple a 287 lignes. Vous pouvez forcer le tout à STDOUT avec quelque chose comme
tmoutput toCRLF , LF ,.~ ": blah rouv blah
sous Windows - supprimez letoCRLF
sous Linux - maisrouv
c'est une fonction et en interne, toutes les lignes existent.Remarque:
La question semble avoir été changée juste sous notre nez, et maintenant la distance du journal est définie comme
abs(log(Rapprox/Rtarget))
au lieu deabs(Rapprox/Rtarget-1)
. Pour corriger cela dans mon golf, nous pouvons changer le|@<:@%
en|@^.@%
:<:
is Decrement while^.
is Logarithm.la source
Mathematica,
151122 caractèresAttend que la résistance cible soit stockée
r
et la liste des résistances disponiblesl
.Moins de golf:
Le format de sortie diffère de celui proposé, mais les configurations sont facilement déterminables. Le résultat est une liste de configurations. Chaque configuration se présente sous l'une des formes suivantes:
Ainsi, les trois premiers éléments de la sortie lus
Si vous êtes d'accord avec les nombres rationnels, je pourrais éviter l'omission de deux caractères
N@
. Autrement dit, le premier élément (par exemple) serait renvoyé comme4675/9
au lieu de519.444
.la source
APL (102)
Cela prend la résistance cible comme argument de gauche et une liste des résistances disponibles comme argument de droite.
Explication:
V←{
...}
:V
est une fonction qui:Z/⍨≤/¨Z←,∘.,⍨⍵
: trouve chaque combinaison unique de deux valeurs dans⍵
,Z←,∘.,⍨⍵
: joindre chaque valeur à⍵
chaque valeur dans⍵
, stocker dansZ
,Z/⍨≤/¨Z
: sélectionner parmiZ
les combinaisons où la première valeur est inférieure ou égale à la deuxième valeur⍺{
...}⍺⍺/¨
: puis applique la fonction suivante, liée avec la fonction gauche (⍺⍺
) à droite et l'argument gauche (⍺
) à gauche, à chaque paire:⍺,⍺⍺,⍵,'=',⍺⍵⍵⍵
, l'argument gauche, suivi de l'argument lié à gauche, suivi de l'argument droit, suivi de=
, suivi de la fonction droite (⍵⍵
) appliquée aux deux arguments. (Il s'agit de la fonction de formatage,.X [configuration] Y [equals] (X [fn] Y)
)⊃¨
: puis décompressez chaque élément.{⍵,' =',⍵}¨⍵
: pour chaque élément dans⍵
, faites les configurations pour les résistances individuelles. (⍵
, Rien, rien,=
,⍵
).('+'+V⍵)
: utilisez laV
fonction pour faire toutes les configurations série (le caractère est'+'
et la fonction est+
).'|'{÷+/÷⍺⍵}V⍵
: utilisez laV
fonction pour faire toutes les configurations parallèles (le caractère est'|'
et la fonction est{÷+/÷⍺⍵}
, inverse de la somme des inverses des arguments).K←↑
: en faire une matrice et la stockerK
.0 4↓K
: supprimez les 4 premières colonnes deK
, ne laissant que les valeurs de résistance.|¯1+⍺÷⍨
: calcule la distance entre⍺
chaque configuration.K[⍋
...;]
: trierK
par les distances.la source
510 code_here 100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700
⍎
), I / O (⎕
), ni aucune variable système (même⎕UCS
et⎕A
ne fonctionne pas), donc la plupart des programmes APL ne s'exécuteront pas. Il donnera en fait une ERREUR SYNTAXE si l'une des fonctions désactivées est utilisée. Le fait que celle-ci n'utilise pas l'une des nombreuses fonctions que TryAPL ne prend pas en charge est une coïncidence.Python 3 -
250247270 octetsCourez comme ceci:
(c'est-à-dire une liste de résistances délimitées par des espaces, avec la valeur cible à la fin)
Sortie:
Je dirais que la sortie, disons,Ce n'était pas acceptable. Me coûte des octets. Maintenant, je trie les tuples avant de les insérer dans l'ensemble, sinon la solution est identique.680|2200
et2200|680
séparément est encore assez claire. Si cela est inacceptable, je peux le changer, mais cela me coûtera des octets.la source
import sys;r=sys.args[1:]
, utilisezr=input().split()
et dites que vous devez donner les valeurs sur stdin. Enfin: vous utilisez1/sum(1/int(n)for n in b)
au lieu de1/sum(map(lambda n:1/int(n),b)
. Somme toute, cela devrait être 274 caractèresRuby 2.1,
156154 octetsNon golfé:
Ce qu'il fait:
e
dansa
;a
, calculer des valeurs simples, en série et parallèles comme clés des valeurs imprimées dans le hachagec
;z
chaque entréec
; et,e[1]
pour chaque clée[0]
dansc
, imprimere[1]=e[0]
.Exemple d'utilisation:
s[[100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700], 510]
Exemple de sortie:
la source
JavaScript (ECMAScript 6) - 186 caractères
Contribution:
R
de résistances; etT
, la résistance cible.Sortie:
Un tableau de tableaux (triés par distance de
T
) contenant chacun:p
,s
ou 0 si les résistances sont en parallèle, en série ou solitaires; etExplication:
la source
Julia -
179163 octetsCela fonctionne de la même manière que l'ancienne version, mais l'argument de l'instruction print a été organisé légèrement différemment pour réduire le nombre de crochets nécessaires. Enregistre 4 octets. L'absorption de la création du vecteur d'espaces dans l'argument d'impression permet d'économiser 2 octets supplémentaires. Il est également passé de l'utilisation de "find" pour obtenir les indices pertinents à l'utilisation de la forme logique. Enregistre 6 octets. L'absorption du calcul du vecteur d'index dans l'ajustement de A a permis d'économiser encore 2 octets. Enfin, le remplacement de endof (v) par sum (v) a permis d'économiser 2 octets supplémentaires. Économie totale: 16 octets.
Ancienne version:
Dans la fonction, voici ce qu'elle fait:
Exemple de sortie:
la source
Javascript (E6) 156
162 164 186Dernière modification En supposant que toutes les valeurs de résistance> 0, vous pouvez les utiliser pour la condition de boucle
Utilisation:
F(510, [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700])
Non golfé
la source
Javascript, 248 octets
Utilisation:
r(510, [100, 150, 220, 330, 470, 680, 1000, 1500, 2200, 3300, 4700]);
Sortie
la source
Perl,
213199185 octets213 octets:
199 octets:
185 octets:
Passez toutes les résistances disponibles comme arguments. La résistance cible doit être la dernière:
Comment ça marche (ancien code)
Définissez des sous
S
- programmes etP
calculez la somme et les valeurs parallèles de deux résistances.Réglez
$"
sur "," pour interpoler@ARGV
à l'intérieur de l'glob
opérateur<{S,P}({@i},{@i})= S({@i})=>
génère un cartésien de toutes les possibilités:S (100,100), S (100,150), S (100,220), ... P (100,100), P (100,150) ... S (100), S (150) ...
Combinez
s///ee
avecgrep
pour évaluer les résistances équivalentes et filtrer les répétitions indésirables (effectuées par(??{$2<$3})
et/\d$/
sort
par fitness calculé dans le sous-programmet
Changements dans le nouveau code
Évitez l'utilisation de
s///ee
, utilisez des expressions rationnelles plus courtes avec vérification conditionnelle et à l'eval
intérieurgrep
Remplacer les répétitions de
"{@i}" with
$ i`Présentez
$x
,$y
au lieu de$2
,$3
Remplacez
split/=/,pop
par$_[0]=~s!!!r
Pas besoin de suivre
;
eval;
est équivalent àeval $_;
Ajouter
=
avec laeval
réponse -ed au lieu de la déclarer d'avanceSortie:
P
représente des résistances en parallèle,S
représente des résistances en série.la source
S(100)=100
etS(1000)=1000
.