trackler 2.2.1.74 → 2.2.1.75
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/fixtures/tracks/fruit/docs/something.md +0 -0
- data/lib/trackler/version.rb +1 -1
- data/problem-specifications/README.md +8 -4
- data/problem-specifications/exercises/acronym/canonical-data.json +19 -7
- data/problem-specifications/exercises/all-your-base/canonical-data.json +106 -64
- data/problem-specifications/exercises/allergies/canonical-data.json +37 -13
- data/tracks/c/config.json +176 -176
- data/tracks/clojure/config.json +17 -1
- data/tracks/clojure/exercises/isbn-verifier/README.md +43 -0
- data/tracks/clojure/exercises/isbn-verifier/project.clj +4 -0
- data/tracks/clojure/exercises/isbn-verifier/src/example.clj +17 -0
- data/tracks/clojure/exercises/isbn-verifier/src/isbn_verifier.clj +3 -0
- data/tracks/clojure/exercises/isbn-verifier/test/isbn_verifier_test.clj +42 -0
- data/tracks/clojure/exercises/proverb/README.md +15 -0
- data/tracks/clojure/exercises/proverb/project.clj +4 -0
- data/tracks/clojure/exercises/proverb/src/example.clj +15 -0
- data/tracks/clojure/exercises/proverb/src/proverb.clj +3 -0
- data/tracks/clojure/exercises/proverb/test/proverb_test.clj +14 -0
- data/tracks/common-lisp/docs/LEARNING.md +4 -3
- data/tracks/common-lisp/docs/RESOURCES.md +11 -0
- data/tracks/delphi/.gitignore +1 -0
- data/tracks/delphi/config.json +24 -0
- data/tracks/delphi/docs/INSTALLATION.md +1 -1
- data/tracks/delphi/exercises/isbn-verifier/ISBNVerifier.dpr +60 -0
- data/tracks/delphi/exercises/isbn-verifier/README.md +68 -0
- data/tracks/delphi/exercises/isbn-verifier/uISBNVerifierExample.pas +46 -0
- data/tracks/delphi/exercises/isbn-verifier/uTestISBNVerifier.pas +136 -0
- data/tracks/delphi/exercises/secret-handshake/README.md +56 -0
- data/tracks/delphi/exercises/secret-handshake/SecretHandshake.dpr +60 -0
- data/tracks/delphi/exercises/secret-handshake/uSecretHandshakeExample.pas +56 -0
- data/tracks/delphi/exercises/secret-handshake/uTestSecretHandshake.pas +215 -0
- data/tracks/ecmascript/docs/ABOUT.md +13 -9
- data/tracks/factor/exercises/two-fer/README.md +1 -1
- data/tracks/fsharp/docs/RESOURCES.md +1 -1
- data/tracks/fsharp/generators/{Input.fs → CanonicalData.fs} +5 -10
- data/tracks/fsharp/generators/Exercise.fs +11 -10
- data/tracks/fsharp/generators/{Output.fs → Formatting.fs} +2 -56
- data/tracks/fsharp/generators/Generators.fs +93 -93
- data/tracks/fsharp/generators/Generators.fsproj +9 -4
- data/tracks/fsharp/generators/Options.fs +1 -1
- data/tracks/fsharp/generators/Program.fs +3 -3
- data/tracks/fsharp/generators/Rendering.fs +57 -0
- data/tracks/go/exercises/all-your-base/.meta/gen.go +80 -0
- data/tracks/go/exercises/all-your-base/.meta/hints.md +13 -0
- data/tracks/go/exercises/all-your-base/README.md +16 -1
- data/tracks/go/exercises/all-your-base/all_your_base_test.go +12 -163
- data/tracks/go/exercises/all-your-base/cases_test.go +183 -0
- data/tracks/go/exercises/all-your-base/example.go +25 -29
- data/tracks/java/CONTRIBUTING.md +1 -1
- data/tracks/java/POLICIES.md +15 -1
- data/tracks/java/exercises/flatten-array/.meta/hints.md +58 -0
- data/tracks/java/exercises/flatten-array/README.md +62 -0
- data/tracks/java/exercises/hamming/src/main/java/Hamming.java +1 -1
- data/tracks/java/exercises/matrix/.meta/src/reference/java/Matrix.java +6 -6
- data/tracks/java/exercises/meetup/.meta/src/reference/java/Meetup.java +2 -2
- data/tracks/java/exercises/meetup/.meta/src/reference/java/MeetupSchedule.java +1 -1
- data/tracks/java/exercises/meetup/src/main/java/MeetupSchedule.java +1 -1
- data/tracks/java/exercises/pig-latin/.meta/hints.md +58 -0
- data/tracks/java/exercises/pig-latin/README.md +61 -0
- data/tracks/java/exercises/reverse-string/src/main/java/ReverseString.java +2 -2
- data/tracks/java/exercises/secret-handshake/README.md +1 -1
- data/tracks/javascript/.eslintignore +0 -3
- data/tracks/javascript/exercises/food-chain/example.js +50 -37
- data/tracks/javascript/exercises/octal/example.js +1 -1
- data/tracks/javascript/exercises/robot-name/robot-name.spec.js +7 -7
- data/tracks/javascript/package-lock.json +1846 -0
- data/tracks/python/docs/EXERCISE_README_INSERT.md +15 -0
- data/tracks/python/exercises/accumulate/README.md +15 -0
- data/tracks/python/exercises/acronym/README.md +15 -0
- data/tracks/python/exercises/all-your-base/README.md +15 -0
- data/tracks/python/exercises/all-your-base/all_your_base_test.py +19 -9
- data/tracks/python/exercises/allergies/README.md +15 -0
- data/tracks/python/exercises/alphametics/README.md +15 -0
- data/tracks/python/exercises/anagram/README.md +15 -0
- data/tracks/python/exercises/atbash-cipher/README.md +15 -0
- data/tracks/python/exercises/beer-song/README.md +16 -1
- data/tracks/python/exercises/binary-search-tree/README.md +16 -2
- data/tracks/python/exercises/binary-search/README.md +15 -0
- data/tracks/python/exercises/binary-search/binary_search_test.py +14 -4
- data/tracks/python/exercises/binary/README.md +15 -0
- data/tracks/python/exercises/binary/binary_test.py +14 -4
- data/tracks/python/exercises/bob/README.md +15 -0
- data/tracks/python/exercises/book-store/README.md +15 -0
- data/tracks/python/exercises/bracket-push/README.md +15 -0
- data/tracks/python/exercises/change/README.md +15 -0
- data/tracks/python/exercises/circular-buffer/README.md +15 -0
- data/tracks/python/exercises/circular-buffer/circular_buffer_test.py +15 -5
- data/tracks/python/exercises/circular-buffer/example.py +2 -2
- data/tracks/python/exercises/clock/README.md +15 -0
- data/tracks/python/exercises/collatz-conjecture/.meta/hints.md +1 -1
- data/tracks/python/exercises/collatz-conjecture/README.md +15 -0
- data/tracks/python/exercises/complex-numbers/README.md +15 -0
- data/tracks/python/exercises/connect/README.md +18 -3
- data/tracks/python/exercises/crypto-square/README.md +15 -0
- data/tracks/python/exercises/diamond/README.md +15 -0
- data/tracks/python/exercises/difference-of-squares/README.md +15 -0
- data/tracks/python/exercises/diffie-hellman/README.md +14 -0
- data/tracks/python/exercises/dominoes/README.md +16 -1
- data/tracks/python/exercises/error-handling/README.md +17 -0
- data/tracks/python/exercises/error-handling/error_handling_test.py +13 -3
- data/tracks/python/exercises/error-handling/example.py +1 -1
- data/tracks/python/exercises/etl/README.md +16 -1
- data/tracks/python/exercises/flatten-array/README.md +15 -0
- data/tracks/python/exercises/food-chain/README.md +15 -0
- data/tracks/python/exercises/forth/README.md +15 -0
- data/tracks/python/exercises/forth/example.py +7 -9
- data/tracks/python/exercises/forth/forth_test.py +107 -17
- data/tracks/python/exercises/gigasecond/README.md +15 -0
- data/tracks/python/exercises/go-counting/README.md +21 -3
- data/tracks/python/exercises/grade-school/README.md +15 -0
- data/tracks/python/exercises/grains/README.md +15 -0
- data/tracks/python/exercises/grains/grains_test.py +16 -6
- data/tracks/python/exercises/grep/README.md +15 -0
- data/tracks/python/exercises/hamming/README.md +15 -0
- data/tracks/python/exercises/hamming/hamming_test.py +12 -2
- data/tracks/python/exercises/hello-world/README.md +15 -0
- data/tracks/python/exercises/hexadecimal/README.md +15 -0
- data/tracks/python/exercises/hexadecimal/hexadecimal_test.py +11 -1
- data/tracks/python/exercises/house/README.md +16 -1
- data/tracks/python/exercises/isogram/README.md +15 -0
- data/tracks/python/exercises/kindergarten-garden/README.md +18 -3
- data/tracks/python/exercises/largest-series-product/README.md +15 -0
- data/tracks/python/exercises/largest-series-product/largest_series_product_test.py +14 -4
- data/tracks/python/exercises/leap/README.md +15 -0
- data/tracks/python/exercises/linked-list/README.md +15 -0
- data/tracks/python/exercises/list-ops/README.md +15 -0
- data/tracks/python/exercises/luhn/README.md +15 -0
- data/tracks/python/exercises/markdown/README.md +18 -0
- data/tracks/python/exercises/matrix/README.md +15 -0
- data/tracks/python/exercises/meetup/README.md +31 -12
- data/tracks/python/exercises/meetup/meetup_test.py +11 -1
- data/tracks/python/exercises/minesweeper/README.md +15 -0
- data/tracks/python/exercises/minesweeper/minesweeper_test.py +12 -2
- data/tracks/python/exercises/nth-prime/README.md +15 -0
- data/tracks/python/exercises/nth-prime/nth_prime_test.py +11 -1
- data/tracks/python/exercises/nucleotide-count/README.md +17 -2
- data/tracks/python/exercises/nucleotide-count/nucleotide_count_test.py +11 -1
- data/tracks/python/exercises/ocr-numbers/README.md +16 -1
- data/tracks/python/exercises/ocr-numbers/ocr_numbers_test.py +12 -2
- data/tracks/python/exercises/octal/README.md +15 -0
- data/tracks/python/exercises/octal/octal_test.py +16 -3
- data/tracks/python/exercises/palindrome-products/README.md +16 -1
- data/tracks/python/exercises/pangram/README.md +15 -0
- data/tracks/python/exercises/pascals-triangle/README.md +16 -1
- data/tracks/python/exercises/perfect-numbers/README.md +15 -0
- data/tracks/python/exercises/perfect-numbers/perfect_numbers_test.py +13 -3
- data/tracks/python/exercises/phone-number/README.md +16 -2
- data/tracks/python/exercises/phone-number/example.py +1 -1
- data/tracks/python/exercises/phone-number/phone_number_test.py +17 -7
- data/tracks/python/exercises/pig-latin/README.md +15 -0
- data/tracks/python/exercises/point-mutations/README.md +15 -0
- data/tracks/python/exercises/poker/README.md +15 -0
- data/tracks/python/exercises/pov/README.md +20 -2
- data/tracks/python/exercises/pov/example.py +2 -2
- data/tracks/python/exercises/pov/pov_test.py +15 -5
- data/tracks/python/exercises/prime-factors/README.md +15 -0
- data/tracks/python/exercises/protein-translation/README.md +15 -0
- data/tracks/python/exercises/protein-translation/protein_translation_test.py +10 -0
- data/tracks/python/exercises/proverb/README.md +14 -0
- data/tracks/python/exercises/pythagorean-triplet/README.md +15 -0
- data/tracks/python/exercises/pythagorean-triplet/pythagorean_triplet_test.py +11 -1
- data/tracks/python/exercises/queen-attack/README.md +15 -0
- data/tracks/python/exercises/queen-attack/queen_attack_test.py +17 -7
- data/tracks/python/exercises/rail-fence-cipher/README.md +15 -0
- data/tracks/python/exercises/raindrops/README.md +15 -0
- data/tracks/python/exercises/react/README.md +15 -1
- data/tracks/python/exercises/rectangles/README.md +24 -9
- data/tracks/python/exercises/rna-transcription/.meta/hints.md +1 -0
- data/tracks/python/exercises/rna-transcription/README.md +18 -5
- data/tracks/python/exercises/rna-transcription/rna_transcription_test.py +13 -3
- data/tracks/python/exercises/robot-name/README.md +15 -0
- data/tracks/python/exercises/robot-simulator/README.md +15 -0
- data/tracks/python/exercises/roman-numerals/README.md +15 -0
- data/tracks/python/exercises/rotational-cipher/README.md +15 -0
- data/tracks/python/exercises/run-length-encoding/README.md +15 -0
- data/tracks/python/exercises/saddle-points/README.md +15 -0
- data/tracks/python/exercises/saddle-points/saddle_points_test.py +11 -1
- data/tracks/python/exercises/say/README.md +15 -0
- data/tracks/python/exercises/say/say_test.py +12 -2
- data/tracks/python/exercises/scale-generator/README.md +15 -0
- data/tracks/python/exercises/scale-generator/example.py +3 -3
- data/tracks/python/exercises/scale-generator/scale_generator_test.py +11 -1
- data/tracks/python/exercises/scrabble-score/README.md +15 -0
- data/tracks/python/exercises/secret-handshake/README.md +16 -1
- data/tracks/python/exercises/series/README.md +15 -0
- data/tracks/python/exercises/series/series_test.py +12 -2
- data/tracks/python/exercises/sieve/README.md +15 -0
- data/tracks/python/exercises/simple-cipher/.meta/hints.md +6 -6
- data/tracks/python/exercises/simple-cipher/README.md +17 -1
- data/tracks/python/exercises/simple-cipher/simple_cipher_test.py +12 -2
- data/tracks/python/exercises/simple-linked-list/{hints.md → .meta/hints.md} +10 -10
- data/tracks/python/exercises/simple-linked-list/README.md +16 -0
- data/tracks/python/exercises/simple-linked-list/example.py +2 -2
- data/tracks/python/exercises/simple-linked-list/simple_linked_list_test.py +13 -3
- data/tracks/python/exercises/space-age/README.md +15 -0
- data/tracks/python/exercises/strain/README.md +16 -3
- data/tracks/python/exercises/sublist/README.md +15 -0
- data/tracks/python/exercises/sum-of-multiples/README.md +18 -3
- data/tracks/python/exercises/tournament/README.md +15 -0
- data/tracks/python/exercises/transpose/README.md +15 -0
- data/tracks/python/exercises/tree-building/README.md +30 -0
- data/tracks/python/exercises/tree-building/example.py +3 -5
- data/tracks/python/exercises/tree-building/tree_building_test.py +16 -6
- data/tracks/python/exercises/triangle/README.md +15 -0
- data/tracks/python/exercises/triangle/example.py +1 -1
- data/tracks/python/exercises/triangle/triangle_test.py +15 -5
- data/tracks/python/exercises/trinary/README.md +15 -0
- data/tracks/python/exercises/twelve-days/README.md +15 -0
- data/tracks/python/exercises/two-bucket/README.md +22 -7
- data/tracks/python/exercises/two-fer/README.md +16 -0
- data/tracks/python/exercises/variable-length-quantity/README.md +15 -0
- data/tracks/python/exercises/variable-length-quantity/variable_length_quantity_test.py +12 -2
- data/tracks/python/exercises/word-count/README.md +15 -0
- data/tracks/python/exercises/word-search/README.md +15 -0
- data/tracks/python/exercises/wordy/README.md +15 -0
- data/tracks/python/exercises/wordy/wordy_test.py +14 -4
- data/tracks/python/exercises/zebra-puzzle/README.md +15 -0
- data/tracks/python/exercises/zipper/README.md +16 -3
- data/tracks/rust/config.json +11 -0
- data/tracks/rust/exercises/saddle-points/.gitignore +8 -0
- data/tracks/rust/exercises/saddle-points/Cargo.toml +5 -0
- data/tracks/rust/exercises/saddle-points/README.md +66 -0
- data/tracks/rust/exercises/saddle-points/example.rs +24 -0
- data/tracks/rust/exercises/saddle-points/src/lib.rs +3 -0
- data/tracks/rust/exercises/saddle-points/tests/saddle-points.rs +60 -0
- metadata +38 -5
@@ -8,8 +8,9 @@
|
|
8
8
|
<ItemGroup>
|
9
9
|
<Compile Include="Common.fs" />
|
10
10
|
<Compile Include="Options.fs" />
|
11
|
-
<Compile Include="
|
12
|
-
<Compile Include="
|
11
|
+
<Compile Include="CanonicalData.fs" />
|
12
|
+
<Compile Include="Formatting.fs" />
|
13
|
+
<Compile Include="Rendering.fs" />
|
13
14
|
<Compile Include="Exercise.fs" />
|
14
15
|
<Compile Include="Generators.fs" />
|
15
16
|
<Compile Include="Program.fs" />
|
@@ -21,12 +22,16 @@
|
|
21
22
|
|
22
23
|
<ItemGroup>
|
23
24
|
<PackageReference Include="CommandLineParser" Version="2.1.1-beta" />
|
24
|
-
<PackageReference Include="DotLiquid" Version="2.0.
|
25
|
+
<PackageReference Include="DotLiquid" Version="2.0.232" />
|
25
26
|
<PackageReference Include="Humanizer" Version="2.2.0" />
|
26
27
|
<PackageReference Include="LibGit2Sharp.Portable" Version="0.24.10" />
|
27
28
|
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
28
|
-
<PackageReference Include="serilog" Version="2.
|
29
|
+
<PackageReference Include="serilog" Version="2.6.0" />
|
29
30
|
<PackageReference Include="serilog.sinks.literate" Version="3.0.0" />
|
30
31
|
</ItemGroup>
|
31
32
|
|
33
|
+
<ItemGroup>
|
34
|
+
<PackageReference Update="FSharp.Core" Version="4.2.3" />
|
35
|
+
</ItemGroup>
|
36
|
+
|
32
37
|
</Project>
|
@@ -26,4 +26,4 @@ let parseOptions argv =
|
|
26
26
|
match result with
|
27
27
|
| :? Parsed<Options> as parsed -> Result.Ok(normalizeOptions parsed.Value)
|
28
28
|
| :? NotParsed<Options> as notParsed -> Result.Error(notParsed.Errors |> Seq.map string)
|
29
|
-
| _ -> Result.Error(
|
29
|
+
| _ -> Result.Error(Seq.singleton "Invalid parsing result")
|
@@ -2,17 +2,17 @@
|
|
2
2
|
|
3
3
|
open Serilog
|
4
4
|
open Exercise
|
5
|
-
open
|
5
|
+
open CanonicalData
|
6
6
|
open Options
|
7
7
|
|
8
|
-
let regenerateTestClass options =
|
8
|
+
let private regenerateTestClass options =
|
9
9
|
let parseCanonicalData' = parseCanonicalData options
|
10
10
|
|
11
11
|
fun (exercise: Exercise) ->
|
12
12
|
let canonicalData = parseCanonicalData' exercise.Name
|
13
13
|
exercise.Regenerate(canonicalData)
|
14
14
|
|
15
|
-
let regenerateTestClasses options =
|
15
|
+
let private regenerateTestClasses options =
|
16
16
|
Log.Information("Re-generating test classes...")
|
17
17
|
|
18
18
|
let regenerateTestClass' = regenerateTestClass options
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Generators.Rendering
|
2
|
+
|
3
|
+
open System.Collections.Generic
|
4
|
+
open System.Reflection
|
5
|
+
open FSharp.Reflection
|
6
|
+
open DotLiquid
|
7
|
+
open DotLiquid.FileSystems
|
8
|
+
open Formatting
|
9
|
+
|
10
|
+
type OutputFilter() =
|
11
|
+
static member Format (input: string) = formatValue input
|
12
|
+
|
13
|
+
static member Indent (input: string) = indent 1 input
|
14
|
+
|
15
|
+
let private fileSystem = EmbeddedFileSystem(Assembly.GetExecutingAssembly(), "Generators.Templates")
|
16
|
+
Template.RegisterFilter(OutputFilter().GetType())
|
17
|
+
Template.FileSystem <- fileSystem :> DotLiquid.FileSystems.IFileSystem
|
18
|
+
|
19
|
+
let private registrations = Dictionary<_,_>()
|
20
|
+
let rec private registerTypeTree templateDataType =
|
21
|
+
if registrations.ContainsKey templateDataType then ()
|
22
|
+
elif FSharpType.IsRecord templateDataType then
|
23
|
+
let properties = templateDataType.GetProperties(BindingFlags.Instance ||| BindingFlags.Public)
|
24
|
+
Template.RegisterSafeType(templateDataType, [| for p in properties -> p.Name |])
|
25
|
+
registrations.[templateDataType] <- true
|
26
|
+
for p in properties do registerTypeTree p.PropertyType
|
27
|
+
elif templateDataType.IsGenericType then
|
28
|
+
let t = templateDataType.GetGenericTypeDefinition()
|
29
|
+
if t = typedefof<seq<_>> || t = typedefof<list<_>> then
|
30
|
+
registrations.[templateDataType] <- true
|
31
|
+
registerTypeTree (templateDataType.GetGenericArguments().[0])
|
32
|
+
elif t = typedefof<IDictionary<_,_>> || t = typedefof<Map<_,_>> then
|
33
|
+
registrations.[templateDataType] <- true
|
34
|
+
registerTypeTree (templateDataType.GetGenericArguments().[0])
|
35
|
+
registerTypeTree (templateDataType.GetGenericArguments().[1])
|
36
|
+
elif t = typedefof<option<_>> then
|
37
|
+
Template.RegisterSafeType(templateDataType, [|"Value"; "IsSome"; "IsNone";|])
|
38
|
+
registrations.[templateDataType] <- true
|
39
|
+
registerTypeTree (templateDataType.GetGenericArguments().[0])
|
40
|
+
elif templateDataType.IsArray then
|
41
|
+
registrations.[templateDataType] <- true
|
42
|
+
registerTypeTree (templateDataType.GetElementType())
|
43
|
+
else
|
44
|
+
let properties = templateDataType.GetProperties(BindingFlags.Instance ||| BindingFlags.Public)
|
45
|
+
Template.RegisterSafeType(templateDataType, [| for p in properties -> p.Name |])
|
46
|
+
registrations.[templateDataType] <- true
|
47
|
+
for p in properties do registerTypeTree p.PropertyType
|
48
|
+
|
49
|
+
let renderInlineTemplate template data =
|
50
|
+
data.GetType() |> registerTypeTree
|
51
|
+
|
52
|
+
let parsedTemplate = Template.Parse template
|
53
|
+
parsedTemplate.Render(Hash.FromAnonymousObject(data))
|
54
|
+
|
55
|
+
let renderPartialTemplate templateName data =
|
56
|
+
let template = sprintf "{%% include \"%s\" %%}" templateName
|
57
|
+
renderInlineTemplate template data
|
@@ -0,0 +1,80 @@
|
|
1
|
+
package main
|
2
|
+
|
3
|
+
import (
|
4
|
+
"log"
|
5
|
+
"text/template"
|
6
|
+
|
7
|
+
"../../../gen"
|
8
|
+
)
|
9
|
+
|
10
|
+
func main() {
|
11
|
+
t, err := template.New("").Parse(tmpl)
|
12
|
+
if err != nil {
|
13
|
+
log.Fatal(err)
|
14
|
+
}
|
15
|
+
var j js
|
16
|
+
if err := gen.Gen("all-your-base", &j, t); err != nil {
|
17
|
+
log.Fatal(err)
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
// The JSON structure we expect to be able to unmarshal into
|
22
|
+
type js struct {
|
23
|
+
Exercise string
|
24
|
+
Version string
|
25
|
+
Cases []oneCase
|
26
|
+
}
|
27
|
+
|
28
|
+
// Test cases
|
29
|
+
type oneCase struct {
|
30
|
+
Description string
|
31
|
+
Property string
|
32
|
+
InputBase int `json:"input_base"`
|
33
|
+
InputDigits []int `json:"input_digits"`
|
34
|
+
OutputBase int `json:"output_base"`
|
35
|
+
Expected interface{}
|
36
|
+
}
|
37
|
+
|
38
|
+
func (o oneCase) Result() []int {
|
39
|
+
s, ok := o.Expected.([]interface{})
|
40
|
+
if !ok {
|
41
|
+
return nil
|
42
|
+
}
|
43
|
+
var res []int
|
44
|
+
for _, v := range s {
|
45
|
+
f, _ := v.(float64)
|
46
|
+
res = append(res, int(f))
|
47
|
+
}
|
48
|
+
return res
|
49
|
+
}
|
50
|
+
func (o oneCase) Err() string {
|
51
|
+
m, ok := o.Expected.(map[string]interface{})
|
52
|
+
if !ok {
|
53
|
+
return ""
|
54
|
+
}
|
55
|
+
return m["error"].(string)
|
56
|
+
}
|
57
|
+
|
58
|
+
// Template to generate test cases.
|
59
|
+
var tmpl = `package allyourbase
|
60
|
+
|
61
|
+
{{.Header}}
|
62
|
+
|
63
|
+
var testCases = []struct {
|
64
|
+
description string
|
65
|
+
inputBase int
|
66
|
+
inputDigits []int
|
67
|
+
outputBase int
|
68
|
+
expected []int
|
69
|
+
err string
|
70
|
+
}{ {{range .J.Cases}}
|
71
|
+
{
|
72
|
+
description: {{printf "%q" .Description}},
|
73
|
+
inputBase: {{printf "%d" .InputBase}},
|
74
|
+
inputDigits: {{printf "%#v" .InputDigits}},
|
75
|
+
outputBase: {{printf "%d" .OutputBase}},
|
76
|
+
expected: {{printf "%#v" .Result}},
|
77
|
+
err: {{printf "%q" .Err}},
|
78
|
+
},{{end}}
|
79
|
+
}
|
80
|
+
`
|
@@ -0,0 +1,13 @@
|
|
1
|
+
## Implementation
|
2
|
+
|
3
|
+
Assumptions:
|
4
|
+
1. Zero is always represented in outputs as [0] instead of [].
|
5
|
+
2. In no other instances are leading zeroes present in any outputs.
|
6
|
+
3. Leading zeroes are accepted in inputs.
|
7
|
+
4. An empty sequence of input digits is considered zero, rather than an error.
|
8
|
+
|
9
|
+
Handle problem cases by returning an error whose Error() method
|
10
|
+
returns one of following messages:
|
11
|
+
* input base must be >= 2
|
12
|
+
* output base must be >= 2
|
13
|
+
* all digits must satisfy 0 <= d < input base
|
@@ -6,6 +6,7 @@ Implement general base conversion. Given a number in base **a**,
|
|
6
6
|
represented as a sequence of digits, convert it to base **b**.
|
7
7
|
|
8
8
|
## Note
|
9
|
+
|
9
10
|
- Try to implement the conversion yourself.
|
10
11
|
Do not use something else to perform the conversion for you.
|
11
12
|
|
@@ -28,9 +29,23 @@ The number 1120, *in base 3*, means:
|
|
28
29
|
|
29
30
|
I think you got the idea!
|
30
31
|
|
31
|
-
|
32
32
|
*Yes. Those three numbers above are exactly the same. Congratulations!*
|
33
33
|
|
34
|
+
## Implementation
|
35
|
+
|
36
|
+
Assumptions:
|
37
|
+
1. Zero is always represented in outputs as [0] instead of [].
|
38
|
+
2. In no other instances are leading zeroes present in any outputs.
|
39
|
+
3. Leading zeroes are accepted in inputs.
|
40
|
+
4. An empty sequence of input digits is considered zero, rather than an error.
|
41
|
+
|
42
|
+
Handle problem cases by returning an error whose Error() method
|
43
|
+
returns one of following messages:
|
44
|
+
* input base must be >= 2
|
45
|
+
* output base must be >= 2
|
46
|
+
* all digits must satisfy 0 <= d < input base
|
47
|
+
|
48
|
+
|
34
49
|
## Running the tests
|
35
50
|
|
36
51
|
To run the tests run the command `go test` from within the exercise directory.
|
@@ -1,177 +1,26 @@
|
|
1
1
|
package allyourbase
|
2
2
|
|
3
|
-
import
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
// Exception: If the value of the output is zero, represent it with a single zero.
|
8
|
-
var testCases = []struct {
|
9
|
-
description string
|
10
|
-
inputBase uint64
|
11
|
-
outputBase uint64
|
12
|
-
inputDigits []uint64
|
13
|
-
outputDigits []uint64
|
14
|
-
error error
|
15
|
-
}{
|
16
|
-
{
|
17
|
-
description: "single bit one to decimal",
|
18
|
-
inputBase: 2,
|
19
|
-
inputDigits: []uint64{1},
|
20
|
-
outputBase: 10,
|
21
|
-
outputDigits: []uint64{1},
|
22
|
-
},
|
23
|
-
{
|
24
|
-
description: "binary to single decimal",
|
25
|
-
inputBase: 2,
|
26
|
-
inputDigits: []uint64{1, 0, 1},
|
27
|
-
outputBase: 10,
|
28
|
-
outputDigits: []uint64{5},
|
29
|
-
},
|
30
|
-
{
|
31
|
-
description: "single decimal to binary",
|
32
|
-
inputBase: 10,
|
33
|
-
inputDigits: []uint64{5},
|
34
|
-
outputBase: 2,
|
35
|
-
outputDigits: []uint64{1, 0, 1},
|
36
|
-
},
|
37
|
-
{
|
38
|
-
description: "binary to multiple decimal",
|
39
|
-
inputBase: 2,
|
40
|
-
inputDigits: []uint64{1, 0, 1, 0, 1, 0},
|
41
|
-
outputBase: 10,
|
42
|
-
outputDigits: []uint64{4, 2},
|
43
|
-
},
|
44
|
-
{
|
45
|
-
description: "decimal to binary",
|
46
|
-
inputBase: 10,
|
47
|
-
inputDigits: []uint64{4, 2},
|
48
|
-
outputBase: 2,
|
49
|
-
outputDigits: []uint64{1, 0, 1, 0, 1, 0},
|
50
|
-
},
|
51
|
-
{
|
52
|
-
description: "trinary to hexadecimal",
|
53
|
-
inputBase: 3,
|
54
|
-
inputDigits: []uint64{1, 1, 2, 0},
|
55
|
-
outputBase: 16,
|
56
|
-
outputDigits: []uint64{2, 10},
|
57
|
-
},
|
58
|
-
{
|
59
|
-
description: "hexadecimal to trinary",
|
60
|
-
inputBase: 16,
|
61
|
-
inputDigits: []uint64{2, 10},
|
62
|
-
outputBase: 3,
|
63
|
-
outputDigits: []uint64{1, 1, 2, 0},
|
64
|
-
},
|
65
|
-
{
|
66
|
-
description: "15-bit integer",
|
67
|
-
inputBase: 97,
|
68
|
-
inputDigits: []uint64{3, 46, 60},
|
69
|
-
outputBase: 73,
|
70
|
-
outputDigits: []uint64{6, 10, 45},
|
71
|
-
},
|
72
|
-
{
|
73
|
-
description: "empty list",
|
74
|
-
inputBase: 2,
|
75
|
-
inputDigits: []uint64{},
|
76
|
-
outputBase: 10,
|
77
|
-
outputDigits: []uint64{0},
|
78
|
-
error: nil,
|
79
|
-
},
|
80
|
-
{
|
81
|
-
description: "single zero",
|
82
|
-
inputBase: 10,
|
83
|
-
inputDigits: []uint64{0},
|
84
|
-
outputBase: 2,
|
85
|
-
outputDigits: []uint64{0},
|
86
|
-
},
|
87
|
-
{
|
88
|
-
description: "multiple zeros",
|
89
|
-
inputBase: 10,
|
90
|
-
inputDigits: []uint64{0, 0, 0},
|
91
|
-
outputBase: 2,
|
92
|
-
outputDigits: []uint64{0},
|
93
|
-
},
|
94
|
-
{
|
95
|
-
description: "leading zeros",
|
96
|
-
inputBase: 7,
|
97
|
-
inputDigits: []uint64{0, 6, 0},
|
98
|
-
outputBase: 10,
|
99
|
-
outputDigits: []uint64{4, 2},
|
100
|
-
},
|
101
|
-
{
|
102
|
-
description: "invalid positive digit",
|
103
|
-
inputBase: 2,
|
104
|
-
inputDigits: []uint64{1, 2, 1, 0, 1, 0},
|
105
|
-
outputBase: 10,
|
106
|
-
outputDigits: nil,
|
107
|
-
error: ErrInvalidDigit,
|
108
|
-
},
|
109
|
-
{
|
110
|
-
description: "first base is one",
|
111
|
-
inputBase: 1,
|
112
|
-
inputDigits: []uint64{},
|
113
|
-
outputBase: 10,
|
114
|
-
outputDigits: nil,
|
115
|
-
error: ErrInvalidBase,
|
116
|
-
},
|
117
|
-
{
|
118
|
-
description: "second base is one",
|
119
|
-
inputBase: 2,
|
120
|
-
inputDigits: []uint64{1, 0, 1, 0, 1, 0},
|
121
|
-
outputBase: 1,
|
122
|
-
outputDigits: nil,
|
123
|
-
error: ErrInvalidBase,
|
124
|
-
},
|
125
|
-
{
|
126
|
-
description: "first base is zero",
|
127
|
-
inputBase: 0,
|
128
|
-
inputDigits: []uint64{},
|
129
|
-
outputBase: 10,
|
130
|
-
outputDigits: nil,
|
131
|
-
error: ErrInvalidBase,
|
132
|
-
},
|
133
|
-
{
|
134
|
-
description: "second base is zero",
|
135
|
-
inputBase: 10,
|
136
|
-
inputDigits: []uint64{7},
|
137
|
-
outputBase: 0,
|
138
|
-
outputDigits: nil,
|
139
|
-
error: ErrInvalidBase,
|
140
|
-
},
|
141
|
-
}
|
142
|
-
|
143
|
-
func digitsEqual(a, b []uint64) bool {
|
144
|
-
if len(a) != len(b) {
|
145
|
-
return false
|
146
|
-
}
|
147
|
-
|
148
|
-
for i := 0; i < len(a); i++ {
|
149
|
-
if a[i] != b[i] {
|
150
|
-
return false
|
151
|
-
}
|
152
|
-
}
|
153
|
-
|
154
|
-
return true
|
155
|
-
}
|
3
|
+
import (
|
4
|
+
"reflect"
|
5
|
+
"testing"
|
6
|
+
)
|
156
7
|
|
157
8
|
func TestConvertToBase(t *testing.T) {
|
158
9
|
for _, c := range testCases {
|
159
10
|
output, err := ConvertToBase(c.inputBase, c.inputDigits, c.outputBase)
|
160
|
-
if err != c.
|
11
|
+
if c.err != "" && (err == nil || c.err != err.Error()) {
|
161
12
|
t.Fatalf(`FAIL: %s
|
162
|
-
Expected error: %
|
163
|
-
Got: %v`, c.description, c.
|
13
|
+
Expected error: %s
|
14
|
+
Got: %v`, c.description, c.err, err)
|
164
15
|
}
|
165
|
-
|
166
|
-
if !digitsEqual(c.outputDigits, output) {
|
16
|
+
if !reflect.DeepEqual(c.expected, output) {
|
167
17
|
t.Fatalf(`FAIL: %s
|
168
18
|
Input base: %d
|
169
|
-
Input digits:
|
19
|
+
Input digits: %#v
|
170
20
|
Output base: %d
|
171
|
-
Expected output digits:
|
172
|
-
Got:
|
173
|
-
} else {
|
174
|
-
t.Logf("PASS: %s", c.description)
|
21
|
+
Expected output digits: %#v
|
22
|
+
Got: %#v`, c.description, c.inputBase, c.inputDigits, c.outputBase, c.expected, output)
|
175
23
|
}
|
24
|
+
t.Logf("PASS: %s", c.description)
|
176
25
|
}
|
177
26
|
}
|
@@ -0,0 +1,183 @@
|
|
1
|
+
package allyourbase
|
2
|
+
|
3
|
+
// Source: exercism/problem-specifications
|
4
|
+
// Commit: ba6375e all-your-base: replace 'first' and 'second' with 'input' and 'output' in descriptions
|
5
|
+
// Problem Specifications Version: 2.0.1
|
6
|
+
|
7
|
+
var testCases = []struct {
|
8
|
+
description string
|
9
|
+
inputBase int
|
10
|
+
inputDigits []int
|
11
|
+
outputBase int
|
12
|
+
expected []int
|
13
|
+
err string
|
14
|
+
}{
|
15
|
+
{
|
16
|
+
description: "single bit one to decimal",
|
17
|
+
inputBase: 2,
|
18
|
+
inputDigits: []int{1},
|
19
|
+
outputBase: 10,
|
20
|
+
expected: []int{1},
|
21
|
+
err: "",
|
22
|
+
},
|
23
|
+
{
|
24
|
+
description: "binary to single decimal",
|
25
|
+
inputBase: 2,
|
26
|
+
inputDigits: []int{1, 0, 1},
|
27
|
+
outputBase: 10,
|
28
|
+
expected: []int{5},
|
29
|
+
err: "",
|
30
|
+
},
|
31
|
+
{
|
32
|
+
description: "single decimal to binary",
|
33
|
+
inputBase: 10,
|
34
|
+
inputDigits: []int{5},
|
35
|
+
outputBase: 2,
|
36
|
+
expected: []int{1, 0, 1},
|
37
|
+
err: "",
|
38
|
+
},
|
39
|
+
{
|
40
|
+
description: "binary to multiple decimal",
|
41
|
+
inputBase: 2,
|
42
|
+
inputDigits: []int{1, 0, 1, 0, 1, 0},
|
43
|
+
outputBase: 10,
|
44
|
+
expected: []int{4, 2},
|
45
|
+
err: "",
|
46
|
+
},
|
47
|
+
{
|
48
|
+
description: "decimal to binary",
|
49
|
+
inputBase: 10,
|
50
|
+
inputDigits: []int{4, 2},
|
51
|
+
outputBase: 2,
|
52
|
+
expected: []int{1, 0, 1, 0, 1, 0},
|
53
|
+
err: "",
|
54
|
+
},
|
55
|
+
{
|
56
|
+
description: "trinary to hexadecimal",
|
57
|
+
inputBase: 3,
|
58
|
+
inputDigits: []int{1, 1, 2, 0},
|
59
|
+
outputBase: 16,
|
60
|
+
expected: []int{2, 10},
|
61
|
+
err: "",
|
62
|
+
},
|
63
|
+
{
|
64
|
+
description: "hexadecimal to trinary",
|
65
|
+
inputBase: 16,
|
66
|
+
inputDigits: []int{2, 10},
|
67
|
+
outputBase: 3,
|
68
|
+
expected: []int{1, 1, 2, 0},
|
69
|
+
err: "",
|
70
|
+
},
|
71
|
+
{
|
72
|
+
description: "15-bit integer",
|
73
|
+
inputBase: 97,
|
74
|
+
inputDigits: []int{3, 46, 60},
|
75
|
+
outputBase: 73,
|
76
|
+
expected: []int{6, 10, 45},
|
77
|
+
err: "",
|
78
|
+
},
|
79
|
+
{
|
80
|
+
description: "empty list",
|
81
|
+
inputBase: 2,
|
82
|
+
inputDigits: []int{},
|
83
|
+
outputBase: 10,
|
84
|
+
expected: []int{0},
|
85
|
+
err: "",
|
86
|
+
},
|
87
|
+
{
|
88
|
+
description: "single zero",
|
89
|
+
inputBase: 10,
|
90
|
+
inputDigits: []int{0},
|
91
|
+
outputBase: 2,
|
92
|
+
expected: []int{0},
|
93
|
+
err: "",
|
94
|
+
},
|
95
|
+
{
|
96
|
+
description: "multiple zeros",
|
97
|
+
inputBase: 10,
|
98
|
+
inputDigits: []int{0, 0, 0},
|
99
|
+
outputBase: 2,
|
100
|
+
expected: []int{0},
|
101
|
+
err: "",
|
102
|
+
},
|
103
|
+
{
|
104
|
+
description: "leading zeros",
|
105
|
+
inputBase: 7,
|
106
|
+
inputDigits: []int{0, 6, 0},
|
107
|
+
outputBase: 10,
|
108
|
+
expected: []int{4, 2},
|
109
|
+
err: "",
|
110
|
+
},
|
111
|
+
{
|
112
|
+
description: "input base is one",
|
113
|
+
inputBase: 1,
|
114
|
+
inputDigits: []int{},
|
115
|
+
outputBase: 10,
|
116
|
+
expected: []int(nil),
|
117
|
+
err: "input base must be >= 2",
|
118
|
+
},
|
119
|
+
{
|
120
|
+
description: "input base is zero",
|
121
|
+
inputBase: 0,
|
122
|
+
inputDigits: []int{},
|
123
|
+
outputBase: 10,
|
124
|
+
expected: []int(nil),
|
125
|
+
err: "input base must be >= 2",
|
126
|
+
},
|
127
|
+
{
|
128
|
+
description: "input base is negative",
|
129
|
+
inputBase: -2,
|
130
|
+
inputDigits: []int{1},
|
131
|
+
outputBase: 10,
|
132
|
+
expected: []int(nil),
|
133
|
+
err: "input base must be >= 2",
|
134
|
+
},
|
135
|
+
{
|
136
|
+
description: "negative digit",
|
137
|
+
inputBase: 2,
|
138
|
+
inputDigits: []int{1, -1, 1, 0, 1, 0},
|
139
|
+
outputBase: 10,
|
140
|
+
expected: []int(nil),
|
141
|
+
err: "all digits must satisfy 0 <= d < input base",
|
142
|
+
},
|
143
|
+
{
|
144
|
+
description: "invalid positive digit",
|
145
|
+
inputBase: 2,
|
146
|
+
inputDigits: []int{1, 2, 1, 0, 1, 0},
|
147
|
+
outputBase: 10,
|
148
|
+
expected: []int(nil),
|
149
|
+
err: "all digits must satisfy 0 <= d < input base",
|
150
|
+
},
|
151
|
+
{
|
152
|
+
description: "output base is one",
|
153
|
+
inputBase: 2,
|
154
|
+
inputDigits: []int{1, 0, 1, 0, 1, 0},
|
155
|
+
outputBase: 1,
|
156
|
+
expected: []int(nil),
|
157
|
+
err: "output base must be >= 2",
|
158
|
+
},
|
159
|
+
{
|
160
|
+
description: "output base is zero",
|
161
|
+
inputBase: 10,
|
162
|
+
inputDigits: []int{7},
|
163
|
+
outputBase: 0,
|
164
|
+
expected: []int(nil),
|
165
|
+
err: "output base must be >= 2",
|
166
|
+
},
|
167
|
+
{
|
168
|
+
description: "output base is negative",
|
169
|
+
inputBase: 2,
|
170
|
+
inputDigits: []int{1},
|
171
|
+
outputBase: -7,
|
172
|
+
expected: []int(nil),
|
173
|
+
err: "output base must be >= 2",
|
174
|
+
},
|
175
|
+
{
|
176
|
+
description: "both bases are negative",
|
177
|
+
inputBase: -2,
|
178
|
+
inputDigits: []int{1},
|
179
|
+
outputBase: -7,
|
180
|
+
expected: []int(nil),
|
181
|
+
err: "input base must be >= 2",
|
182
|
+
},
|
183
|
+
}
|