Compare commits

...

No commits in common. "master" and "cui_master" have entirely different histories.

10 changed files with 441 additions and 0 deletions

2
.rspec Normal file
View File

@ -0,0 +1,2 @@
--format documentation
--color

4
Gemfile Normal file
View File

@ -0,0 +1,4 @@
source 'https://rubygems.org'
ruby '2.3'
gem 'rspec'

29
Gemfile.lock Normal file
View File

@ -0,0 +1,29 @@
GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.2.5)
rspec (3.5.0)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-core (3.5.4)
rspec-support (~> 3.5.0)
rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
PLATFORMS
ruby
DEPENDENCIES
rspec
RUBY VERSION
ruby 2.3.0p0
BUNDLED WITH
1.13.3

124
README.md Normal file
View File

@ -0,0 +1,124 @@
Ruby Intro
=============
This 3-part homework gives some basic practice in Ruby as well as
getting you accustomed to making testing a regular part of your workflow.
Learning Goals
--------------
After completing this assignment, you will know how to:
* Write simple code that uses basic constructs in the Ruby language, including methods and arguments, conditionals, string and array manipulation, regular expressions, and basic object-oriented programming mechanisms
* Understand the Ruby project conventions for where code files and test files are located in a project's directory hierarchy
* Run individual tests or suites of tests using the RSpec unit testing tool
* Understand the basic syntax of RSpec unit tests
Overview
--------
The repo for this assigment follows a fairly standard Ruby convention for codebases: the code
files are stored in `lib/` and the test files are stored in `spec/`.
(We use the RSpec unit-testing framework; if we were using Ruby's default
framework, known as `Test::Unit`, the test files would be under
`test/`.)
We've placed "starter code" in `lib/ruby_intro.rb`; when you're all done, you
can submit this single file to the autograder.
However, you can test each of the 3 parts separately. The files
`spec/part[123]_spec.rb` contain RSpec tests for each of the three
parts. For example, to test your answers to Part 1, say `rspec
spec/part1_spec.rb`. `rspec` with no arguments runs the tests in all
the files `spec/*_spec.rb`.
* The line numbers in the RSpec error report will
give you guidance as to which tests failed. (You can check the [RSpec
documentation](http://rspec.info) to see how the `.rspec` file can be
used to customize the output format.)
To ensure you have the rspec gem installed you need bundler and can then
run bundle install like so (if you accidently do not use c9 ide):
```sh
$ gem install bundler
$ cd hw-ruby-intro
$ bundle
```
When the above completes successfully you'll have RSpec installed and can
run `rspec` from the command line to test your code.
Before starting your homework, please refer to the recommanded workflow as below for this and future assignment:
* Create a project with the name hw-ruby-intro in your Trustie workspace
* Create a project repository with the name hw-ruby-intro in the setting page of the project
* Link the project repository to this assignment
* Clone the homework repository to your c9 ide workspace or anywhere you coding `$ git clone http://git.trustie.net/cgao/hw-ruby-intro.git`
* Do your homework and test your solution
* Commit change to your local git repository
* Push your local repository at c9 workspace to your Trustie project repository
* Submit your homework assignment
Please refer to the Trustie user guide for creating project, repository, and using basic git command to manage your code repositories.
# 1. Arrays, Hashes, and Enumerables
Check the [Ruby 2.x documentation](http://ruby-doc.org) on `Array`,
`Hash` and `Enumerable` as they could help tremendously with these
exercises. :-)
0. Define a method `sum(array)` that takes an array of integers as an argument and returns the sum of its elements. For an empty array it should return zero. Run associated tests via: `$ rspec spec/part1_spec.rb:5`
0. Define a method `max_2_sum(array)` which takes an array of integers as an argument and returns the sum of its two largest elements. For an empty array it should return zero. For an array with just one element, it should return that element. Run associated tests via: `$ rspec spec/part1_spec.rb:23`
0. Define a method `sum_to_n?(array, n)` that takes an array of integers and an additional integer, n, as arguments and returns true if any two elements in the array of integers sum to n. `sum_to_n?([], n)` should return false for any value of n, by definition. Run associated tests via: `$ rspec spec/part1_spec.rb:42`
You can check your progress on the all the above by running `$ rspec spec/part1_spec.rb`.
# 2. Strings and Regular Expressions
Check the documentation on String and Regexp as they could help tremendously with these exercises. :-)
0. Define a method `hello(name)` that takes a string representing a name and returns the string "Hello, " concatenated with the name. Run associated tests via: `$ rspec -e '#hello' spec/part2_spec.rb`
0. Define a method `starts_with_consonant?(s)` that takes a string and returns true if it starts with a consonant and false otherwise. (For our purposes, a consonant is any letter other than A, E, I, O, U.) NOTE: be sure it works for both upper and lower case and for nonletters! Run associated tests via: `$ rspec -e '#starts_with_consonant?' spec/part2_spec.rb`
0. Define a method `binary_multiple_of_4?(s)` that takes a string and returns true if the string represents a binary number that is a multiple of 4. NOTE: be sure it returns false if the string is not a valid binary number! Run associated tests via: `$ rspec -e '#binary_multiple_of_4?' spec/part2_spec.rb`
You can check your progress on the all the above by running `$ rspec spec/part2_spec.rb`.
# 3. Object Oriented Basics
Define a class `BookInStock` which represents a book with an ISBN
number, `isbn`, and price of the book as a floating-point number,
`price`, as attributes. Run associated tests via: `$ rspec -e 'getters and setters' spec/part3_spec.rb`
The constructor should accept the ISBN number
(a string, since in real life ISBN numbers can begin with zero and can
include hyphens) as the first argument and price as second argument, and
should raise `ArgumentError` (one of Ruby's built-in exception types) if
the ISBN number is the empty string or if the price is less than or
equal to zero. Include the proper getters and setters for these
attributes. Run associated tests via: `$ rspec -e 'constructor' spec/part3_spec.rb`
Include a method `price_as_string` that returns the price of
the book formatted with a leading dollar sign and two decimal places, that is, a price
of 20 should format as "$20.00" and a price of 33.8 should format as
"$33.80". Run associated tests via: `$ rspec -e '#price_as_string' spec/part3_spec.rb`
You can check your progress on the all the above by running `rspec spec/part3_spec.rb`.
## More Challenges
* Try getting setup with
an automated test framework such as [guard](http://code.tutsplus.com/tutorials/testing-your-ruby-code-with-guard-rspec-pry--cms-19974) or [autotest](https://rubygems.org/gems/autotest). Guard or AutoTest can be set up so that
they will run all the tests in `spec/`, but every time you edit and save
your code file, the tests are automatically re-run, so you don't have to
run them manually. As we'll see later, this is the "watch the test fail"
part of the TDD or test-driven process of development: write the tests before
you write the code, watch the test fail, fill in the code and save the code file,
then watch the test pass!

103
lib/ruby_intro.rb Normal file
View File

@ -0,0 +1,103 @@
# When done, submit this entire file to the autograder.
# Part 1
def sum arr
# YOUR CODE HERE
sum = 0
arr.each do |i|
sum += i
end
return sum
end
def max_2_sum arr
# YOUR CODE HERE
if arr.size == 0
return 0
elsif arr.size == 1
return arr[0]
else
sum = 0
sum += arr.max
arr.delete_at arr.index(sum)
sum += arr.max
return sum
end
end
def sum_to_n? arr, n
# YOUR CODE HERE
if arr.size < 2
return false
end
arr.each_with_index do |first_number, i|
j = i + 1
while j < arr.size
if first_number + arr[j] == n
return true
end
j += 1
end
end
return false
end
# Part 2
def hello(name)
# YOUR CODE HERE
"Hello, " + name
end
def starts_with_consonant? s
# YOUR CODE HERE
if /^[^aeiouAEIOU]/ =~ s and /^[a-zA-Z]/ =~ s # 必须不能一以原因以原音字母开头,而且必须以字母开头
return true
end
return false
end
def binary_multiple_of_4? s
# YOUR CODE HERE
if /[^01]/ =~ s # 判断是否有效
return false
end
if s.size == 0
return false
end
if s.size == 1
return s == "0"
end
if s.size == 2
return s == "00"
end
if s[-2..-1].to_s.include?('1')
return false
else
return true
end
end
# Part 3
class BookInStock
# YOUR CODE HERE
def initialize(isbn, price)
if isbn.empty? or price <= 0
raise ArgumentError
end
@isbn = isbn
@price = price
end
attr_accessor :isbn
attr_accessor :price
def price_as_string
format('$%.2f', @price)
end
end

0
spec/.gitkeep Normal file
View File

73
spec/part1_spec.rb Normal file
View File

@ -0,0 +1,73 @@
require 'ruby_intro.rb'
describe 'Ruby intro part 1' do
describe "#sum" do
it "should be defined" do
expect { sum([1,3,4]) }.not_to raise_error
end
it "returns correct sum [20 points]" , points: 20 do
expect(sum([1,2,3,4,5])).to be_a_kind_of Fixnum
expect(sum([1,2,3,4,5])).to eq(15)
expect(sum([1,2,3,4,-5])).to eq(5)
expect(sum([1,2,3,4,-5,5,-100])).to eq(-90)
end
it "works on the empty array [10 points]" , points: 10 do
expect { sum([]) }.not_to raise_error
expect(sum([])).to be_zero
end
end
describe "#max_2_sum" do
it "should be defined" do
expect { max_2_sum([1,2,3]) }.not_to raise_error
end
it "returns the correct sum [7 points]" , points: 7 do
expect(max_2_sum([1,2,3,4,5])).to be_a_kind_of Fixnum
expect(max_2_sum([1,-2,-3,-4,-5])).to eq(-1)
end
it 'works even if 2 largest values are the same [3 points]' , points: 3 do
expect(max_2_sum([1,2,3,3])).to eq(6)
end
it "returns zero if array is empty [10 points]" , points: 10 do
expect(max_2_sum([])).to be_zero
end
it "returns value of the element if just one element [10 points]" , points: 10 do
expect(max_2_sum([3])).to eq(3)
end
end
describe "#sum_to_n" do
it "should be defined" do
expect { sum_to_n?([1,2,3],4) }.not_to raise_error
end
it "returns true when any two elements sum to the second argument [30 points]" , points: 30 do
expect(sum_to_n?([1,2,3,4,5], 5)).to be true # 2 + 3 = 5
expect(sum_to_n?([3,0,5], 5)).to be true # 0 + 5 = 5
expect(sum_to_n?([-1,-2,3,4,5,-8], -3)).to be true # handles negative sum
expect(sum_to_n?([-1,-2,3,4,5,-8], 12)).to be false # 3 + 4 + 5 = 12 (not 3 elements)
expect(sum_to_n?([-1,-2,3,4,6,-8], 12)).to be false # no two elements that sum
end
# for rspec 2.14.1
# it "returns false for the single element array [5 points]" , points: 5 do
# sum_to_n?([1], 1).should be_false
# sum_to_n?([3], 0).should be_false
# end
# it "returns false for the empty array [5 points]" , points: 5 do
# sum_to_n?([], 0).should be_false
# sum_to_n?([], 7).should be_false
# end
it "returns false for any single element array [5 points]" , points: 5 do
expect(sum_to_n?([0], 0)).to be false
expect(sum_to_n?([1], 1)).to be false
expect(sum_to_n?([-1], -1)).to be false
expect(sum_to_n?([-3], 0)).to be false
end
it "returns false for an empty array [5 points]" , points: 5 do
expect(sum_to_n?([], 0)).to be false
expect(sum_to_n?([], 7)).to be false
end
end
end

56
spec/part2_spec.rb Normal file
View File

@ -0,0 +1,56 @@
require 'ruby_intro.rb'
describe "#hello" do
it "should be defined" do
expect { hello("Testing") }.not_to raise_error()#::NoMethodError)
end
it "The hello method returns the correct string [30 points]" , points: 30 do
expect(hello("Dan").class).to eq(String)
expect(hello("Dan")).to eq('Hello, Dan'), "Incorrect results for input: \"Dan\""
expect(hello("BILL")).to eq('Hello, BILL'), "Incorrect results for input: \"BILL\""
expect(hello("Mr. Ilson")).to eq('Hello, Mr. Ilson'), "Incorrect results for input: \"Mr. Ilson\""
end
end
describe "#starts_with_consonant?" do
it "should be defined" do
expect { starts_with_consonant?("d") }.not_to raise_error()#::NoMethodError)
end
it 'classifies true cases [10 points]' , points: 10 do
expect(starts_with_consonant?('v')).to be_truthy, "'v' is a consonant"
['v', 'vest', 'Veeee', 'crypt'].each do |string|
expect(starts_with_consonant?(string)).to be_truthy, "Incorrect results for input: \"#{string}\""
end
end
it 'classifies false cases [10 points]' , points: 10 do
expect(starts_with_consonant?('a')).to be_falsy, "'a' is not a consonant"
['asdfgh', 'Unix'].each do |string|
expect(starts_with_consonant?(string)).to be_falsy, "Incorrect results for input: \"#{string}\""
end
end
it 'works on the empty string [5 points]' , points: 5 do
expect(starts_with_consonant?('')).to be_falsy
end
it 'works on nonletters [5 points]' , points: 5 do
expect(starts_with_consonant?('#foo')).to be_falsy
end
end
describe "#binary_multiple_of_4?" do
it "should be defined" do
expect { binary_multiple_of_4?("yes") }.not_to raise_error()#::NoMethodError)
end
it "classifies valid binary numbers [30 points]" , points: 30 do
["1010101010100", "0101010101010100", "100", "0"].each do |string|
expect(binary_multiple_of_4?(string)).to be_truthy, "Incorrect results for input: \"#{string}\""
end
["101", "1000000000001"].each do |string|
expect(binary_multiple_of_4?(string)).not_to be_truthy, "Incorrect results for input: \"#{string}\""
end
end
it "rejects invalid binary numbers [10 points]" , points: 10 do
expect(binary_multiple_of_4?('a100')).to be_falsy, "'a100' is not a valid binary number!"
expect(binary_multiple_of_4?('')).to be_falsy, "The empty string is not a valid binary number!"
end
end

50
spec/part3_spec.rb Normal file
View File

@ -0,0 +1,50 @@
require 'ruby_intro.rb'
describe "BookInStock" do
it "should be defined" do
expect { BookInStock }.not_to raise_error
end
describe 'getters and setters' do
before(:each) { @book = BookInStock.new('isbn1', 33.8) }
it 'should set ISBN [10 points]' , points: 10 do
expect(@book.isbn).to eq('isbn1')
end
it 'should set price [10 points]' , points: 10 do
expect(@book.price).to eq(33.8)
end
it 'should be able to change ISBN [10 points]' , points: 10 do
@book.isbn = 'isbn2'
expect(@book.isbn).to eq('isbn2')
end
it 'should be able to change price [10 points]' , points: 10 do
@book.price = 300.0
expect(@book.price).to eq(300.0)
end
end
describe 'constructor' do
it 'should reject invalid ISBN number [10 points]' , points: 10 do
expect { BookInStock.new('', 25.00) }.to raise_error(ArgumentError)
end
it 'should reject zero price [10 points]' , points: 10 do
expect { BookInStock.new('isbn1', 0) }.to raise_error(ArgumentError)
end
it 'should reject negative price [10 points]' , points: 10 do
expect { BookInStock.new('isbn1', -5.0) }.to raise_error(ArgumentError)
end
end
describe "#price_as_string" do
it "should be defined" do
expect(BookInStock.new('isbn1', 10)).to respond_to(:price_as_string)
end
it 'should display 33.95 as "$33.95" [10 points]' , points: 10 do
expect(BookInStock.new('isbn11', 33.95).price_as_string).to eq('$33.95')
end
it "should display 1.1 as $1.10 [10 points]" , points: 10 do
expect(BookInStock.new('isbn11', 1.1).price_as_string).to eq('$1.10')
end
it "should display 20 as $20.00 [10 points]" , points: 10 do
expect(BookInStock.new('isbn11', 20).price_as_string).to eq('$20.00')
end
end
end