patternMinor
Resistance is futile, Resistors have been dispatched to model your Resistance
Viewed 0 times
yourresistorsbeenresistancemodeldispatchedfutilehave
Problem
Since it was getting boring to always do OOP Languages I decided to dabble in the functional realm of programming.
For that I chose the narrowly missed community-challenge by Edward: Resistor Mania, since it really is a quick-to solve using recursive and functional style.
Challenge description:
In electronics, two resistors in series have a combined resistance
\$R_1+R_2\$, and two resistors in parallel have combined resistance of
\$\displaystyle \frac{R_1 R_2}{R_1 + R_2}\$. Given an infinite supply
of \$270\Omega\$ resistors with \$5\%\$ tolerance, write a program to
describe how to combine them into any arbitrary resistance value.
To make things a little easier for me, I decided to ditch the tolerance for this first prototype. Instead of \$270\Omega\$ I also ask the user to provide the values for our resistors.
The code works as expected for rather simple inputs, and I didn't check for more complicated stuff yet.
The ouptut comes as a wiring help that uses simple "equations" to describe parallel and combining wiring.
Output of some manual tests:
Code:
There's quite a few things th
For that I chose the narrowly missed community-challenge by Edward: Resistor Mania, since it really is a quick-to solve using recursive and functional style.
Challenge description:
In electronics, two resistors in series have a combined resistance
\$R_1+R_2\$, and two resistors in parallel have combined resistance of
\$\displaystyle \frac{R_1 R_2}{R_1 + R_2}\$. Given an infinite supply
of \$270\Omega\$ resistors with \$5\%\$ tolerance, write a program to
describe how to combine them into any arbitrary resistance value.
To make things a little easier for me, I decided to ditch the tolerance for this first prototype. Instead of \$270\Omega\$ I also ask the user to provide the values for our resistors.
The code works as expected for rather simple inputs, and I didn't check for more complicated stuff yet.
The ouptut comes as a wiring help that uses simple "equations" to describe parallel and combining wiring.
Output of some manual tests:
*Main> resistor_mania 60 120
"60.0+60.0"
*Main> resistor_mania 120 60
"120.0||(120.0)"
*Main> resistor_mania 120 120
"120.0"Code:
module Main where
import System.IO
main = do
hSetBuffering stdin LineBuffering;
putStrLn "Please enter the value of resistors we use";
res_input a -> a -> a
p_resistor = (\existing target -> (1 / ((1 / target) - (1 / existing))));
{-
Resistor_Mania: Create a wiring schema for a given target resistor value
with one single available kind of resistor
-}
resistor_mania :: (Show a, Ord a, Fractional a) => a -> a -> String
resistor_mania resistor target =
if resistor == target;
then (show resistor);
else if resistor < target;
then (show resistor) ++ "+" ++ (resistor_mania resistor (target - resistor));
else (show resistor) ++ "||(" ++ (resistor_mania resistor (p_resistor resistor target)) ++ ")";There's quite a few things th
Solution
Guards
Using so many
This is the standard way of listing mutually exclusive conditions in a function definition.
Semicolons
Haskell uses a two-dimensional syntax, semicolons are not needed and should be omitted as they convey no additional information, just noise.
Prefer mainstream function definitions
Becomes:
That looks maybe less cool, but surely faster to understand.
Types
the type-signature of resistor_mania makes me uneasy :/
Haskell is type-centric, so it is good that you are worrying about types.
I deleted your types and asked the compiler what types it would like for your functions.
I think these suggested types are simpler, and I would use them instead of your bulky type declarations.
Non-closing parenthesis
This is somewhat subjective though...
Using so many
if then and else is really weird in Haskell, I suggest using the guards:resistor_mania resistor target
| resistor == target = (show resistor)
| resistor < target = (show resistor) ++ "+" ++ (resistor_mania resistor (target - resistor))
| otherwise = (show resistor) ++ "||(" ++ (resistor_mania resistor (p_resistor resistor target)) ++ ")"This is the standard way of listing mutually exclusive conditions in a function definition.
Semicolons
Haskell uses a two-dimensional syntax, semicolons are not needed and should be omitted as they convey no additional information, just noise.
Prefer mainstream function definitions
p_resistor = (\existing target -> (1 / ((1 / target) - (1 / existing))))Becomes:
p_resistor existing target = (1 / ((1 / target) - (1 / existing))))That looks maybe less cool, but surely faster to understand.
Types
the type-signature of resistor_mania makes me uneasy :/
Haskell is type-centric, so it is good that you are worrying about types.
I deleted your types and asked the compiler what types it would like for your functions.
*Main> :t p_resistor
p_resistor :: Double -> Double -> Double
*Main> :t resistor_mania
resistor_mania :: Double -> Double -> StringI think these suggested types are simpler, and I would use them instead of your bulky type declarations.
Non-closing parenthesis
$ is like a parenthesis but you do not need to close it:putStrLn $ show $ resistor_mania (read res_input) (read target_value)This is somewhat subjective though...
Code Snippets
resistor_mania resistor target
| resistor == target = (show resistor)
| resistor < target = (show resistor) ++ "+" ++ (resistor_mania resistor (target - resistor))
| otherwise = (show resistor) ++ "||(" ++ (resistor_mania resistor (p_resistor resistor target)) ++ ")"p_resistor = (\existing target -> (1 / ((1 / target) - (1 / existing))))p_resistor existing target = (1 / ((1 / target) - (1 / existing))))*Main> :t p_resistor
p_resistor :: Double -> Double -> Double
*Main> :t resistor_mania
resistor_mania :: Double -> Double -> StringputStrLn $ show $ resistor_mania (read res_input) (read target_value)Context
StackExchange Code Review Q#115924, answer score: 8
Revisions (0)
No revisions yet.