trackler 2.2.1.174 → 2.2.1.175
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://travis-ci.org/exercism/javascript.svg?branch=master)](https://travis-ci.org/exercism/javascript)[![Join the chat at https://gitter.im/exercism/xecmascript](https://badges.gitter.im/exercism/xecmascript.svg)](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
|
+
```
|