|
| 1 | +# Elon's Toys |
| 2 | + |
| 3 | +Welcome to Elon's Toys 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 | +A method is a function with a special _receiver_ argument. The receiver appears in its own argument list between `func` keyword and the name of the method. |
| 10 | + |
| 11 | +```go |
| 12 | +func (receiver type) MethodName(parameters) (returnTypes) { |
| 13 | +} |
| 14 | +``` |
| 15 | + |
| 16 | +You can only define a method with a receiver whose type is defined in the same package as the method. |
| 17 | + |
| 18 | +```go |
| 19 | +package person |
| 20 | + |
| 21 | +type Person struct { |
| 22 | + Name string |
| 23 | +} |
| 24 | + |
| 25 | +func (p Person) Greetings() string { |
| 26 | + return fmt.Sprintf("Welcome %s!", p.Name) |
| 27 | +} |
| 28 | +``` |
| 29 | + |
| 30 | +The method on the struct can be called via dot notation. |
| 31 | + |
| 32 | +```go |
| 33 | +p := Person{Name: "Bronson"} |
| 34 | +fmt.Println(p.Greetings()) |
| 35 | +// Output: Welcome Bronson! |
| 36 | +``` |
| 37 | + |
| 38 | +Notice the way we called the method `Greetings()` on the `Person` instance `p`. |
| 39 | +It’s exactly like the way you call methods in an object-oriented programming language. |
| 40 | + |
| 41 | +Remember: a method is just a function with a receiver argument. |
| 42 | +Methods help to avoid naming conflicts - since a method is tied to a particular receiver type, you can have the same method name on different types. |
| 43 | + |
| 44 | +```go |
| 45 | +import "math" |
| 46 | + |
| 47 | +type rect struct { |
| 48 | + width, height int |
| 49 | +} |
| 50 | +func (r rect) area() int { |
| 51 | + return r.width * r.height |
| 52 | +} |
| 53 | + |
| 54 | +type circle struct { |
| 55 | + radius int |
| 56 | +} |
| 57 | +func (c circle) area() float64 { |
| 58 | + return math.Pow(float64(c.radius), 2) * math.Pi |
| 59 | +} |
| 60 | +``` |
| 61 | + |
| 62 | +There are two types of receivers, value receivers, and pointer receivers. |
| 63 | + |
| 64 | +All the methods we have seen so far have a value receiver which means they will receive a copy of the value passed to the method, meaning that any modification done to the receiver inside the method is not visible to the caller. |
| 65 | + |
| 66 | +You can declare methods with pointer receivers in order to modify the value to which the receiver points. |
| 67 | +This is done by prefixing the type name with a `*`. |
| 68 | +For example with the `rect` type, a pointer receiver would be declared as `*rect`. |
| 69 | +Such modifications are visible to the caller of the method as well. |
| 70 | + |
| 71 | +```go |
| 72 | +type rect struct { |
| 73 | + width, height int |
| 74 | +} |
| 75 | +func (r *rect) squareIt() { |
| 76 | + r.height = r.width |
| 77 | +} |
| 78 | + |
| 79 | +r := rect{width: 10, height: 20} |
| 80 | +fmt.Printf("Width: %d, Height: %d\n", r.width, r.height) |
| 81 | +// Output: Width: 10, Height: 20 |
| 82 | + |
| 83 | +r.squareIt() |
| 84 | +fmt.Printf("Width: %d, Height: %d\n", r.width, r.height) |
| 85 | +// Output: Width: 10, Height: 10 |
| 86 | +``` |
| 87 | + |
| 88 | +## Instructions |
| 89 | + |
| 90 | +Note: This exercise is a continuation of the `need-for-speed` exercise. |
| 91 | + |
| 92 | +In this exercise you'll be organizing races between various types of remote controlled cars. Each car has its own speed and battery drain characteristics. |
| 93 | + |
| 94 | +Cars start with full (100%) batteries. Each time you drive the car using the remote control, it covers the car's speed in meters and decreases the remaining battery percentage by its battery drain. |
| 95 | + |
| 96 | +If a car's battery is below its battery drain percentage, you can't drive the car anymore. |
| 97 | + |
| 98 | +The remote controlled car has a fancy LED display that shows two bits of information: |
| 99 | + |
| 100 | +- The total distance it has driven, displayed as: `"Driven <METERS> meters"`. |
| 101 | +- The remaining battery charge, displayed as: `"Battery at <PERCENTAGE>%"`. |
| 102 | + |
| 103 | +Each race track has its own distance. Cars are tested by checking if they can finish the track without running out of battery. |
| 104 | + |
| 105 | +## 1. Drive the car |
| 106 | + |
| 107 | +Implement the `Drive` method on the `Car` that updates the number of meters driven based on the car's speed, and reduces the battery according to the battery drainage: |
| 108 | + |
| 109 | +```go |
| 110 | +speed := 5 |
| 111 | +batteryDrain := 2 |
| 112 | +car := NewCar(speed, batteryDrain) |
| 113 | +car.Drive() |
| 114 | +// car is now Car{speed: 5, batteryDrain: 2, battery: 98, distance: 5} |
| 115 | +``` |
| 116 | + |
| 117 | +Note: You should not try to drive the car if doing so will cause the car's battery to be below 0. |
| 118 | + |
| 119 | +## 2. Display the distance driven |
| 120 | + |
| 121 | +Implement a `DisplayDistance` method on `Car` to return the distance as displayed on the LED display as a `string`: |
| 122 | + |
| 123 | +```go |
| 124 | +speed := 5 |
| 125 | +batteryDrain := 2 |
| 126 | +car := NewCar(speed, batteryDrain) |
| 127 | + |
| 128 | +fmt.Println(car.DisplayDistance()) |
| 129 | +// Output: "Driven 0 meters" |
| 130 | +``` |
| 131 | + |
| 132 | +## 3. Display the battery percentage |
| 133 | + |
| 134 | +Implement the `DisplayBattery` method on `Car` to return the battery percentage as displayed on the LED display as a `string`: |
| 135 | + |
| 136 | +```go |
| 137 | +speed := 5 |
| 138 | +batteryDrain := 2 |
| 139 | +car := NewCar(speed, batteryDrain) |
| 140 | + |
| 141 | +fmt.Println(car.DisplayBattery()) |
| 142 | +// Output: "Battery at 100%" |
| 143 | +``` |
| 144 | + |
| 145 | +## 4. Check if a remote control car can finish a race |
| 146 | + |
| 147 | +To finish a race, a car has to be able to drive the race's distance. This means not draining its battery before having crossed the finish line. Implement the `CanFinish` method that takes a `trackDistance int` as its parameter and returns `true` if the car can finish the race; otherwise, return `false`: |
| 148 | + |
| 149 | +```go |
| 150 | +speed := 5 |
| 151 | +batteryDrain := 2 |
| 152 | +car := NewCar(speed, batteryDrain) |
| 153 | + |
| 154 | +trackDistance := 100 |
| 155 | + |
| 156 | +car.CanFinish(trackDistance) |
| 157 | +// => true |
| 158 | +``` |
| 159 | + |
| 160 | +## Source |
| 161 | + |
| 162 | +### Created by |
| 163 | + |
| 164 | +- @tehsphinx |
| 165 | + |
| 166 | +### Contributed to by |
| 167 | + |
| 168 | +- @oanaOM |
| 169 | +- @mcastorina |
0 commit comments