some exercises are solved now

This commit is contained in:
Vitor Gonçalves 2024-02-15 12:53:01 -03:00
commit 66198b71fe
Signed by: vitorg
GPG Key ID: B90BF113DF56EB41
95 changed files with 5145 additions and 0 deletions

View File

@ -0,0 +1,26 @@
{
"authors": [
"oanaOM"
],
"files": {
"solution": [
"annalyns_infiltration.go"
],
"test": [
"annalyns_infiltration_test.go"
],
"exemplar": [
".meta/exemplar.go"
],
"invalidator": [
"go.mod"
]
},
"forked_from": [
"csharp/annalyns-infiltration"
],
"blurb": "Learn about booleans by helping Annalyn free her best friend.",
"custom": {
"taskIdsEnabled": true
}
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"annalyns-infiltration","id":"dbf707eea45b418b8a58f8a953b5df23","url":"https://exercism.org/tracks/go/exercises/annalyns-infiltration","handle":"vtrgnc","is_requester":true,"auto_approve":false}

View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit annalyns_infiltration.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

View File

@ -0,0 +1,23 @@
# Hints
## General
- There are three [boolean operators][logical operators] to work with boolean values.
- Multiple operators can be combined in a single expression.
## 1. Check if a fast attack can be made
- The logical NOT operator (`!`) can be placed before an expression to negate its value.
## 2. Check if the group can be spied upon
- Logical operators are typically used to evaluate whether two or more expressions are true or not true.
## 3. Check if the prisoner can be signaled
- Logical operators execute in the order of their precedence (from highest to lowest): `!`, `&&`, `||`.
- For more details check out the Operator Precedence section on the [official golang documentation][operators] and the [truth table][truth table].
[logical operators]: https://golang.org/ref/spec#Logical_operators
[operators]: https://golang.org/ref/spec#Operators
[truth table]: https://www.digitalocean.com/community/tutorials/understanding-boolean-logic-in-go

View File

@ -0,0 +1,96 @@
# Annalyn's Infiltration
Welcome to Annalyn's Infiltration on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
Booleans in Go are represented by the predeclared boolean type `bool`, which values can be either `true` or `false`.
It's a defined type.
```go
var closed bool // boolean variable 'closed' implicitly initialized with 'false'
speeding := true // boolean variable 'speeding' initialized with 'true'
hasError := false // boolean variable 'hasError' initialized with 'false'
```
Go supports three logical operators that can evaluate expressions down to Boolean values, returning either `true` or `false`.
| Operator | What it means |
| ----------- | --------------------------------------------- |
| `&&` (and) | It is true if both statements are true. |
| `\|\|` (or) | It is true if at least one statement is true. |
| `!` (not) | It is true only if the statement is false. |
## Instructions
In this exercise, you'll be implementing the quest logic for a new RPG game a friend is developing. The game's main character is Annalyn, a brave girl with a fierce and loyal pet dog. Unfortunately, disaster strikes, as her best friend was kidnapped while searching for berries in the forest. Annalyn will try to find and free her best friend, optionally taking her dog with her on this quest.
After some time spent following her best friend's trail, she finds the camp in which her best friend is imprisoned. It turns out there are two kidnappers: a mighty knight and a cunning archer.
Having found the kidnappers, Annalyn considers which of the following actions she can engage in:
- _Fast attack_: a fast attack can be made if the knight is sleeping, as it takes time for him to get his armor on, so he will be vulnerable.
- _Spy_: the group can be spied upon if at least one of them is awake. Otherwise, spying is a waste of time.
- _Signal prisoner_: the prisoner can be signaled using bird sounds if the prisoner is awake and the archer is sleeping, as archers are trained in bird signaling so they could intercept the message.
- _Free prisoner_: Annalyn can try sneaking into the camp to free the prisoner.
This is a risky thing to do and can only succeed in one of two ways:
- If Annalyn has her pet dog with her she can rescue the prisoner if the archer is asleep.
The knight is scared of the dog and the archer will not have time to get ready before Annalyn and the prisoner can escape.
- If Annalyn does not have her dog then she and the prisoner must be very sneaky!
Annalyn can free the prisoner if the prisoner is awake and the knight and archer are both sleeping, but if the prisoner is sleeping they can't be rescued: the prisoner would be startled by Annalyn's sudden appearance and wake up the knight and archer.
You have four tasks: to implement the logic for determining if the above actions are available based on the state of the three characters found in the forest and whether Annalyn's pet dog is present or not.
## 1. Check if a fast attack can be made
Define the `CanFastAttack()` function that takes a boolean value that indicates if the knight is awake. This function returns `true` if a fast attack can be made based on the state of the knight. Otherwise, returns `false`:
```go
var knightIsAwake = true
fmt.Println(CanFastAttack(knightIsAwake))
// Output: false
```
## 2. Check if the group can be spied upon
Define the `CanSpy()` function that takes three boolean values, indicating if the knight, archer and the prisoner, respectively, are awake. The function returns `true` if the group can be spied upon, based on the state of the three characters. Otherwise, returns `false`:
```go
var knightIsAwake = false
var archerIsAwake = true
var prisonerIsAwake = false
fmt.Println(CanSpy(knightIsAwake, archerIsAwake, prisonerIsAwake))
// Output: true
```
## 3. Check if the prisoner can be signaled
Define the `CanSignalPrisoner()` function that takes two boolean values, indicating if the archer and the prisoner, respectively, are awake. The function returns `true` if the prisoner can be signaled, based on the state of the two characters. Otherwise, returns `false`:
```go
var archerIsAwake = false
var prisonerIsAwake = true
fmt.Println(CanSignalPrisoner(archerIsAwake, prisonerIsAwake))
// Output: true
```
## 4. Check if the prisoner can be freed
Define the `CanFreePrisoner()` function that takes four boolean values. The first three parameters indicate if the knight, archer and the prisoner, respectively, are awake. The last parameter indicates if Annalyn's pet dog is present. The function returns `true` if the prisoner can be freed based on the state of the three characters and Annalyn's pet dog presence. Otherwise, it returns `false`:
```go
var knightIsAwake = false
var archerIsAwake = true
var prisonerIsAwake = false
var petDogIsPresent = false
fmt.Println(CanFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent))
// Output: false
```
## Source
### Created by
- @oanaOM

View File

@ -0,0 +1,22 @@
package annalyn
// CanFastAttack can be executed only when the knight is sleeping.
func CanFastAttack(knightIsAwake bool) bool {
return !knightIsAwake
}
// CanSpy can be executed if at least one of the characters is awake.
func CanSpy(knightIsAwake, archerIsAwake, prisonerIsAwake bool) bool {
return knightIsAwake || archerIsAwake || prisonerIsAwake
}
// CanSignalPrisoner can be executed if the prisoner is awake and the archer is sleeping.
func CanSignalPrisoner(archerIsAwake, prisonerIsAwake bool) bool {
return !archerIsAwake && prisonerIsAwake
}
// CanFreePrisoner can be executed if the prisoner is awake and the other 2 characters are asleep
// or if Annalyn's pet dog is with her and the archer is sleeping.
func CanFreePrisoner(knightIsAwake, archerIsAwake, prisonerIsAwake, petDogIsPresent bool) bool {
return petDogIsPresent && !archerIsAwake || !petDogIsPresent && prisonerIsAwake && !knightIsAwake && !archerIsAwake
}

View File

@ -0,0 +1,294 @@
package annalyn
import "testing"
type charactersState struct {
desc string
knightIsAwake bool
archerIsAwake bool
prisonerIsAwake bool
dogIsPresent bool
expected bool
}
func TestCanFastAttack(t *testing.T) {
tests := []charactersState{
{
desc: "Knight is awake",
knightIsAwake: true,
expected: false,
},
{
desc: "Knight is sleeping",
knightIsAwake: false,
expected: true,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
if got := CanFastAttack(tt.knightIsAwake); got != tt.expected {
t.Errorf("CanFastAttack(%v) = %v; want %v", tt.knightIsAwake, tt.knightIsAwake, tt.expected)
}
})
}
}
func TestCanSpy(t *testing.T) {
tests := []charactersState{
{
desc: "All characters are sleeping",
knightIsAwake: false,
archerIsAwake: false,
prisonerIsAwake: false,
expected: false,
},
{
desc: "Knight is awake, archer and prisoner are sleeping",
knightIsAwake: true,
archerIsAwake: false,
prisonerIsAwake: false,
expected: true,
},
{
desc: "Knight and archer are awake, prisoner is sleeping",
knightIsAwake: true,
archerIsAwake: true,
prisonerIsAwake: false,
expected: true,
},
{
desc: "Knight and prisoner are awake, archer is sleeping",
knightIsAwake: true,
archerIsAwake: false,
prisonerIsAwake: true,
expected: true,
},
{
desc: "Archer is awake, knight and prisoner are sleeping",
knightIsAwake: false,
archerIsAwake: true,
prisonerIsAwake: false,
expected: true,
},
{
desc: "Archer and prisoner are awake, knight is sleeping",
knightIsAwake: false,
archerIsAwake: true,
prisonerIsAwake: true,
expected: true,
},
{
desc: "Prisoner is awake, knight and archer are sleeping",
knightIsAwake: false,
archerIsAwake: false,
prisonerIsAwake: true,
expected: true,
},
{
desc: "All characters are awake",
knightIsAwake: true,
archerIsAwake: true,
prisonerIsAwake: true,
expected: true,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
if got := CanSpy(tt.knightIsAwake, tt.archerIsAwake, tt.prisonerIsAwake); got != tt.expected {
t.Errorf("CanSpy(%v, %v, %v) = %v; want %v", tt.knightIsAwake, tt.archerIsAwake, tt.prisonerIsAwake, got, tt.expected)
}
})
}
}
func TestCanSignalPrisoner(t *testing.T) {
tests := []charactersState{
{
desc: "All characters are sleeping",
archerIsAwake: false,
prisonerIsAwake: false,
expected: false,
},
{
desc: "Archer is sleeping, prisoner is awake",
archerIsAwake: false,
prisonerIsAwake: true,
expected: true,
},
{
desc: "Archer is awake, prisoner is sleeping",
archerIsAwake: true,
prisonerIsAwake: false,
expected: false,
},
{
desc: "All characters are awake",
archerIsAwake: true,
prisonerIsAwake: true,
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
if got := CanSignalPrisoner(tt.archerIsAwake, tt.prisonerIsAwake); got != tt.expected {
t.Errorf("CanSignalPrisoner(%v, %v) = %v; want %v", tt.archerIsAwake, tt.prisonerIsAwake, got, tt.expected)
}
})
}
}
func TestCanFreePrisoner(t *testing.T) {
tests := []charactersState{
{
desc: "All characters are sleeping. Dog is not present.",
knightIsAwake: false,
archerIsAwake: false,
prisonerIsAwake: false,
dogIsPresent: false,
expected: false,
},
{
desc: "All characters are sleeping. Dog is present.",
knightIsAwake: false,
archerIsAwake: false,
prisonerIsAwake: false,
dogIsPresent: true,
expected: true,
},
{
desc: "Knight and archer are sleeping. Prisoner is awake. Dog is not present.",
knightIsAwake: false,
archerIsAwake: false,
prisonerIsAwake: true,
dogIsPresent: false,
expected: true,
},
{
desc: "Knight and archer are sleeping. Prisoner is awake. Dog is present.",
knightIsAwake: false,
archerIsAwake: false,
prisonerIsAwake: true,
dogIsPresent: true,
expected: true,
},
{
desc: "Knight is sleeping. Archer is awake. Prisoner is sleeping. Dog is not present.",
knightIsAwake: false,
archerIsAwake: true,
prisonerIsAwake: false,
dogIsPresent: false,
expected: false,
},
{
desc: "Knight is sleeping. Archer is awake. Prisoner is sleeping. Dog is present.",
knightIsAwake: false,
archerIsAwake: true,
prisonerIsAwake: false,
dogIsPresent: true,
expected: false,
},
{
desc: "Knight is sleeping. Archer is awake. Prisoner is awake. Dog is not present.",
knightIsAwake: false,
archerIsAwake: true,
prisonerIsAwake: true,
dogIsPresent: false,
expected: false,
},
{
desc: "Knight is sleeping. Archer is awake. Prisoner is awake. Dog is present.",
knightIsAwake: false,
archerIsAwake: true,
prisonerIsAwake: true,
dogIsPresent: true,
expected: false,
},
{
desc: "Knight is awake. Archer is sleeping. Prisoner is sleeping. Dog is not present.",
knightIsAwake: true,
archerIsAwake: false,
prisonerIsAwake: false,
dogIsPresent: false,
expected: false,
},
{
desc: "Knight is awake. Archer is sleeping. Prisoner is sleeping. Dog is present.",
knightIsAwake: true,
archerIsAwake: false,
prisonerIsAwake: false,
dogIsPresent: true,
expected: true,
},
{
desc: "Knight is awake. Archer is sleeping. Prisoner is awake. Dog is not present",
knightIsAwake: true,
archerIsAwake: false,
prisonerIsAwake: true,
dogIsPresent: false,
expected: false,
},
{
desc: "Knight is awake. Archer is sleeping. Prisoner is awake. Dog is present",
knightIsAwake: true,
archerIsAwake: false,
prisonerIsAwake: true,
dogIsPresent: true,
expected: true,
},
{
desc: "Knight and archer are awake. Prisoner is sleeping. Dog is not present",
knightIsAwake: true,
archerIsAwake: true,
prisonerIsAwake: false,
dogIsPresent: false,
expected: false,
},
{
desc: "Knight and archer are awake. Prisoner is sleeping. Dog is present",
knightIsAwake: true,
archerIsAwake: true,
prisonerIsAwake: false,
dogIsPresent: true,
expected: false,
},
{
desc: "Knight and archer are awake. Prisoner is awake. Dog is not present",
knightIsAwake: true,
archerIsAwake: true,
prisonerIsAwake: true,
dogIsPresent: false,
expected: false,
},
{
desc: "Knight and archer are awake. Prisoner is awake. Dog is present",
knightIsAwake: true,
archerIsAwake: true,
prisonerIsAwake: true,
dogIsPresent: true,
expected: false,
},
{
desc: "Knight and archer are awake. Prisoner is sleeping. Dog is not present",
knightIsAwake: true,
archerIsAwake: true,
prisonerIsAwake: false,
dogIsPresent: false,
expected: false,
},
{
desc: "Everyone is sleeping. Dog is not present",
knightIsAwake: false,
archerIsAwake: false,
prisonerIsAwake: false,
dogIsPresent: false,
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.desc, func(t *testing.T) {
if got := CanFreePrisoner(tt.knightIsAwake, tt.archerIsAwake, tt.prisonerIsAwake, tt.dogIsPresent); got != tt.expected {
t.Errorf("CanFreePrisoner(%v,%v,%v,%v) = %v; want %v", tt.knightIsAwake, tt.archerIsAwake, tt.prisonerIsAwake, tt.dogIsPresent, got, tt.expected)
}
})
}
}

View File

@ -0,0 +1,3 @@
module annalyn
go 1.18

View File

@ -0,0 +1,28 @@
{
"authors": [
"andres-zartab"
],
"contributors": [
"tehsphinx",
"andrerfcsantos",
"norbs57"
],
"files": {
"solution": [
"blackjack.go"
],
"test": [
"blackjack_test.go"
],
"exemplar": [
".meta/exemplar.go"
],
"invalidator": [
"go.mod"
]
},
"blurb": "Learn about conditionals by playing Blackjack.",
"custom": {
"taskIdsEnabled": true
}
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"blackjack","id":"ad71b94c95a244f9897e237fb3578ef8","url":"https://exercism.org/tracks/go/exercises/blackjack","handle":"vtrgnc","is_requester":true,"auto_approve":false}

41
go/blackjack/HELP.md Normal file
View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit blackjack.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

23
go/blackjack/HINTS.md Normal file
View File

@ -0,0 +1,23 @@
# Hints
## 1. Calculate the value of any given card.
- The `ParseCard` function should take the `card` string (e.g. `ace`) and return its value (e.g. 11).
- Use a big [`switch` statement][switch_statement] on the `card` variable.
- King, Queen, Jack and 10 can be handled with a single case.
- The switch can have a `default` case. In any case the function should return `0` for unknown cards.
## 2. Implement the decision logic for the first turn.
- Use function `ParseCard` to determined the value for each card.
- Compute the player score by adding up the values of the two player cards
- You can either use a big [`switch` statement][switch_statement] on the player
score (maybe with nested `if`-statements on the dealer-score in some cases),
- or you could distinguish separate player score categories (say "small hands"
with a score less than 12, "medium hands" with a score in the range 12..20 and
"large hands" with a score greater than 20) and write separate functions for
all (or some) of these categories.
[logical_operators]: https://golang.org/ref/spec#Logical_operators
[if_statement]: https://golang.org/ref/spec#If_statements
[switch_statement]: https://golang.org/ref/spec#Switch_statements

110
go/blackjack/README.md Normal file
View File

@ -0,0 +1,110 @@
# Blackjack
Welcome to Blackjack on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
Like other languages, Go also provides a `switch` statement. Switch statements are a shorter way to write long `if ... else if` statements. To make a switch, we start by using the keyword `switch` followed by a value or expression. We then declare each one of the conditions with the `case` keyword. We can also declare a `default` case, that will run when none of the previous `case` conditions matched:
```go
operatingSystem := "windows"
switch operatingSystem {
case "windows":
// do something if the operating system is windows
case "linux":
// do something if the operating system is linux
case "macos":
// do something if the operating system is macos
default:
// do something if the operating system is none of the above
}
```
One interesting thing about switch statements, is that the value after the `switch` keyword can be omitted, and we can have boolean conditions for each `case`:
```go
age := 21
switch {
case age > 20 && age < 30:
// do something if age is between 20 and 30
case age == 10:
// do something if age is equal to 10
default:
// do something else for every other case
}
```
## Instructions
In this exercise we will simulate the first turn of a [Blackjack](https://en.wikipedia.org/wiki/Blackjack) game.
You will receive two cards and will be able to see the face up card of the dealer. All cards are represented using a string such as "ace", "king", "three", "two", etc. The values of each card are:
| card | value | card | value |
| :---: | :---: | :-----: | :---: |
| ace | 11 | eight | 8 |
| two | 2 | nine | 9 |
| three | 3 | ten | 10 |
| four | 4 | jack | 10 |
| five | 5 | queen | 10 |
| six | 6 | king | 10 |
| seven | 7 | *other* | 0 |
**Note**: Commonly, aces can take the value of 1 or 11 but for simplicity we will assume that they can only take the value of 11.
Depending on your two cards and the card of the dealer, there is a strategy for the first turn of the game, in which you have the following options:
- Stand (S)
- Hit (H)
- Split (P)
- Automatically win (W)
Although not optimal yet, you will follow the strategy your friend Alex has been developing, which is as follows:
- If you have a pair of aces you must always split them.
- If you have a Blackjack (two cards that sum up to a value of 21), and the dealer does not have an ace, a figure or a ten then you automatically win. If the dealer does have any of those cards then you'll have to stand and wait for the reveal of the other card.
- If your cards sum up to a value within the range [17, 20] you should always stand.
- If your cards sum up to a value within the range [12, 16] you should always stand unless the dealer has a 7 or higher, in which case you should always hit.
- If your cards sum up to 11 or lower you should always hit.
## 1. Calculate the value of any given card.
Implement a function to calculate the numerical value of a card:
```go
value := ParseCard("ace")
fmt.Println(value)
// Output: 11
```
## 2. Implement the decision logic for the first turn.
Write a function that implements the decision logic as described above:
```go
func FirstTurn(card1, card2, dealerCard string) string
```
Here are some examples for the expected outcomes:
```go
FirstTurn("ace", "ace", "jack") == "P"
FirstTurn("ace", "king", "ace") == "S"
FirstTurn("five", "queen", "ace") == "H"
```
## Source
### Created by
- @andres-zartab
### Contributed to by
- @tehsphinx
- @andrerfcsantos
- @norbs57

68
go/blackjack/blackjack.go Normal file
View File

@ -0,0 +1,68 @@
package blackjack
// ParseCard returns the integer value of a card following blackjack ruleset.
func ParseCard(card string) int {
switch {
case card == "ace":
return 11
case card == "two":
return 2
case card == "three":
return 3
case card == "four":
return 4
case card == "five":
return 5
case card == "six":
return 6
case card == "seven":
return 7
case card == "eight":
return 8
case card == "nine":
return 9
case card == "ten":
return 10
case card == "jack":
return 10
case card == "queen":
return 10
case card == "king":
return 10
default:
return 0
}
}
// FirstTurn returns the decision for the first turn, given two cards of the
// player and one card of the dealer.
func FirstTurn(card1, card2, dealerCard string) string {
var card1val int = ParseCard(card1)
var card2val int = ParseCard(card2)
var dealcardval int = ParseCard(dealerCard)
switch {
case card1 == "ace" && card2 == "ace":
return "P"
case card1val + card2val == 21:
if (dealcardval == 10 || dealcardval == 11) {
return "S"
} else {
return "W"
}
case card1val + card2val >= 17 && card1val + card2val <= 20:
return "S"
case card1val + card2val >= 12 && card1val + card2val <= 16 :
if (dealcardval >= 7) {
return "H"
} else {
return "S"
}
case card1val + card2val <= 11:
return "H"
default:
return "oonga boonga"
}
}

View File

@ -0,0 +1,301 @@
package blackjack
import "testing"
func TestParseCard(t *testing.T) {
tests := []struct {
name string
card string
want int
}{
{
name: "parse ace",
card: "ace",
want: 11,
},
{
name: "parse two",
card: "two",
want: 2,
},
{
name: "parse three",
card: "three",
want: 3,
},
{
name: "parse four",
card: "four",
want: 4,
},
{
name: "parse five",
card: "five",
want: 5,
},
{
name: "parse six",
card: "six",
want: 6,
},
{
name: "parse seven",
card: "seven",
want: 7,
},
{
name: "parse eight",
card: "eight",
want: 8,
},
{
name: "parse nine",
card: "nine",
want: 9,
},
{
name: "parse ten",
card: "ten",
want: 10,
},
{
name: "parse jack",
card: "jack",
want: 10,
},
{
name: "parse queen",
card: "queen",
want: 10,
},
{
name: "parse king",
card: "king",
want: 10,
},
{
name: "parse other",
card: "joker",
want: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ParseCard(tt.card); got != tt.want {
t.Errorf("ParseCard(%s) = %d, want %d", tt.card, got, tt.want)
}
})
}
}
func TestFirstTurn(t *testing.T) {
type hand struct {
card1, card2 string
}
tests := []struct {
name string
hand hand
dealer string
want string
}{
{
name: "pair of aces",
hand: hand{card1: "ace", card2: "ace"},
dealer: "ace",
want: "P",
},
{
name: "pair of jacks",
hand: hand{card1: "jack", card2: "jack"},
dealer: "ace",
want: "S",
},
{
name: "pair of kings",
hand: hand{card1: "king", card2: "king"},
dealer: "ace",
want: "S",
},
{
name: "pair of twos",
hand: hand{card1: "two", card2: "two"},
dealer: "ace",
want: "H",
},
{
name: "pair of fives",
hand: hand{card1: "five", card2: "five"},
dealer: "ace",
want: "H",
},
{
name: "blackjack with ace for dealer",
hand: hand{card1: "ace", card2: "jack"},
dealer: "ace",
want: "S",
},
{
name: "blackjack with queen for dealer",
hand: hand{card1: "king", card2: "ace"},
dealer: "queen",
want: "S",
},
{
name: "blackjack with five for dealer",
hand: hand{card1: "ace", card2: "ten"},
dealer: "five",
want: "W",
},
{
name: "blackjack with nine for dealer",
hand: hand{card1: "ace", card2: "king"},
dealer: "nine",
want: "W",
},
{
name: "score of 20",
hand: hand{card1: "ten", card2: "king"},
dealer: "ace",
want: "S",
},
{
name: "score of 19",
hand: hand{card1: "ten", card2: "nine"},
dealer: "ace",
want: "S",
},
{
name: "score of 18",
hand: hand{card1: "ten", card2: "eight"},
dealer: "ace",
want: "S",
},
{
name: "score of 17",
hand: hand{card1: "seven", card2: "king"},
dealer: "ace",
want: "S",
},
{
name: "score of 16 with six for dealer",
hand: hand{card1: "ten", card2: "six"},
dealer: "six",
want: "S",
},
{
name: "score of 16 with seven for dealer",
hand: hand{card1: "ten", card2: "six"},
dealer: "seven",
want: "H",
},
{
name: "score of 16 with ace for dealer",
hand: hand{card1: "ten", card2: "six"},
dealer: "ace",
want: "H",
},
{
name: "score of 15 with six for dealer",
hand: hand{card1: "ten", card2: "five"},
dealer: "six",
want: "S",
},
{
name: "score of 15 with seven for dealer",
hand: hand{card1: "ten", card2: "five"},
dealer: "seven",
want: "H",
},
{
name: "score of 15 with king for dealer",
hand: hand{card1: "ten", card2: "five"},
dealer: "king",
want: "H",
},
{
name: "score of 14 with six for dealer",
hand: hand{card1: "ten", card2: "four"},
dealer: "six",
want: "S",
},
{
name: "score of 14 with seven for dealer",
hand: hand{card1: "ten", card2: "four"},
dealer: "seven",
want: "H",
},
{
name: "score of 14 with queen for dealer",
hand: hand{card1: "ten", card2: "four"},
dealer: "queen",
want: "H",
},
{
name: "score of 13 with six for dealer",
hand: hand{card1: "ten", card2: "three"},
dealer: "six",
want: "S",
},
{
name: "score of 13 with seven for dealer",
hand: hand{card1: "ten", card2: "three"},
dealer: "seven",
want: "H",
},
{
name: "score of 13 with queen for dealer",
hand: hand{card1: "ten", card2: "three"},
dealer: "queen",
want: "H",
},
{
name: "score of 12 with six for dealer",
hand: hand{card1: "ten", card2: "two"},
dealer: "six",
want: "S",
},
{
name: "score of 12 with seven for dealer",
hand: hand{card1: "ten", card2: "two"},
dealer: "seven",
want: "H",
},
{
name: "score of 12 with queen for dealer",
hand: hand{card1: "ten", card2: "two"},
dealer: "queen",
want: "H",
},
{
name: "score of 11 with queen for dealer",
hand: hand{card1: "nine", card2: "two"},
dealer: "queen",
want: "H",
},
{
name: "score of 10 with two for dealer",
hand: hand{card1: "eight", card2: "two"},
dealer: "two",
want: "H",
},
{
name: "score of 5 with queen for dealer",
hand: hand{card1: "three", card2: "two"},
dealer: "queen",
want: "H",
},
{
name: "score of 4 with five for dealer",
hand: hand{card1: "two", card2: "two"},
dealer: "five",
want: "H",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := FirstTurn(tt.hand.card1, tt.hand.card2, tt.dealer); got != tt.want {
t.Errorf("FirstTurn(%s, %s, %s) = %s, want %s", tt.hand.card1, tt.hand.card2, tt.dealer, got, tt.want)
}
})
}
}

3
go/blackjack/go.mod Normal file
View File

@ -0,0 +1,3 @@
module blackjack
go 1.18

View File

@ -0,0 +1,26 @@
{
"authors": [
"tehsphinx"
],
"contributors": [
"norbs57"
],
"files": {
"solution": [
"card_tricks.go"
],
"test": [
"card_tricks_test.go"
],
"exemplar": [
".meta/exemplar.go"
],
"invalidator": [
"go.mod"
]
},
"blurb": "Learn about slices by doing card tricks.",
"custom": {
"taskIdsEnabled": true
}
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"card-tricks","id":"e7d8c479a7bd4a4e909a6703219033ed","url":"https://exercism.org/tracks/go/exercises/card-tricks","handle":"vtrgnc","is_requester":true,"auto_approve":false}

41
go/card-tricks/HELP.md Normal file
View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit card_tricks.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

44
go/card-tricks/HINTS.md Normal file
View File

@ -0,0 +1,44 @@
# Hints
## General
- Slices in Go are zero-based. The first index in a slice is `0`.
- The builtin [`append`][append-builtin] function is [`variadic`][variadic-gobyexample]
- You can append the elements of one slice to another slice by using the three dots notation:
```go
a := []int{1, 3}
b := []int{4, 2, 6}
c := append(a, b...)
fmt.Println(c)
// Output: [1 3 4 2 6]
```
## 1. Create a slice with certain cards
- To create a slice pre-filled with some data, use the slice literal notation:
`s := []T{x1, x2, ..., xn}`
## 2. Retrieve a card from a stack
- To get the `n`th item of a slice [use an index][go-slices].
- To check if an item exists in a slice use a conditional and compare the index with the [length of the slice][len-builtin].
## 3. Exchange a card in the stack
- To set the `n`th item in a slice [use an index][go-slices] and assign a new value to it.
- To add a new item to then end of a slice use the `append` function.
## 4. Add cards to the top of the stack
- Adding items to the front of a slice can be done by appending the elements of the original slice to the `value` argument slice.
## 5. Remove a card from the stack
- Removing an item from a slice can be done by appending the part after `index` to the part before index.
[go-slices]: https://blog.golang.org/go-slices-usage-and-internals
[make-builtin]: https://golang.org/pkg/builtin/#make
[len-builtin]: https://golang.org/pkg/builtin/#len
[append-builtin]: https://golang.org/pkg/builtin/#append
[variadic-gobyexample]: https://gobyexample.com/variadic-functions

253
go/card-tricks/README.md Normal file
View File

@ -0,0 +1,253 @@
# Card Tricks
Welcome to Card Tricks on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
## Slices
Slices in Go are similar to lists or arrays in other languages.
They hold several elements of a specific type (or interface).
Slices in Go are based on arrays.
Arrays have a fixed size.
A slice, on the other hand, is a dynamically-sized, flexible view of the elements of an array.
A slice is written like `[]T` with `T` being the type of the elements in the slice:
```go
var empty []int // an empty slice
withData := []int{0,1,2,3,4,5} // a slice pre-filled with some data
```
You can get or set an element at a given zero-based index using the square-bracket notation:
```go
withData[1] = 5
x := withData[1] // x is now 5
```
You can create a new slice from an existing slice by getting a range of elements.
Once again using square-bracket notation, but specifying both a starting (inclusive) and ending (exclusive) index.
If you don't specify a starting index, it defaults to 0.
If you don't specify an ending index, it defaults to the length of the slice.
```go
newSlice := withData[2:4]
// => []int{2,3}
newSlice := withData[:2]
// => []int{0,1}
newSlice := withData[2:]
// => []int{2,3,4,5}
newSlice := withData[:]
// => []int{0,1,2,3,4,5}
```
You can add elements to a slice using the `append` function.
Below we append `4` and `2` to the `a` slice.
```go
a := []int{1, 3}
a = append(a, 4, 2)
// => []int{1,3,4,2}
```
`append` always returns a new slice, and when we just want to append elements to an existing slice, it's common to reassign it back to the slice variable we pass as the first argument as we did above.
`append` can also be used to merge two slices:
```go
nextSlice := []int{100,101,102}
newSlice := append(withData, nextSlice...)
// => []int{0,1,2,3,4,5,100,101,102}
```
## Variadic Functions
Usually, functions in Go accept only a fixed number of arguments.
However, it is also possible to write variadic functions in Go.
A variadic function is a function that accepts a variable number of arguments.
If the type of the last parameter in a function definition is prefixed by ellipsis `...`, then the function can accept any number of arguments for that parameter.
```go
func find(a int, b ...int) {
// ...
}
```
In the above function, parameter `b` is variadic and we can pass 0 or more arguments to `b`.
```go
find(5, 6)
find(5, 6, 7)
find(5)
```
~~~~exercism/caution
The variadic parameter must be the last parameter of the function.
~~~~
The way variadic functions work is by converting the variable number of arguments to a slice of the type of the variadic parameter.
Here is an example of an implementation of a variadic function.
```go
func find(num int, nums ...int) {
fmt.Printf("type of nums is %T\n", nums)
for i, v := range nums {
if v == num {
fmt.Println(num, "found at index", i, "in", nums)
return
}
}
fmt.Println(num, "not found in ", nums)
}
func main() {
find(89, 90, 91, 95)
// =>
// type of nums is []int
// 89 not found in [90 91 95]
find(45, 56, 67, 45, 90, 109)
// =>
// type of nums is []int
// 45 found at index 2 in [56 67 45 90 109]
find(87)
// =>
// type of nums is []int
// 87 not found in []
}
```
In line `find(89, 90, 91, 95)` of the program above, the variable number of arguments to the find function are `90`, `91` and `95`.
The `find` function expects a variadic int parameter after `num`.
Hence these three arguments will be converted by the compiler to a slice of type `int` `[]int{90, 91, 95}` and then it will be passed to the find function as `nums`.
Sometimes you already have a slice and want to pass that to a variadic function.
This can be achieved by passing the slice followed by `...`.
That will tell the compiler to use the slice as is inside the variadic function.
The step described above where a slice is created will simply be omitted in this case.
```go
list := []int{1, 2, 3}
find(1, list...) // "find" defined as shown above
```
[append-yourbasic]: https://yourbasic.org/golang/append-explained/
## Instructions
As a magician-to-be, Elyse needs to practice some basics. She has a stack of cards that she wants to manipulate.
To make things a bit easier she only uses the cards 1 to 10.
## 1. Create a slice with certain cards
When practicing with her cards, Elyse likes to start with her favorite three cards of the deck: 2, 6 and 9.
Write a function `FavoriteCards` that returns a slice with those cards in that order.
```go
cards := FavoriteCards()
fmt.Println(cards)
// Output: [2 6 9]
```
## 2. Retrieve a card from a stack
Return the card at position `index` from the given stack.
```go
card := GetItem([]int{1, 2, 4, 1}, 2) // card == 4
```
If the index is out of bounds (ie. if it is negative or after the end of the stack), we want to return `-1`:
```go
card := GetItem([]int{1, 2, 4, 1}, 10) // card == -1
```
~~~~exercism/note
By convention in Go, an error is returned instead of returning an "out-of-band" value.
Here the "out-of-band" value is `-1` when a positive integer is expected.
When returning an error, it's considered idiomatic to return the [`zero value`](https://www.geeksforgeeks.org/zero-value-in-golang/) with the error.
Returning an error with the proper return value will be covered in a future exercise.
~~~~
## 3. Exchange a card in the stack
Exchange the card at position `index` with the new card provided and return the adjusted stack.
Note that this will modify the input slice which is the expected behavior.
```go
index := 2
newCard := 6
cards := SetItem([]int{1, 2, 4, 1}, index, newCard)
fmt.Println(cards)
// Output: [1 2 6 1]
```
If the index is out of bounds (ie. if it is negative or after the end of the stack), we want to append the new card to the end of the stack:
```go
index := -1
newCard := 6
cards := SetItem([]int{1, 2, 4, 1}, index, newCard)
fmt.Println(cards)
// Output: [1 2 4 1 6]
```
## 4. Add cards to the top of the stack
Add the card(s) specified in the `value` parameter at the top of the stack.
```go
slice := []int{3, 2, 6, 4, 8}
cards := PrependItems(slice, 5, 1)
fmt.Println(cards)
// Output: [5 1 3 2 6 4 8]
```
If no argument is given for the `value` parameter, then the result equals the original slice.
```go
slice := []int{3, 2, 6, 4, 8}
cards := PrependItems(slice)
fmt.Println(cards)
// Output: [3 2 6 4 8]
```
## 5. Remove a card from the stack
Remove the card at position `index` from the stack and return the stack.
Note that this may modify the input slice which is ok.
```go
cards := RemoveItem([]int{3, 2, 6, 4, 8}, 2)
fmt.Println(cards)
// Output: [3 2 4 8]
```
If the index is out of bounds (ie. if it is negative or after the end of the stack), we want to leave the stack unchanged:
```go
cards := RemoveItem([]int{3, 2, 6, 4, 8}, 11)
fmt.Println(cards)
// Output: [3 2 6 4 8]
```
## Source
### Created by
- @tehsphinx
### Contributed to by
- @norbs57

View File

@ -0,0 +1,57 @@
package cards
// FavoriteCards returns a slice with the cards 2, 6 and 9 in that order.
func FavoriteCards() []int {
return []int{2, 6, 9}
}
// GetItem retrieves an item from a slice at given position.
// If the index is out of range, we want it to return -1.
func GetItem(slice []int, index int) int {
if (index >= 0 && index < len(slice)) {
return slice[index]
} else {
return -1
}
}
// SetItem writes an item to a slice at given position overwriting an existing value.
// If the index is out of range the value needs to be appended.
func SetItem(slice []int, index, value int) []int {
if (index > len(slice) - 1 || index < 0) {
slice = append(slice, value)
return slice
}
slice[index] = value
return slice
}
// PrependItems adds an arbitrary number of values at the front of a slice.
func PrependItems(slice []int, values ...int) []int {
tempslice := []int{}
for i := 0; i < len(values); i++ {
tempslice = append(tempslice, values[i])
}
for i := 0; i < len(slice); i++ {
tempslice = append(tempslice, slice[i])
}
return tempslice
}
// RemoveItem removes an item from a slice by modifying the existing slice.
func RemoveItem(slice []int, index int) []int {
if (index > 0 && index < len(slice)) {
l := len(slice)
t1 := slice[0:index]
t2 := slice[index+1:l]
for i := 0; i < len(t2); i++ {
t1 = append(t1, t2[i])
}
return t1
} else if (index == 0 && index < len(slice)) {
return slice[index+1:]
} else {
return slice
}
}

View File

@ -0,0 +1,299 @@
package cards
import (
"reflect"
"testing"
)
func TestFavoriteCards(t *testing.T) {
got := FavoriteCards()
want := []int{2, 6, 9}
if !slicesEqual(got, want) {
t.Errorf("NewCards() got = %v, want %v", got, want)
}
}
func TestGetItem(t *testing.T) {
type args struct {
slice []int
index int
}
tests := []struct {
name string
args args
want int
}{
{
name: "Retrieve item from slice by index",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
index: 4,
},
want: 8,
},
{
name: "Get first item from slice",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
index: 0,
},
want: 5,
},
{
name: "Get last item from slice",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
index: 7,
},
want: 9,
},
{
name: "Index out of bounds",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
index: 8,
},
want: -1,
},
{
name: "Negative index",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
index: -1,
},
want: -1,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := GetItem(tt.args.slice, tt.args.index)
if got != tt.want {
t.Errorf("GetItem(slice:%v, index:%v) got = %v, want %v", tt.args.slice, tt.args.index, got, tt.want)
}
})
}
}
func TestSetItem(t *testing.T) {
type args struct {
slice []int
index int
value int
}
tests := []struct {
name string
args args
want []int
}{
{
name: "Overwrite an existing item",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
index: 4,
value: 1,
},
want: []int{5, 2, 10, 6, 1, 7, 0, 9},
},
{
name: "Overwrite first item",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
index: 0,
value: 8,
},
want: []int{8, 2, 10, 6, 8, 7, 0, 9},
},
{
name: "Overwrite last item",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
index: 7,
value: 8,
},
want: []int{5, 2, 10, 6, 8, 7, 0, 8},
},
{
name: "Index out of bounds",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
index: 8,
value: 8,
},
want: []int{5, 2, 10, 6, 8, 7, 0, 9, 8},
},
{
name: "Negative index",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
index: -1,
value: 8,
},
want: []int{5, 2, 10, 6, 8, 7, 0, 9, 8},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := SetItem(tt.args.slice, tt.args.index, tt.args.value)
if !slicesEqual(got, tt.want) {
t.Errorf("SetItem(slice:%v, index:%v, value:%v) = %v, want %v",
tt.args.slice, tt.args.index, tt.args.value, got, tt.want)
}
if len(tt.args.slice) == len(got) {
for i := range got {
got[i] = -1
}
if reflect.ValueOf(got).Pointer() != reflect.ValueOf(tt.args.slice).Pointer() {
t.Errorf("SetItem(slice:%v, index:%v) does not return the modified input slice)", tt.args.slice,
tt.args.value)
}
}
})
}
}
func TestPrependItems(t *testing.T) {
type args struct {
slice []int
value []int
}
tests := []struct {
name string
args args
want []int
}{
{
name: "Prepend one item",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
value: []int{1},
},
want: []int{1, 5, 2, 10, 6, 8, 7, 0, 9},
},
{
name: "Prepend two items",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
value: []int{0, 6},
},
want: []int{0, 6, 5, 2, 10, 6, 8, 7, 0, 9},
},
{
name: "prepend nil",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
value: nil,
},
want: []int{5, 2, 10, 6, 8, 7, 0, 9},
},
{
name: "prepend zero items",
args: args{
slice: []int{5, 2, 10, 6, 8, 7, 0, 9},
value: []int{},
},
want: []int{5, 2, 10, 6, 8, 7, 0, 9},
},
{
name: "Prepend slice to itself",
args: args{
slice: []int{5, 2, 10, 6},
value: []int{5, 2, 10, 6},
},
want: []int{5, 2, 10, 6, 5, 2, 10, 6},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := PrependItems(tt.args.slice, tt.args.value...)
if !slicesEqual(got, tt.want) {
t.Errorf("PrependItems(slice:%v, value:%v) = %v, want %v",
tt.args.slice, tt.args.value, got, tt.want)
}
})
}
}
func TestRemoveItem(t *testing.T) {
type args struct {
slice []int
index int
}
tests := []struct {
name string
args args
want []int
}{
{
name: "Remove an item",
args: args{
slice: []int{3, 4, 5, 6},
index: 1,
},
want: []int{3, 5, 6},
},
{
name: "Remove the first item",
args: args{
slice: []int{3, 4, 5, 6},
index: 0,
},
want: []int{4, 5, 6},
},
{
name: "Remove the last item",
args: args{
slice: []int{3, 4, 5, 6},
index: 3,
},
want: []int{3, 4, 5},
},
{
name: "Remove out of bounds index",
args: args{
slice: []int{3, 4, 5, 6},
index: 7,
},
want: []int{3, 4, 5, 6},
},
{
name: "Remove negative index",
args: args{
slice: []int{3, 4, 5, 6},
index: -7,
},
want: []int{3, 4, 5, 6},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := RemoveItem(copySlice(tt.args.slice), tt.args.index); !slicesEqual(got, tt.want) {
t.Errorf("RemoveItem(slice:%v, index:%v) = %v, want %v", tt.args.slice, tt.args.index, got, tt.want)
}
})
}
}
func slicesEqual(a, b []int) bool {
if len(a) != len(b) {
return false
}
if len(a) == 0 {
return true
}
size := len(a)
for i := 0; i < size; i++ {
if a[i] != b[i] {
return false
}
}
return true
}
func copySlice(s []int) []int {
var slice = make([]int, len(s))
copy(slice, s)
return slice
}

3
go/card-tricks/go.mod Normal file
View File

@ -0,0 +1,3 @@
module cards
go 1.18

View File

@ -0,0 +1,28 @@
{
"authors": [
"DavyJ0nes",
"kahgoh"
],
"contributors": [
"tehsphinx",
"andrerfcsantos"
],
"files": {
"solution": [
"cars_assemble.go"
],
"test": [
"cars_assemble_test.go"
],
"exemplar": [
".meta/exemplar.go"
],
"invalidator": [
"go.mod"
]
},
"blurb": "Learn about numbers and type conversion by analyzing an assembly line in a car factory.",
"custom": {
"taskIdsEnabled": true
}
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"cars-assemble","id":"525fe641878c4d7bb902166a1c92dff6","url":"https://exercism.org/tracks/go/exercises/cars-assemble","handle":"vtrgnc","is_requester":true,"auto_approve":false}

41
go/cars-assemble/HELP.md Normal file
View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit cars_assemble.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

28
go/cars-assemble/HINTS.md Normal file
View File

@ -0,0 +1,28 @@
# Hints
## General
- To learn more about types in Go, check [Tour of Go: Basic Types][basic types].
- To learn more about type conversions in Go, check [Tour of Go: Type Conversions][type conversions].
## 1. Calculate the number of working cars produced per hour
- The percentage (passed as an argument) is a number between 0-100. To make this percentage a bit easier to work with, start by dividing it by 100.
- To compute the number of cars produced successfully, multiply the percentage (divided by 100) by the number of cars produced.
- When multiplying two numbers together, they both need to be of the same type. Use [type conversions][type conversions] if needed.
## 2. Calculate the number of working cars produced per minute
- Start by calculating the production of successful cars per hour. For this, you can use the `CalculateProductionRatePerHour` function you made from the previous step.
- Knowing the production per hour of cars, you can get the production per minute by dividing the production per hour by 60 (the number of minutes in an hour).
- Remember to cast the result to an `int`.
## 3. Calculate the cost of production
- Start by working out how many groups of 10 cars there are. You can do this by dividing the number of cars by 10.
- Then work out how many cars are remaining (the [modulo operator][modulo operator] is useful for this).
- To arrive at the cost, multiply the number of groups by the cost to produce 10 cars and then multiply the number of cars remaining by the cost to produce each individual car. Then sum the results of the multiplication together.
[basic types]: https://tour.golang.org/basics/11
[type conversions]: https://tour.golang.org/basics/13
[modulo operator]: https://golangbyexample.com/remainder-modulus-go-golang/

133
go/cars-assemble/README.md Normal file
View File

@ -0,0 +1,133 @@
# Cars Assemble
Welcome to Cars Assemble on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
## Numbers
Go contains basic numeric types that can represent sets of either integer or floating-point values.
There are different types depending on the size of value you require and the architecture of the computer where the application is running (e.g. 32-bit and 64-bit).
For the sake of this exercise you will only be dealing with:
- `int`: e.g. `0`, `255`, `2147483647`. A signed integer that is at least 32 bits in size (value range of: -2147483648 through 2147483647).
But this will depend on the systems architecture.
Most modern computers are 64 bit, therefore `int` will be 64 bits in size (value rate of: -9223372036854775808 through 9223372036854775807).
- `float64`: e.g. `0.0`, `3.14`. Contains the set of all 64-bit floating-point numbers.
- `uint`: e.g. `0`, `255`. An unsigned integer that is the same size as `int` (value range of: 0 through 4294967295 for 32 bits and 0 through 18446744073709551615 for 64 bits)
Numbers can be converted to other numeric types through Type Conversion.
## Arithmetic Operators
Go supports many standard arithmetic operators:
| Operator | Example |
| -------- | -------------- |
| `+` | `4 + 6 == 10` |
| `-` | `15 - 10 == 5` |
| `*` | `2 * 3 == 6` |
| `/` | `13 / 3 == 4` |
| `%` | `13 % 3 == 1` |
For integer division, the remainder is dropped (e.g. `5 / 2 == 2`).
Go has shorthand assignment for the operators above (e.g. `a += 5` is short for `a = a + 5`).
Go also supports the increment and decrement statements `++` and `--` (e.g. `a++`).
## Converting between types
Converting between types is done via a function with the name of the type to convert to.
For example:
```go
var x int = 42 // x has type int
f := float64(x) // f has type float64 (ie. 42.0)
var y float64 = 11.9 // y has type float64
i := int(y) // i has type int (ie. 11)
```
## Arithmetic operations on different types
In many languages you can perform arithmetic operations on different types of variables, but in Go this gives an error.
For example:
```go
var x int = 42
// this line produces an error
value := float32(2.0) * x // invalid operation: mismatched types float32 and int
// you must convert int type to float32 before performing arithmetic operation
value := float32(2.0) * float32(x)
```
## Instructions
In this exercise you'll be writing code to analyze the production in a car factory.
## 1. Calculate the number of working cars produced per hour
The cars are produced on an assembly line.
The assembly line has a certain speed, that can be changed.
The faster the assembly line speed is, the more cars are produced.
However, changing the speed of the assembly line also changes the number of cars that are produced successfully, that is cars without any errors in their production.
Implement a function that takes in the number of cars produced per hour and the success rate and calculates the number of successful cars made per hour. The success rate is given as a percentage, from `0` to `100`:
```go
CalculateWorkingCarsPerHour(1547, 90)
// => 1392.3
```
**Note:** the return value should be a `float64`.
## 2. Calculate the number of working cars produced per minute
Implement a function that takes in the number of cars produced per hour and the success rate and calculates how many cars are successfully produced each minute:
```go
CalculateWorkingCarsPerMinute(1105, 90)
// => 16
```
**Note:** the return value should be an `int`.
## 3. Calculate the cost of production
Each car normally costs $10,000 to produce individually, regardless of whether it is successful or not.
But with a bit of planning, 10 cars can be produced together for $95,000.
For example, 37 cars can be produced in the following way:
37 = 3 x groups of ten + 7 individual cars
So the cost for 37 cars is:
3\*95,000+7\*10,000=355,000
Implement the function `CalculateCost` that calculates the cost of producing a number of cars, regardless of whether they are successful:
```go
CalculateCost(37)
// => 355000
CalculateCost(21)
// => 200000
```
**Note:** the return value should be an `uint`.
## Source
### Created by
- @DavyJ0nes
- @kahgoh
### Contributed to by
- @tehsphinx
- @andrerfcsantos

View File

@ -0,0 +1,20 @@
package cars
// CalculateWorkingCarsPerHour calculates how many working cars are
// produced by the assembly line every hour.
func CalculateWorkingCarsPerHour(productionRate int, successRate float64) float64 {
return float64(productionRate) / float64(100) * successRate
}
// CalculateWorkingCarsPerMinute calculates how many working cars are
// produced by the assembly line every minute.
func CalculateWorkingCarsPerMinute(productionRate int, successRate float64) int {
return productionRate / 100 * int(successRate) / 59
}
// CalculateCost works out the cost of producing the given number of cars.
func CalculateCost(carsCount int) uint {
var tenCars = carsCount / 10
var remainingCars = carsCount % 10
return uint(tenCars * 95000 + remainingCars * 10000)
}

View File

@ -0,0 +1,197 @@
package cars
import (
"math"
"testing"
)
const floatEqualityThreshold = 1e-9
func floatingPointEquals(got, want float64) bool {
absoluteDifferenceBelowThreshold := math.Abs(got-want) <= floatEqualityThreshold
relativeDifferenceBelowThreshold := math.Abs(got-want)/(math.Abs(got)+math.Abs(want)) <= floatEqualityThreshold
return absoluteDifferenceBelowThreshold || relativeDifferenceBelowThreshold
}
func TestCalculateWorkingCarsPerHour(t *testing.T) {
tests := []struct {
name string
productionRate int
successRate float64
want float64
}{
{
name: "calculate working cars per hour for production rate 0",
productionRate: 0,
successRate: 100,
want: 0.0,
},
{
name: "calculate working cars per hour for 100% success rate",
productionRate: 221,
successRate: 100,
want: 221.0,
},
{
name: "calculate working cars per hour for 80% success rate",
productionRate: 426,
successRate: 80,
want: 340.8,
},
{
name: "calculate working cars per hour for 20.5% success rate",
productionRate: 6824,
successRate: 20.5,
want: 1398.92,
},
{
name: "calculate working cars per hour for 0% success rate",
productionRate: 8000,
successRate: 0,
want: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := CalculateWorkingCarsPerHour(tt.productionRate, tt.successRate)
if !floatingPointEquals(got, tt.want) {
t.Errorf(
"CalculateWorkingCarsPerHour(%d, %f) = %f, want %f",
tt.productionRate,
tt.successRate,
got,
tt.want,
)
}
})
}
}
func TestCalculateWorkingCarsPerMinute(t *testing.T) {
tests := []struct {
name string
productionRate int
successRate float64
want int
}{
{
name: "calculate working cars per minute for production rate 0",
productionRate: 0,
successRate: 100,
want: 0,
},
{
name: "calculate working cars per minute for 100% success rate",
productionRate: 221,
successRate: 100,
want: 3,
},
{
name: "calculate working cars per minute for 80% success rate",
productionRate: 426,
successRate: 80,
want: 5,
},
{
name: "calculate working cars per minute for 20.5% success rate",
productionRate: 6824,
successRate: 20.5,
want: 23,
},
{
name: "calculate working cars per minute for 0% success rate",
productionRate: 8000,
successRate: 0,
want: 0,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := CalculateWorkingCarsPerMinute(tt.productionRate, tt.successRate)
if got != tt.want {
t.Errorf(
"CalculateWorkingCarsPerMinute(%d, %f) = %d, want %d",
tt.productionRate,
tt.successRate,
got,
tt.want,
)
}
})
}
}
func TestCalculateCost(t *testing.T) {
tests := []struct {
name string
carsCount int
want uint
}{
{
name: "calculate cost to produce 0 cars",
carsCount: 0,
want: 0,
},
{
name: "calculate the cost of materials to produce 1 car",
carsCount: 1,
want: 10000,
},
{
name: "calculate cost to produce 2 cars",
carsCount: 2,
want: 20000,
},
{
name: "calculate cost to produce 9 cars",
carsCount: 9,
want: 90000,
},
{
name: "calculate cost to produce 10 cars",
carsCount: 10,
want: 95000,
},
{
name: "calculate cost to produce 100 cars",
carsCount: 100,
want: 950000,
},
{
name: "calculate cost to produce 21 cars",
carsCount: 21,
want: 200000,
},
{
name: "calculate cost to produce 37 cars",
carsCount: 37,
want: 355000,
},
{
name: "calculate cost to produce 56 cars",
carsCount: 56,
want: 535000,
},
{
name: "calculate cost to produce 148 cars",
carsCount: 148,
want: 1410000,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := CalculateCost(tt.carsCount)
if got != tt.want {
t.Errorf(
"CalculateCost(%d) = %d, want %d",
tt.carsCount,
got,
tt.want,
)
}
})
}
}

3
go/cars-assemble/go.mod Normal file
View File

@ -0,0 +1,3 @@
module cars
go 1.18

View File

@ -0,0 +1,35 @@
{
"authors": [
"k4rtik"
],
"contributors": [
"bitfield",
"ekingery",
"ferhatelmas",
"hilary",
"kytrinyx",
"leenipper",
"petertseng",
"robphoenix",
"SebastianKristof",
"sebito91",
"tleen"
],
"files": {
"solution": [
"hello_world.go"
],
"test": [
"hello_world_test.go"
],
"example": [
".meta/example.go"
],
"invalidator": [
"go.mod"
]
},
"blurb": "The classical introductory exercise. Just say \"Hello, World!\".",
"source": "This is an exercise to introduce users to using Exercism",
"source_url": "https://en.wikipedia.org/wiki/%22Hello,_world!%22_program"
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"hello-world","id":"57bc47269b674404a7c0a8ff24a955d6","url":"https://exercism.org/tracks/go/exercises/hello-world","handle":"vtrgnc","is_requester":true,"auto_approve":false}

41
go/hello-world/HELP.md Normal file
View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit hello_world.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

45
go/hello-world/README.md Normal file
View File

@ -0,0 +1,45 @@
# Hello World
Welcome to Hello World on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Instructions
The classical introductory exercise.
Just say "Hello, World!".
["Hello, World!"][hello-world] is the traditional first program for beginning programming in a new language or environment.
The objectives are simple:
- Modify the provided code so that it produces the string "Hello, World!".
- Run the test suite and make sure that it succeeds.
- Submit your solution and check it at the website.
If everything goes well, you will be ready to fetch your first real exercise.
[hello-world]: https://en.wikipedia.org/wiki/%22Hello,_world!%22_program
## Source
### Created by
- @k4rtik
### Contributed to by
- @bitfield
- @ekingery
- @ferhatelmas
- @hilary
- @kytrinyx
- @leenipper
- @petertseng
- @robphoenix
- @SebastianKristof
- @sebito91
- @tleen
### Based on
This is an exercise to introduce users to using Exercism - https://en.wikipedia.org/wiki/%22Hello,_world!%22_program

3
go/hello-world/go.mod Normal file
View File

@ -0,0 +1,3 @@
module greeting
go 1.18

View File

@ -0,0 +1,6 @@
package greeting
// HelloWorld greets the world.
func HelloWorld() string {
return "Hello, World!"
}

View File

@ -0,0 +1,40 @@
package greeting
import "testing"
// Define a function named HelloWorld that takes no arguments,
// and returns a string.
// In other words, define a function with the following signature:
// HelloWorld() string
func TestHelloWorld(t *testing.T) {
expected := "Hello, World!"
if observed := HelloWorld(); observed != expected {
t.Fatalf("HelloWorld() = %v, want %v", observed, expected)
}
}
// BenchmarkHelloWorld() is a benchmarking function. These functions follow the
// form `func BenchmarkXxx(*testing.B)` and can be used to test the performance
// of your implementation. They may not be present in every exercise, but when
// they are you can run them by including the `-bench` flag with the `go test`
// command, like so: `go test -v --bench . --benchmem`
//
// You will see output similar to the following:
//
// BenchmarkHelloWorld 2000000000 0.46 ns/op
//
// This means that the loop ran 2000000000 times at a speed of 0.46 ns per loop.
//
// While benchmarking can be useful to compare different iterations of the same
// exercise, keep in mind that others will run the same benchmarks on different
// machines, with different specs, so the results from these benchmark tests may
// vary.
func BenchmarkHelloWorld(b *testing.B) {
if testing.Short() {
b.Skip("skipping benchmark in short mode.")
}
for i := 0; i < b.N; i++ {
HelloWorld()
}
}

View File

@ -0,0 +1,31 @@
{
"authors": [
"tehsphinx"
],
"contributors": [
"ekingery",
"andrerfcsantos",
"bobtfish"
],
"files": {
"solution": [
"lasagna.go"
],
"test": [
"lasagna_test.go"
],
"exemplar": [
".meta/exemplar.go"
],
"invalidator": [
"go.mod"
]
},
"forked_from": [
"csharp/lucians-luscious-lasagna"
],
"blurb": "Learn about packages, functions, and variables by helping Gopher cook lasagna.",
"custom": {
"taskIdsEnabled": true
}
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"lasagna","id":"e8f35515622948358562577ae1669324","url":"https://exercism.org/tracks/go/exercises/lasagna","handle":"vtrgnc","is_requester":true,"auto_approve":false}

41
go/lasagna/HELP.md Normal file
View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit lasagna.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

44
go/lasagna/HINTS.md Normal file
View File

@ -0,0 +1,44 @@
# Hints
## General
- An [integer value][integers] can be defined as one or more consecutive digits.
- If you see a `panic:` error when running the tests, this is because you have not implemented one of the functions (it should say which one) or you have left the boilerplate in place. You need to remove the `panic(...)` line from the supplied code and replace it with a real implementation.
## 1. Define the expected oven time in minutes
- You need to define a [constant][constants] and assign it the expected oven time in minutes.
- If you see an `undefined: OvenTime` error then double check that you have the constant defined.
- If you see an `invalid operation: got != tt.expected (mismatched types float64 and int)` error then you have likely put a decimal point into the `OvenTime` causing Go to infer the type as a floating point number. Remove the decimal and the type will be inferred as an `int`.
- If you see a `syntax error: non-declaration statement outside function body` error then it is likely that you forgot the `const` keyword.
- If you see a `syntax error: unexpected :=, expecting =` error then you are likely trying to assign the constant using `:=` like a variable; constants are assigned using `=` not `:=`.
## 2. Calculate the remaining oven time in minutes
- You need to define a [function][functions] with a single parameter.
- You have to [explicitly return an integer][return] from a function.
- The function's parameter is an [integer][integers].
- You can [call][calls] one of the other functions you've defined previously.
- You can use the [mathematical operator for subtraction][operators] to subtract values.
## 3. Calculate the preparation time in minutes
- You need to define a [function][functions] with a single parameter.
- You have to [explicitly return an integer][return] from a function.
- The function's parameter is an [integer][integers].
- You can use the [mathematical operator for multiplication][operators] to multiply values.
## 4. Calculate the elapsed working time in minutes
- You need to define a [function][functions] with two parameters.
- You have to [explicitly return an integer][return] from a function.
- The function's parameter is an [integer][integers].
- You can [call][calls] one of the other functions you've defined previously.
- You can use the [mathematical operator for addition][operators] to add values.
[functions]: https://tour.golang.org/basics/4
[return]: https://golang.org/ref/spec#Return_statements
[operators]: https://golang.org/ref/spec#Operators
[integers]: https://golang.org/ref/spec#Integer_literals
[calls]: https://golang.org/ref/spec#Calls
[constants]: https://tour.golang.org/basics/15

151
go/lasagna/README.md Normal file
View File

@ -0,0 +1,151 @@
# Gopher's Gorgeous Lasagna
Welcome to Gopher's Gorgeous Lasagna on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
[Go](https://golang.org) is a statically typed, compiled programming language.
This exercise introduces three major language features: Packages, Functions, and Variables.
## Packages
Go applications are organized in packages.
A package is a collection of source files located in the same directory.
All source files in a directory must share the same package name.
When a package is imported, only entities (functions, types, variables, constants) whose names start with a capital letter can be used / accessed.
The recommended style of naming in Go is that identifiers will be named using `camelCase`, except for those meant to be accessible across packages which should be `PascalCase`.
```go
package lasagna
```
## Variables
Go is statically-typed, which means all variables [must have a defined type](https://en.wikipedia.org/wiki/Type_system) at compile-time.
Variables can be defined by explicitly specifying a type:
```go
var explicit int // Explicitly typed
```
You can also use an initializer, and the compiler will assign the variable type to match the type of the initializer.
```go
implicit := 10 // Implicitly typed as an int
```
Once declared, variables can be assigned values using the `=` operator.
Once declared, a variable's type can never change.
```go
count := 1 // Assign initial value
count = 2 // Update to new value
count = false // This throws a compiler error due to assigning a non `int` type
```
## Constants
Constants hold a piece of data just like variables, but their value cannot change during the execution of the program.
Constants are defined using the `const` keyword and can be numbers, characters, strings or booleans:
```go
const Age = 21 // Defines a numeric constant 'Age' with the value of 21
```
## Functions
Go functions accept zero or more parameters.
Parameters must be explicitly typed, there is no type inference.
Values are returned from functions using the `return` keyword.
A function is invoked by specifying the function name and passing arguments for each of the function's parameters.
Note that Go supports two types of comments.
Single line comments are preceded by `//` and multiline comments are inserted between `/*` and `*/`.
```go
package greeting
// Hello is a public function.
func Hello (name string) string {
return hi(name)
}
// hi is a private function.
func hi (name string) string {
return "hi " + name
}
```
## Instructions
In this exercise you're going to write some code to help you cook a brilliant lasagna from your favorite cooking book.
You have four tasks, all related to the time spent cooking the lasagna.
## 1. Define the expected oven time in minutes
Define the `OvenTime` constant with how many minutes the lasagna should be in the oven. According to the cooking book, the expected oven time in minutes is 40:
```go
OvenTime
// => 40
```
## 2. Calculate the remaining oven time in minutes
Define the `RemainingOvenTime()` function that takes the actual minutes the lasagna has been in the oven as a parameter and returns how many minutes the lasagna still has to remain in the oven, based on the expected oven time in minutes from the previous task.
```go
func RemainingOvenTime(actual int) int {
// TODO
}
RemainingOvenTime(30)
// => 10
```
## 3. Calculate the preparation time in minutes
Define the `PreparationTime` function that takes the number of layers you added to the lasagna as a parameter and returns how many minutes you spent preparing the lasagna, assuming each layer takes you 2 minutes to prepare.
```go
func PreparationTime(numberOfLayers int) int {
// TODO
}
PreparationTime(2)
// => 4
```
## 4. Calculate the elapsed working time in minutes
Define the `ElapsedTime` function that takes two parameters: the first parameter is the number of layers you added to the lasagna, and the second parameter is the number of minutes the lasagna has been in the oven.
The function should return how many minutes in total you've worked on cooking the lasagna, which is the sum of the preparation time in minutes, and the time in minutes the lasagna has spent in the oven at the moment.
```go
func ElapsedTime(numberOfLayers, actualMinutesInOven int) int {
// TODO
}
ElapsedTime(3, 20)
// => 26
```
## Source
### Created by
- @tehsphinx
### Contributed to by
- @ekingery
- @andrerfcsantos
- @bobtfish

3
go/lasagna/go.mod Normal file
View File

@ -0,0 +1,3 @@
module lasagna
go 1.18

19
go/lasagna/lasagna.go Normal file
View File

@ -0,0 +1,19 @@
package lasagna
// TODO: define the 'OvenTime' constant
const OvenTime = 40
// RemainingOvenTime returns the remaining minutes based on the `actual` minutes already in the oven.
func RemainingOvenTime(actualMinutesInOven int) int {
return OvenTime - actualMinutesInOven
}
// PreparationTime calculates the time needed to prepare the lasagna based on the amount of layers.
func PreparationTime(numberOfLayers int) int {
return numberOfLayers * 2
}
// ElapsedTime calculates the time elapsed cooking the lasagna. This time includes the preparation time and the time the lasagna is baking in the oven.
func ElapsedTime(numberOfLayers, actualMinutesInOven int) int {
return numberOfLayers * 2 + actualMinutesInOven
}

View File

@ -0,0 +1,94 @@
package lasagna
import "testing"
type lasagnaTests struct {
name string
layers, time, expected int
}
func TestOvenTime(t *testing.T) {
tests := []lasagnaTests{
{
name: "Calculates how many minutes the lasagna should be in the oven",
layers: 0,
time: 40,
expected: 40,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := OvenTime; got != tt.expected {
t.Errorf("OvenTime(%d) = %d; want %d", tt.expected, got, tt.expected)
}
})
}
}
func TestRemainingOvenTime(t *testing.T) {
tests := []lasagnaTests{
{
name: "Remaining minutes in oven",
layers: 0,
time: 15,
expected: 25,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := RemainingOvenTime(tt.time); got != tt.expected {
t.Errorf("RemainingOvenTime(%d) = %d; want %d", tt.time, got, tt.expected)
}
})
}
}
func TestPreparationTime(t *testing.T) {
tests := []lasagnaTests{
{
name: "Preparation time in minutes for one layer",
layers: 1,
time: 0,
expected: 2,
},
{
name: "Preparation time in minutes for multiple layers",
layers: 4,
time: 0,
expected: 8,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := PreparationTime(tt.layers); got != tt.expected {
t.Errorf("PreparationTime(%d) = %d; want %d", tt.layers, got, tt.expected)
}
})
}
}
func TestElapsedTime(t *testing.T) {
tests := []lasagnaTests{
{
name: "Total time in minutes for one layer",
layers: 1,
time: 30,
expected: 32,
},
{
name: "Total time in minutes for multiple layers",
layers: 4,
time: 8,
expected: 16,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := ElapsedTime(tt.layers, tt.time); got != tt.expected {
t.Errorf("ElapsedTime(%d, %d) = %d; want %d", tt.layers, tt.time, got, tt.expected)
}
})
}
}

View File

@ -0,0 +1,31 @@
{
"authors": [
"tehsphinx"
],
"contributors": [
"oanaOM",
"eklatzer",
"andrerfcsantos"
],
"files": {
"solution": [
"need_for_speed.go"
],
"test": [
"need_for_speed_test.go"
],
"exemplar": [
".meta/exemplar.go"
],
"invalidator": [
"go.mod"
]
},
"forked_from": [
"csharp/need-for-speed"
],
"blurb": "Learn about structs by racing remote controlled cars.",
"custom": {
"taskIdsEnabled": true
}
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"need-for-speed","id":"d208ab84bd8846078f03ccd0462ed682","url":"https://exercism.org/tracks/go/exercises/need-for-speed","handle":"vtrgnc","is_requester":true,"auto_approve":false}

41
go/need-for-speed/HELP.md Normal file
View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit need_for_speed.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

View File

@ -0,0 +1,30 @@
# Hints
## General
- A `struct` is a sequence of named elements, called fields, each one having a name and a type.
## 1. Create a remote controlled car
- Instantiate a new [struct][struct] and fill the fields except `distance`.
- Create a function that returns the type of the newly created struct and update the fields accordingly
## 2. Create a race track
- Define a new [struct][struct] with 1 field
- Create a function that returns the type of the new created struct and updates the fields accordingly
## 3. Drive the car
- Add a new field to keep track of the distance driven
- You need to check if there is enough battery to drive the car
## 4. Check if a remote controlled car can finish a race
- Assume the car is just starting the race
- You need to calculate the maximum distance a car can drive with the current level of battery
- The number of times a car can be driven can be calculated by `battery / batteryDrain`.
- The maximum distance the car can cover is the product of the car's speed and the number of times it can be driven.
- Knowing the maximum distance the car can drive, compare it with the distance of the race track
[struct]: https://tour.golang.org/moretypes/2

194
go/need-for-speed/README.md Normal file
View File

@ -0,0 +1,194 @@
# Need For Speed
Welcome to Need For Speed on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
In Go, a `struct` is a sequence of named elements called _fields_, each field has a name and type.
The name of a field must be unique within the struct.
Structs can be compared with _classes_ in the Object-Oriented Programming paradigm.
## Defining a struct
You create a new struct by using the `type` and `struct` keywords, and explicitly define the name and type of the fields.
For example, here we define `Shape` struct, that holds the name of a shape and its size:
```go
type Shape struct {
name string
size int
}
```
Field names in structs follow the Go convention - fields whose name starts with a lower case letter are only visible to code in the same package, whereas those whose name starts with an upper case letter are visible in other packages.
## Creating instances of a struct
Once you have defined the `struct`, you need to create a new instance defining the fields using their field name
in any order:
```go
s := Shape {
name: "Square",
size: 25,
}
```
To read or modify instance fields, use the `.` notation:
```go
// Update the name and the size
s.name = "Circle"
s.size = 35
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 35
```
Fields that don't have an initial value assigned, will have their zero value. For example:
```go
s := Shape{name: "Circle"}
fmt.Printf("name: %s size: %d\n", s.name, s.size)
// Output: name: Circle size: 0
```
You can create an instance of a `struct` without using the field names, as long as you define the fields _in order_:
```go
s := Shape {
"Oval",
20,
}
```
However, this syntax is considered _brittle code_ since it can break when a field is added, especially when the new field is of a different type.
In the following example we add an extra field to `Shape`:
```go
type Shape struct {
name string
description string // new field 'description' added
size int
}
s := Shape{
"Circle",
20,
}
// Since the second field of the struct is now a string and not an int,
// the compiler will throw an error when compiling the program:
// Output: cannot use 20 (type untyped int) as type string in field value
// Output: too few values in Shape{...}
```
## "New" functions
Sometimes it can be nice to have functions that help us create struct instances.
By convention, these functions are usually called `New` or have their names starting with `New`, but since they are just regular functions, you can give them any name you want.
They might remind you of constructors in other languages, but in Go they are just regular functions.
In the following example, one of these `New` functions is used to create a new instance of `Shape` and automatically set a default value for the `size` of the shape:
```go
func NewShape(name string) Shape {
return Shape{
name: name,
size: 100, //default-value for size is 100
}
}
NewShape("Triangle")
// => Shape { name: "Triangle", size: 100 }
```
Using `New` functions can have the following advantages:
* validation of the given values
* handling of default-values
* since `New` functions are often declared in the same package of the structs they initialize, they can initialize even private fields of the struct
## Instructions
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.
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.
If a car's battery is below its battery drain percentage, you can't drive the car anymore.
Each race track has its own distance. Cars are tested by checking if they can finish the track without running out of battery.
## 1. Create a remote controlled car
Define a `Car` struct with the following `int` type fields:
- battery
- batteryDrain
- speed
- distance
Allow creating a remote controlled car by defining a function `NewCar` that takes the speed of the car in meters,
and the battery drain percentage as its two parameters (both of type `int`) and returns a `Car` instance:
```go
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
// => Car{speed: 5, batteryDrain: 2, battery:100, distance: 0}
```
## 2. Create a race track
Define another struct type called `Track` with the field `distance` of type integer.
Allow creating a race track by defining a function `NewTrack` that takes the track's distance in meters as its sole parameter (which is of type `int`):
```go
distance := 800
track := NewTrack(distance)
// => Track{distance: 800}
```
## 3. Drive the car
Implement the `Drive` function that updates the number of meters driven based on the car's speed, and reduces the battery according to the battery drainage.
If there is not enough battery to drive one more time the car will not move:
```go
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
car = Drive(car)
// => Car{speed: 5, batteryDrain: 2, battery: 98, distance: 5}
```
## 4. Check if a remote controlled car can finish a race
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` function that takes a `Car` and a `Track` instance as its parameter and returns `true` if the car can finish the race; otherwise, return `false`.
Assume that you are currently at the starting line of the race and start the engine of the car for the race. Take into account that the car's battery might not necessarily be fully charged when starting the race:
```go
speed := 5
batteryDrain := 2
car := NewCar(speed, batteryDrain)
distance := 100
track := NewTrack(distance)
CanFinish(car, track)
// => true
```
## Source
### Created by
- @tehsphinx
### Contributed to by
- @oanaOM
- @eklatzer
- @andrerfcsantos

3
go/need-for-speed/go.mod Normal file
View File

@ -0,0 +1,3 @@
module speed
go 1.18

View File

@ -0,0 +1,56 @@
package speed
// TODO: define the 'Car' type struct
type Car struct {
battery int
batteryDrain int
speed int
distance int
}
// NewCar creates a new remote controlled car with full battery and given specifications.
func NewCar(speed, batteryDrain int) Car {
return Car{
speed: speed,
batteryDrain: batteryDrain,
battery: 100,
distance: 0,
}
}
// TODO: define the 'Track' type struct
type Track struct {
distance int
}
// NewTrack creates a new track
func NewTrack(distance int) Track {
return Track{
distance: distance,
}
}
// Drive drives the car one time. If there is not enough battery to drive one more time,
// the car will not move.
func Drive(car Car) Car {
if (car.battery != 0) {
if (car.battery < car.batteryDrain) { return car }
car.battery = car.battery - car.batteryDrain
car.distance = car.distance + car.speed
return car
} else {
return car
}
}
// CanFinish checks if a car is able to finish a certain track.
func CanFinish(car Car, track Track) bool {
var x int = car.battery / car.batteryDrain
var y int = track.distance / car.speed
if (y <= x) {
return true
} else {
return false
}
}

View File

@ -0,0 +1,267 @@
package speed
import "testing"
func TestNewCar(t *testing.T) {
tests := []struct {
name string
car Car
expected Car
}{
{
name: "Create a new car.",
car: Car{
speed: 5,
batteryDrain: 2,
battery: 100,
},
expected: Car{
speed: 5,
batteryDrain: 2,
battery: 100,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := NewCar(tt.car.speed, tt.car.batteryDrain)
if got != tt.expected {
t.Errorf("NewCar(%+v,%+v) = %+v; expected %+v", tt.car.speed, tt.car.batteryDrain, got, tt.expected)
}
})
}
}
func TestNewTrack(t *testing.T) {
tests := []struct {
name string
track Track
expected Track
}{
{
name: "Create a new track.",
track: Track{
distance: 800,
},
expected: Track{
distance: 800,
},
},
{
name: "Create a new track.",
track: Track{
distance: 360,
},
expected: Track{
distance: 360,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := NewTrack(tt.track.distance)
if got != tt.expected {
t.Errorf("NewTrack(%+v) = %+v; expected %+v", tt.track.distance, tt.track, tt.expected)
}
})
}
}
func TestDrive(t *testing.T) {
tests := []struct {
name string
car Car
expected Car
}{
{
name: "Drive the car with full battery.",
car: Car{
speed: 5,
batteryDrain: 2,
battery: 100,
distance: 0,
},
expected: Car{
speed: 5,
batteryDrain: 2,
battery: 98,
distance: 5,
},
},
{
name: "Drive the car with exactly enough battery.",
car: Car{
speed: 18,
batteryDrain: 10,
battery: 10,
distance: 0,
},
expected: Car{
speed: 18,
batteryDrain: 10,
battery: 0,
distance: 18,
},
},
{
name: "Drive when battery percentage is below battery drain",
car: Car{
speed: 5,
batteryDrain: 7,
battery: 3,
distance: 0,
},
expected: Car{
speed: 5,
batteryDrain: 7,
battery: 3,
distance: 0,
},
},
{
name: "Drive the car with battery drained.",
car: Car{
speed: 5,
batteryDrain: 5,
battery: 4,
distance: 0,
},
expected: Car{
speed: 5,
batteryDrain: 5,
battery: 4,
distance: 0,
},
},
{
name: "Drive the car with positive initial distance and battery drained",
car: Car{
speed: 5,
batteryDrain: 3,
battery: 2,
distance: 1,
},
expected: Car{
speed: 5,
batteryDrain: 3,
battery: 2,
distance: 1,
},
},
{
name: "Drive the car with positive initial distance and full battery",
car: Car{
speed: 5,
batteryDrain: 3,
battery: 100,
distance: 1,
},
expected: Car{
speed: 5,
batteryDrain: 3,
battery: 97,
distance: 6,
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := Drive(tt.car)
if got != tt.expected {
t.Errorf("Drive(%+v) = %+v; expected %+v", tt.car, got, tt.expected)
}
})
}
}
func TestCanFinish(t *testing.T) {
tests := []struct {
name string
car Car
track Track
expected bool
}{
{
name: "Car can easily finish the track distance.",
car: Car{
speed: 5,
batteryDrain: 2,
battery: 100,
distance: 20,
},
track: Track{
distance: 30,
},
expected: true,
},
{
name: "Car can finish the track distance just as the battery is drained.",
car: Car{
speed: 5,
batteryDrain: 5,
battery: 100,
distance: 20,
},
track: Track{
distance: 100,
},
expected: true,
},
{
name: "Car cannot finish the track distance.",
car: Car{
speed: 2,
batteryDrain: 6,
battery: 100,
distance: 5,
},
track: Track{
distance: 80,
},
expected: false,
},
{
name: "Car can finish the track distance with initial battery less than 100%",
car: Car{
speed: 2,
batteryDrain: 3,
battery: 25,
distance: 0,
},
track: Track{
distance: 16,
},
expected: true,
},
{
name: "Car cannot finish the track distance with initial battery less than 100%",
car: Car{
speed: 2,
batteryDrain: 3,
battery: 25,
distance: 0,
},
track: Track{
distance: 24,
},
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := CanFinish(tt.car, tt.track)
if got != tt.expected {
t.Errorf("CanFinish(%#v, %#v) = %+v; expected %+v", tt.car, tt.track, got, tt.expected)
}
})
}
}

View File

@ -0,0 +1,27 @@
{
"authors": [
"tehsphinx"
],
"contributors": [
"oanaOM",
"bobtfish"
],
"files": {
"solution": [
"party_robot.go"
],
"test": [
"party_robot_test.go"
],
"exemplar": [
".meta/exemplar.go"
],
"invalidator": [
"go.mod"
]
},
"blurb": "Learn about strings by programming a party robot.",
"custom": {
"taskIdsEnabled": true
}
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"party-robot","id":"d268915c67c04a149eeba744317e8eb8","url":"https://exercism.org/tracks/go/exercises/party-robot","handle":"vtrgnc","is_requester":true,"auto_approve":false}

41
go/party-robot/HELP.md Normal file
View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit party_robot.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

27
go/party-robot/HINTS.md Normal file
View File

@ -0,0 +1,27 @@
# Hints
## General
- The `fmt` package of the standard library has some [formatting functionality for strings][fmt-package].
- There is a way to [concatenate strings][string-concatenation].
## 1. Welcome a new guest to the party
- `fmt.Sprintf` lets you use a [template to create a string][sprintf].
## 2. Welcome a new guest to the party whose birthday is today
- `fmt.Sprintf` can interpolate [more than one value into your string][sprintf-multiple-values]!
## 3. Give directions
- You can use [newline characters in your string][string-newline].
- Padding with zeroes could be achieved with one of the [formatting verbs][formatting-verbs].
- The shorthand assignment operator `+=` can help you build up your result via string concatenation.
[fmt-package]: https://golang.org/pkg/fmt/
[string-concatenation]: https://golang.org/ref/spec#String_concatenation
[sprintf]: https://pkg.go.dev/fmt#Sprintf
[sprintf-multiple-values]: https://www.geeksforgeeks.org/fmt-sprintf-function-in-golang-with-examples/
[string-newline]: https://yourbasic.org/golang/multiline-string/#interpreted-string-literals
[formatting-verbs]: https://yourbasic.org/golang/fmt-printf-reference-cheat-sheet/#cheat-sheet

145
go/party-robot/README.md Normal file
View File

@ -0,0 +1,145 @@
# Party Robot
Welcome to Party Robot on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
## Packages
In Go an application is organized in packages.
A package is a collection of source files located in the same folder.
All source files in a folder must have the same package name at the top of the file.
By convention packages are named to be the same as the folder they are located in.
```go
package greeting
```
Go provides an extensive standard library of packages which you can use in your program using the `import` keyword.
Standard library packages are imported using their name.
```go
package greeting
import "fmt"
```
An imported package is then addressed with the package name:
```go
world := "World"
fmt.Sprintf("Hello %s", world)
```
Go determines if an item can be called by code in other packages through how it is declared.
To make a function, type, variable, constant or struct field externally visible (known as _exported_) the name must start with a capital letter.
```go
package greeting
// Hello is a public function (callable from other packages).
func Hello(name string) string {
return "Hello " + name
}
// hello is a private function (not callable from other packages).
func hello(name string) string {
return "Hello " + name
}
```
## String Formatting
Go provides an in-built package called `fmt` (format package) which offers a variety of functions to manipulate the format of input and output.
The most commonly used function is `Sprintf`, which uses verbs like `%s` to interpolate values into a string and returns that string.
```go
import "fmt"
food := "taco"
fmt.Sprintf("Bring me a %s", food)
// Returns: Bring me a taco
```
In Go floating point values are conveniently formatted with Sprintf's verbs: `%g` (compact representation), `%e` (exponent) or `%f` (non exponent).
All three verbs allow the field's width and numeric position to be controlled.
```go
import "fmt"
number := 4.3242
fmt.Sprintf("%.2f", number)
// Returns: 4.32
```
You can find a full list of available verbs in the [format package documentation][fmt-docs].
`fmt` contains other functions for working with strings, such as `Println` which simply prints the arguments it receives to the console and `Printf` which formats the input in the same way as `Sprintf` before printing it.
[fmt-docs]: https://pkg.go.dev/fmt
## Instructions
Once there was an eccentric programmer living in a strange house with barred windows.
One day he accepted a job from an online job board to build a party robot. The
robot is supposed to greet people and help them to their seats. The first edition
was very technical and showed the programmer's lack of human interaction. Some of
which also made it into the next edition.
## 1. Welcome a new guest to the party
Implement the `Welcome` function to return a welcome message using the given name:
```go
Welcome("Christiane")
// => Welcome to my party, Christiane!
```
## 2. Welcome a new guest to the party whose birthday is today
Implement the `HappyBirthday` function to return a birthday message using the given name and age of the person.
Unfortunately the programmer is a bit of a show-off, so the robot has to demonstrate its knowledge of every guest's birthday.
```go
HappyBirthday("Frank", 58)
// => Happy birthday Frank! You are now 58 years old!
```
## 3. Give directions
Implement the `AssignTable` function to give directions.
It should accept 5 parameters.
- The name of the new guest to greet (`string`)
- The table number (`int`)
- The name of the seatmate (`string`)
- The direction where to find the table (`string`)
- The distance to the table (`float64`)
The exact result format can be seen in the example below.
The robot provides the table number in a 3 digits format.
If the number is less than 3 digits it gets extra leading zeroes to become 3 digits (e.g. 3 becomes 003).
The robot also mentions the distance of the table.
Fortunately only with a precision that's limited to 1 digit.
```go
AssignTable("Christiane", 27, "Frank", "on the left", 23.7834298)
// =>
// Welcome to my party, Christiane!
// You have been assigned to table 027. Your table is on the left, exactly 23.8 meters from here.
// You will be sitting next to Frank.
```
## Source
### Created by
- @tehsphinx
### Contributed to by
- @oanaOM
- @bobtfish

3
go/party-robot/go.mod Normal file
View File

@ -0,0 +1,3 @@
module partyrobot
go 1.18

View File

@ -0,0 +1,18 @@
package partyrobot
import "fmt"
// Welcome greets a person by name.
func Welcome(name string) string {
return "Welcome to my party, " + name + "!"
}
// HappyBirthday wishes happy birthday to the birthday person and exclaims their age.
func HappyBirthday(name string, age int) string {
return fmt.Sprintf("Happy birthday %s! You are now %d years old!", name, age)
}
// AssignTable assigns a table to each guest.
func AssignTable(name string, table int, neighbor, direction string, distance float64) string {
return fmt.Sprintf("Welcome to my party, %s!\nYou have been assigned to table %03d. Your table is %s, exactly %.1f meters from here.\nYou will be sitting next to %s.", name, table, direction, distance, neighbor)
}

View File

@ -0,0 +1,133 @@
package partyrobot
import (
"strings"
"testing"
)
func TestWelcome(t *testing.T) {
tests := []struct {
description string
name string
want string
}{
{
description: "Greet Chihiro with a welcoming message",
name: "Chihiro",
want: "Welcome to my party, Chihiro!",
},
{
description: "Greet Xuân Jing with a welcoming message",
name: "Xuân Jing",
want: "Welcome to my party, Xuân Jing!",
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
if got := Welcome(tt.name); got != tt.want {
t.Errorf("Welcome(%s) = %s, want %s", tt.name, got, tt.want)
}
})
}
}
func TestHappyBirthday(t *testing.T) {
tests := []struct {
description string
name string
age int
want string
}{
{
description: "Wish Chihiro Happy Birthday with name and age",
name: "Chihiro",
age: 61,
want: "Happy birthday Chihiro! You are now 61 years old!",
},
{
description: "Wish Xuân Jing Happy Birthday with name and age",
name: "Xuân Jing",
age: 17,
want: "Happy birthday Xuân Jing! You are now 17 years old!",
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
if got := HappyBirthday(tt.name, tt.age); got != tt.want {
t.Errorf("HappyBirthday(%s, %d) = %s, want %s", tt.name, tt.age, got, tt.want)
}
})
}
}
func TestAssignTable(t *testing.T) {
tests := []struct {
description string
name string
direction string
tableNumber int
distance float64
seatmate string
want string
}{
{
description: "Greet Chihiro and give them directions to their seat",
name: "Chihiro",
direction: "straight ahead",
tableNumber: 22,
distance: 9.2394381,
seatmate: "Akachi Chikondi",
want: "Welcome to my party, Chihiro!\nYou have been assigned to table 022. Your table is straight ahead, exactly 9.2 meters from here.\nYou will be sitting next to Akachi Chikondi.",
},
{
description: "Greet Xuân Jing and give them directions to their seat",
name: "Xuân Jing",
direction: "by the façade",
tableNumber: 4,
distance: 23.470103,
seatmate: "Renée",
want: "Welcome to my party, Xuân Jing!\nYou have been assigned to table 004. Your table is by the façade, exactly 23.5 meters from here.\nYou will be sitting next to Renée.",
},
{
description: "Greet Paula and give them directions to their seat",
name: "Paula",
direction: "on the right",
tableNumber: 101,
distance: 100.0,
seatmate: "Chioma",
want: "Welcome to my party, Paula!\nYou have been assigned to table 101. Your table is on the right, exactly 100.0 meters from here.\nYou will be sitting next to Chioma.",
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
if got := AssignTable(tt.name, tt.tableNumber, tt.seatmate, tt.direction, tt.distance); got != tt.want {
t.Errorf(`AssignTable(%s,%d,%s,%s,%f)
got:
%q
want:
%q`,
tt.name, tt.tableNumber, tt.seatmate, tt.direction, tt.distance, got, tt.want)
wantLen := len(tt.want)
gotLen := len(got)
wantNewlines := strings.Count(tt.want, "\n")
gotNewlines := strings.Count(got, "\n")
wantSpaces := strings.Count(tt.want, " ")
gotSpaces := strings.Count(got, " ")
if wantLen != gotLen {
t.Errorf("String lengths do not match - got: %d, want: %d", gotLen, wantLen)
}
if wantNewlines != gotNewlines {
t.Errorf("Check your newline characters - got: %d, want: %d", gotNewlines, wantNewlines)
}
if wantSpaces != gotSpaces {
t.Errorf("Check your space characters - got: %d, want: %d", gotSpaces, wantSpaces)
}
}
})
}
}

View File

@ -0,0 +1,26 @@
{
"authors": [
"kahgoh"
],
"files": {
"solution": [
"vehicle_purchase.go"
],
"test": [
"vehicle_purchase_test.go"
],
"exemplar": [
".meta/exemplar.go"
],
"invalidator": [
"go.mod"
]
},
"forked_from": [
"javascript/vehicle-purchase"
],
"blurb": "Learn about comparison and conditional-ifs while preparing for your next vehicle purchase",
"custom": {
"taskIdsEnabled": true
}
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"vehicle-purchase","id":"4e7e97d2bf7049c6952c483c19376110","url":"https://exercism.org/tracks/go/exercises/vehicle-purchase","handle":"vtrgnc","is_requester":true,"auto_approve":false}

View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit vehicle_purchase.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

View File

@ -0,0 +1,23 @@
# Hints
## 1. Determine if you will need a driver's license
- Use the [equals comparison operator][comparison-operators] to check whether your input equals a certain string.
- Use one of the two [logical operators][logical-operators] you learned about in the boolean concept to combine the two requirements.
- You do **not** need an if-statement to solve this task. You can return the boolean expression you build directly.
## 2. Choose between two potential vehicles to buy
- Use a [comparison operator][comparison-operators] to determine which option comes first in lexicographical order.
- Then set the value of a helper variable depending of the outcome of that comparison with the help of an an [if-else statement][if-statement].
- Finally construct the recommendation sentence. For that you can use the `+` operator to concatenate the two strings.
## 3. Calculate an estimation for the price of a used vehicle
- Start with determining the percentage of the original price based on the age of the vehicle. Save it in a helper variable. Use an [if-else if-else statement][if-statement] as mentioned in the instructions.
- In the two if conditions use [comparison operators][comparison-operators] to compare the age of the car to the threshold values.
- To calculate the result, apply the percentage to the original price. For example `30% of x` can be calculated by dividing `30` by `100` and multiplying with `x`.
[comparison-operators]: https://golang.org/ref/spec#Comparison_operators
[logical-operators]: https://golang.org/ref/spec#Logical_operators
[if-statement]: https://golang.org/ref/spec#If_statements

View File

@ -0,0 +1,152 @@
# Vehicle Purchase
Welcome to Vehicle Purchase on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
## Comparison
In Go numbers can be compared using the following relational and equality operators.
| Comparison | Operator |
| ------------------| --------- |
| equal | `==` |
| not equal | `!=` |
| less | `<` |
| less or equal | `<=` |
| greater | `>` |
| greater or equal | `>=` |
The result of the comparison is always a boolean value, so either `true` or `false`.
```go
a := 3
a != 4 // true
a > 5 // false
```
The comparison operators above can also be used to compare strings.
In that case a lexicographical (dictionary) order is applied.
For example:
```Go
"apple" < "banana" // true
"apple" > "banana" // false
```
## If Statements
Conditionals in Go are similar to conditionals in other languages.
The underlying type of any conditional operation is the `bool` type, which can have the value of `true` or `false`.
Conditionals are often used as flow control mechanisms to check for various conditions.
For checking a particular case an `if` statement can be used, which executes its code if the underlying condition is `true` like this:
```go
var value string
if value == "val" {
return "was val"
}
```
In scenarios involving more than one case many `if` statements can be chained together using the `else if` and `else` statements.
```go
var number int
result := "This number is "
if number > 0 {
result += "positive"
} else if number < 0 {
result += "negative"
} else {
result += "zero"
}
```
If statements can also include a short initialization statement that can be used to initialize one or more variables for the if statement.
For example:
```go
num := 7
if v := 2 * num; v > 10 {
fmt.Println(v)
} else {
fmt.Println(num)
}
// Output: 14
```
> Note: any variables created in the initialization statement go out of scope after the end of the if statement.
## Instructions
In this exercise, you are going to write some code to help you prepare to buy a vehicle.
You have three tasks, one to determine if you need a license, one to help you choose between two vehicles and one to estimate the acceptable price for a used vehicle.
## 1. Determine if you will need a driver's license
Some vehicle kinds require a driver's license to operate them.
Assume only the kinds `"car"` and `"truck"` require a license, everything else can be operated without a license.
Implement the `NeedsLicense(kind)` function that takes the kind of vehicle and returns a boolean indicating whether you need a license for that kind of vehicle.
```go
needLicense := NeedsLicense("car")
// => true
needLicense = NeedsLicense("bike")
// => false
needLicense = NeedsLicense("truck")
// => true
```
## 2. Choose between two potential vehicles to buy
You evaluate your options of available vehicles.
You manage to narrow it down to two options but you need help making the final decision.
For that, implement the function `ChooseVehicle(option1, option2)` that takes two vehicles as arguments and returns a decision that includes the option that comes first in lexicographical order.
```go
vehicle := ChooseVehicle("Wuling Hongguang", "Toyota Corolla")
// => "Toyota Corolla is clearly the better choice."
ChooseVehicle("Volkswagen Beetle", "Volkswagen Golf")
// => "Volkswagen Beetle is clearly the better choice."
```
## 3. Calculate an estimation for the price of a used vehicle
Now that you made a decision, you want to make sure you get a fair price at the dealership.
Since you are interested in buying a used vehicle, the price depends on how old the vehicle is.
For a rough estimate, assume if the vehicle is less than 3 years old, it costs 80% of the original price it had when it was brand new.
If it is at least 10 years old, it costs 50%.
If the vehicle is at least 3 years old but less than 10 years, it costs 70% of the original price.
Implement the `CalculateResellPrice(originalPrice, age)` function that applies this logic using `if`, `else if` and `else` (there are other ways if you want to practice).
It takes the original price and the age of the vehicle as arguments and returns the estimated price in the dealership.
```go
CalculateResellPrice(1000, 1)
// => 800
CalculateResellPrice(1000, 5)
// => 700
CalculateResellPrice(1000, 15)
// => 500
```
**Note** the return value is a `float64`.
## Source
### Created by
- @kahgoh

View File

@ -0,0 +1,3 @@
module purchase
go 1.18

View File

@ -0,0 +1,30 @@
package purchase
import "slices"
// NeedsLicense determines whether a license is needed to drive a type of vehicle. Only "car" and "truck" require a license.
func NeedsLicense(kind string) bool {
if kind == "bike" || kind == "e-scooter" || kind == "stroller" {
return false
} else {
return true
}
}
// ChooseVehicle recommends a vehicle for selection. It always recommends the vehicle that comes first in lexicographical order.
func ChooseVehicle(option1, option2 string) string {
strings := []string{option1, option2}
slices.Sort(strings)
return strings[0] + " is clearly the better choice."
}
// CalculateResellPrice calculates how much a vehicle can resell for at a certain age.
func CalculateResellPrice(originalPrice, age float64) float64 {
if age < 3 {
return float64(originalPrice / 100 * 80)
} else if age < 10 {
return float64(originalPrice / 100 * 70)
} else {
return float64(originalPrice / 100 * 50)
}
}

View File

@ -0,0 +1,188 @@
package purchase
import (
"math"
"testing"
)
const floatEqualityThreshold = 1e-5
func TestNeedsLicense(t *testing.T) {
tests := []struct {
name string
kind string
expected bool
}{
{
name: "need a license for a car",
kind: "car",
expected: true,
},
{
name: "need a license for a truck",
kind: "truck",
expected: true,
},
{
name: "does not need a license for a bike",
kind: "bike",
expected: false,
},
{
name: "does not need a license for a stroller",
kind: "stroller",
expected: false,
},
{
name: "does not need a license for a e-scooter",
kind: "e-scooter",
expected: false,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual := NeedsLicense(test.kind)
if actual != test.expected {
t.Errorf(
"NeedsLicense(%q) = %t, want %t",
test.kind,
actual,
test.expected)
}
})
}
}
func TestChooseVehicle(t *testing.T) {
tests := []struct {
name string
choice1 string
choice2 string
expected string
}{
{
name: "chooses Bugatti over Ford",
choice1: "Bugatti Veyron",
choice2: "Ford Pinto",
expected: "Bugatti Veyron is clearly the better choice.",
}, {
name: "chooses Chery over Kia",
choice1: "Chery EQ",
choice2: "Kia Niro Elektro",
expected: "Chery EQ is clearly the better choice.",
}, {
name: "chooses Ford Focus over Ford Pinto",
choice1: "Ford Focus",
choice2: "Ford Pinto",
expected: "Ford Focus is clearly the better choice.",
}, {
name: "chooses 2018 over 2020",
choice1: "2018 Bergamont City",
choice2: "2020 Gazelle Medeo",
expected: "2018 Bergamont City is clearly the better choice.",
}, {
name: "chooses Bugatti over ford",
choice1: "Bugatti Veyron",
choice2: "ford",
expected: "Bugatti Veyron is clearly the better choice.",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual := ChooseVehicle(test.choice1, test.choice2)
if actual != test.expected {
t.Errorf(
"ChooseVehicle(%q, %q) = %q, want %q",
test.choice1,
test.choice2,
actual,
test.expected)
}
// The result should be independent of the order in which the choices are given.
actual = ChooseVehicle(test.choice2, test.choice1)
if actual != test.expected {
t.Errorf(
"ChooseVehicle(%q, %q) = %q, want %q",
test.choice2,
test.choice1,
actual,
test.expected)
}
})
}
}
func TestCalculateResellPrice(t *testing.T) {
tests := []struct {
name string
originalPrice float64
age float64
expected float64
}{
{
name: "price is reduced to 80% for age below 3",
originalPrice: 40000,
age: 2,
expected: 32000,
},
{
name: "price is reduced to 80% for age below 3",
originalPrice: 40000,
age: 2.5,
expected: 32000,
},
{
name: "price is reduced to 70% for age 3",
originalPrice: 40000,
age: 3,
expected: 28000,
},
{
name: "price is reduced to 70% for age 7",
originalPrice: 40000,
age: 7,
expected: 28000,
},
{
name: "price is reduced to 50% for age 10",
originalPrice: 25000,
age: 10,
expected: 12500,
},
{
name: "price is reduced to 50% for age 11",
originalPrice: 50000,
age: 11,
expected: 25000,
},
{
name: "float price is reduced to 70% for age 8,",
originalPrice: 39000.000001,
age: 8,
expected: 27300.0000007,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual := CalculateResellPrice(test.originalPrice, test.age)
if !floatingPointEquals(actual, test.expected) {
t.Errorf(
"CalculateResellPrice(%v, %v) = %v, want %v",
test.originalPrice,
test.age,
actual,
test.expected)
}
})
}
}
func floatingPointEquals(got, want float64) bool {
absoluteDifferenceBelowThreshold := math.Abs(got-want) <= floatEqualityThreshold
relativeDifferenceBelowThreshold := math.Abs(got-want)/(math.Abs(got)+math.Abs(want)) <= floatEqualityThreshold
return absoluteDifferenceBelowThreshold || relativeDifferenceBelowThreshold
}

View File

@ -0,0 +1,24 @@
{
"authors": [
"nikimanoledaki",
"micuffaro"
],
"files": {
"solution": [
"weather_forecast.go"
],
"test": [
"weather_forecast_test.go"
],
"exemplar": [
".meta/exemplar.go"
],
"invalidator": [
"go.mod"
]
},
"blurb": "Learn about comments by helping a weather station manage their weather forecasting program.",
"custom": {
"taskIdsEnabled": false
}
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"weather-forecast","id":"c63b23cf94eb45ceb103ac95e47a984d","url":"https://exercism.org/tracks/go/exercises/weather-forecast","handle":"vtrgnc","is_requester":true,"auto_approve":false}

View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit weather_forecast.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

View File

@ -0,0 +1,20 @@
# Hints
## General
- A [documentation comment][comment] should be written directly before the entity that it is describing, start with the name of what it is describing, take the form of a sentence, and end with a period.
## 1. Document package weather
- The [package comment][comment] should be written directly before the package, start with `Package x`, and end with a period.
## 2. Document the CurrentCondition and CurrentLocation variables
- The [variable comment][variable comment] should be written right before the variable that it is describing, start with its name, and end with a period.
## 3. Document the Forecast() function
- The [function comment][comment] should come directly before the function, start with the name of the function and end with a period.
[comment]: https://golang.org/doc/effective_go.html#commentary
[variable comment]: https://dave.cheney.net/practical-go/presentations/qcon-china.html#_comments

View File

@ -0,0 +1,66 @@
# Weather Forecast
Welcome to Weather Forecast on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
In the previous exercise, we saw that there are two ways to write comments in Go: single-line comments that are preceded by `//`, and multiline comment blocks that are wrapped with `/*` and `*/`.
## Documentation comments
In Go, comments play an important role in documenting code. They are used by the `godoc` command, which extracts these comments to create documentation about Go packages. A documentation comment should be a complete sentence that starts with the name of the thing being described and ends with a period.
Comments should precede packages as well as exported identifiers, for example exported functions, methods, package variables, constants, and structs, which you will learn more about in the next exercises.
A package-level variable can look like this:
```go
// TemperatureCelsius represents a certain temperature in degrees Celsius.
var TemperatureCelsius float64
```
## Package comments
Package comments should be written directly before a package clause (`package x`) and begin with `Package x ...` like this:
```go
// Package kelvin provides tools to convert
// temperatures to and from Kelvin.
package kelvin
```
## Function comments
A function comment should be written directly before the function declaration. It should be a full sentence that starts with the function name. For example, an exported comment for the function `Calculate` should take the form `Calculate ...`. It should also explain what arguments the function takes, what it does with them, and what its return values mean, ending in a period):
```go
// CelsiusFreezingTemp returns an integer value equal to the temperature at which water freezes in degrees Celsius.
func CelsiusFreezingTemp() int {
return 0
}
```
## Instructions
Goblinocus is a country that takes its weather forecast very seriously. Since you are a renowned responsible and proficient developer, they asked you to write a program that can forecast the current weather condition of various cities in Goblinocus. You were busy at the time and asked one of your friends to do the job instead. After a while, the president of Goblinocus contacted you and said they do not understand your friend's code. When you check the code, you discover that your friend did not act as a responsible programmer and there are no comments in the code. You feel obligated to clarify the program so goblins can understand them as well.
## 1. Document package weather
Since goblins are not as smart as you are, they forgot what the package should do for them. Please write a comment for `package weather` that describes its contents. The package comment should introduce the package and provide information relevant to the package as a whole.
## 2. Document the CurrentCondition and CurrentLocation variables
The president of Goblinocus is a bit paranoid and fears uncommented variables are used to destroy their country. Please clarify the usage of the package variables `CurrentCondition` and `CurrentLocation` and put the president's mind at ease. This should tell any user of the package what information the variables store, and what they can do with it.
## 3. Document the Forecast() function
Goblinocus forecast operators want to know what the `Forecast()` function does (but do not tell them how it works, since unfortunately, they will get more confused). Please write a comment for this function that describes what the function does, but not how it does it.
## Source
### Created by
- @nikimanoledaki
- @micuffaro

View File

@ -0,0 +1,3 @@
module weather
go 1.18

View File

@ -0,0 +1,13 @@
// Package weather who cares.
package weather
// CurrentCondition wtf even is this exercise it shouldn't exist.
var CurrentCondition string
// CurrentLocation what a stupid thing ngl.
var CurrentLocation string
// Forecast i hate this exercise.
func Forecast(city, condition string) string {
CurrentLocation, CurrentCondition = city, condition
return CurrentLocation + " - current weather condition: " + CurrentCondition
}

View File

@ -0,0 +1,140 @@
package weather
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"strings"
"testing"
)
func TestComments(t *testing.T) {
filename := "weather_forecast.go"
fs := token.NewFileSet()
f, err := parser.ParseFile(fs, filename, nil, parser.ParseComments)
if err != nil {
t.Fatal(err)
}
wantedComments := 4
got := len(f.Comments)
if got != wantedComments {
t.Errorf("Incorrect number of comments: got %d, want %d", got, wantedComments)
}
testPackageComment(t, f)
ast.Inspect(f, func(node ast.Node) bool {
switch n := node.(type) {
case *ast.GenDecl:
if n.Lparen.IsValid() {
for _, v := range n.Specs {
testBlockIdentifierComment(t, v.(*ast.ValueSpec))
}
} else {
testIdentifierComment(t, n)
}
case *ast.FuncDecl:
testFunctionComment(t, n)
}
return true
})
}
func testPackageComment(t *testing.T, node *ast.File) {
t.Helper()
if node.Doc == nil {
t.Errorf("Package weather should have a comment")
}
packageName := node.Name.Name
want := "Package " + packageName
packageComment := node.Doc.Text()
if ok, errStr := testComment("Package", packageName, packageComment, want); !ok {
t.Error(errStr)
}
}
func testIdentifierComment(t *testing.T, node *ast.GenDecl) {
t.Helper()
identifierName := node.Specs[0].(*ast.ValueSpec).Names[0].Name
if node.Doc == nil {
t.Errorf("Exported identifier %s should have a comment", identifierName)
}
identifierComment := node.Doc.Text()
want := identifierName
if ok, errStr := testComment("Variable", identifierName, identifierComment, want); !ok {
t.Error(errStr)
}
}
func testBlockIdentifierComment(t *testing.T, node *ast.ValueSpec) {
t.Helper()
identifierName := node.Names[0].Name
if node.Doc == nil {
t.Errorf("Exported identifier %s should have a comment", identifierName)
}
identifierComment := node.Doc.Text()
want := identifierName
if ok, errStr := testComment("Variable", identifierName, identifierComment, want); !ok {
t.Error(errStr)
}
}
func testFunctionComment(t *testing.T, node *ast.FuncDecl) {
t.Helper()
funcName := node.Name.Name
if node.Doc == nil {
t.Errorf("Exported function %s() should have a comment", funcName)
}
funcComment := node.Doc.Text()
want := funcName
if ok, errStr := testComment("Function", funcName, funcComment, want); !ok {
t.Error(errStr)
}
}
func testComment(entityKind, entityName, comment, wantedPrefix string) (ok bool, errString string) {
trimmedComment := strings.TrimSpace(comment)
lowerEntity := strings.ToLower(entityKind)
// Check if comment has wanted prefix
if !strings.HasPrefix(trimmedComment, wantedPrefix) {
errorString := fmt.Sprintf("%s comment for %s '%s' should start with '// %s ...': got '// %s'",
entityKind, lowerEntity, entityName, wantedPrefix, trimmedComment)
return false, errorString
}
// Check if comment content is empty
commentContent := strings.TrimPrefix(trimmedComment, wantedPrefix)
commentContent = strings.TrimSpace(commentContent)
commentContent = strings.TrimSuffix(commentContent, ".")
if commentContent == "" {
lowerEntity := strings.ToLower(entityKind)
errorString := fmt.Sprintf("%s comment of '%s' should provide a description of the %s, e.g '// %s <%s_description>'",
entityKind, entityName, lowerEntity, wantedPrefix, lowerEntity)
return false, errorString
}
// Check if comment ends in a period
if !strings.HasSuffix(trimmedComment, ".") {
return false, fmt.Sprintf("%s comment for %s '%s' should end with a period (.)",
entityKind, lowerEntity, entityName)
}
return true, ""
}

View File

@ -0,0 +1,27 @@
{
"authors": [
"erikschierboom",
"junedev"
],
"contributors": [
"kekimaker"
],
"files": {
"solution": [
"welcome_to_tech_palace.go"
],
"test": [
"welcome_to_tech_palace_test.go"
],
"exemplar": [
".meta/exemplar.go"
],
"invalidator": [
"go.mod"
]
},
"blurb": "Learn about strings and the strings package by generating text for a store's new display.",
"custom": {
"taskIdsEnabled": true
}
}

View File

@ -0,0 +1 @@
{"track":"go","exercise":"welcome-to-tech-palace","id":"c93aacc5dc7243cb81b1aabf5b4cd2fa","url":"https://exercism.org/tracks/go/exercises/welcome-to-tech-palace","handle":"vtrgnc","is_requester":true,"auto_approve":false}

View File

@ -0,0 +1,41 @@
# Help
## Running the tests
To run the tests run the command `go test` from within the exercise directory.
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
flags:
go test -v --bench . --benchmem
Keep in mind that each reviewer will run benchmarks on a different machine, with
different specs, so the results from these benchmark tests may vary.
## Submitting your solution
You can submit your solution using the `exercism submit welcome_to_tech_palace.go` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
- The [Go track's programming category on the forum](https://forum.exercism.org/c/programming/go)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
To get help if you're having trouble, you can use one of the following resources:
- [How to Write Go Code](https://golang.org/doc/code.html)
- [Effective Go](https://golang.org/doc/effective_go.html)
- [Go Resources](http://golang.org/help)
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)

View File

@ -0,0 +1,29 @@
# Hints
## General
- The [strings package][strings-package] contains many useful `string` functions.
- The `strings` package needs to be imported before it can be used.
- To call functions within the `strings` package, prefix them with `strings.`.
## 1. Create the welcome message
- Strings can be concatenated using the `+` operator.
- There is a function to [convert a `string` to upper case][to-upper].
## 2. Add a fancy border
- There is a function to [create a `string` with a specific character repeated a number of times][repeat].
- A newline is a special [escape character][escape-characters].
## 3. Clean up old marketing messages
- There is a function to [replace strings within a `string`][replace-all].
- There is a function to [trim leading and trailing spaces from a `string`][trim-space].
[strings-package]: https://pkg.go.dev/strings
[to-upper]: https://pkg.go.dev/strings#ToUpper
[repeat]: https://pkg.go.dev/strings#Repeat
[replace-all]: https://pkg.go.dev/strings#ReplaceAll
[trim-space]: https://pkg.go.dev/strings#TrimSpace
[escape-characters]: https://yourbasic.org/golang/multiline-string/#all-escape-characters

View File

@ -0,0 +1,119 @@
# Welcome To Tech Palace!
Welcome to Welcome To Tech Palace! on Exercism's Go Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
## Introduction
A `string` in Go is an immutable sequence of bytes, which don't necessarily have to represent characters.
A string literal is defined between double quotes:
```go
const name = "Jane"
```
Strings can be concatenated via the `+` operator:
```go
"Jane" + " " + "Austen"
// => "Jane Austen"
```
Some special characters need to be escaped with a leading backslash, such as `\t` for a tab and `\n` for a new line in strings.
```go
"How is the weather today?\nIt's sunny"
// =>
// How is the weather today?
// It's sunny
```
The `strings` package contains many useful functions to work on strings.
For more information about string functions, check out the [strings package documentation](https://pkg.go.dev/strings).
Here are some examples:
```go
import "strings"
// strings.ToLower returns the string given as argument with all its characters lowercased
strings.ToLower("MaKEmeLoweRCase")
// => "makemelowercase"
// strings.Repeat returns a string with a substring given as argument repeated many times
strings.Repeat("Go", 3)
// => "GoGoGo"
```
## Instructions
There is an appliance store called "Tech Palace" nearby.
The owner of the store recently installed a big display to use for marketing messages and to show a special greeting when customers scan their loyalty cards at the entrance.
The display consists of lots of small LED lights and can show multiple lines of text.
The store owner needs your help with the code that is used to generate the text for the new display.
## 1. Create the welcome message
For most customers who scan their loyalty cards, the store owner wants to see `Welcome to the Tech Palace, ` followed by the name of the customer in capital letters on the display.
Implement the function `WelcomeMessage` that accepts the name of the customer as a `string` argument and returns the desired message as a `string`.
```go
WelcomeMessage("Judy")
// => Welcome to the Tech Palace, JUDY
```
## 2. Add a fancy border
For loyal customers that buy a lot at the store, the owner wants the welcome display to be more fancy by adding a line of stars before and after the welcome message.
They are not sure yet how many stars should be in the lines so they want that to be configurable.
Write a function `AddBorder` that accepts a welcome message (a `string`) and the number of stars per line (type `int`) as arguments.
It should return a `string` that consists of 3 lines, a line with the desired number of stars, then the welcome message as it was passed in, then another line of stars.
```go
AddBorder("Welcome!", 10)
```
Should return the following:
```
**********
Welcome!
**********
```
## 3. Clean up old marketing messages
Before installing this new display, the store had a similar display that could only show non-configurable, static lines.
The owner would like to reuse some of the old marketing messages on the new display.
However, the data already includes a star border and some unfortunate whitespaces.
Your task is to clean up the messages so they can be re-used.
Implement a function `CleanUpMessage` that accepts the old marketing message as a string.
The function should first remove all stars from the text and afterwards remove the leading and trailing whitespaces from the remaining text.
The function should then return the cleaned up message.
```go
message := `
**************************
* BUY NOW, SAVE 10% *
**************************
`
CleanUpMessage(message)
// => BUY NOW, SAVE 10%
```
## Source
### Created by
- @erikschierboom
- @junedev
### Contributed to by
- @kekimaker

View File

@ -0,0 +1,3 @@
module techpalace
go 1.18

View File

@ -0,0 +1,19 @@
package techpalace
import "strings"
// WelcomeMessage returns a welcome message for the customer.
func WelcomeMessage(customer string) string {
return "Welcome to the Tech Palace, " + strings.ToUpper(customer)
}
// AddBorder adds a border to a welcome message.
func AddBorder(welcomeMsg string, numStarsPerLine int) string {
return strings.Repeat("*", numStarsPerLine) + "\n" + welcomeMsg + "\n" + strings.Repeat("*", numStarsPerLine)
}
// CleanupMessage cleans up an old marketing message.
func CleanupMessage(oldMsg string) string {
var newMsg = strings.ReplaceAll(oldMsg, "*", "")
return strings.TrimSpace(newMsg)
}

View File

@ -0,0 +1,102 @@
package techpalace
import "testing"
func TestWelcomeMessage(t *testing.T) {
tests := []struct {
name string
customer string
want string
}{
{
name: "Welcome message for customer with first letter capitalized",
customer: "Judy",
want: "Welcome to the Tech Palace, JUDY",
},
{
name: "Welcome message for customer with only lowercase letters",
customer: "lars",
want: "Welcome to the Tech Palace, LARS",
},
{
name: "Welcome message for customer with dash in name",
customer: "Peter-James",
want: "Welcome to the Tech Palace, PETER-JAMES",
},
{
name: "Welcome message for customer with only uppercase letters",
customer: "MJ",
want: "Welcome to the Tech Palace, MJ",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := WelcomeMessage(tt.customer); got != tt.want {
t.Errorf("WelcomeMessage(\"%s\") = \"%s\", want \"%s\"", tt.customer, got, tt.want)
}
})
}
}
func TestAddBorder(t *testing.T) {
tests := []struct {
name string
welcomeMessage string
numStarsPerLine int
want string
}{
{
name: "Add border with 10 stars per line",
welcomeMessage: "Welcome!",
numStarsPerLine: 10,
want: "**********\nWelcome!\n**********",
},
{
name: "Add border with 2 stars per line",
welcomeMessage: "Hi",
numStarsPerLine: 2,
want: "**\nHi\n**",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := AddBorder(tt.welcomeMessage, tt.numStarsPerLine); got != tt.want {
t.Errorf("AddBorder(\"%s\", %d) = \"%s\", want \"%s\"", tt.welcomeMessage, tt.numStarsPerLine, got, tt.want)
}
})
}
}
func TestCleanupMessage(t *testing.T) {
tests := []struct {
name string
oldMessage string
want string
}{
{
name: "Cleanup message with many stars and leading and trailing whitespace",
oldMessage: "**************************\n* BUY NOW, SAVE 10% *\n**************************",
want: "BUY NOW, SAVE 10%",
},
{
name: "Cleanup message without leading or trailing whitespace",
oldMessage: "**********\n*DISCOUNT*\n**********",
want: "DISCOUNT",
},
{
name: "Cleanup message without leading whitespace",
oldMessage: "*****\n SALE\n*****",
want: "SALE",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := CleanupMessage(tt.oldMessage); got != tt.want {
t.Errorf("CleanupMessage(\"%s\") = \"%s\", want \"%s\"", tt.oldMessage, got, tt.want)
}
})
}
}

View File

@ -0,0 +1,32 @@
{
"authors": [
"ErikSchierboom"
],
"contributors": [
"iHiD",
"kytrinyx",
"petertseng",
"ppartarr",
"rbasso",
"sshine",
"tejasbubane"
],
"files": {
"solution": [
"src/HelloWorld.hs",
"package.yaml"
],
"test": [
"test/Tests.hs"
],
"example": [
".meta/examples/success-standard/src/HelloWorld.hs"
],
"invalidator": [
"stack.yaml"
]
},
"blurb": "The classical introductory exercise. Just say \"Hello, World!\".",
"source": "This is an exercise to introduce users to using Exercism",
"source_url": "https://en.wikipedia.org/wiki/%22Hello,_world!%22_program"
}

View File

@ -0,0 +1 @@
{"track":"haskell","exercise":"hello-world","id":"2c2af88c28dd4603b38b4c35e26a3151","url":"https://exercism.org/tracks/haskell/exercises/hello-world","handle":"vtrgnc","is_requester":true,"auto_approve":false}

View File

@ -0,0 +1,87 @@
# Help
## Running the tests
To run the test suite, execute the following command:
```bash
stack test
```
#### If you get an error message like this...
```
No .cabal file found in directory
```
or
```
RedownloadInvalidResponse Request {
...
}
"/home/username/.stack/build-plan/lts-xx.yy.yaml" (Response {responseStatus = Status {statusCode = 404, statusMessage = "Not Found"},
```
You are probably running an old stack version and need
to upgrade it. Try running:
```bash
stack upgrade
```
Or see other options for upgrading at [Stack documentation](https://docs.haskellstack.org/en/stable/install_and_upgrade/#upgrade).
#### Otherwise, if you get an error message like this...
```
No compiler found, expected minor version match with...
Try running "stack setup" to install the correct GHC...
```
Just do as it says and it will download and install
the correct compiler version:
```bash
stack setup
```
If you want to play with your solution in GHCi, just run the command:
```bash
stack ghci
```
## Submitting your solution
You can submit your solution using the `exercism submit src/HelloWorld.hs package.yaml` command.
This command will upload your solution to the Exercism website and print the solution page's URL.
It's possible to submit an incomplete solution which allows you to:
- See how others have completed the exercise
- Request help from a mentor
## Need to get help?
If you'd like help solving the exercise, check the following pages:
- The [Haskell track's documentation](https://exercism.org/docs/tracks/haskell)
- The [Haskell track's programming category on the forum](https://forum.exercism.org/c/programming/haskell)
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
## Getting Started
Please refer to the [installation](https://exercism.io/tracks/haskell/installation)
and [learning](https://exercism.io/tracks/haskell/learning) help pages.
## Feedback, Issues, Pull Requests
The [exercism/haskell](https://github.com/exercism/haskell) repository on
GitHub is the home for all of the Haskell exercises.
If you have feedback about an exercise, or want to help implementing a new
one, head over there and create an issue. We'll do our best to help you!

View File

@ -0,0 +1,46 @@
# Hello World
Welcome to Hello World on Exercism's Haskell Track.
If you need help running the tests or submitting your code, check out `HELP.md`.
## Instructions
The classical introductory exercise.
Just say "Hello, World!".
["Hello, World!"][hello-world] is the traditional first program for beginning programming in a new language or environment.
The objectives are simple:
- Modify the provided code so that it produces the string "Hello, World!".
- Run the test suite and make sure that it succeeds.
- Submit your solution and check it at the website.
If everything goes well, you will be ready to fetch your first real exercise.
[hello-world]: https://en.wikipedia.org/wiki/%22Hello,_world!%22_program
To complete this exercise, you need to define the constant `hello`.
You will find the type signature for `hello` already in place,
but it is up to you to define its value.
## Source
### Created by
- @ErikSchierboom
### Contributed to by
- @iHiD
- @kytrinyx
- @petertseng
- @ppartarr
- @rbasso
- @sshine
- @tejasbubane
### Based on
This is an exercise to introduce users to using Exercism - https://en.wikipedia.org/wiki/%22Hello,_world!%22_program

View File

@ -0,0 +1,21 @@
name: hello-world
version: 1.1.0.5
dependencies:
- base
library:
exposed-modules: HelloWorld
source-dirs: src
ghc-options: -Wall
# dependencies:
# - foo # List here the packages you
# - bar # want to use in your solution.
tests:
test:
main: Tests.hs
source-dirs: test
dependencies:
- hello-world
- hspec

View File

@ -0,0 +1,4 @@
module HelloWorld (hello) where
hello :: String
hello = "Goodbye, Mars!"

View File

@ -0,0 +1 @@
resolver: lts-20.18

View File

@ -0,0 +1,11 @@
import Test.Hspec (Spec, it, shouldBe)
import Test.Hspec.Runner (configFailFast, defaultConfig, hspecWith)
import HelloWorld (hello)
main :: IO ()
main = hspecWith defaultConfig {configFailFast = True} specs
specs :: Spec
specs = it "hello" $
hello `shouldBe` "Hello, World!"