Skip to content

Commit abdff59

Browse files
ystrommMartin Carlsson
authored andcommitted
chars exercise
* Started porting chars exercise from c#. * Added chars to list of exercises. * Updated hints. * Made the after-text shorter. Removed todo. * Fixes style for @ignore. * Adds config.json. * Adds entry for chars exercise. * Fixes csharp in instructions. * Added design document. * Fixes method name in instructions. * Adds a test for leading and trailing spaces. Co-authored-by: Martin Carlsson <martin.carlsson@svt.se>
1 parent 994e53a commit abdff59

10 files changed

Lines changed: 238 additions & 0 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
`char`s are generally easy to use. They can be extracted from strings, added back
2+
(by means of a string builder), defined and initialised using literals with single quotes, as in `char ch = 'A';`
3+
, assigned and compared.
4+
5+
The Character class encapsulates the char value.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
### 1. Replace any spaces encountered with underscores
2+
3+
- [This tutorial][chars-tutorial] is useful.
4+
- [Reference documentation][chars-docs] for `char`s is here.
5+
- You can retrieve `char`s from a string using the [charAt][char-at] method.
6+
- You should use a [`StringBuilder`][string-builder] to build the output string.
7+
- See [this method][iswhitespace] for detecting spaces. Remember it is a static method.
8+
- `char` literals are enclosed in single quotes.
9+
10+
### 2. Replace control characters with the upper case string "CTRL"
11+
12+
- See [this method][iscontrol] to check if a character is a control character.
13+
14+
### 3. Convert kebab-case to camel-case
15+
16+
- See [this method][toupper] to convert a character to upper case.
17+
18+
### 4. Omit Greek lower case letters
19+
20+
- `char`s support the default equality and comparison operators.
21+
22+
[chars-docs]: https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Character.html
23+
[chars-tutorial]: https://docs.oracle.com/javase/tutorial/java/data/characters.html
24+
[char-at]: https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/String.html#charAt(int)
25+
[string-builder]: https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/StringBuilder.html
26+
[iswhitespace]: https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Character.html#isWhitespace(char)
27+
[iscontrol]: https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Character.html#isISOControl(char)
28+
[toupper]: https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Character.html#toUpperCase(char)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
In this exercise you will implement a partial set of utility routines to help a developer
2+
clean up identifier names.
3+
4+
In the 4 tasks you will gradually build up the routine `clean` A valid identifier comprises
5+
zero or more letters and underscores.
6+
7+
In all cases the input string is guaranteed to be non-null. Note that the `clean` method should treat an empty string as valid.
8+
9+
### 1. Replace any spaces encountered with underscores
10+
11+
Implement the (_static_) `Identifier.clean()` method to replace any spaces with underscores. This also applies to leading and trailing spaces.
12+
13+
```java
14+
Identifier.clean("my Id");
15+
// => "my___Id"
16+
```
17+
18+
### 2. Replace control characters with the upper case string "CTRL"
19+
20+
Modify the (_static_) `Identifier.clean()` method to replace control characters with the upper case string `"CTRL"`.
21+
22+
```java
23+
Identifier.clean("my\0Id");
24+
// => "myCTRLId",
25+
```
26+
27+
### 3. Convert kebab-case to camelCase
28+
29+
Modify the (_static_) `Identifier.clean()` method to convert kebab-case to camelCase.
30+
31+
```java
32+
Identifier.Clean("à-ḃç");
33+
// => "àḂç"
34+
```
35+
36+
### 4. Omit Greek lower case letters
37+
38+
Modify the (_static_) `Identifier.clean()` method to omit any Greek letters in the range 'α' to 'ω'.
39+
40+
```java
41+
Identifier.Clean("MyΟβιεγτFinder");
42+
// => "MyΟFinder"
43+
```
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
The Java `char` type represents the smallest addressable components of text.
2+
Multiple `char`s can comprise a string such as `"word"` or `char`s can be
3+
processed independently. Their literals have single quotes e.g. `'A'`.
4+
5+
Java `char`s support Unicode encoding so in addition to the latin character set
6+
pretty much all the writing systems in use world can be represented,
7+
e.g. ancient greek `'β'`.
8+
9+
There are many builtin library methods to inspect and manipulate `char`s. These
10+
can be found as static methods of the `java.lang.Character` class.
11+
12+
`char`s are sometimes used in conjunction with a `StringBuilder` object.
13+
This object has methods that allow a string to be constructed
14+
character by character and manipulated. At the end of the process
15+
`toString` can be called on it to output a complete string.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"authors": [
3+
{
4+
"github_username": "ystromm",
5+
"exercism_username": "ystromm"
6+
}
7+
],
8+
"forked_from": ["csharp/chars"]
9+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
## Learning objectives
2+
3+
- Know of the existence of the `char` type.
4+
- Know what a char represents (a Unicode character).
5+
- Know how to define a `char`.
6+
- Know that a `char` is not the same as a single character string
7+
- Know how to access a `char` in a string by index.
8+
- Know of some basic `char` methods (like converting to uppercase).
9+
- Know that `char`s are immutable.
10+
- Know how to compare characters.
11+
- Know how to use a `StringBuilder`.
12+
13+
## Out of scope
14+
15+
- Converting an integer to a character and vice versa.
16+
- Advanced unicode issues such as surrogates, text normalization, combining characters.
17+
- Cultural considerations and invariants.
18+
19+
## Concepts
20+
21+
- `chars`: know of the existence of the `char` type; know that a `char` represents; know how to define a `char`; know how to access a `char` in a string by index; know of some basic `char` methods (like converting to uppercase).
22+
- `StringBuilder`: know how to use this.
23+
24+
## Prerequisites
25+
26+
- `strings`: know of the `string` type that will be iterated over and accessed by index.
27+
- `for-loop` for loops (rather than foreach) are the best means of highlighting the relationship between strings and `char`s
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
class Identifier {
2+
static String clean(String identifier) {
3+
final StringBuilder cleanIdentifier = new StringBuilder();
4+
for (int i = 0; i < identifier.length(); i++) {
5+
final char ch = identifier.charAt(i);
6+
if (Character.isSpaceChar(ch)) {
7+
cleanIdentifier.append("_");
8+
} else if (Character.isISOControl(ch)) {
9+
cleanIdentifier.append("CTRL");
10+
} else if (ch == '-' && i < identifier.length() + 1) {
11+
i++;
12+
cleanIdentifier.append(Character.toUpperCase(identifier.charAt(i)));
13+
} else if (ch >= 'α' && ch <= 'ω') {
14+
} else if (Character.isAlphabetic(ch)) {
15+
cleanIdentifier.append(ch);
16+
}
17+
}
18+
return cleanIdentifier.toString();
19+
}
20+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
apply plugin: "java"
2+
apply plugin: "eclipse"
3+
apply plugin: "idea"
4+
5+
repositories {
6+
mavenCentral()
7+
}
8+
9+
dependencies {
10+
testCompile "junit:junit:4.13"
11+
testImplementation "org.assertj:assertj-core:3.15.0"
12+
}
13+
14+
test {
15+
testLogging {
16+
exceptionFormat = 'short'
17+
showStandardStreams = true
18+
events = ["passed", "failed", "skipped"]
19+
}
20+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class Identifier {
2+
static String clean(String identifier) {
3+
throw new UnsupportedOperationException("Please implement the (static) Chars.clean() method");
4+
}
5+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import org.junit.Test;
2+
import org.junit.Ignore;
3+
4+
import static org.assertj.core.api.Assertions.assertThat;
5+
6+
public class IdentifierTest {
7+
8+
@Test
9+
public void empty() {
10+
assertThat(Identifier.clean("")).isEmpty();
11+
}
12+
13+
@Ignore("Remove to run test")
14+
@Test
15+
public void single_letter() {
16+
assertThat(Identifier.clean("A")).isEqualTo("A");
17+
}
18+
19+
@Ignore("Remove to run test")
20+
@Test
21+
public void string() {
22+
assertThat(Identifier.clean("àḃç")).isEqualTo("àḃç");
23+
}
24+
25+
@Ignore("Remove to run test")
26+
@Test
27+
public void spaces() {
28+
assertThat(Identifier.clean("my Id")).isEqualTo("my___Id");
29+
}
30+
31+
@Ignore("Remove to run test")
32+
@Test
33+
public void leading_and_trailing_spaces() {
34+
assertThat(Identifier.clean(" myId ")).isEqualTo("_myId_");
35+
}
36+
37+
@Ignore("Remove to run test")
38+
@Test
39+
public void ctrl() {
40+
assertThat(Identifier.clean("my\0Id")).isEqualTo("myCTRLId");
41+
}
42+
43+
@Ignore("Remove to run test")
44+
@Test
45+
public void string_with_no_letters() {
46+
assertThat(Identifier.clean("\uD83D\uDE00\uD83D\uDE00\uD83D\uDE00")).isEmpty();
47+
}
48+
49+
@Ignore("Remove to run test")
50+
@Test
51+
public void kebab_to_camel_case() {
52+
assertThat(Identifier.clean("à-ḃç")).isEqualTo("àḂç");
53+
}
54+
55+
@Ignore("Remove to run test")
56+
@Test
57+
public void omit_lower_case_greek_letters() {
58+
assertThat(Identifier.clean("MyΟβιεγτFinder")).isEqualTo("MyΟFinder");
59+
}
60+
61+
@Ignore("Remove to run test")
62+
@Test
63+
public void combine_conversions() {
64+
assertThat(Identifier.clean("9 -abcĐ\uD83D\uDE00ω\0")).isEqualTo("_AbcĐCTRL");
65+
}
66+
}

0 commit comments

Comments
 (0)