HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Resistance is futile, Resistors have been dispatched to model your Resistance

Submitted by: @import:stackexchange-codereview··
0
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:

*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 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 -> String


I 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 -> String
putStrLn $ show $ resistor_mania (read res_input) (read target_value)

Context

StackExchange Code Review Q#115924, answer score: 8

Revisions (0)

No revisions yet.