Code Efficiency

I've created a code that calculates the resistance of a resistor based on the color combination the user inputs. The code works fine but I feel like my series of else if statements is completely inefficient and I can't seem to find another way the avoid them. Is there anything I could be doing differently
while still keeping the struct and still allow the user to input the color as type string?



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#include <iostream>
#include<string>
using namespace std;
struct bandLayout
{
    
    
    
    double band1;
    
    double band2;
    
    double band3;
    
    double band4;
    
    double tolerance;
    
    double tempBand;
    
    
};

enum {black, brown, red, orange, yellow, green, blue, violet, grey, white, gold, silver, colorNames};

bandLayout colors[colorNames] =

{
    //black
    { 0,  0,  0, 1 , 0, 0} ,
    //brown
    { 1, 1, 1, 10, .01, 100 },
    //red
    { 2, 2, 2, 100, 0.02, 50 },
    //orange
    { 3, 3, 3, 1000, 0.03, 15 },
    //yellow
    { 4, 4 , 4, 10000, 0.04, 25 },
    //green
    { 5, 5, 5, 100000, 0.05, 0.005 },
    //blue
    { 6, 6, 6, 1000000, 0.0025, 10 },
    //violet
    { 7, 7, 7, 10000000, 0.001, 5 },
    //grey
    { 8, 8, 8, 10e8, 0.0005, 0 },
    //white
    { 9, 9, 9, 0, 0.01, 0 },
    //gold
    { 0, 0, 0, 0, 0.05, 0 },
    //silver
    { 0, 0, 0, 0, 0.1, 0 },
    
};

string bandColor;
int n(0);
int userNum;

int main()
{
    
    
    
    
    double value1, value2, value3, multBand, tempBand;
    
    cout<<"How many bands will you be using? ";
    cin>>userNum;
    
    while(n<userNum)
    {
        cout<<"Band Color"<<endl;
        cin>>bandColor;
        n++;
        if(n==1)
        {
            
            if(bandColor=="brown")
            {
                value1=colors[brown].band1;
            }
            
            else if(bandColor=="red")
            {
                value1=colors[red].band1;
            }
            
            else if(bandColor=="yellow")
            {
                value1=colors[yellow].band1;
            }
            
            else if(bandColor=="green")
            {
                value1=colors[green].band1;
            }
            
            else if(bandColor=="blue")
            {
                value1=colors[blue].band1;
            }
            
            else if(bandColor=="violet")
            {
                value1=colors[violet].band1;
            }
            
            else if(bandColor=="grey")
            {
                value1=colors[grey].band1;
            }
            
            else if(bandColor=="white")
            {
                value1=colors[white].band1;
            }
            
            
        }
        
        if(n==2)
        {
            
            if(bandColor=="brown")
            {
                value2=colors[brown].band2;
            }
            
            else if(bandColor=="red")
            {
                value2=colors[red].band2;
            }
            
            else if(bandColor=="yellow")
            {
                value2=colors[yellow].band2;
            }
            
            else if(bandColor=="green")
            {
                value2=colors[green].band2;
            }
            
            else if(bandColor=="blue")
            {
                value2=colors[blue].band2;
            }
            
            else if(bandColor=="violet")
            {
                value2=colors[violet].band2;
            }
            
            else if(bandColor=="grey")
            {
                value2=colors[grey].band2;
            }
            
            else if(bandColor=="white")
            {
                value2=colors[white].band2;
            }
            
        }
        

        if(n==3)
        {
            
            if(bandColor=="brown")
            {
                multBand=colors[brown].band4;
            }
            
            else if(bandColor=="red")
            {
                multBand=colors[red].band4;
            }
            
            else if(bandColor=="yellow")
            {
                multBand=colors[yellow].band4;
            }
            
            else if(bandColor=="green")
            {
                multBand=colors[green].band4;
            }
            
            else if(bandColor=="blue")
            {
                multBand=colors[blue].band4;
            }
            
            else if(bandColor=="violet")
            {
                multBand=colors[violet].band4;
            }
            
            else if(bandColor=="grey")
            {
                multBand=colors[grey].band4;
            }
            
            else if(bandColor=="white")
            {
                multBand=colors[white].band4;
            }
            
        }
        
        
    }
    
    
    double val1, val2, val3, val4,val5, ohmsValue;
    if(userNum==4)
    {
        val1 = value1*multBand;
        val2 = value2*multBand;
        val3 = val2/10;
        val4 = val1+val3;
        ohmsValue = val4*10;
        cout<<ohmsValue<<" Ohms"<<endl;
        //    toleranceValue = ohmsValue*tolerance;
        //    cout<<ohmsValue<<endl;
        //    cout<<tolerance<<endl;
        
    }
    
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
const int NUM_BANDS{ 4 };
struct bandLayout
{
    double band[NUM_BANDS];
    double tolerance;
    double tempBand;
};

int get_color( const string& col )
{
    static const string colors_str[]{
        "black", "brown", "red", "orange", "yellow", "green",
        "blue", "violet", "grey", "white", "gold", "silver"
    };

    // maybe convert col to all lowercase

    for( size_t i{}; i < sizeof( colors_str ); i++ )
        if( colors_str[i] == col ) return i;

    return -1;
}

int main()
{
    // don't use global variables
    string bandColor;
    int n(0), int userNum{};

    // initialise values
    // put similar variables in an array
    double value[3]{}, multBand{}, tempBand{};
    
    cout<<"How many bands will you be using? ";
    cin>>userNum;
    // check for invalid input, such as negative numbers, characters, etc.
    // looks like userNum is in the range [0, 3)
    
    while(n<userNum)
    {
        cout<<"Band Color"<<endl;
        cin>>bandColor;
        
        int col{ get_colour( bandColor ) };
        if( col == -1 ) 
            // error

        value[n] = colors[col].band[n];
        n++;
    }
    
    // val5 is unused?
    double val[4]{},val5, ohmsValue;
    val[0] = value[0]*multBand;
    val[1] = value[1]*multBand;
    val[2] = val[1]/10;
    val[3] = val[0]+val[2];
    ohmsValue = val[3]*10;
    cout<<ohmsValue<<" Ohms"<<endl;
    //    toleranceValue = ohmsValue*tolerance;
    //    cout<<ohmsValue<<endl;
    //    cout<<tolerance<<endl;
        
    
    return 0;
}
Last edited on
Thanks for the feedback! I had one question. What exactly are you doing to the string at


int get_color( const string& col )
{
static const string colors_str[]{
"black", "brown", "red", "orange", "yellow", "green",
"blue", "violet", "grey", "white", "gold", "silver"
};

// maybe convert col to all lowercase

for( size_t i{}; i < sizeof( colors_str ); i++ )
if( colors_str[i] == col ) return i;

return -1;
}
In your enumeration, black == 0, brown == 1, red == 2, etc...
This function will convert, for example, "black" to whatever value it is in the enumeration. In this case it will return 0.
Okay I understand now! That should make my code significantly shorter now! Thank you for the help.
A few months ago, I hacked together a program that does exactly this.
I did it in about an hour or two; the code is not the nicest, but it's been surprisingly useful. Perhaps you can adapt something from it. Consider sending me a patch.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/* Calculate resistor values in ohms.  Approximate string matching is supported. */
/* Copyright (C) 2015, Max Bozzi */

/* This file is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This file is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * This file.  If not, see <http://www.gnu.org/licenses/>.
 */

# include <iostream>
# include <memory>
# include <vector>
# include <cmath>

// wagner-fischer/levenshtein/ukkonen's alrorithm: what's the difference?
# include <string>
# include <algorithm>
# include <numeric>
int levenshtein(std::string a, std::string b) {
  /* TODO: Maybe slightly buggy(?) */
  if (a == b)           return 0;
  if (a.length () == 0) return b.length ();
  if (b.length () == 0) return a.length ();

  std::vector <std::size_t> r0 (b.length () + 1, 0);
  std::iota(r0.begin(), r0.end(), 0);
  std::vector <std::size_t> r1 (b.length () + 1, 0);

  for (std::size_t i = 0; i < a.length (); i ++) {
    r1 [0] = i + 1;

    for (std::size_t j = 0; j < b.length (); j ++) {
      bool const diff = a [j] != b [j];
      r1 [j + 1] = std::min
        (std::min (r1 [j] + 1, r0 [j + 1] + 1), r0 [j] + (diff? 2: 0));

      /* if (r0 [j + 1] >= max_edit_distance) { return 0; } */
    }

    std::swap(r0, r1);
  }

  return r1 [b.length()];
}

# include <map>
std::map <std::string, int> const band_value {
  {"black" ,  0}, {"brown", 1}, {"red" , 2}, {"orange",  3},
  {"yellow",  4}, {"green", 5}, {"blue", 6}, {"violet",  7},
  {"grey"  ,  8}, {"white", 9},
};

std::map <std::string, double> const multiplier_value {
  {"black" , 1e0}, {"brown", 1e1}, {"red" ,  1e2}, {"orange",  1e3},
  {"yellow", 1e4}, {"green", 1e5}, {"blue",  1e6}, {"violet",  1e7},
  {"grey"  , 1e8}, {"white", 1e9}, {"gold", 1e-1}, {"silver", 1e-2}
};

/* Temperature coefficient in parts-per-million per degree celsius. */
std::map <std::string, int> const temp_coeff_value {
  {"brown", 100}, {"red" , 50}, {"orange", 15}, {"yellow", 25}
};

/* Resistance tolerance in +/- %. */
std::map <std::string, double> const tolerance_value {
  {"brown",   1.0}, {"red" ,  2.0},  {"green", 0.5}, {"blue",    0.25},
  {"violet",  0.1}, {"grey",  0.05}, {"gold",  5.0}, {"silver", 10.0},
  {"none",   20.0}
};

std::vector <std::string> const colors {
  "black" , "brown", "red"  , "orange", "yellow", "green", "blue",
  "violet", "grey" , "white", "silver", "gold"
};

std::vector <std::string> match_prefixes(std::string match,
                                         std::vector <std::string> candidates) {
  /* The best way to do this is via a trie.  I'm not writng one now. */
  std::vector <std::string> prev_candidates;

  for (std::size_t i = 0; i < match.length (); i ++) {
    prev_candidates = candidates;

    for (auto iter = candidates.begin (); iter != candidates.end (); ) {
      if (i >= iter->length () || match [i] != (*iter)[i])
        iter = candidates.erase (iter);
      else
        iter ++;
    }
    // return candidates;
    if (!candidates.size ()) return (prev_candidates);
  }

  return candidates;
}

/* Does some sort of ad-hoc approximate matching.  Code was copied in from
   various programs, all GPL'd, all my property.  Don't even try to use this for
   large dictionaries. */
std::string amatch (std::string match,
                    std::vector<std::string> candidates) {
  auto results = match_prefixes(match, candidates);
  if (results.size() == 1) {
    return results.back();
  }

  /* Check for matching ending characters: */
  auto backmatch = results;
  for (auto iter = backmatch.begin(); iter != backmatch.end(); ) {
    if (match.back() != iter->back())
      iter = backmatch.erase(iter);
    else
      iter ++;
  }

  if (backmatch.size() == 1) {
    return backmatch.back();
  }

  /* Sort by levenshtein distance... */
  std::sort (results.begin (), results.end (), [match](std::string a,
                                                       std::string b) {
                return levenshtein(match, a) < levenshtein(match, b);
    });

  return results.front();
}

void __attribute__((noreturn)) usage_and_die (char ** argv) {
  std::cerr << "usage: " << *argv << "\n"
             << "  (band1 band2 band3 [band4] [band5] [tolerance_band])|\n"
             << "output: resistor value in ohms, tolerance.\n";
  std::exit(1);
}

void print_resistor (std::vector <std::string> bands) {
  auto compute_ohms = [](auto start_iter, auto end_iter) -> double {
    double ohm_result = 0.0;
    while (start_iter != end_iter) {
      /* Make sure we're not looking at the multiplier band */
      if (start_iter != (end_iter - 1)) {
        ohm_result *= 10; /* decimal ALSH (e.g., 14 -> 140) */
        ohm_result += band_value.at(*start_iter++);
      } else { /* Looking at last band. */
        return ohm_result * multiplier_value.at(*start_iter);
      }
    }

    return ohm_result;
  };

  double ohm_result, tolerance, temp_coeff;
  ohm_result = tolerance = temp_coeff =
    std::numeric_limits<double>::infinity();

  try {
    switch (bands.size()) {
    case 3: {
      ohm_result = compute_ohms(bands.begin(), bands.end());
      tolerance  = tolerance_value.at("none");
    } break;

    case 4:
    case 5: {
      ohm_result = compute_ohms(bands.begin(), bands.end() - 1);
      tolerance  = tolerance_value.at(bands.back());
    } break;

    case 6: {
      ohm_result = compute_ohms(bands.begin(), bands.end() - 2);
      tolerance  = tolerance_value.at(*(bands.end () - 2));
      temp_coeff = temp_coeff_value.at(bands.back());
    } break;

    default:
      std::cerr << "Incorrect number of bands. \n";
      std::exit(1);
    }
  } catch (std::out_of_range const e) {
    std::cerr << "Unrecognized band type.  Check your resistor!\n";
    std::exit(1);
  }

  using namespace std::literals::string_literals;
  std::cout << ohm_result << " ohms at " << tolerance << " percent tolerance";

  if (! std::isinf(temp_coeff)) {
    std::cout <<", temperature coeff. " << temp_coeff << "\n";
  } else std::cout << ".\n";
}

auto main (int argc, char **argv) -> int {
  if (argc == 1 || argc > 7) { /* no more than 6 bands! */
    usage_and_die (argv);
  }

  std::vector<std::string> curr_bands;
  for (int i = 1; i < argc; i ++) {
    curr_bands.emplace_back(amatch(argv [i], colors));
  }

  print_resistor(curr_bands);

  for (auto c: curr_bands) std::cout << c << " ";
  std::cout << "\n";
}
Topic archived. No new replies allowed.