Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions exercises/practice/bob/.approaches/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,24 @@
"introduction": {
"authors": [
"bobahop"
],
"contributors": [
"jagdish-15"
]
},
"approaches": [
{
"uuid": "6ca5c7c0-f8f1-49b2-b137-951fa39f89eb",
"slug": "method-based",
"title": "Method based",
"blurb": "Uses boolean functions to check conditions",
"authors": [
"jagdish-15"
],
"contributors": [
"BenjaminGale"
]
},
{
"uuid": "323eb230-7f27-4301-88ea-19c39d3eb5b6",
"slug": "if-statements",
Expand Down
79 changes: 56 additions & 23 deletions exercises/practice/bob/.approaches/introduction.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,58 @@
# Introduction

There are various idiomatic approaches to solve Bob.
A basic approach can use a series of `if` statements to test the conditions.
An array can contain answers from which the right response is selected by an index calculated from scores given to the conditions.
In this exercise, we’re working on a program to determine Bob’s responses based on the tone and style of given messages. Bob responds differently depending on whether a message is a question, a shout, both, or silence. Various approaches can be used to implement this logic efficiently and cleanly, ensuring the code remains readable and easy to maintain.

## General guidance
## General Guidance

Regardless of the approach used, some things you could look out for include
When implementing your solution, consider the following tips to keep your code optimized and idiomatic:

- If the input is trimmed, [`trim()`][trim] only once.
- **Trim the Input Once**: Use [`trim()`][trim] only once at the start to remove any unnecessary whitespace.
- **Use Built-in Methods**: For checking if a message is a question, prefer [`endsWith("?")`][endswith] instead of manually checking the last character.
- **Single Determinations**: Use variables for `questioning` and `shouting` rather than calling these checks multiple times to improve efficiency.
- **DRY Code**: Avoid duplicating code by combining the logic for determining a shout and a question when handling shouted questions. Following the [DRY][dry] principle helps maintain clear and maintainable code.
- **Return Statements**: An early return in an `if` statement eliminates the need for additional `else` blocks, making the code more readable.
- **Curly Braces**: While optional for single-line statements, some teams may require them for readability and consistency.

- Use the [`endsWith()`][endswith] `String` method instead of checking the last character by index for `?`.
## Approach: Method-Based

- Don't copy/paste the logic for determining a shout and for determining a question into determining a shouted question.
Combine the two determinations instead of copying them.
Not duplicating the code will keep the code [DRY][dry].
```java
class Bob {
String hey(String input) {
var inputTrimmed = input.trim();

if (isSilent(inputTrimmed))
return "Fine. Be that way!";
if (isYelling(inputTrimmed) && isAsking(inputTrimmed))
return "Calm down, I know what I'm doing!";
if (isYelling(inputTrimmed))
return "Whoa, chill out!";
if (isAsking(inputTrimmed))
return "Sure.";

return "Whatever.";
}

private boolean isYelling(String input) {
return input.chars()
.anyMatch(Character::isLetter) &&
input.chars()
.filter(Character::isLetter)
.allMatch(Character::isUpperCase);
}

- Perhaps consider making `questioning` and `shouting` values set once instead of functions that are possibly called twice.
private boolean isAsking(String input) {
return input.endsWith("?");
}

- If an `if` statement can return, then an `else if` or `else` is not needed.
Execution will either return or will continue to the next statement anyway.
private boolean isSilent(String input) {
return input.length() == 0;
}
}
```

- If the body of an `if` statement is only one line, curly braces aren't needed.
Some teams may still require them in their style guidelines, though.
This approach defines helper methods for each type of message—silent, yelling, and asking—to keep each condition clean and easily testable. For more details, refer to the [Method-Based Approach][approach-method-based].

## Approach: `if` statements
## Approach: `if` Statements

```java
import java.util.function.Predicate;
Expand Down Expand Up @@ -56,9 +84,9 @@ class Bob {
}
```

For more information, check the [`if` statements approach][approach-if].
This approach utilizes nested `if` statements and a predicate for determining if a message is a shout. For more details, refer to the [`if` Statements Approach][approach-if].

## Approach: answer array
## Approach: Answer Array

```java
import java.util.function.Predicate;
Expand Down Expand Up @@ -86,16 +114,21 @@ class Bob {
}
```

For more information, check the [Answer array approach][approach-answer-array].
This approach uses an array of answers and calculates the appropriate index based on flags for shouting and questioning. For more details, refer to the [Answer Array Approach][approach-answer-array].

## Which Approach to Use?

Choosing between the method-based approach, `if` statements, and answer array approach can come down to readability and maintainability. Each has its advantages:

## Which approach to use?
- **Method-Based**: Clear and modular, great for readability.
- **`if` Statements**: Compact and straightforward, suited for smaller projects.
- **Answer Array**: Minimizes condition checks by using indices, efficient for a variety of responses.

Since benchmarking with the [Java Microbenchmark Harness][jmh] is currently outside the scope of this document,
the choice between `if` statements and answers array can be made by perceived readability.
Experiment with these approaches to find the balance between readability and performance that best suits your needs.

[trim]: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#trim()
[endswith]: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#endsWith(java.lang.String)
[dry]: https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
[approach-method-based]: https://exercism.org/tracks/java/exercises/bob/approaches/method-based
[approach-if]: https://exercism.org/tracks/java/exercises/bob/approaches/if-statements
[approach-answer-array]: https://exercism.org/tracks/java/exercises/bob/approaches/answer-array
[jmh]: https://github.com/openjdk/jmh
83 changes: 83 additions & 0 deletions exercises/practice/bob/.approaches/method-based/content.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Method-Based Approach

```java
class Bob {
String hey(String input) {
var inputTrimmed = input.trim();

if (isSilent(inputTrimmed))
return "Fine. Be that way!";
if (isYelling(inputTrimmed) && isAsking(inputTrimmed))
return "Calm down, I know what I'm doing!";
if (isYelling(inputTrimmed))
return "Whoa, chill out!";
if (isAsking(inputTrimmed))
return "Sure.";

return "Whatever.";
}

private boolean isYelling(String input) {
return input.chars()
.anyMatch(Character::isLetter) &&
input.chars()
.filter(Character::isLetter)
.allMatch(Character::isUpperCase);
}

private boolean isAsking(String input) {
return input.endsWith("?");
}

private boolean isSilent(String input) {
return input.length() == 0;
}
}
```

In this approach, the different conditions for Bob’s responses are separated into dedicated private methods within the `Bob` class. This method-based approach improves readability and modularity by organizing each condition check into its own method, making the main response method easier to understand and maintain.

## Explanation

This approach simplifies the main method `hey` by breaking down each response condition into helper methods:

1. **Trimming the Input**:
The `input` is trimmed using the `String` [`trim()`][trim] method to remove any leading or trailing whitespace. This helps to accurately detect if the input is empty and should prompt a `"Fine. Be that way!"` response.

2. **Delegating to Helper Methods**:
Each condition is evaluated using the following helper methods:

- **`isSilent`**: Checks if the trimmed input has no characters.
- **`isYelling`**: Checks if the input is all uppercase and contains at least one alphabetic character, indicating shouting.
- **`isAsking`**: Verifies if the trimmed input ends with a question mark.

This modular approach keeps each condition encapsulated, enhancing code clarity.

3. **Order of Checks**:
The order of checks within `hey` is important:
- Silence is evaluated first, as it requires an immediate response.
- Shouted questions take precedence over individual checks for yelling and asking.
- Yelling comes next, requiring its response if not combined with a question.
- Asking (a non-shouted question) is checked afterward.

This ordering ensures that Bob’s response matches the expected behavior without redundancy.

## Shortening

When the body of an `if` statement is a single line, both the test expression and the body _could_ be put on the same line, like so:

```java
if (isSilent(inputTrimmed)) return "Fine. Be that way!";
```

or the body _could_ be put on a separate line without curly braces:

```java
if (isSilent(inputTrimmed))
return "Fine. Be that way!";
```

However, the [Java Coding Conventions][coding-conventions] advise always using curly braces for `if` statements, which helps to avoid errors. Your team may choose to overrule them at its own risk.

[trim]: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#trim()
[coding-conventions]: https://www.oracle.com/java/technologies/javase/codeconventions-statements.html#449
8 changes: 8 additions & 0 deletions exercises/practice/bob/.approaches/method-based/snippet.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
if (isSilent(inputTrimmed))
return "Fine. Be that way!";
if (isYelling(inputTrimmed) && isAsking(inputTrimmed))
return "Calm down, I know what I'm doing!";
if (isYelling(inputTrimmed))
return "Whoa, chill out!";
if (isAsking(inputTrimmed))
return "Sure.";
3 changes: 3 additions & 0 deletions exercises/practice/dot-dsl/.meta/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
"editor": [
"src/main/java/Node.java",
"src/main/java/Edge.java"
],
"invalidator": [
"build.gradle"
]
},
"blurb": "Write a Domain Specific Language similar to the Graphviz dot language.",
Expand Down
10 changes: 5 additions & 5 deletions exercises/practice/hamming/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Instructions

Calculate the Hamming Distance between two DNA strands.
Calculate the Hamming distance between two DNA strands.

Your body is made up of cells that contain DNA.
Those cells regularly wear out and need replacing, which they achieve by dividing into daughter cells.
Expand All @@ -9,18 +9,18 @@ In fact, the average human body experiences about 10 quadrillion cell divisions
When cells divide, their DNA replicates too.
Sometimes during this process mistakes happen and single pieces of DNA get encoded with the incorrect information.
If we compare two strands of DNA and count the differences between them we can see how many mistakes occurred.
This is known as the "Hamming Distance".
This is known as the "Hamming distance".

We read DNA using the letters C,A,G and T.
We read DNA using the letters C, A, G and T.
Two strands might look like this:

GAGCCTACTAACGGGAT
CATCGTAATGACGGCCT
^ ^ ^ ^ ^ ^^

They have 7 differences, and therefore the Hamming Distance is 7.
They have 7 differences, and therefore the Hamming distance is 7.

The Hamming Distance is useful for lots of things in science, not just biology, so it's a nice phrase to be familiar with :)
The Hamming distance is useful for lots of things in science, not just biology, so it's a nice phrase to be familiar with :)

## Implementation notes

Expand Down
2 changes: 1 addition & 1 deletion exercises/practice/hamming/.meta/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"build.gradle"
]
},
"blurb": "Calculate the Hamming difference between two DNA strands.",
"blurb": "Calculate the Hamming distance between two DNA strands.",
"source": "The Calculating Point Mutations problem at Rosalind",
"source_url": "https://rosalind.info/problems/hamm/"
}
3 changes: 2 additions & 1 deletion exercises/practice/luhn/.docs/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ The first step of the Luhn algorithm is to double every second digit, starting f
We will be doubling

```text
4_3_ 3_9_ 0_4_ 6_6_
4539 3195 0343 6467
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ (double these)
```

If doubling the number results in a number greater than 9 then subtract 9 from the product.
Expand Down
2 changes: 1 addition & 1 deletion exercises/practice/pov/.meta/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@
},
"blurb": "Reparent a graph on a selected node.",
"source": "Adaptation of exercise from 4clojure",
"source_url": "https://www.4clojure.com/"
"source_url": "https://github.com/oxalorg/4ever-clojure"
}
8 changes: 4 additions & 4 deletions exercises/practice/protein-translation/.docs/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

Translate RNA sequences into proteins.

RNA can be broken into three nucleotide sequences called codons, and then translated to a polypeptide like so:
RNA can be broken into three-nucleotide sequences called codons, and then translated to a protein like so:

RNA: `"AUGUUUUCU"` => translates to

Codons: `"AUG", "UUU", "UCU"`
=> which become a polypeptide with the following sequence =>
=> which become a protein with the following sequence =>

Protein: `"Methionine", "Phenylalanine", "Serine"`

Expand All @@ -27,9 +27,9 @@ Protein: `"Methionine", "Phenylalanine", "Serine"`

Note the stop codon `"UAA"` terminates the translation and the final methionine is not translated into the protein sequence.

Below are the codons and resulting Amino Acids needed for the exercise.
Below are the codons and resulting amino acids needed for the exercise.

| Codon | Protein |
| Codon | Amino Acid |
| :----------------- | :------------ |
| AUG | Methionine |
| UUU, UUC | Phenylalanine |
Expand Down
6 changes: 3 additions & 3 deletions exercises/practice/rna-transcription/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
# Instructions

Your task is determine the RNA complement of a given DNA sequence.
Your task is to determine the RNA complement of a given DNA sequence.

Both DNA and RNA strands are a sequence of nucleotides.

The four nucleotides found in DNA are adenine (**A**), cytosine (**C**), guanine (**G**) and thymine (**T**).
The four nucleotides found in DNA are adenine (**A**), cytosine (**C**), guanine (**G**), and thymine (**T**).

The four nucleotides found in RNA are adenine (**A**), cytosine (**C**), guanine (**G**) and uracil (**U**).
The four nucleotides found in RNA are adenine (**A**), cytosine (**C**), guanine (**G**), and uracil (**U**).

Given a DNA strand, its transcribed RNA strand is formed by replacing each nucleotide with its complement:

Expand Down
17 changes: 11 additions & 6 deletions exercises/practice/square-root/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
# Instructions

Given a natural radicand, return its square root.
Your task is to calculate the square root of a given number.

Note that the term "radicand" refers to the number for which the root is to be determined.
That is, it is the number under the root symbol.
- Try to avoid using the pre-existing math libraries of your language.
- As input you'll be given a positive whole number, i.e. 1, 2, 3, 4…
- You are only required to handle cases where the result is a positive whole number.

Check out the Wikipedia pages on [square root][square-root] and [methods of computing square roots][computing-square-roots].
Some potential approaches:

Recall also that natural numbers are positive real whole numbers (i.e. 1, 2, 3 and up).
- Linear or binary search for a number that gives the input number when squared.
- Successive approximation using Newton's or Heron's method.
- Calculating one digit at a time or one bit at a time.

[square-root]: https://en.wikipedia.org/wiki/Square_root
You can check out the Wikipedia pages on [integer square root][integer-square-root] and [methods of computing square roots][computing-square-roots] to help with choosing a method of calculation.

[integer-square-root]: https://en.wikipedia.org/wiki/Integer_square_root
[computing-square-roots]: https://en.wikipedia.org/wiki/Methods_of_computing_square_roots
10 changes: 10 additions & 0 deletions exercises/practice/square-root/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Introduction

We are launching a deep space exploration rocket and we need a way to make sure the navigation system stays on target.

As the first step in our calculation, we take a target number and find its square root (that is, the number that when multiplied by itself equals the target number).

The journey will be very long.
To make the batteries last as long as possible, we had to make our rocket's onboard computer very power efficient.
Unfortunately that means that we can't rely on fancy math libraries and functions, as they use more power.
Instead we want to implement our own square root calculation.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
In this exercise, you're going to implement a program that determines the state of a [tic-tac-toe][] game.
(_You may also know the game as "noughts and crosses" or "Xs and Os"._)

The games is played on a 3×3 grid.
The game is played on a 3×3 grid.
Players take turns to place `X`s and `O`s on the grid.
The game ends when one player has won by placing three of marks in a row, column, or along a diagonal of the grid, or when the entire grid is filled up.

Expand Down
4 changes: 2 additions & 2 deletions exercises/practice/sublist/.docs/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ Given any two lists `A` and `B`, determine if:
- None of the above is true, thus lists `A` and `B` are unequal

Specifically, list `A` is equal to list `B` if both lists have the same values in the same order.
List `A` is a superlist of `B` if `A` contains a sub-sequence of values equal to `B`.
List `A` is a sublist of `B` if `B` contains a sub-sequence of values equal to `A`.
List `A` is a superlist of `B` if `A` contains a contiguous sub-sequence of values equal to `B`.
List `A` is a sublist of `B` if `B` contains a contiguous sub-sequence of values equal to `A`.

Examples:

Expand Down