trackler 2.1.0.8 → 2.1.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/.gitmodules +3 -0
  3. data/lib/trackler/version.rb +1 -1
  4. data/tracks/coq/.git +1 -0
  5. data/tracks/coq/.github/PULL_REQUEST_TEMPLATE.md +23 -0
  6. data/tracks/coq/.gitignore +4 -0
  7. data/tracks/coq/.travis.yml +5 -0
  8. data/tracks/coq/LICENSE +21 -0
  9. data/tracks/coq/README.md +84 -0
  10. data/tracks/coq/bin/fetch-configlet +32 -0
  11. data/tracks/coq/config.json +21 -0
  12. data/tracks/coq/docs/ABOUT.md +0 -0
  13. data/tracks/coq/docs/INSTALLATION.md +0 -0
  14. data/tracks/coq/docs/LEARNING.md +0 -0
  15. data/tracks/coq/docs/RESOURCES.md +0 -0
  16. data/tracks/coq/docs/TESTS.md +0 -0
  17. data/tracks/coq/exercises/TRACK_HINTS.md +0 -0
  18. data/tracks/coq/img/.keep +0 -0
  19. data/tracks/cpp/docs/INSTALLATION.md +1 -0
  20. data/tracks/go/exercises/phone-number/.meta/gen.go +82 -0
  21. data/tracks/go/exercises/phone-number/cases_test.go +91 -0
  22. data/tracks/go/exercises/phone-number/example.go +20 -18
  23. data/tracks/go/exercises/phone-number/phone_number_test.go +17 -52
  24. data/tracks/go/exercises/scrabble-score/.meta/gen.go +45 -0
  25. data/tracks/go/exercises/scrabble-score/cases_test.go +24 -0
  26. data/tracks/go/exercises/scrabble-score/example.go +1 -1
  27. data/tracks/go/exercises/scrabble-score/scrabble_score_test.go +3 -17
  28. data/tracks/java/exercises/binary-search-tree/src/test/java/BSTTest.java +2 -2
  29. data/tracks/java/exercises/change/src/test/java/ChangeCalculatorTest.java +8 -8
  30. data/tracks/java/exercises/clock/src/test/java/ClockAddTest.java +16 -16
  31. data/tracks/java/exercises/clock/src/test/java/ClockCreationTest.java +18 -18
  32. data/tracks/java/exercises/clock/src/test/java/ClockEqualTest.java +15 -15
  33. data/tracks/java/exercises/custom-set/src/test/java/CustomSetTest.java +36 -36
  34. data/tracks/java/exercises/diamond/src/test/java/DiamondPrinterTest.java +4 -4
  35. data/tracks/java/exercises/etl/src/test/java/EtlTest.java +3 -3
  36. data/tracks/java/exercises/flatten-array/src/test/java/FlattenerTest.java +5 -5
  37. data/tracks/java/exercises/grade-school/src/test/java/SchoolTest.java +7 -7
  38. data/tracks/java/exercises/hamming/src/test/java/HammingTest.java +8 -8
  39. data/tracks/java/exercises/isogram/src/test/java/IsogramCheckerTest.java +9 -9
  40. data/tracks/java/exercises/largest-series-product/src/test/java/LargestSeriesProductCalculatorTest.java +17 -17
  41. data/tracks/java/exercises/linked-list/src/test/java/DoublyLinkedListTest.java +4 -4
  42. data/tracks/java/exercises/list-ops/src/test/java/ListOpsTest.java +19 -19
  43. data/tracks/java/exercises/luhn/src/test/java/LuhnValidatorTest.java +12 -12
  44. data/tracks/java/exercises/matrix/src/test/java/MatrixTest.java +5 -5
  45. data/tracks/java/exercises/meetup/src/test/java/MeetupTest.java +90 -90
  46. data/tracks/java/exercises/minesweeper/src/test/java/MinesweeperBoardTest.java +14 -14
  47. data/tracks/java/exercises/nth-prime/src/test/java/PrimeCalculatorTest.java +4 -4
  48. data/tracks/java/exercises/nucleotide-count/src/test/java/NucleotideTest.java +8 -8
  49. data/tracks/java/exercises/palindrome-products/src/test/java/PalindromeCalculatorTest.java +4 -4
  50. data/tracks/java/exercises/pascals-triangle/src/test/java/PascalsTriangleGeneratorTest.java +5 -5
  51. data/tracks/java/exercises/phone-number/src/test/java/PhoneNumberTest.java +9 -9
  52. data/tracks/java/exercises/pythagorean-triplet/src/test/java/PythagoreanTripletTest.java +6 -6
  53. data/tracks/java/exercises/queen-attack/src/test/java/QueenAttackCalculatorTest.java +12 -12
  54. data/tracks/java/exercises/rectangles/src/test/java/RectangleCounterTest.java +11 -11
  55. data/tracks/java/exercises/robot-name/src/test/java/RobotTest.java +2 -2
  56. data/tracks/java/exercises/robot-simulator/src/test/java/RobotTest.java +19 -19
  57. data/tracks/java/exercises/series/src/test/java/SeriesTest.java +10 -10
  58. data/tracks/java/exercises/sieve/src/test/java/SieveTest.java +2 -2
  59. data/tracks/java/exercises/simple-cipher/src/test/java/SimpleCipherStepOneTest.java +2 -2
  60. data/tracks/java/exercises/simple-cipher/src/test/java/SimpleCipherStepThreeTest.java +7 -7
  61. data/tracks/java/exercises/simple-cipher/src/test/java/SimpleCipherStepTwoTest.java +9 -9
  62. data/tracks/java/exercises/sublist/src/test/java/RelationshipComputerTest.java +16 -16
  63. data/tracks/java/exercises/sum-of-multiples/src/test/java/SumOfMultiplesTest.java +11 -11
  64. data/tracks/java/exercises/triangle/src/test/java/TriangleTest.java +14 -14
  65. data/tracks/java/exercises/twelve-days/src/test/java/TwelveDaysTest.java +13 -13
  66. data/tracks/java/exercises/word-count/src/test/java/WordCountTest.java +5 -5
  67. data/tracks/java/exercises/wordy/src/test/java/WordProblemSolverTest.java +15 -15
  68. data/tracks/perl6/.travis.yml +4 -8
  69. metadata +21 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ec2f4cd34dfc7dbf52cf1d8e4cb28988645c49c9
4
- data.tar.gz: 3fa1693a233cbe8577a1de5471837c46c0f39fc8
3
+ metadata.gz: c4641a9164d7c10684cccf03044f43ec746c4652
4
+ data.tar.gz: af6cf2aff8d93a5ec110a2c65fe5676f90e836d8
5
5
  SHA512:
6
- metadata.gz: 8a826abb1418180c655acbdd990a0648ff01f5bd516bf93a706713355616fa12c278d0d919448c78a016ab893c28416ccb3e5a3e1f14d2fa4b979dfcb02f2ba8
7
- data.tar.gz: 60d261785db5d911a5912626b78b98d25de0cb9bff6f8e14e02a4a190bef45d35d6c90fde343a813a024dfc83aced2856e8e4d1a2fc36706bc9f0f6dd9ead423
6
+ metadata.gz: ed95dff49c3c7509719cc4a8d8abfe8ef26c9f4e39869b2eccf934f077357c6d6a1446fe93433c609d8cf474a6e3756bdc26cc573aeefaac6045e13d4ceee25a
7
+ data.tar.gz: 03373c698f08a120bab897e8613e7da90e00c8455044c86d774494d338e6e083308dc7fb5f8827a857e15b0989ba81422183e614787dc6e99c1e60e77252a61b
data/.gitmodules CHANGED
@@ -175,3 +175,6 @@
175
175
  [submodule "tracks/clojurescript"]
176
176
  path = tracks/clojurescript
177
177
  url = https://github.com/exercism/xclojurescript
178
+ [submodule "tracks/coq"]
179
+ path = tracks/coq
180
+ url = https://github.com/exercism/xcoq
@@ -1,3 +1,3 @@
1
1
  module Trackler
2
- VERSION = "2.1.0.8"
2
+ VERSION = "2.1.0.9"
3
3
  end
data/tracks/coq/.git ADDED
@@ -0,0 +1 @@
1
+ gitdir: ../../.git/modules/tracks/coq
@@ -0,0 +1,23 @@
1
+ Thank you for this PR! :tada:
2
+
3
+ When we review your submission we will check the following:
4
+
5
+ - [ ] TODO: Update this list based on the appropriate checks for this specific track
6
+ - [ ] No trailing whitespace nor extraneous blank lines
7
+ - [ ] Proper indentation and consistent code formatting
8
+ - [ ] Free from spelling and grammatical errors
9
+ - [ ] Readable code style
10
+ - [ ] Exemplifies the idioms of {{LANGUAGE}}
11
+ - [ ] Absence of non-standard libraries
12
+ - [ ] No extraneous configuration files
13
+ - [ ] Free of development/debug artifacts such as `puts`, `console.log`, or `debugger` calls
14
+
15
+ If you are submitting a new exercise, we will compare your submission to the common guidelines set out for the exercise in [x-common](https://github.com/exercism/x-common/tree/master/exercises).
16
+
17
+ Your submission will be run through a series of automated tests and checks. The outcome will be displayed below. In addition to the test suite, the following issues are automatically checked:
18
+
19
+ - TODO: Update this list based on the linting available for this specific track
20
+ - No trailing whitespace nor extraneous blank lines
21
+ - Proper indentation and consistent code formatting
22
+ - Spelling and grammatical errors
23
+ - Compiler and deprecation warnings
@@ -0,0 +1,4 @@
1
+ *.swp
2
+ .DS_Store
3
+ bin/configlet
4
+ bin/configlet.exe
@@ -0,0 +1,5 @@
1
+ language: bash
2
+
3
+ script:
4
+ - bin/fetch-configlet
5
+ - bin/configlet .
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Exercism, Inc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,84 @@
1
+ # Exercism Coq Track
2
+
3
+ ![build status](https://travis-ci.org/exercism/xslug.svg?branch=master)
4
+
5
+ Exercism exercises in Coq.
6
+
7
+ ## Setup
8
+
9
+
10
+
11
+ There are 2 ways to insal Coq:
12
+
13
+ 1. [Recommened] Using OPAM package manger: https://coq.inria.fr/opam/www/using.html
14
+ 2. [Alternative] Direct download Coq binaries from the official site: https://coq.inria.fr/download
15
+
16
+ For editing Coq sources we recomend using one of the following:
17
+ 1. [Recommened] Emacs editor with ProofGenera] and CompanyCoq. See https://github.com/cpitclaudel/company-coq) for instalation instructions.
18
+ 2. [Alternative] Using CoqIDE
19
+
20
+ Presently, exercises do not require any additional Coq libraries.
21
+ Recommended version of Coq: 8.6
22
+
23
+ ## Contributing
24
+
25
+ Thank you so much for contributing! :tada:
26
+
27
+ Please start by reading how to [get involved in a track](https://github.com/exercism/exercism.io/blob/master/docs/getting-involved-in-a-track.md). Comprehensive details on contributing can be found [here](https://github.com/exercism/x-common/blob/master/CONTRIBUTING.md). Be sure to read the Exercism [Code of Conduct](https://github.com/exercism/exercism.io/blob/master/CODE_OF_CONDUCT.md).
28
+
29
+ We welcome pull requests of all kinds. No contribution is too small.
30
+
31
+ We encourage contributions that provide fixes and improvements to existing exercises. Please note that this track's exercises must conform to the standards determined in the [exercism/x-common](https://github.com/exercism/x-common) repo. Changes to the tests or documentation of a common exercise will often warrant a PR in that repo before it can be incorporated into this track's exercises. If you're unsure, then go ahead and open a GitHub issue, and we'll discuss the change.
32
+
33
+ ## Exercise Tests ##
34
+
35
+ At the most basic level, Exercism is all about the tests. They drive the user's implementation forward and tell them when the exercise is complete.
36
+
37
+ The utmost care and attention should be used when adding or making changes to the tests for an exercise. When implementing an exercise test suite, we want to provide a good user experience for the people writing a solution to the exercise. People should not be confused or overwhelmed.
38
+
39
+ We simulate Test-Driven Development (TDD) by implementing the tests in order of increasing complexity. We try to ensure that each test either
40
+
41
+ - helps triangulate a solution to be more generic, or
42
+ - requires new functionality incrementally.
43
+
44
+ Test files should use the following format:
45
+
46
+ ```
47
+ # include the body of an example test
48
+ ```
49
+
50
+ ## Submitting a Pull Request ##
51
+
52
+ Please keep the following in mind:
53
+
54
+ - Pull requests should be focused on a single exercise, issue, or change.
55
+
56
+ - We welcome changes to code style, and wording. Please open a separate PR for these changes if possible.
57
+
58
+ - Please open an issue before creating a PR that makes significant (breaking) changes to an existing exercise or makes changes across many exercises. It is best to discuss these changes before doing the work. Discussions related to exercises that are not track specific can be found in [exercism/discussions](https://github.com/exercism/discussions/issues).
59
+
60
+ - Follow the coding standards for Coq. (If there is a formatter for the track's language, add instructions for using it here.)
61
+
62
+ - Watch out for trailing spaces, extra blank lines, and spaces in blank lines.
63
+
64
+ - All the tests for Coq exercises can be run from the top level of the repo with ... Please run this command before submitting your PR.
65
+
66
+ ## Contributing a New Exercise ##
67
+
68
+ - All Exercism exercises must be defined in [x-common](https://github.com/exercism/x-common/tree/master/exercises) before they are implemented for a specific track. Please submit a PR there if your exercise is new to Exercism.
69
+
70
+ - Please make sure the new exercise conforms to specifications in the [exercism/x-common](https://github.com/exercism/x-common) repo.
71
+
72
+ - Each exercise must stand on its own. Do not reference files outside the exercise directory. They will not be included when the user fetches the exercise.
73
+
74
+ - Exercises should use only the Coq core libraries.
75
+
76
+ - Please do not add a README or README.md file to the exercise directory. The READMEs are constructed using shared metadata, which lives in the
77
+ [exercism/x-common](https://github.com/exercism/x-common) repository. Further explanation can be found in [fixing-exercise-readmes](https://github.com/exercism/exercism.io/blob/master/docs/fixing-exercise-readmes.md)
78
+
79
+ - Each exercise should have a test suite, an example solution, a template file for the real implementation and ... (anything else that needs to go with each exercise for this track). The CI build expects files to be named using the following convention: (describe the Coq convention for naming the various files that make up an exercise).
80
+
81
+ - Please do not commit any configuration files or directories inside the exercise other than ...
82
+
83
+ - Be sure to add it to the appropriate place in the `config.json` file. Also, please run `bin/fetch-configlet && bin/configlet` to ensure the exercise is configured correctly.
84
+
@@ -0,0 +1,32 @@
1
+ #!/bin/bash
2
+
3
+ LATEST=https://github.com/exercism/configlet/releases/latest
4
+
5
+ OS=$(
6
+ case $(uname) in
7
+ (Darwin*)
8
+ echo "mac";;
9
+ (Linux*)
10
+ echo "linux";;
11
+ (Windows*)
12
+ echo "windows";;
13
+ (*)
14
+ echo "linux";;
15
+ esac)
16
+
17
+ ARCH=$(
18
+ case $(uname -m) in
19
+ (*64*)
20
+ echo 64bit;;
21
+ (*686*)
22
+ echo 32bit;;
23
+ (*386*)
24
+ echo 32bit;;
25
+ (*)
26
+ echo 64bit;;
27
+ esac)
28
+
29
+ VERSION="$(curl --head --silent $LATEST | awk -v FS=/ '/Location:/{print $NF}' | tr -d '\r')"
30
+ URL=https://github.com/exercism/configlet/releases/download/$VERSION/configlet-$OS-${ARCH}.tgz
31
+
32
+ curl -s --location $URL | tar xz -C bin/
@@ -0,0 +1,21 @@
1
+ {
2
+ "slug": "coq",
3
+ "language": "Coq",
4
+ "repository": "https://github.com/exercism/xcoq",
5
+ "active": false,
6
+ "test_pattern": "TODO",
7
+ "exercises": [
8
+
9
+ ],
10
+ "deprecated": [
11
+
12
+ ],
13
+ "ignored": [
14
+ "bin",
15
+ "img",
16
+ "docs"
17
+ ],
18
+ "foregone": [
19
+
20
+ ]
21
+ }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -110,6 +110,7 @@ Boost 1.60 for Ubuntu 16.04 LTS by using a PPA.
110
110
 
111
111
  ```
112
112
  $ sudo add-apt-repository -y ppa:samuel-bachmann/boost
113
+ $ sudo apt-get -qq -d update
113
114
  $ sudo apt-get install boost1.60
114
115
  ```
115
116
 
@@ -0,0 +1,82 @@
1
+ // +build ignore
2
+
3
+ package main
4
+
5
+ import (
6
+ "log"
7
+ "text/template"
8
+
9
+ "../../../gen"
10
+ )
11
+
12
+ func main() {
13
+ t := template.New("").Funcs(template.FuncMap{
14
+ "areacode": areacode,
15
+ "expectErr": expectErr,
16
+ "formatted": formatted,
17
+ })
18
+ t, err := t.Parse(tmpl)
19
+ if err != nil {
20
+ log.Fatal(err)
21
+ }
22
+ var j js
23
+ if err := gen.Gen("phone-number", &j, t); err != nil {
24
+ log.Fatal(err)
25
+ }
26
+ }
27
+
28
+ func expectErr(expected string) bool {
29
+ return len(expected) == 0
30
+ }
31
+
32
+ func areacode(expected string) string {
33
+ if expectErr(expected) {
34
+ return ""
35
+ }
36
+ return expected[0:3]
37
+ }
38
+
39
+ func formatted(expected string) string {
40
+ if expectErr(expected) {
41
+ return ""
42
+ }
43
+ return "(" + areacode(expected) + ") " + expected[3:6] + "-" + expected[6:10]
44
+ }
45
+
46
+ // The JSON structure we expect to be able to unmarshal into
47
+ type js struct {
48
+ Cases []struct {
49
+ Description string
50
+ Cases []struct {
51
+ Description string
52
+ Phrase string
53
+ Expected string
54
+ }
55
+ }
56
+ }
57
+
58
+ // template applied to above data structure generates the Go test cases
59
+ var tmpl = `package phonenumber
60
+
61
+ {{.Header}}
62
+
63
+ {{range .J.Cases}}// {{.Description}}
64
+ var numberTests = []struct {
65
+ description string
66
+ input string
67
+ expectErr bool
68
+ number string
69
+ areaCode string
70
+ formatted string
71
+ }{
72
+ {{range .Cases}}{
73
+ description: {{printf "%q" .Description}},
74
+ input: {{printf "%q" .Phrase}},
75
+ {{if expectErr .Expected}} expectErr: {{expectErr .Expected | printf "%v" }},
76
+ {{else}} number: {{printf "%q" .Expected}},
77
+ areaCode: {{areacode .Expected | printf "%q" }},
78
+ formatted: {{formatted .Expected | printf "%q" }},{{- end}}
79
+ },
80
+ {{end}}{{end}}
81
+ }
82
+ `
@@ -0,0 +1,91 @@
1
+ package phonenumber
2
+
3
+ // Source: exercism/x-common
4
+ // Commit: 51d2475 number: Rewrite description and add tests
5
+ // x-common version: 1.1.0
6
+
7
+ // Cleanup user-entered phone numbers
8
+ var numberTests = []struct {
9
+ description string
10
+ input string
11
+ expectErr bool
12
+ number string
13
+ areaCode string
14
+ formatted string
15
+ }{
16
+ {
17
+ description: "cleans the number",
18
+ input: "(223) 456-7890",
19
+ number: "2234567890",
20
+ areaCode: "223",
21
+ formatted: "(223) 456-7890",
22
+ },
23
+ {
24
+ description: "cleans numbers with dots",
25
+ input: "223.456.7890",
26
+ number: "2234567890",
27
+ areaCode: "223",
28
+ formatted: "(223) 456-7890",
29
+ },
30
+ {
31
+ description: "cleans numbers with multiple spaces",
32
+ input: "223 456 7890 ",
33
+ number: "2234567890",
34
+ areaCode: "223",
35
+ formatted: "(223) 456-7890",
36
+ },
37
+ {
38
+ description: "invalid when 9 digits",
39
+ input: "123456789",
40
+ expectErr: true,
41
+ },
42
+ {
43
+ description: "invalid when 11 digits does not start with a 1",
44
+ input: "22234567890",
45
+ expectErr: true,
46
+ },
47
+ {
48
+ description: "valid when 11 digits and starting with 1",
49
+ input: "12234567890",
50
+ number: "2234567890",
51
+ areaCode: "223",
52
+ formatted: "(223) 456-7890",
53
+ },
54
+ {
55
+ description: "valid when 11 digits and starting with 1 even with punctuation",
56
+ input: "+1 (223) 456-7890",
57
+ number: "2234567890",
58
+ areaCode: "223",
59
+ formatted: "(223) 456-7890",
60
+ },
61
+ {
62
+ description: "invalid when more than 11 digits",
63
+ input: "321234567890",
64
+ expectErr: true,
65
+ },
66
+ {
67
+ description: "invalid with letters",
68
+ input: "123-abc-7890",
69
+ expectErr: true,
70
+ },
71
+ {
72
+ description: "invalid with punctuations",
73
+ input: "123-@:!-7890",
74
+ expectErr: true,
75
+ },
76
+ {
77
+ description: "invalid with right number of digits but letters mixed in",
78
+ input: "1a2b3c4d5e6f7g8h9i0j",
79
+ expectErr: true,
80
+ },
81
+ {
82
+ description: "invalid if area code does not start with 2-9",
83
+ input: "(123) 456-7890",
84
+ expectErr: true,
85
+ },
86
+ {
87
+ description: "invalid if exchange code does not start with 2-9",
88
+ input: "(223) 056-7890",
89
+ expectErr: true,
90
+ },
91
+ }
@@ -2,44 +2,46 @@ package phonenumber
2
2
 
3
3
  import (
4
4
  "fmt"
5
- "strings"
6
5
  "unicode"
7
6
  )
8
7
 
9
- const testVersion = 1
8
+ const testVersion = 2
10
9
 
11
10
  // Number takes in a potential phone number string and returns the number
12
11
  // without any formatting if it's valid.
13
12
  //
14
13
  // * If the phone number is less than 10 digits assume that it is bad number
15
- // * If the phone number is 10 digits assume that it is good
14
+ // * If the phone number is 10 digits, it is good if 1st digit is not 1 and 3 digit exchange begins with 2..9
16
15
  // * If the phone number is 11 digits and the first number is 1, trim the 1 and use the first 10 digits
17
16
  // * If the phone number is 11 digits and the first number is not 1, then it is a bad number
18
17
  // * If the phone number is more than 11 digits assume that it is a bad number
19
18
  func Number(s string) (string, error) {
20
- //remove any characters that aren't digits
21
- clean := strings.Map(
22
- func(r rune) rune {
23
- if unicode.IsDigit(r) {
24
- return r
25
- }
26
- return -1
27
- }, s)
28
-
19
+ // Extract just the digits.
20
+ n := make([]rune, 0, len(s))
21
+ for _, c := range s {
22
+ if c == ' ' || c == '+' || c == '(' || c == ')' || c == '-' || c == '.' {
23
+ continue
24
+ } else if unicode.IsDigit(c) {
25
+ n = append(n, c)
26
+ } else {
27
+ return "", fmt.Errorf("Phone number %q has invalid characters", s)
28
+ }
29
+ }
30
+ clean := string(n)
29
31
  numDigits := len(clean)
30
32
  switch {
31
33
  // bad number if less than 10 digits
32
34
  case numDigits < 10:
33
35
  return "", fmt.Errorf("Phone number %q contains too few digits", s)
34
- // good number if exactly 10 digits
35
- case numDigits == 10:
36
+ // good number if exactly 10 digits and area code & exchange are valid
37
+ case numDigits == 10 && clean[0] >= '2' && clean[3] >= '2':
36
38
  return clean, nil
37
- // good number if 11 digits and 1st digit is a 1. Return last 10 digits.
38
- case numDigits == 11 && clean[0] == '1':
39
+ // good number if 11 digits and 1st digit is a 1. Return last 10 digits, if valid.
40
+ case numDigits == 11 && clean[0] == '1' && clean[1] >= '2' && clean[4] >= '2':
39
41
  return clean[1:], nil
40
42
  }
41
- // all other numbers are a bad
42
- return "", fmt.Errorf("Phone number %q contains too many digits", s)
43
+ // all other numbers are bad
44
+ return "", fmt.Errorf("Phone number %q is invalid", s)
43
45
  }
44
46
 
45
47
  // AreaCode takes in a phone number string and returns the area code (first three digits)
@@ -4,22 +4,7 @@ import (
4
4
  "testing"
5
5
  )
6
6
 
7
- const targetTestVersion = 1
8
-
9
- type testCase struct {
10
- input string
11
- expected string
12
- expectErr bool
13
- }
14
-
15
- var numberTests = []testCase{
16
- {"(123) 456-7890", "1234567890", false},
17
- {"123.456.7890", "1234567890", false},
18
- {"1234567890", "1234567890", false},
19
- {"12345678901234567", "", true},
20
- {"21234567890", "", true},
21
- {"123456789", "", true},
22
- }
7
+ const targetTestVersion = 2
23
8
 
24
9
  func TestTestVersion(t *testing.T) {
25
10
  if testVersion != targetTestVersion {
@@ -34,14 +19,14 @@ func TestNumber(t *testing.T) {
34
19
  if actualErr != nil {
35
20
  // if we don't expect an error and there is one
36
21
  var _ error = actualErr
37
- t.Errorf("Number(%s): expected no error, but error is: %s", test.input, actualErr)
22
+ t.Errorf("FAIL: %s\nNumber(%q): expected no error, but error is: %s", test.description, test.input, actualErr)
38
23
  }
39
- if actual != test.expected {
40
- t.Errorf("Number(%s): expected [%s], actual: [%s]", test.input, test.expected, actual)
24
+ if actual != test.number {
25
+ t.Errorf("FAIL: %s\nNumber(%q): expected [%s], actual: [%s]", test.description, test.input, test.number, actual)
41
26
  }
42
27
  } else if actualErr == nil {
43
28
  // if we expect an error and there isn't one
44
- t.Errorf("Number(%s): expected an error, but error is nil", test.input)
29
+ t.Errorf("FAIL: %s\nNumber(%q): expected an error, but error is nil", test.description, test.input)
45
30
  }
46
31
  }
47
32
  }
@@ -57,38 +42,28 @@ func BenchmarkNumber(b *testing.B) {
57
42
  }
58
43
  }
59
44
 
60
- var areaCodeTests = []testCase{
61
- {"1234567890", "123", false},
62
- {"213.456.7890", "213", false},
63
- {"213.456.7890.2345", "", true},
64
- {"213.456", "", true},
65
- }
66
-
67
45
  func TestAreaCode(t *testing.T) {
68
- if testVersion != targetTestVersion {
69
- t.Errorf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
70
- }
71
- for _, test := range areaCodeTests {
46
+ for _, test := range numberTests {
72
47
  actual, actualErr := AreaCode(test.input)
73
48
  if !test.expectErr {
74
- if actual != test.expected {
75
- t.Errorf("AreaCode(%s): expected [%s], actual: [%s]", test.input, test.expected, actual)
49
+ if actual != test.areaCode {
50
+ t.Errorf("FAIL: %s\nAreaCode(%q): expected [%s], actual: [%s]", test.description, test.input, test.areaCode, actual)
76
51
  }
77
52
  if actualErr != nil {
78
53
  // if we don't expect an error and there is one
79
54
  var _ error = actualErr
80
- t.Errorf("AreaCode(%s): expected no error, but error is: %s", test.input, actualErr)
55
+ t.Errorf("FAIL: %s\nAreaCode(%q): expected no error, but error is: %s", test.description, test.input, actualErr)
81
56
  }
82
57
  } else if actualErr == nil {
83
58
  // if we expect an error and there isn't one
84
- t.Errorf("AreaCode(%s): expected an error, but error is nil", test.input)
59
+ t.Errorf("FAIL: %s\nAreaCode(%q): expected an error, but error is nil", test.description, test.input)
85
60
  }
86
61
  }
87
62
  }
88
63
 
89
64
  func BenchmarkAreaCode(b *testing.B) {
90
65
  b.StopTimer()
91
- for _, test := range areaCodeTests {
66
+ for _, test := range numberTests {
92
67
  b.StartTimer()
93
68
  for i := 0; i < b.N; i++ {
94
69
  AreaCode(test.input)
@@ -97,38 +72,28 @@ func BenchmarkAreaCode(b *testing.B) {
97
72
  }
98
73
  }
99
74
 
100
- var formatTests = []testCase{
101
- {"1234567890", "(123) 456-7890", false},
102
- {"11234567890", "(123) 456-7890", false},
103
- {"112345", "", true},
104
- {"11234590870986", "", true},
105
- }
106
-
107
75
  func TestFormat(t *testing.T) {
108
- if testVersion != targetTestVersion {
109
- t.Errorf("Found testVersion = %v, want %v.", testVersion, targetTestVersion)
110
- }
111
- for _, test := range formatTests {
76
+ for _, test := range numberTests {
112
77
  actual, actualErr := Format(test.input)
113
78
  if !test.expectErr {
114
79
  if actualErr != nil {
115
80
  // if we don't expect an error and there is one
116
81
  var _ error = actualErr
117
- t.Errorf("Format(%s): expected no error, but error is: %s", test.input, actualErr)
82
+ t.Errorf("FAIL: %s\nFormat(%q): expected no error, but error is: %s", test.description, test.input, actualErr)
118
83
  }
119
- if actual != test.expected {
120
- t.Errorf("Format(%s): expected [%s], actual: [%s]", test.input, test.expected, actual)
84
+ if actual != test.formatted {
85
+ t.Errorf("FAIL: %s\nFormat(%q): expected [%s], actual: [%s]", test.description, test.input, test.formatted, actual)
121
86
  }
122
87
  } else if actualErr == nil {
123
88
  // if we expect an error and there isn't one
124
- t.Errorf("Format(%s): expected an error, but error is nil", test.input)
89
+ t.Errorf("FAIL: %s\nFormat(%q): expected an error, but error is nil", test.description, test.input)
125
90
  }
126
91
  }
127
92
  }
128
93
 
129
94
  func BenchmarkFormat(b *testing.B) {
130
95
  b.StopTimer()
131
- for _, test := range areaCodeTests {
96
+ for _, test := range numberTests {
132
97
  b.StartTimer()
133
98
  for i := 0; i < b.N; i++ {
134
99
  Format(test.input)
@@ -0,0 +1,45 @@
1
+ // +build ignore
2
+
3
+ package main
4
+
5
+ import (
6
+ "log"
7
+ "text/template"
8
+
9
+ "../../../gen"
10
+ )
11
+
12
+ func main() {
13
+ t, err := template.New("").Parse(tmpl)
14
+ if err != nil {
15
+ log.Fatal(err)
16
+ }
17
+ var j js
18
+ if err := gen.Gen("scrabble-score", &j, t); err != nil {
19
+ log.Fatal(err)
20
+ }
21
+ }
22
+
23
+ // The JSON structure we expect to be able to unmarshal into
24
+ type js struct {
25
+ Cases []struct {
26
+ Description string
27
+ Input string
28
+ Expected int
29
+ }
30
+ }
31
+
32
+ // template applied to above data structure generates the Go test cases
33
+ var tmpl = `package scrabble
34
+
35
+ {{.Header}}
36
+
37
+ type scrabbleTest struct {
38
+ input string
39
+ expected int
40
+ }
41
+
42
+ var scrabbleScoreTests = []scrabbleTest {
43
+ {{range .J.Cases}}{ "{{.Input}}", {{.Expected}}}, // {{.Description}}
44
+ {{end}}}
45
+ `