Skip to content

Commit b29e243

Browse files
authored
Add resistor color trio (#863)
1 parent 65abe5f commit b29e243

File tree

9 files changed

+313
-0
lines changed

9 files changed

+313
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,14 @@
795795
"prerequisites": [],
796796
"difficulty": 3
797797
},
798+
{
799+
"slug": "resistor-color-trio",
800+
"name": "Resistor Color Trio",
801+
"uuid": "bfd64381-b035-46e5-827b-99ed8b674cde",
802+
"practices": [],
803+
"prerequisites": [],
804+
"difficulty": 3
805+
},
798806
{
799807
"slug": "acronym",
800808
"name": "Acronym",
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Instructions
2+
3+
If you want to build something using a Raspberry Pi, you'll probably use _resistors_.
4+
For this exercise, you need to know only three things about them:
5+
6+
- Each resistor has a resistance value.
7+
- Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read.
8+
To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values.
9+
- Each band acts as a digit of a number.
10+
For example, if they printed a brown band (value 1) followed by a green band (value 5), it would translate to the number 15.
11+
In this exercise, you are going to create a helpful program so that you don't have to remember the values of the bands.
12+
The program will take 3 colors as input, and outputs the correct value, in ohms.
13+
The color bands are encoded as follows:
14+
15+
- black: 0
16+
- brown: 1
17+
- red: 2
18+
- orange: 3
19+
- yellow: 4
20+
- green: 5
21+
- blue: 6
22+
- violet: 7
23+
- grey: 8
24+
- white: 9
25+
26+
In Resistor Color Duo you decoded the first two colors.
27+
For instance: orange-orange got the main value `33`.
28+
The third color stands for how many zeros need to be added to the main value.
29+
The main value plus the zeros gives us a value in ohms.
30+
For the exercise it doesn't matter what ohms really are.
31+
For example:
32+
33+
- orange-orange-black would be 33 and no zeros, which becomes 33 ohms.
34+
- orange-orange-red would be 33 and 2 zeros, which becomes 3300 ohms.
35+
- orange-orange-orange would be 33 and 3 zeros, which becomes 33000 ohms.
36+
37+
(If Math is your thing, you may want to think of the zeros as exponents of 10.
38+
If Math is not your thing, go with the zeros.
39+
It really is the same thing, just in plain English instead of Math lingo.)
40+
41+
This exercise is about translating the colors into a label:
42+
43+
> "... ohms"
44+
45+
So an input of `"orange", "orange", "black"` should return:
46+
47+
> "33 ohms"
48+
49+
When we get to larger resistors, a [metric prefix][metric-prefix] is used to indicate a larger magnitude of ohms, such as "kiloohms".
50+
That is similar to saying "2 kilometers" instead of "2000 meters", or "2 kilograms" for "2000 grams".
51+
52+
For example, an input of `"orange", "orange", "orange"` should return:
53+
54+
> "33 kiloohms"
55+
56+
[metric-prefix]: https://en.wikipedia.org/wiki/Metric_prefix
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import Foundation
2+
3+
enum Color: String, CaseIterable {
4+
case black
5+
case brown
6+
case red
7+
case orange
8+
case yellow
9+
case green
10+
case blue
11+
case violet
12+
case grey
13+
case white
14+
}
15+
16+
enum Unit: String {
17+
case ohms
18+
case kiloohms
19+
case megaohms
20+
case gigaohms
21+
}
22+
23+
enum ResistorColorTrioError: Error {
24+
case invalidInput
25+
case unknownColor
26+
}
27+
28+
enum ResistorColorTrio {
29+
30+
static func label(for colors: [String]) throws -> String {
31+
guard colors.count >= 3 else {
32+
throw ResistorColorTrioError.invalidInput
33+
}
34+
35+
let convertedColors = try colors.reduce(into: [Color]()) { partialResult, string in
36+
guard let color = Color(rawValue: string) else {
37+
throw ResistorColorTrioError.unknownColor
38+
}
39+
partialResult.append(color)
40+
}
41+
42+
var zeros = 0
43+
var value = 0
44+
let firstDigit = code(for: convertedColors[0])
45+
if (firstDigit > 0) {
46+
value += firstDigit
47+
}
48+
49+
let secondDigit = code(for: convertedColors[1])
50+
if (secondDigit == 0) {
51+
zeros += 1
52+
}
53+
else {
54+
value = value * 10 + secondDigit
55+
}
56+
57+
zeros += code(for: convertedColors[2])
58+
let (remaining, unit) = strip(zeros)
59+
return "\(value * Int(pow(10.0, Double(remaining)))) \(unit)"
60+
}
61+
62+
private static func strip(_ zeros: Int) -> (remaining: Int, unit: String) {
63+
switch zeros {
64+
case 0, 1, 2: return (zeros % 3, Unit.ohms.rawValue)
65+
case 3, 4, 5: return (zeros % 3, Unit.kiloohms.rawValue)
66+
case 6, 7, 8: return (zeros % 3, Unit.megaohms.rawValue)
67+
case 9: return (0, Unit.gigaohms.rawValue)
68+
default: return (0, Unit.ohms.rawValue)
69+
}
70+
}
71+
}
72+
73+
fileprivate func code(for color: Color) -> Int {
74+
switch color {
75+
case .black: return 0
76+
case .brown: return 1
77+
case .red: return 2
78+
case .orange: return 3
79+
case .yellow: return 4
80+
case .green: return 5
81+
case .blue: return 6
82+
case .violet: return 7
83+
case .grey: return 8
84+
case .white: return 9
85+
}
86+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"Sencudra"
4+
],
5+
"files": {
6+
"solution": [
7+
"Sources/ResistorColorTrio/ResistorColorTrio.swift"
8+
],
9+
"test": [
10+
"Tests/ResistorColorTrioTests/ResistorColorTrioTests.swift"
11+
],
12+
"example": [
13+
".meta/Sources/ResistorColorTrio/ResistorColorTrioExample.swift"
14+
]
15+
},
16+
"blurb": "Convert color codes, as used on resistors, to a human-readable label.",
17+
"source": "Maud de Vries, Erik Schierboom",
18+
"source_url": "https://github.com/exercism/problem-specifications/issues/1549"
19+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import Testing
2+
import Foundation
3+
@testable import {{ exercise | camelCase }}
4+
5+
let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false
6+
7+
@Suite struct {{ exercise | camelCase }}Tests {
8+
{% for case in cases %}
9+
{% if forloop.first -%}
10+
@Test("{{case.description}}")
11+
{% else -%}
12+
@Test("{{case.description}}", .enabled(if: RUNALL))
13+
{% endif -%}
14+
func test{{ case.description | camelCase }}() throws {
15+
#expect(try ResistorColorTrio.{{ case.property }}(for: {{ case.input.colors | toStringArray }}) == "{{ case.expected.value }} {{case.expected.unit}}")
16+
}
17+
{% endfor -%}
18+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[d6863355-15b7-40bb-abe0-bfb1a25512ed]
13+
description = "Orange and orange and black"
14+
15+
[1224a3a9-8c8e-4032-843a-5224e04647d6]
16+
description = "Blue and grey and brown"
17+
18+
[b8bda7dc-6b95-4539-abb2-2ad51d66a207]
19+
description = "Red and black and red"
20+
21+
[5b1e74bc-d838-4eda-bbb3-eaba988e733b]
22+
description = "Green and brown and orange"
23+
24+
[f5d37ef9-1919-4719-a90d-a33c5a6934c9]
25+
description = "Yellow and violet and yellow"
26+
27+
[5f6404a7-5bb3-4283-877d-3d39bcc33854]
28+
description = "Blue and violet and blue"
29+
30+
[7d3a6ab8-e40e-46c3-98b1-91639fff2344]
31+
description = "Minimum possible value"
32+
33+
[ca0aa0ac-3825-42de-9f07-dac68cc580fd]
34+
description = "Maximum possible value"
35+
36+
[0061a76c-903a-4714-8ce2-f26ce23b0e09]
37+
description = "First two colors make an invalid octal number"
38+
39+
[30872c92-f567-4b69-a105-8455611c10c4]
40+
description = "Ignore extra colors"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// swift-tools-version:6.0
2+
3+
import PackageDescription
4+
5+
let package = Package(
6+
name: "ResistorColorTrio",
7+
products: [
8+
.library(
9+
name: "ResistorColorTrio",
10+
targets: ["ResistorColorTrio"])
11+
],
12+
dependencies: [],
13+
targets: [
14+
.target(
15+
name: "ResistorColorTrio",
16+
dependencies: []),
17+
.testTarget(
18+
name: "ResistorColorTrioTests",
19+
dependencies: ["ResistorColorTrio"]),
20+
]
21+
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import Foundation
2+
3+
enum ResistorColorTrio {
4+
// Write your code for the 'ResistorColorTrio' exercise in this file.
5+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import Foundation
2+
import Testing
3+
4+
@testable import ResistorColorTrio
5+
6+
let RUNALL = Bool(ProcessInfo.processInfo.environment["RUNALL", default: "false"]) ?? false
7+
8+
@Suite struct ResistorColorTrioTests {
9+
10+
@Test("Orange and orange and black")
11+
func testOrangeAndOrangeAndBlack() throws {
12+
#expect(try ResistorColorTrio.label(for: ["orange", "orange", "black"]) == "33 ohms")
13+
}
14+
15+
@Test("Blue and grey and brown", .enabled(if: RUNALL))
16+
func testBlueAndGreyAndBrown() throws {
17+
#expect(try ResistorColorTrio.label(for: ["blue", "grey", "brown"]) == "680 ohms")
18+
}
19+
20+
@Test("Red and black and red", .enabled(if: RUNALL))
21+
func testRedAndBlackAndRed() throws {
22+
#expect(try ResistorColorTrio.label(for: ["red", "black", "red"]) == "2 kiloohms")
23+
}
24+
25+
@Test("Green and brown and orange", .enabled(if: RUNALL))
26+
func testGreenAndBrownAndOrange() throws {
27+
#expect(try ResistorColorTrio.label(for: ["green", "brown", "orange"]) == "51 kiloohms")
28+
}
29+
30+
@Test("Yellow and violet and yellow", .enabled(if: RUNALL))
31+
func testYellowAndVioletAndYellow() throws {
32+
#expect(try ResistorColorTrio.label(for: ["yellow", "violet", "yellow"]) == "470 kiloohms")
33+
}
34+
35+
@Test("Blue and violet and blue", .enabled(if: RUNALL))
36+
func testBlueAndVioletAndBlue() throws {
37+
#expect(try ResistorColorTrio.label(for: ["blue", "violet", "blue"]) == "67 megaohms")
38+
}
39+
40+
@Test("Minimum possible value", .enabled(if: RUNALL))
41+
func testMinimumPossibleValue() throws {
42+
#expect(try ResistorColorTrio.label(for: ["black", "black", "black"]) == "0 ohms")
43+
}
44+
45+
@Test("Maximum possible value", .enabled(if: RUNALL))
46+
func testMaximumPossibleValue() throws {
47+
#expect(try ResistorColorTrio.label(for: ["white", "white", "white"]) == "99 gigaohms")
48+
}
49+
50+
@Test("First two colors make an invalid octal number", .enabled(if: RUNALL))
51+
func testFirstTwoColorsMakeAnInvalidOctalNumber() throws {
52+
#expect(try ResistorColorTrio.label(for: ["black", "grey", "black"]) == "8 ohms")
53+
}
54+
55+
@Test("Ignore extra colors", .enabled(if: RUNALL))
56+
func testIgnoreExtraColors() throws {
57+
#expect(
58+
try ResistorColorTrio.label(for: ["blue", "green", "yellow", "orange"]) == "650 kiloohms")
59+
}
60+
}

0 commit comments

Comments
 (0)