diff --git a/csharp/current b/csharp/current index 2529de8..aa155fc 120000 --- a/csharp/current +++ b/csharp/current @@ -1 +1 @@ -bob \ No newline at end of file +gigasecond \ No newline at end of file diff --git a/csharp/gigasecond/GigasecondTest.cs b/csharp/gigasecond/GigasecondTest.cs new file mode 100644 index 0000000..e8ab020 --- /dev/null +++ b/csharp/gigasecond/GigasecondTest.cs @@ -0,0 +1,29 @@ +using System; +using NUnit.Framework; + +[TestFixture] +public class GigasecondTest +{ + [Test] + public void First_date() + { + var date = Gigasecond.Date(new DateTime(2011, 4, 25, 0, 0, 0, DateTimeKind.Utc)); + Assert.That(date, Is.EqualTo(new DateTime(2043, 1, 1, 1, 46, 40, DateTimeKind.Utc))); + } + + [Test] + [Ignore("Remove to run test")] + public void Another_date() + { + var date = Gigasecond.Date(new DateTime(1977, 6, 13, 0, 0, 0, DateTimeKind.Utc)); + Assert.That(date, Is.EqualTo(new DateTime(2009, 2, 19, 1, 46, 40, DateTimeKind.Utc))); + } + + [Test] + [Ignore("Remove to run test")] + public void Yet_another_date() + { + var date = Gigasecond.Date(new DateTime(1959, 7, 19, 0, 0, 0, DateTimeKind.Utc)); + Assert.That(date, Is.EqualTo(new DateTime(1991, 3, 27, 1, 46, 40, DateTimeKind.Utc))); + } +} \ No newline at end of file diff --git a/csharp/gigasecond/README.md b/csharp/gigasecond/README.md new file mode 100644 index 0000000..e3ae2b7 --- /dev/null +++ b/csharp/gigasecond/README.md @@ -0,0 +1,19 @@ +# Gigasecond + +Write a program that calculates the moment when someone has lived for 10^9 seconds. + +A gigasecond is 10^9 (1,000,000,000) seconds. + +### Submitting Exercises + +Note that, when trying to submit an exercise, make sure you're exercise file you're submitting is in the `exercism/csharp/` directory. + +For example, if you're submitting `bob.cs` for the Bob exercise, the submit command would be something like `exercism submit /csharp/bob/bob.cs`. + +## Source + +Chapter 9 in Chris Pine's online Learn to Program tutorial. [http://pine.fm/LearnToProgram/?Chapter=09](http://pine.fm/LearnToProgram/?Chapter=09) + +## Submitting Incomplete Problems +It's possible to submit an incomplete solution so you can see how others have completed the exercise. + diff --git a/go/current b/go/current index 0ec21b7..eff4962 120000 --- a/go/current +++ b/go/current @@ -1 +1 @@ -matrix \ No newline at end of file +hexadecimal \ No newline at end of file diff --git a/go/hexadecimal/README.md b/go/hexadecimal/README.md new file mode 100644 index 0000000..47f857c --- /dev/null +++ b/go/hexadecimal/README.md @@ -0,0 +1,26 @@ +# Hexadecimal + +Write a program that will convert a hexadecimal number, represented as a string (e.g. "10af8c"), to its decimal equivalent using first principles (i.e. no, you may not use built-in or external libraries to accomplish the conversion). + +On the web we use hexadecimal to represent colors, e.g. green: 008000, +teal: 008080, navy: 000080). + +The program should handle invalid hexadecimal strings. + +To run the tests simply run the command `go test` in the exercise directory. + +If the test suite contains benchmarks, you can run these with the `-bench` +flag: + + go test -bench . + +For more detailed info about the Go track see the [help +page](http://exercism.io/languages/go). + +## Source + +All of Computer Science [http://www.wolframalpha.com/examples/NumberBases.html](http://www.wolframalpha.com/examples/NumberBases.html) + +## Submitting Incomplete Problems +It's possible to submit an incomplete solution so you can see how others have completed the exercise. + diff --git a/go/hexadecimal/hexadecimal.go b/go/hexadecimal/hexadecimal.go new file mode 100644 index 0000000..8ebb29f --- /dev/null +++ b/go/hexadecimal/hexadecimal.go @@ -0,0 +1,56 @@ +package hexadecimal + +import ( + "errors" + "fmt" + "math/big" + "strings" +) + +func ParseHex(in string) (int64, error) { + return convertNumStringBase(in, int64(16)) +} + +func HandleErrors(in []string) []string { + var ret []string + for i := range in { + _, err := convertNumStringBase(in[i], 16) + ret = append(ret, err.Error()) + } + return ret +} + +// convertNumStringBase takes a numeric string and the base of that string +// and returns an int64 of the decimal representation +func convertNumStringBase(in string, oldBase int64) (int64, error) { + if in == "" { + return 0, errors.New("syntax") + } + in = strings.ToLower(in) + base := big.NewInt(oldBase) + var sum big.Int + for i := range in { + var x *big.Int + if in[i] >= '0' && in[i] <= '9' { + x = big.NewInt(int64(in[i] - '0')) + } else if in[i] >= 'a' && in[i] <= 'z' { + x = big.NewInt(int64(in[i]-'a') + 10) + } + fmt.Println("Comparing Converted Value ", x, "<", oldBase) + if x.Int64() > oldBase { + return 0, errors.New("syntax") + } + + pow := big.NewInt(int64(len(in) - i - 1)) + + var n big.Int + n.Exp(base, pow, nil) + n.Mul(x, &n) + + sum.Add(&sum, &n) + if sum.Int64() < 0 { + return 0, errors.New("Integer Overflow") + } + } + return sum.Int64(), nil +} diff --git a/go/hexadecimal/hexadecimal_test.go b/go/hexadecimal/hexadecimal_test.go new file mode 100644 index 0000000..f097057 --- /dev/null +++ b/go/hexadecimal/hexadecimal_test.go @@ -0,0 +1,77 @@ +// Your solution must include the following definitions: +// +// func ParseHex(string) (int64, error) +// func HandleErrors([]string) []string +// +// HandleErrors takes a list of inputs for ParseHex and returns a matching list +// of error cases. It must call ParseHex on each input, handle the error result, +// and put one of three strings, "none", "syntax", or "range" in the result list +// according to the error. + +package hexadecimal + +import ( + "testing" +) + +var testCases = []struct { + in string + out int64 + errCase string +}{ + {"1", 1, "none"}, + {"10", 0x10, "none"}, + {"2d", 0x2d, "none"}, + {"012", 0x12, "none"}, + {"cfcfcf", 0xcfcfcf, "none"}, + {"CFCFCF", 0xcfcfcf, "none"}, + {"", 0, "syntax"}, + {"peanut", 0, "syntax"}, + {"2cg134", 0, "syntax"}, + {"8000000000000000", 0, "range"}, + {"9223372036854775809", 0, "range"}, +} + +func TestParseHex(t *testing.T) { + for _, test := range testCases { + switch out, err := ParseHex(test.in); { + case err != nil: + if test.errCase == "none" { + t.Errorf("ParseHex(%q) returned error %q. Error not expected.", + test.in, err) + } + case test.errCase != "none": + t.Errorf("ParseHex(%q) = %d, %v. Expected error.", + test.in, out, err) + case out != test.out: + t.Errorf("ParseHex(%q) = %d. Expected %d.", + test.in, out, test.out) + } + } +} + +func TestHandleErrors(t *testing.T) { + tests := make([]string, len(testCases)) + for i, test := range testCases { + tests[i] = test.in + } + er := HandleErrors(tests) + if len(er) != len(tests) { + t.Fatalf("For %d tests, HandleErrors returned %d results, want %d", + len(tests), len(er), len(tests)) + } + for i, e := range er { + if e != testCases[i].errCase { + t.Errorf("For ParseHex(%q), HandleErrors reports %q, want %q", + tests[i], e, testCases[i].errCase) + } + } +} + +func BenchmarkParseHex(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, test := range testCases { + ParseHex(test.in) + } + } +} diff --git a/go/trinary/trinary.go b/go/trinary/trinary.go index e23d129..5b98396 100644 --- a/go/trinary/trinary.go +++ b/go/trinary/trinary.go @@ -2,30 +2,32 @@ package trinary import ( "errors" - "fmt" - "math" + "math/big" ) // ParseTrinary takes a trinary string and returns the // decimal value func ParseTrinary(in string) (int64, error) { - fmt.Println("=== New Parse (" + in + ") ===") - var ret int - place := len(in) - - for i := range in { - fmt.Print("Finding ", (place - i), " place value ", string(in[i])) - switch in[i] { - case '0': - case '1': - ret = ret + ((place - i) * 3) - case '2': - ret = ret + ((place - i) * int(math.Pow(3, 2))) - default: - return 0, errors.New("Invalid String") - } - fmt.Println("==", ret) - place-- - } - return int64(ret), nil + return convertNumStringBase(in, int64(3)) +} + +// convertNumStringBase takes a numeric string and the base of that string +// and returns an int64 of the decimal representation +func convertNumStringBase(in string, oldBase int64) (int64, error) { + base := big.NewInt(oldBase) + var sum big.Int + for i := range in { + x := big.NewInt(int64(in[i] - '0')) + pow := big.NewInt(int64(len(in) - i - 1)) + + var n big.Int + n.Exp(base, pow, nil) + n.Mul(x, &n) + + sum.Add(&sum, &n) + if sum.Int64() < 0 { + return 0, errors.New("Integer Overflow") + } + } + return sum.Int64(), nil }