-
-
Notifications
You must be signed in to change notification settings - Fork 518
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[New Concept]: Range #1569
[New Concept]: Range #1569
Changes from 2 commits
f069b1b
f4329ae
ed0f087
f95af79
ec60828
1d07871
84ee065
d1c2ab0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"blurb": "Ruby has a Range object which represents an interval between two values.", | ||
"authors": [ | ||
"meatball133" | ||
], | ||
"contributors": [] | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,125 @@ | ||||||||||||||||||||||||||
# Ranges | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
[Ranges][ranges] represents an interval between two values. | ||||||||||||||||||||||||||
The most common types that support ranges are `Int` and `String`. | ||||||||||||||||||||||||||
They can be used for many things like quickly creating a collection, slicing strings, checking if a value is in a range and iteration. | ||||||||||||||||||||||||||
They are created using the range operator `..` or `...` (inclusive and exclusive respectively). | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```ruby | ||||||||||||||||||||||||||
1..5 # => 1, 2, 3, 4, 5 | ||||||||||||||||||||||||||
1...5 # => 1, 2, 3, 4 | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
The reason for having two range operators is to allow to create ranges that are inclusive or exclusive of the end value, which can be useful when for example working with indexes, that are zero based. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Ranges can also be created using the `Range` initializer. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```ruby | ||||||||||||||||||||||||||
Range.new(1, 5) # => 1, 2, 3, 4, 5 | ||||||||||||||||||||||||||
kotp marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
````exercism/note | ||||||||||||||||||||||||||
When creating a range in Ruby using the range operators `..` or `...`, and wanting to call a method on the range, you need to wrap the range in parentheses. | ||||||||||||||||||||||||||
This is because the otherwise will the method be called on the 2nd argument of the range operator. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```ruby | ||||||||||||||||||||||||||
(1..5).sum # => 15 | ||||||||||||||||||||||||||
1..5.sum # => Error: undefined method `sum' for 5:Integer (NoMethodError) | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
```` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
## Getting substrings | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
When wanting to slice a string, you can use the range operator to get a substring. | ||||||||||||||||||||||||||
That is by creating a range with the start and end index of the substring. | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```ruby | ||||||||||||||||||||||||||
"Hello World"[0..4] # => "Hello" | ||||||||||||||||||||||||||
"Hello World"[6..10] # => "World" | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
You can also use negative indexes to get the substring from the end of the string. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```ruby | ||||||||||||||||||||||||||
"Hello World"[-5..-1] # => "World" | ||||||||||||||||||||||||||
"Hello World"[6..-4] # => "Wor" | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
## Range methods | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Ranges do have a set of methods that can be used to work with them. | ||||||||||||||||||||||||||
These methods when for example want to get the sum of all the values in the range, or check if the range includes a value. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
| Method | Description | Example | | ||||||||||||||||||||||||||
| ----------------------- | ----------------------------------------------------------------------- | ------------------------------- | | ||||||||||||||||||||||||||
| [`sum`][sum] | Returns the sum of all the values in the range | `(1..5).sum # => 15` | | ||||||||||||||||||||||||||
| [`size`][size] | Returns the size of the range | `(1..5).size # => 5` | | ||||||||||||||||||||||||||
| [`include?`][indlude] | Returns `true` if the range includes the given value, otherwise `false` | `(1..5).include?(3) # => true` | | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
## Endless & Beginless ranges | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
There are two special types of ranges, the endless and beginless ranges. | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if they are really special ranges, or if this is more "syntactic sugar" that lets us express the normal ranges like this. |
||||||||||||||||||||||||||
This means that the range has no beginning or end. | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we terminate them with negative infinity and positive infinity, then we can see that they do have a beginning or end. |
||||||||||||||||||||||||||
The endless or beginless range has there start or end value being `nil`, but when defining the range so can nil be omitted. | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I do not think this is true, demonstrably. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looking in the docs are there also mention of nil: https://rubyapi.org/3.2/o/range. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks. That is why I said think... and did it in an REPL, to verify. Seems like it has changed for newer versions of Ruby. So I would then expect it to no longer be a terminated by infinity anything, and perhaps "undefined" in behavior. I will definitely look at the source code. Pretty sure the use will not change from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, you sent a picture too. Whatever it is, I a sure it supports your statement. Not at a good device at the moment to get interpretations for pictures. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just for information, I happened to have a Pry session open, where Pry has a bug that does not show this as it is supposed to. That was the reason it was broken as shown. Not the syntax itself. "Bad Pry!"
meatball133 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Using beginless and endless ranges is useful when you want to for example slice a string from the beginning or to the end. | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```ruby | ||||||||||||||||||||||||||
"Hello World"[0..] # => "Hello World" | ||||||||||||||||||||||||||
"Hello World"[4..] # => "o World" | ||||||||||||||||||||||||||
"Hello World"[..5] # => "Hello" | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```exercism/caution | ||||||||||||||||||||||||||
If not used on a collection, the endless range can cause an infinite loop, if not used with caution. | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Because it does not loop, it is more an endless sequence than and endless loop. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I mean it could cause an infinte loop if you iterate over the sequence, but yes I think saying it is an endless sequence is better. |
||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
## String ranges | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
Strings can also be used in ranges and allow one to get an interval of strings between two strings. | ||||||||||||||||||||||||||
But its behavior is a bit different than with chars, when using multiple characters in a string range. | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I believe you may be referring to the method, and so that should be code formatted. |
||||||||||||||||||||||||||
Its behavior can become when doing more complex string ranges, so use it with caution. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```ruby | ||||||||||||||||||||||||||
"aa".."az" # => "aa", "ab", "ac", ..., "az" | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
We could use a smaller sequence as well, and still demonstrate this, so we do not have to allude to the missing content. |
||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
## Custom objects in ranges | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
````exercism/advanced | ||||||||||||||||||||||||||
Ruby allows to use custom objects in ranges, the requirement for this is that the object implements the following: | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
- include the `Comparable` module | ||||||||||||||||||||||||||
- `succ` method | ||||||||||||||||||||||||||
- `<=>` method | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
These methods make it so that the range can iterate over the object, and compare the objects in the range. | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
```ruby | ||||||||||||||||||||||||||
class Foo | ||||||||||||||||||||||||||
include Comparable | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
attr_reader :value | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def initialize(value) | ||||||||||||||||||||||||||
@value = value | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def succ | ||||||||||||||||||||||||||
Foo.new(value + 1) | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
def <=>(other) | ||||||||||||||||||||||||||
value <=> other.value | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
(Foo.new(1)..Foo.new(5)) | ||||||||||||||||||||||||||
# => #<Foo:0x7f3552bebe70 @value=1>, #<Foo:0x7f3552bebe50 @value=2>, #<Foo:0x7f3552bebe40 @value=3>, #<Foo:0x7f3552bebe30 @value=4>, #<Foo:0x7f3552bebe20 @value=5> | ||||||||||||||||||||||||||
``` | ||||||||||||||||||||||||||
```` | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
[range]: https://rubyapi.org/o/range | ||||||||||||||||||||||||||
[sum]: https://rubyapi.org/o/enumerable#method-i-sum | ||||||||||||||||||||||||||
[size]: https://rubyapi.org/o/range#method-i-size | ||||||||||||||||||||||||||
[indlude]: https://rubyapi.org/o/range#method-i-include-3F |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# Ranges | ||
|
||
[Ranges][ranges] represents an interval between two values. | ||
The most common types that support ranges are `Int` and `String`. | ||
They can be used for many things like quickly creating a collection, slicing strings, checking if a value is in a range and iteration. | ||
They are created using the range operator `..` or `...` (inclusive and exclusive respectively). | ||
|
||
```ruby | ||
1..5 # => 1, 2, 3, 4, 5 | ||
1...5 # => 1, 2, 3, 4 | ||
``` | ||
|
||
The reason for having two range operators is to allow to create ranges that are inclusive or exclusive of the end value, which can be useful when for example working with indexes, that are zero based. | ||
|
||
Ranges can also be created using the `Range` initializer. | ||
|
||
```ruby | ||
Range.new(1, 5) # => 1, 2, 3, 4, 5 | ||
``` | ||
|
||
````exercism/note | ||
When creating a range in Ruby using the range operators `..` or `...`, and wanting to call a method on the range, you need to wrap the range in parentheses. | ||
This is because the otherwise will the method be called on the 2nd argument of the range operator. | ||
|
||
```ruby | ||
(1..5).sum # => 15 | ||
1..5.sum # => Error: undefined method `sum' for 5:Integer (NoMethodError) | ||
``` | ||
```` | ||
|
||
## Getting substrings | ||
|
||
When wanting to slice a string, you can use the range operator to get a substring. | ||
That is by creating a range with the start and end index of the substring. | ||
|
||
```ruby | ||
"Hello World"[0..4] # => "Hello" | ||
"Hello World"[6..10] # => "World" | ||
``` | ||
|
||
You can also use negative indexes to get the substring from the end of the string. | ||
|
||
```ruby | ||
"Hello World"[-5..-1] # => "World" | ||
"Hello World"[6..-4] # => "Wor" | ||
``` | ||
|
||
## Range methods | ||
|
||
Ranges do have a set of methods that can be used to work with them. | ||
These methods when for example want to get the sum of all the values in the range, or check if the range includes a value. | ||
|
||
| Method | Description | Example | | ||
| ----------------------- | ----------------------------------------------------------------------- | ------------------------------- | | ||
| [`sum`][sum] | Returns the sum of all the values in the range | `(1..5).sum # => 15` | | ||
| [`size`][size] | Returns the size of the range | `(1..5).size # => 5` | | ||
| [`include?`][indlude] | Returns `true` if the range includes the given value, otherwise `false` | `(1..5).include?(3) # => true` | | ||
|
||
## Endless & Beginless ranges | ||
|
||
There are two special types of ranges, the endless and beginless ranges. | ||
This means that the range has no beginning or end. | ||
The endless or beginless range has there start or end value being `nil`, but when defining the range so can nil be omitted. | ||
|
||
Using beginless and endless ranges is useful when you want to for example slice a string from the beginning or to the end. | ||
|
||
```ruby | ||
"Hello World"[0..] # => "Hello World" | ||
"Hello World"[4..] # => "o World" | ||
"Hello World"[..5] # => "Hello" | ||
``` | ||
|
||
```exercism/caution | ||
If not used on a collection, the endless range can cause an infinite loop, if not used with caution. | ||
``` | ||
|
||
## String ranges | ||
|
||
Strings can also be used in ranges and allow one to get an interval of strings between two strings. | ||
But its behavior is a bit different than with chars, when using multiple characters in a string range. | ||
Its behavior can become when doing more complex string ranges, so use it with caution. | ||
|
||
```ruby | ||
"aa".."az" # => "aa", "ab", "ac", ..., "az" | ||
``` | ||
|
||
[range]: https://rubyapi.org/o/range | ||
[sum]: https://rubyapi.org/o/enumerable#method-i-sum | ||
[size]: https://rubyapi.org/o/range#method-i-size | ||
[indlude]: https://rubyapi.org/o/range#method-i-include-3F |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[ | ||
{ | ||
"url": "https://www.rubyguides.com/2016/06/ruby-ranges-how-do-they-work/", | ||
"description": "Ruby Guides: Ruby Ranges: How Do They Work?" | ||
}, | ||
{ | ||
"url": "https://rubyapi.org/o/range", | ||
"description": "Ruby api: Ranges" | ||
} | ||
] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# Hints | ||
|
||
## 1. Define rank & file range | ||
|
||
- You need to define two [constant][constants] that should hold a [`Range`][range] of ranks and files. | ||
- The ranks should be an [`Int`][integers] `range` from 1 to 8. | ||
- The files should be a [`String`][string] `Range` from 'A' to 'H'. | ||
- The constant needs to be defined in the `Chess` [module][module]. | ||
|
||
## 2. Check if square is valid | ||
|
||
- You need to check if a value is within a range. | ||
- There is [a method][include] that can be used to check if a value is within a range. | ||
|
||
## 3. Get player's nickname | ||
|
||
- You can get a slice by using a `Range` as input. | ||
- There is a [method][upcase] that can be used to upcase a string. | ||
|
||
## 4. Create move message | ||
|
||
- You can index the square string to get the rank and file. | ||
- You can use already defined methods to get the nickname of the player, and to check if the move is valid. | ||
|
||
[constants]: https://www.rubyguides.com/2017/07/ruby-constants/ | ||
[integers]: https://rubyapi.org/o/integer | ||
[string]: https://rubyapi.org/o/string | ||
[module]: https://rubyapi.org/o/module | ||
[include]: https://rubyapi.org/o/range#method-i-include-3F | ||
[range]: https://rubyapi.org/o/range | ||
[upcase]: https://rubyapi.org/o/string#method-i-upcase |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Instructions | ||
|
||
As a chess enthusiast, you would like to write your own version of the game. | ||
Yes, there maybe plenty of implementations of chess available online already, but yours will be unique! | ||
|
||
You start with implementing a basic movement system for the pieces. | ||
|
||
The chess game will be played on a board that is 8 squares wide and 8 squares high. | ||
The squares are identified by a letter and a number. | ||
|
||
## 1. Define rank & file range | ||
|
||
The game will have to store the ranks of the board. | ||
The ranks are the rows of the board, and are numbered from 1 to 8. | ||
|
||
The game will also have to store the files of the board. | ||
The files are the columns of the board, and are identified by the letters A to H. | ||
|
||
Define the `Chess::Ranks` and `Chess::Files` constants that store the range of ranks and files respectively. | ||
|
||
```ruby | ||
Chess::Ranks | ||
# => 1..8 | ||
|
||
Chess::Files | ||
# => 'A'..'H' | ||
``` | ||
|
||
## 2. Check if square is valid | ||
|
||
The game will have to check if a square is valid. | ||
A square is valid if the rank and file are within the range of ranks and files. | ||
|
||
Define the `Chess.valid_square?` method that takes the arguments `rank` that holds an int of the rank, and `file` that holds a char of the file. | ||
The method should return `true` if the rank and file are within the range of ranks and files, and return `false` otherwise. | ||
|
||
```ruby | ||
Chess.valid_square?(1, 'A') | ||
# => true | ||
``` | ||
|
||
## 3. Get player's nickname | ||
|
||
The game will have to get the nickname of the player. | ||
The nickname is the first 2 characters of the player's first name, and the last 2 characters of the player's last name. | ||
The nickname should be capitalized. | ||
|
||
Define the `Chess.nickname` method that takes the arguments `first_name` that holds a string of the player's first name, and `last_name` that holds a string of the player's last name. | ||
The method should return the nickname of the player as capitalized string. | ||
|
||
```ruby | ||
Chess.nickname("John", "Doe") | ||
# => "JOOE" | ||
``` | ||
|
||
## 4. Create move message | ||
|
||
The game will have to create a message for a move, to say which player moved to which square. | ||
The message should use the player's nickname, and the square they moved to. | ||
The game also have to determine if the move is valid by checking if the file and rank of the square are within the range of files and ranks. | ||
|
||
If the move is valid, the message should be: `"{nickname} moved to {square}}"` | ||
If the move is invalid, the message should be: `"{nickname} attempted to move to {square}, but that is not a valid square"` | ||
|
||
Define the `Chess.move_message` method that takes the arguments `first_name` that holds a string of the player's first_name, `last_name` that holds a string of the player's last_name, `square` that holds a string of the square the player moved to. | ||
The method should return the message for the move as a string. | ||
|
||
```ruby | ||
Chess.move_message("John", "Doe", "A1") | ||
# => "JOOE moved to A1" | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return is not what this statement returns, as we can see. Using IRB, since IRB "evaluated" syntax is being used here in the code example:
What do you think? The return is not like it would be with an Array.
Probably not in this section, but we can coerce this to an Array to show what is originally here: