trackler 2.2.1.174 → 2.2.1.175
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/trackler/version.rb +1 -1
- data/tracks/ecmascript/config.json +1 -0
- data/tracks/javascript/README.md +9 -0
- data/tracks/reasonml/.travis.yml +19 -2
- data/tracks/reasonml/Makefile +35 -0
- data/tracks/reasonml/README.md +2 -1
- data/tracks/reasonml/bsconfig.json +25 -0
- data/tracks/reasonml/config/maintainers.json +12 -1
- data/tracks/reasonml/config.json +22 -0
- data/tracks/reasonml/exercises/anagram/README.md +18 -0
- data/tracks/reasonml/exercises/binary-search/README.md +50 -0
- data/tracks/reasonml/exercises/binary-search/__tests__/BinarySearch_test.re +39 -0
- data/tracks/reasonml/exercises/binary-search/bsconfig.json +30 -0
- data/tracks/reasonml/exercises/binary-search/package.json +20 -0
- data/tracks/reasonml/exercises/binary-search/src/Example.re +17 -0
- data/tracks/reasonml/exercises/bob/README.md +0 -1
- data/tracks/reasonml/exercises/leap/README.md +26 -0
- data/tracks/reasonml/exercises/rna-transcription/README.md +31 -0
- data/tracks/reasonml/exercises/run-length-encoding/README.md +39 -0
- data/tracks/reasonml/exercises/run-length-encoding/__tests__/RunLengthEncoding_test.re +51 -0
- data/tracks/reasonml/exercises/run-length-encoding/bsconfig.json +30 -0
- data/tracks/reasonml/exercises/run-length-encoding/package.json +20 -0
- data/tracks/reasonml/exercises/run-length-encoding/src/Example.re +60 -0
- data/tracks/reasonml/exercises/space-age/README.md +30 -0
- data/tracks/reasonml/exercises/space-age/__tests__/SpaceAge_test.re +37 -0
- data/tracks/reasonml/package-lock.json +5853 -0
- data/tracks/reasonml/package.json +20 -0
- metadata +20 -4
- data/tracks/reasonml/exercises/hello-world/.gitignore +0 -8
- data/tracks/reasonml/exercises/space-age/__tests__/Space_age_test.re +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f8ba749e7d72c728ef66d3ae7e4172a0a24063de
|
4
|
+
data.tar.gz: a23cb78cfda6299e50baacaf47590e14b46c0d56
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 224ce7c0af67cb3ff9896e1b578918e6e0a46f0588e6dc9ea0cab3fbbf661162ee4e6394233096d2a1597e949688573324c6dd05cf2bd7fa0b0678d73245377a
|
7
|
+
data.tar.gz: e640bf79b918cd47f365955731fb8f197f524e0b9309f54b57d2a806bece389707e8a94dd80317f2379bfd667fb94202c6e12e270de91394268b43bdfe40494e
|
data/lib/trackler/version.rb
CHANGED
data/tracks/javascript/README.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
# DEPRECATION NOTICE
|
2
|
+
|
3
|
+
This track will be deprecated as part of the migration of Exercism to V2. Going forward, the EcmaScript track will replace the JavaScript track as "the new JavaScript" track.
|
4
|
+
- User's old submissions will be migrated
|
5
|
+
- PRs unrelated to the deprecation will be closed as `wontfix`
|
6
|
+
- Issues unrelated to deprecation will be closed as `wontfix`
|
7
|
+
|
8
|
+
Thank you to all the many invested and hardworking contributors who have helped to make this track a success!!
|
9
|
+
|
1
10
|
# JavaScript [](https://travis-ci.org/exercism/javascript)[](https://gitter.im/exercism/xecmascript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
2
11
|
|
3
12
|
Exercism exercises in JavaScript
|
data/tracks/reasonml/.travis.yml
CHANGED
@@ -1,5 +1,22 @@
|
|
1
|
-
language:
|
1
|
+
language: node_js
|
2
|
+
|
3
|
+
node_js:
|
4
|
+
- 'node'
|
5
|
+
|
6
|
+
before_install:
|
7
|
+
- npm i -g npm@latest
|
8
|
+
|
9
|
+
install:
|
10
|
+
- npm ci
|
11
|
+
|
12
|
+
cache:
|
13
|
+
directories:
|
14
|
+
- node_modules
|
2
15
|
|
3
16
|
script:
|
4
17
|
- bin/fetch-configlet
|
5
|
-
- bin/configlet lint --track
|
18
|
+
- bin/configlet lint --track-id reasonml .
|
19
|
+
- make copy-all-exercises
|
20
|
+
- npm run build
|
21
|
+
- npm run test:ci
|
22
|
+
- make clean
|
@@ -0,0 +1,35 @@
|
|
1
|
+
EXERCISE ?= ""
|
2
|
+
IGNOREDIRS := "^(\.git|docs|bin|node_modules|.idea)$$"
|
3
|
+
EXERCISES = $(shell find ./exercises -maxdepth 1 -mindepth 1 -type d | cut -d'/' -f3 | sort | grep -Ev $(IGNOREDIRS))
|
4
|
+
|
5
|
+
default: testgenerator test
|
6
|
+
|
7
|
+
# output directories
|
8
|
+
OUTDIR ?= "tmp"
|
9
|
+
|
10
|
+
# language specific config (tweakable per language)
|
11
|
+
FILEEXT := "re"
|
12
|
+
EXAMPLE := "Example.$(FILEEXT)"
|
13
|
+
SRCFILE := "$(shell echo $(EXERCISE) | sed -r 's/(^|-)([a-z])/\U\2/g')"
|
14
|
+
TSTFILE := "$(SRCFILE)_test.$(FILEEXT)"
|
15
|
+
# Any additional arguments, such as -p for pretty output and others
|
16
|
+
ARGS ?= ""
|
17
|
+
|
18
|
+
# copy example and test file for single exercise to OUTDIR
|
19
|
+
# Rename Example.re to ExerciseName.re in the process
|
20
|
+
copy-exercise:
|
21
|
+
@cp exercises/$(EXERCISE)/__tests__/$(TSTFILE) $(OUTDIR)/__tests__/
|
22
|
+
@cp exercises/$(EXERCISE)/src/$(EXAMPLE) $(OUTDIR)/src/$(SRCFILE).$(FILEEXT)
|
23
|
+
|
24
|
+
# copy all source files to OUTDIR - easier to compile from there
|
25
|
+
copy-all-exercises:
|
26
|
+
@echo "Copying files..."
|
27
|
+
@mkdir -p $(OUTDIR)/src
|
28
|
+
@mkdir -p $(OUTDIR)/__tests__
|
29
|
+
@for exercise in $(EXERCISES); do EXERCISE=$$exercise $(MAKE) -s copy-exercise || exit 1; done
|
30
|
+
|
31
|
+
# Remove the OUTDIR
|
32
|
+
clean:
|
33
|
+
@rm -rf $(OUTDIR)
|
34
|
+
|
35
|
+
.PHONY: clean
|
data/tracks/reasonml/README.md
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
{
|
2
|
+
"name": "exercism-reason",
|
3
|
+
"version": "0.1.0",
|
4
|
+
"sources": [
|
5
|
+
{
|
6
|
+
"dir" : "tmp/src",
|
7
|
+
"subdirs" : true
|
8
|
+
},
|
9
|
+
{
|
10
|
+
"dir": "tmp/__tests__",
|
11
|
+
"type": "dev"
|
12
|
+
}
|
13
|
+
],
|
14
|
+
"package-specs": {
|
15
|
+
"module": "commonjs",
|
16
|
+
"in-source": true
|
17
|
+
},
|
18
|
+
"suffix": ".bs.js",
|
19
|
+
"bs-dev-dependencies": ["@glennsl/bs-jest"],
|
20
|
+
"warnings": {
|
21
|
+
"error" : "+101"
|
22
|
+
},
|
23
|
+
"namespace": true,
|
24
|
+
"refmt": 3
|
25
|
+
}
|
@@ -1,4 +1,15 @@
|
|
1
1
|
{
|
2
2
|
"docs_url": "https://github.com/exercism/docs/blob/master/maintaining-a-track/maintainer-configuration.md",
|
3
|
-
"maintainers": [
|
3
|
+
"maintainers": [
|
4
|
+
{
|
5
|
+
"github_username": "stevejb71",
|
6
|
+
"alumnus": false,
|
7
|
+
"show_on_website": false,
|
8
|
+
"name": null,
|
9
|
+
"link_text": null,
|
10
|
+
"link_url": null,
|
11
|
+
"avatar_url": null,
|
12
|
+
"bio": null
|
13
|
+
}
|
14
|
+
]
|
4
15
|
}
|
data/tracks/reasonml/config.json
CHANGED
@@ -102,6 +102,28 @@
|
|
102
102
|
"list_map_function"
|
103
103
|
]
|
104
104
|
},
|
105
|
+
{
|
106
|
+
"slug": "binary-search",
|
107
|
+
"uuid": "eb635d37-a70b-47b2-883b-8ec9ca6098ef",
|
108
|
+
"core": false,
|
109
|
+
"unlocked_by": null,
|
110
|
+
"difficulty": 3,
|
111
|
+
"topics": [
|
112
|
+
"arrays",
|
113
|
+
"recursion"
|
114
|
+
]
|
115
|
+
},
|
116
|
+
{
|
117
|
+
"slug": "run-length-encoding",
|
118
|
+
"uuid": "1c8245de-3ae2-4b59-83a9-d34c540f67f0",
|
119
|
+
"core": false,
|
120
|
+
"unlocked_by": null,
|
121
|
+
"difficulty": 4,
|
122
|
+
"topics": [
|
123
|
+
"strings",
|
124
|
+
"converting_strings_to_ints"
|
125
|
+
]
|
126
|
+
},
|
105
127
|
{
|
106
128
|
"slug": "change",
|
107
129
|
"uuid": "3526ae52-5962-43d6-ae83-dd6a9ca6e25b",
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Anagram
|
2
|
+
|
3
|
+
Given a word and a list of possible anagrams, select the correct sublist.
|
4
|
+
|
5
|
+
Given `"listen"` and a list of candidates like `"enlists" "google"
|
6
|
+
"inlets" "banana"` the program should return a list containing
|
7
|
+
`"inlets"`.
|
8
|
+
|
9
|
+
# Build
|
10
|
+
```
|
11
|
+
npm run build
|
12
|
+
```
|
13
|
+
|
14
|
+
# Build + Watch
|
15
|
+
|
16
|
+
```
|
17
|
+
npm run start
|
18
|
+
```
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Binary Search
|
2
|
+
|
3
|
+
Implement a binary search algorithm.
|
4
|
+
|
5
|
+
Searching a sorted collection is a common task. A dictionary is a sorted
|
6
|
+
list of word definitions. Given a word, one can find its definition. A
|
7
|
+
telephone book is a sorted list of people's names, addresses, and
|
8
|
+
telephone numbers. Knowing someone's name allows one to quickly find
|
9
|
+
their telephone number and address.
|
10
|
+
|
11
|
+
If the list to be searched contains more than a few items (a dozen, say)
|
12
|
+
a binary search will require far fewer comparisons than a linear search,
|
13
|
+
but it imposes the requirement that the list be sorted.
|
14
|
+
|
15
|
+
In computer science, a binary search or half-interval search algorithm
|
16
|
+
finds the position of a specified input value (the search "key") within
|
17
|
+
an array sorted by key value.
|
18
|
+
|
19
|
+
In each step, the algorithm compares the search key value with the key
|
20
|
+
value of the middle element of the array.
|
21
|
+
|
22
|
+
If the keys match, then a matching element has been found and its index,
|
23
|
+
or position, is returned.
|
24
|
+
|
25
|
+
Otherwise, if the search key is less than the middle element's key, then
|
26
|
+
the algorithm repeats its action on the sub-array to the left of the
|
27
|
+
middle element or, if the search key is greater, on the sub-array to the
|
28
|
+
right.
|
29
|
+
|
30
|
+
If the remaining array to be searched is empty, then the key cannot be
|
31
|
+
found in the array and a special "not found" indication is returned.
|
32
|
+
|
33
|
+
A binary search halves the number of items to check with each iteration,
|
34
|
+
so locating an item (or determining its absence) takes logarithmic time.
|
35
|
+
A binary search is a dichotomic divide and conquer search algorithm.
|
36
|
+
|
37
|
+
# Build
|
38
|
+
```
|
39
|
+
npm run build
|
40
|
+
```
|
41
|
+
|
42
|
+
# Build + Watch
|
43
|
+
|
44
|
+
```
|
45
|
+
npm run start
|
46
|
+
```
|
47
|
+
|
48
|
+
|
49
|
+
# Editor
|
50
|
+
If you use `vscode`, Press `Windows + Shift + B` it will build automatically
|
@@ -0,0 +1,39 @@
|
|
1
|
+
open Jest;
|
2
|
+
open Expect;
|
3
|
+
open BinarySearch;
|
4
|
+
|
5
|
+
describe("Binary search", () => {
|
6
|
+
test("finds a value in an array with one element", () =>
|
7
|
+
expect(find([|6|], 6)) |> toEqual(Some(0))
|
8
|
+
);
|
9
|
+
test("finds a value in the middle of an array", () =>
|
10
|
+
expect(find([|1, 3, 4, 6, 8, 9, 11|], 6)) |> toEqual(Some(3))
|
11
|
+
);
|
12
|
+
test("finds a value at the beginning of an array", () =>
|
13
|
+
expect(find([|1, 3, 4, 6, 8, 9, 11|], 1)) |> toEqual(Some(0))
|
14
|
+
);
|
15
|
+
test("finds a value at the end of an array", () =>
|
16
|
+
expect(find([|1, 3, 4, 6, 8, 9, 11|], 11)) |> toEqual(Some(6))
|
17
|
+
);
|
18
|
+
test("finds a value in an array of odd length", () =>
|
19
|
+
expect(find([|1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 634|], 144)) |> toEqual(Some(9))
|
20
|
+
);
|
21
|
+
test("finds a value in an array of even length", () =>
|
22
|
+
expect(find([|1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377|], 21)) |> toEqual(Some(5))
|
23
|
+
);
|
24
|
+
test("identifies that a value is not included in the array", () =>
|
25
|
+
expect(find([|1, 3, 4, 6, 8, 9, 11|], 7)) |> toEqual(None)
|
26
|
+
);
|
27
|
+
test("a value smaller than the array's smallest value is not included", () =>
|
28
|
+
expect(find([|1, 3, 4, 6, 8, 9, 11|], 0)) |> toEqual(None)
|
29
|
+
);
|
30
|
+
test("a value larger than the array's largest value is not included", () =>
|
31
|
+
expect(find([|1, 3, 4, 6, 8, 9, 11|], 13)) |> toEqual(None)
|
32
|
+
);
|
33
|
+
test("nothing is included in an empty array", () =>
|
34
|
+
expect(find([||], 1)) |> toEqual(None)
|
35
|
+
);
|
36
|
+
});
|
37
|
+
|
38
|
+
|
39
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
// This is the configuration file used by BuckleScript's build system bsb. Its documentation lives here: http://bucklescript.github.io/bucklescript/docson/#build-schema.json
|
2
|
+
// BuckleScript comes with its own parser for bsconfig.json, which is normal JSON, with the extra support of comments and trailing commas.
|
3
|
+
{
|
4
|
+
"name": "binary-search",
|
5
|
+
"version": "0.1.0",
|
6
|
+
"sources": [
|
7
|
+
{
|
8
|
+
"dir" : "src",
|
9
|
+
"subdirs" : true
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"dir": "__tests__",
|
13
|
+
"type": "dev"
|
14
|
+
}
|
15
|
+
],
|
16
|
+
"package-specs": {
|
17
|
+
"module": "commonjs",
|
18
|
+
"in-source": true
|
19
|
+
},
|
20
|
+
"suffix": ".bs.js",
|
21
|
+
"bs-dependencies": [
|
22
|
+
// add your dependencies here. You'd usually install them normally through `npm install my-dependency`. If my-dependency has a bsconfig.json too, then everything will work seamlessly.
|
23
|
+
],
|
24
|
+
"bs-dev-dependencies": ["@glennsl/bs-jest"],
|
25
|
+
"warnings": {
|
26
|
+
"error" : "+101"
|
27
|
+
},
|
28
|
+
"namespace": true,
|
29
|
+
"refmt": 3
|
30
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
{
|
2
|
+
"name": "binary-search",
|
3
|
+
"version": "0.1.0",
|
4
|
+
"scripts": {
|
5
|
+
"build": "bsb -make-world",
|
6
|
+
"start": "bsb -make-world -w",
|
7
|
+
"clean": "bsb -clean-world",
|
8
|
+
"test": "jest --watchAll",
|
9
|
+
"test:ci": "jest --ci --bail --no-cache"
|
10
|
+
},
|
11
|
+
"keywords": [
|
12
|
+
"BuckleScript"
|
13
|
+
],
|
14
|
+
"author": "",
|
15
|
+
"license": "MIT",
|
16
|
+
"devDependencies": {
|
17
|
+
"@glennsl/bs-jest": "^0.4.2",
|
18
|
+
"bs-platform": "^3.1.5"
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
let find = (array, value) => {
|
2
|
+
let rec go = (lo, hi) =>
|
3
|
+
if (lo > hi) {
|
4
|
+
None;
|
5
|
+
} else {
|
6
|
+
let mid = lo + (hi - lo) / 2;
|
7
|
+
let mid_val = array[mid];
|
8
|
+
if (mid_val < value) {
|
9
|
+
go(mid + 1, hi);
|
10
|
+
} else if (mid_val > value) {
|
11
|
+
go(lo, mid - 1);
|
12
|
+
} else {
|
13
|
+
Some(mid);
|
14
|
+
};
|
15
|
+
};
|
16
|
+
go(0, Array.length(array) - 1);
|
17
|
+
};
|
@@ -1,5 +1,31 @@
|
|
1
1
|
# Leap in ReasonML
|
2
2
|
|
3
|
+
Given a year, report if it is a leap year.
|
4
|
+
|
5
|
+
The tricky thing here is that a leap year in the Gregorian calendar occurs:
|
6
|
+
|
7
|
+
```text
|
8
|
+
on every year that is evenly divisible by 4
|
9
|
+
except every year that is evenly divisible by 100
|
10
|
+
unless the year is also evenly divisible by 400
|
11
|
+
```
|
12
|
+
|
13
|
+
For example, 1997 is not a leap year, but 1996 is. 1900 is not a leap
|
14
|
+
year, but 2000 is.
|
15
|
+
|
16
|
+
If your language provides a method in the standard library that does
|
17
|
+
this look-up, pretend it doesn't exist and implement it yourself.
|
18
|
+
|
19
|
+
## Notes
|
20
|
+
|
21
|
+
Though our exercise adopts some very simple rules, there is more to
|
22
|
+
learn!
|
23
|
+
|
24
|
+
For a delightful, four minute explanation of the whole leap year
|
25
|
+
phenomenon, go watch [this youtube video][video].
|
26
|
+
|
27
|
+
[video]: http://www.youtube.com/watch?v=xX96xng7sAE
|
28
|
+
|
3
29
|
# Build + Watch
|
4
30
|
|
5
31
|
```
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# RNA Transcription
|
2
|
+
|
3
|
+
Given a DNA strand, return its RNA complement (per RNA transcription).
|
4
|
+
|
5
|
+
Both DNA and RNA strands are a sequence of nucleotides.
|
6
|
+
|
7
|
+
The four nucleotides found in DNA are adenine (**A**), cytosine (**C**),
|
8
|
+
guanine (**G**) and thymine (**T**).
|
9
|
+
|
10
|
+
The four nucleotides found in RNA are adenine (**A**), cytosine (**C**),
|
11
|
+
guanine (**G**) and uracil (**U**).
|
12
|
+
|
13
|
+
Given a DNA strand, its transcribed RNA strand is formed by replacing
|
14
|
+
each nucleotide with its complement:
|
15
|
+
|
16
|
+
* `G` -> `C`
|
17
|
+
* `C` -> `G`
|
18
|
+
* `T` -> `A`
|
19
|
+
* `A` -> `U`
|
20
|
+
|
21
|
+
# Build + Watch
|
22
|
+
|
23
|
+
```
|
24
|
+
npm start
|
25
|
+
```
|
26
|
+
|
27
|
+
# Test + Watch
|
28
|
+
|
29
|
+
```
|
30
|
+
npm test
|
31
|
+
```
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Run Length Encoding
|
2
|
+
|
3
|
+
Implement run-length encoding and decoding.
|
4
|
+
|
5
|
+
Run-length encoding (RLE) is a simple form of data compression, where runs
|
6
|
+
(consecutive data elements) are replaced by just one data value and count.
|
7
|
+
|
8
|
+
For example we can represent the original 53 characters with only 13.
|
9
|
+
|
10
|
+
```text
|
11
|
+
"WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB" -> "12WB12W3B24WB"
|
12
|
+
```
|
13
|
+
|
14
|
+
RLE allows the original data to be perfectly reconstructed from
|
15
|
+
the compressed data, which makes it a lossless data compression.
|
16
|
+
|
17
|
+
```text
|
18
|
+
"AABCCCDEEEE" -> "2AB3CD4E" -> "AABCCCDEEEE"
|
19
|
+
```
|
20
|
+
|
21
|
+
For simplicity, you can assume that the unencoded string will only contain
|
22
|
+
the letters A through Z (either lower or upper case) and whitespace. This way
|
23
|
+
data to be encoded will never contain any numbers and numbers inside data to
|
24
|
+
be decoded always represent the count for the following character.
|
25
|
+
|
26
|
+
# Build
|
27
|
+
```
|
28
|
+
npm run build
|
29
|
+
```
|
30
|
+
|
31
|
+
# Build + Watch
|
32
|
+
|
33
|
+
```
|
34
|
+
npm run start
|
35
|
+
```
|
36
|
+
|
37
|
+
|
38
|
+
# Editor
|
39
|
+
If you use `vscode`, Press `Windows + Shift + B` it will build automatically
|
@@ -0,0 +1,51 @@
|
|
1
|
+
open Jest;
|
2
|
+
open Expect;
|
3
|
+
open RunLengthEncoding;
|
4
|
+
|
5
|
+
describe("encode function", () => {
|
6
|
+
test("empty string", () =>
|
7
|
+
expect(encode("")) |> toBe("")
|
8
|
+
);
|
9
|
+
test("single characters only are encoded without count", () =>
|
10
|
+
expect(encode("XYZ")) |> toBe("XYZ")
|
11
|
+
);
|
12
|
+
test("string with no single characters", () =>
|
13
|
+
expect(encode("AABBBCCCC")) |> toBe("2A3B4C")
|
14
|
+
);
|
15
|
+
test("single characters mixed with repeated characters", () =>
|
16
|
+
expect(encode("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB")) |> toBe("12WB12W3B24WB")
|
17
|
+
);
|
18
|
+
test("multiple whitespace mixed in string", () =>
|
19
|
+
expect(encode(" hsqq qww ")) |> toBe("2 hs2q q2w2 ")
|
20
|
+
);
|
21
|
+
test("lowercase characters", () =>
|
22
|
+
expect(encode("aabbbcccc")) |> toBe("2a3b4c")
|
23
|
+
);
|
24
|
+
});
|
25
|
+
|
26
|
+
describe("decode function", () => {
|
27
|
+
test("empty string", () =>
|
28
|
+
expect(decode("")) |> toBe("")
|
29
|
+
);
|
30
|
+
test("single characters only", () =>
|
31
|
+
expect(decode("XYZ")) |> toBe("XYZ")
|
32
|
+
);
|
33
|
+
test("string with no single characters", () =>
|
34
|
+
expect(decode("2A3B4C")) |> toBe("AABBBCCCC")
|
35
|
+
);
|
36
|
+
test("single characters with repeated characters", () =>
|
37
|
+
expect(decode("12WB12W3B24WB")) |> toBe("WWWWWWWWWWWWBWWWWWWWWWWWWBBBWWWWWWWWWWWWWWWWWWWWWWWWB")
|
38
|
+
);
|
39
|
+
test("multiple whitespace mixed in string", () =>
|
40
|
+
expect(decode("2 hs2q q2w2 ")) |> toBe(" hsqq qww ")
|
41
|
+
);
|
42
|
+
test("lower case string", () =>
|
43
|
+
expect(decode("2a3b4c")) |> toBe("aabbbcccc")
|
44
|
+
);
|
45
|
+
});
|
46
|
+
|
47
|
+
describe("Encode/decode are inverse operations", () => {
|
48
|
+
test("encode(followed by decode gives original string", () =>
|
49
|
+
expect(encode("zzz ZZ zZ") |> decode) |> toBe("zzz ZZ zZ")
|
50
|
+
);
|
51
|
+
});
|
@@ -0,0 +1,30 @@
|
|
1
|
+
// This is the configuration file used by BuckleScript's build system bsb. Its documentation lives here: http://bucklescript.github.io/bucklescript/docson/#build-schema.json
|
2
|
+
// BuckleScript comes with its own parser for bsconfig.json, which is normal JSON, with the extra support of comments and trailing commas.
|
3
|
+
{
|
4
|
+
"name": "run-length-encoding",
|
5
|
+
"version": "0.1.0",
|
6
|
+
"sources": [
|
7
|
+
{
|
8
|
+
"dir" : "src",
|
9
|
+
"subdirs" : true
|
10
|
+
},
|
11
|
+
{
|
12
|
+
"dir": "__tests__",
|
13
|
+
"type": "dev"
|
14
|
+
}
|
15
|
+
],
|
16
|
+
"package-specs": {
|
17
|
+
"module": "commonjs",
|
18
|
+
"in-source": true
|
19
|
+
},
|
20
|
+
"suffix": ".bs.js",
|
21
|
+
"bs-dependencies": [
|
22
|
+
// add your dependencies here. You'd usually install them normally through `npm install my-dependency`. If my-dependency has a bsconfig.json too, then everything will work seamlessly.
|
23
|
+
],
|
24
|
+
"bs-dev-dependencies": ["@glennsl/bs-jest"],
|
25
|
+
"warnings": {
|
26
|
+
"error" : "+101"
|
27
|
+
},
|
28
|
+
"namespace": true,
|
29
|
+
"refmt": 3
|
30
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
{
|
2
|
+
"name": "run-length-encoding",
|
3
|
+
"version": "0.1.0",
|
4
|
+
"scripts": {
|
5
|
+
"build": "bsb -make-world",
|
6
|
+
"start": "bsb -make-world -w",
|
7
|
+
"clean": "bsb -clean-world",
|
8
|
+
"test": "jest --watchAll",
|
9
|
+
"test:ci": "jest --ci --bail --no-cache"
|
10
|
+
},
|
11
|
+
"keywords": [
|
12
|
+
"BuckleScript"
|
13
|
+
],
|
14
|
+
"author": "",
|
15
|
+
"license": "MIT",
|
16
|
+
"devDependencies": {
|
17
|
+
"@glennsl/bs-jest": "^0.4.2",
|
18
|
+
"bs-platform": "^3.1.5"
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1,60 @@
|
|
1
|
+
let isDigit = (ch: char) => {
|
2
|
+
let ord = Char.code(ch);
|
3
|
+
ord >= 48 && ord <= 57;
|
4
|
+
};
|
5
|
+
|
6
|
+
let rec toInt = (s: string, ptr: int, acc: int) => {
|
7
|
+
if(ptr == String.length(s)) {
|
8
|
+
(ptr, acc)
|
9
|
+
} else {
|
10
|
+
if(!isDigit(s.[ptr])) {
|
11
|
+
(ptr, acc)
|
12
|
+
} else {
|
13
|
+
toInt(s, ptr + 1, 10 * acc + Char.code(s.[ptr]) - 48)
|
14
|
+
}
|
15
|
+
}
|
16
|
+
};
|
17
|
+
|
18
|
+
let rec unfoldString = (startPtr: int, acc: string, consume, s: string): string => {
|
19
|
+
if(s == "" || startPtr == String.length(s)) {
|
20
|
+
acc;
|
21
|
+
} else {
|
22
|
+
let (nextPtr, nextChunk) = consume(s, startPtr);
|
23
|
+
unfoldString(nextPtr, acc ++ nextChunk, consume, s);
|
24
|
+
}
|
25
|
+
};
|
26
|
+
|
27
|
+
let rec skipWhileUnchanged = (s: string, startPtr: int, ptr: int): int => {
|
28
|
+
if(ptr < String.length(s) && s.[ptr] == s.[startPtr]) {
|
29
|
+
skipWhileUnchanged(s, startPtr, ptr + 1)
|
30
|
+
} else {
|
31
|
+
ptr
|
32
|
+
}
|
33
|
+
};
|
34
|
+
|
35
|
+
let chunk = (plainText: string, startPtr: int) => {
|
36
|
+
let nextPtr = skipWhileUnchanged(plainText, startPtr, startPtr + 1);
|
37
|
+
let chunkLength = nextPtr - startPtr;
|
38
|
+
let chunkChar = plainText.[startPtr];
|
39
|
+
let chunked = if(chunkLength == 1) {
|
40
|
+
String.make(1, chunkChar)
|
41
|
+
} else {
|
42
|
+
string_of_int(chunkLength) ++ String.make(1, chunkChar)
|
43
|
+
};
|
44
|
+
(nextPtr, chunked);
|
45
|
+
};
|
46
|
+
|
47
|
+
let expand = (rleText: string, startPtr: int) => {
|
48
|
+
let firstChar = rleText.[startPtr];
|
49
|
+
let (nextPtr, size) = if(isDigit(firstChar)) {
|
50
|
+
toInt(rleText, startPtr, 0)
|
51
|
+
} else {
|
52
|
+
(startPtr, 1)
|
53
|
+
};
|
54
|
+
let expansionChar = rleText.[nextPtr];
|
55
|
+
(nextPtr + 1, String.make(size, expansionChar))
|
56
|
+
};
|
57
|
+
|
58
|
+
let encode = unfoldString(0, "", chunk);
|
59
|
+
|
60
|
+
let decode = unfoldString(0, "", expand);
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Space Age
|
2
|
+
|
3
|
+
Given an age in seconds, calculate how old someone would be on:
|
4
|
+
|
5
|
+
- Earth: orbital period 365.25 Earth days, or 31557600 seconds
|
6
|
+
- Mercury: orbital period 0.2408467 Earth years
|
7
|
+
- Venus: orbital period 0.61519726 Earth years
|
8
|
+
- Mars: orbital period 1.8808158 Earth years
|
9
|
+
- Jupiter: orbital period 11.862615 Earth years
|
10
|
+
- Saturn: orbital period 29.447498 Earth years
|
11
|
+
- Uranus: orbital period 84.016846 Earth years
|
12
|
+
- Neptune: orbital period 164.79132 Earth years
|
13
|
+
|
14
|
+
So if you were told someone were 1,000,000,000 seconds old, you should
|
15
|
+
be able to say that they're 31.69 Earth-years old.
|
16
|
+
|
17
|
+
If you're wondering why Pluto didn't make the cut, go watch [this
|
18
|
+
youtube video](http://www.youtube.com/watch?v=Z_2gbGXzFbs).
|
19
|
+
|
20
|
+
# Build + Watch
|
21
|
+
|
22
|
+
```
|
23
|
+
npm start
|
24
|
+
```
|
25
|
+
|
26
|
+
# Test + Watch
|
27
|
+
|
28
|
+
```
|
29
|
+
npm test
|
30
|
+
```
|