Skip to content

Commit 76274e2

Browse files
[Go] Airport Robot
1 parent 4248b45 commit 76274e2

File tree

7 files changed

+298
-0
lines changed

7 files changed

+298
-0
lines changed

go/airport-robot/HELP.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Help
2+
3+
## Running the tests
4+
5+
To run the tests run the command `go test` from within the exercise directory.
6+
7+
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
8+
flags:
9+
10+
go test -v --bench . --benchmem
11+
12+
Keep in mind that each reviewer will run benchmarks on a different machine, with
13+
different specs, so the results from these benchmark tests may vary.
14+
15+
## Submitting your solution
16+
17+
You can submit your solution using the `exercism submit airport_robot.go` command.
18+
This command will upload your solution to the Exercism website and print the solution page's URL.
19+
20+
It's possible to submit an incomplete solution which allows you to:
21+
22+
- See how others have completed the exercise
23+
- Request help from a mentor
24+
25+
## Need to get help?
26+
27+
If you'd like help solving the exercise, check the following pages:
28+
29+
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
30+
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
31+
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
32+
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
33+
34+
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
35+
36+
To get help if you're having trouble, you can use one of the following resources:
37+
38+
- [How to Write Go Code](https://golang.org/doc/code.html)
39+
- [Effective Go](https://golang.org/doc/effective_go.html)
40+
- [Go Resources](http://golang.org/help)
41+
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

go/airport-robot/HINTS.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Hints
2+
3+
## General
4+
5+
- Maybe have a look at [Interfaces in the Tour of Go][interfaces-tour-of-go] to see more examples if you struggle with the exercise.
6+
7+
## 1. Create the abstract greeting functionality
8+
9+
- Look back at `Counter` example the introduction to find out how to define an interface.
10+
- Revisit the [functions concepts][concept-functions] to recap how to write function signatures in Go.
11+
- The abstract `Greeter` type can be used in a function signature the same way as a normal concrete type like `string`.
12+
- To implement `SayHello`, call the methods on the argument of type `Greeter`.
13+
Then use string formatting or string concatenation to construct the final result.
14+
15+
## 2. Implement Italian
16+
17+
- Revisit the [structs concept][concept-structs] to see how to define a struct type.
18+
- To solve the task, the struct does not need any fields at all.
19+
- Once you defined the struct, you want to add the methods `LanguageName` and `Greet` to it.
20+
Revisit the [methods concept][concept-methods] to find out how to add a method for a type.
21+
22+
## 3. Implement Portuguese
23+
24+
- See hints for task 2.
25+
26+
[interfaces-tour-of-go]: https://go.dev/tour/methods/9
27+
[concept-functions]: /tracks/go/concepts/functions
28+
[concept-structs]: /tracks/go/concepts/structs
29+
[concept-methods]: /tracks/go/concepts/methods

go/airport-robot/README.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Airport Robot
2+
3+
Welcome to Airport Robot on Exercism's Go Track.
4+
If you need help running the tests or submitting your code, check out `HELP.md`.
5+
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
6+
7+
## Introduction
8+
9+
## Interface as a set of methods
10+
11+
In its simplest form, an **interface type** is a set of method signatures.
12+
Here is an example of an interface definition that includes two methods `Add` and `Value`:
13+
14+
```go
15+
type Counter interface {
16+
Add(increment int)
17+
Value() int
18+
}
19+
```
20+
21+
The parameter names like `increment` can be omitted from the interface definition but they often increase readability.
22+
23+
Interface names in Go do not contain the word `Interface` or `I`.
24+
Instead, they often end with `er`, e.g. `Reader`, `Stringer`.
25+
26+
## Implementing an interface
27+
28+
Any type that defines the methods of the interface automatically implicitly "implements" the interface.
29+
There is no `implements` keyword in Go.
30+
31+
The following type implements the `Counter` interface we saw above.
32+
33+
```go
34+
type Stats struct {
35+
value int
36+
// ...
37+
}
38+
39+
func (s Stats) Add(v int) {
40+
s.value += v
41+
}
42+
43+
func (s Stats) Value() int {
44+
return s.value
45+
}
46+
47+
func (s Stats) SomeOtherMethod() {
48+
// The type can have additional methods not mentioned in the interface.
49+
}
50+
```
51+
52+
For implementing the interface, it does not matter whether the method has a value or pointer receiver.
53+
(Revisit the [methods concepts][concept-methods] if you are unsure about those.)
54+
55+
> A value of interface type can hold any value that implements those methods. [^1]
56+
57+
That means `Stats` can now be used in all the places that expect the `Counter` interface.
58+
59+
```go
60+
func SetUpAnalytics(counter Counter) {
61+
// ...
62+
}
63+
64+
stats := Stats{}
65+
SetUpAnalytics(stats)
66+
// works because Stats implements Counter
67+
```
68+
69+
Because interfaces are implemented implicitly, a type can easily implement multiple interfaces.
70+
It only needs to have all the necessary methods defined.
71+
72+
## Empty interface
73+
74+
There is one very special interface type in Go, the **empty interface** type that contains zero methods.
75+
The empty interface is written like this: `interface{}`.
76+
In Go 1.18 or higher, `any` can be used as well. It was defined as an alias.
77+
78+
Since the empty interface has no methods, every type implements it implicitly.
79+
This is helpful for defining a function that can generically accept any value.
80+
In that case, the function parameter uses the empty interface type.
81+
82+
[concept-methods]: /tracks/go/concepts/methods
83+
84+
## Instructions
85+
86+
The new airport in Berlin hired developers for their robots lab and you are starting your job there.
87+
They have clunky, somewhat humanoid-looking robots that they are trying to use to improve customer service.
88+
89+
Your first task on the job is to write a program so that the robot can greet people in their native language after they scanned their passports at the self-check-in counter.
90+
91+
The robot is proud of its abilities so it will always say which language it can speak first and then greet the person.
92+
For example, if someone scans a German passport the robot would say:
93+
94+
```txt
95+
I can speak German: Hallo Dietrich!
96+
```
97+
98+
## 1. Create the abstract greeting functionality
99+
100+
You will not write the code for the different languages yourself so you need to structure your code for the robot so that other developers can easily add more languages later.
101+
102+
As a first step, define an interface `Greeter` with two methods.
103+
104+
- `LanguageName` which returns the name of the language (a `string`) that the robot is supposed to greet the visitor in.
105+
- `Greet` which accepts a visitor's name (a `string`) and returns a `string` with the greeting message in a specific language.
106+
107+
Next, implement a function `SayHello` that accepts the name of the visitor and anything that implements the `Greeter` interface as arguments and returns the desired greeting string.
108+
For example, imagine a German `Greeter` implementation for which `LanguageName` returns `"German"` and `Greet` returns `"Hallo {name}!"`:
109+
110+
```go
111+
SayHello("Dietrich", germanGreeter)
112+
// => "I can speak German: Hallo Dietrich!"
113+
```
114+
115+
## 2. Implement Italian
116+
117+
Now your job is to make the robot work for people that scan Italian passports.
118+
119+
For that, create a struct `Italian` and implement the two methods that are needed for the struct to fulfill the `Greeter` interface you set up in task 1.
120+
You can greet someone in Italian with `"Ciao {name}!"`.
121+
122+
## 3. Implement Portuguese
123+
124+
Before you call it a day, you are also supposed to finish the functionality to greet people in Portuguese.
125+
126+
For that, create a struct `Portuguese` and implement the two methods that are needed for the struct to fulfill the `Greeter` interface here as well.
127+
You can greet someone in Portuguese with `"Olá {name}!"`.
128+
129+
## Source
130+
131+
### Created by
132+
133+
- @junedev

go/airport-robot/airport_robot.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package airportrobot
2+
3+
import "fmt"
4+
5+
type Greeter interface {
6+
LanguageName() string
7+
Greet(name string) string
8+
}
9+
10+
func SayHello(name string, greeter Greeter) string {
11+
return greeter.Greet(name)
12+
}
13+
14+
type Italian struct {}
15+
16+
func (i Italian) LanguageName() string {
17+
return "Italian"
18+
}
19+
20+
func (i Italian) Greet(name string) string {
21+
return fmt.Sprintf("I can speak %s: Ciao %s!", i.LanguageName(), name)
22+
}
23+
24+
type Portuguese struct {}
25+
26+
func (i Portuguese) LanguageName() string {
27+
return "Portuguese"
28+
}
29+
30+
func (i Portuguese) Greet(name string) string {
31+
return fmt.Sprintf("I can speak %s: Olá %s!", i.LanguageName(), name)
32+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package airportrobot
2+
3+
import "testing"
4+
5+
// testRunnerTaskID=2
6+
func TestSayHello_Italien(t *testing.T) {
7+
tests := []struct {
8+
testName string
9+
name string
10+
want string
11+
}{
12+
{
13+
testName: "name without spaces",
14+
name: "Flora",
15+
want: "I can speak Italian: Ciao Flora!",
16+
},
17+
{
18+
testName: "full name",
19+
name: "Tomaso Giulio Micheli",
20+
want: "I can speak Italian: Ciao Tomaso Giulio Micheli!",
21+
},
22+
}
23+
24+
for _, tt := range tests {
25+
t.Run(tt.testName, func(t *testing.T) {
26+
if got := SayHello(tt.name, Italian{}); got != tt.want {
27+
t.Errorf("SayHello(%q, \"Italian{}\") = %q, want %q", tt.name, got, tt.want)
28+
}
29+
})
30+
}
31+
}
32+
33+
// testRunnerTaskID=3
34+
func TestSayHello_Portuguese(t *testing.T) {
35+
tests := []struct {
36+
testName string
37+
name string
38+
want string
39+
}{
40+
{
41+
testName: "name without spaces",
42+
name: "Fabrício",
43+
want: "I can speak Portuguese: Olá Fabrício!",
44+
},
45+
{
46+
testName: "full name",
47+
name: "Manuela Alberto",
48+
want: "I can speak Portuguese: Olá Manuela Alberto!",
49+
},
50+
}
51+
52+
for _, tt := range tests {
53+
t.Run(tt.testName, func(t *testing.T) {
54+
if got := SayHello(tt.name, Portuguese{}); got != tt.want {
55+
t.Errorf("SayHello(%q, \"Portuguese{}\") = %q, want %q", tt.name, got, tt.want)
56+
}
57+
})
58+
}
59+
}

go/airport-robot/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module airportrobot
2+
3+
go 1.18

go/go.work

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ go 1.19
22

33
use (
44
./accumulate
5+
./airport-robot
56
./annalyns-infiltration
67
./bird-watcher
78
./blackjack

0 commit comments

Comments
 (0)