This repository was archived by the owner on Jun 8, 2019. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 36
First try #4
Open
gniquil
wants to merge
6
commits into
thoughtbot:master
Choose a base branch
from
gniquil:master
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
First try #4
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
fea4798
first try
gniquil cd7b3f2
correct a few words and added some "pictures" for clarity
gniquil a1332c9
added errors
gniquil aa0e950
refactored and clarified the code a bit more
gniquil c896ad1
renamed and changed reset_errors
gniquil 304b8cf
moved class methods to instance and made some methods clearer
gniquil File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| /tmp |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| --color |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
|
|
||
| gem 'rspec' | ||
| gem 'guard-rspec' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| GEM | ||
| specs: | ||
| celluloid (0.15.2) | ||
| timers (~> 1.1.0) | ||
| coderay (1.0.9) | ||
| diff-lcs (1.2.4) | ||
| ffi (1.9.0) | ||
| formatador (0.2.4) | ||
| guard (2.0.3) | ||
| formatador (>= 0.2.4) | ||
| listen (~> 2.0) | ||
| lumberjack (~> 1.0) | ||
| pry (>= 0.9.12) | ||
| thor (>= 0.18.1) | ||
| guard-rspec (3.1.0) | ||
| guard (>= 1.8) | ||
| rspec (~> 2.13) | ||
| listen (2.0.1) | ||
| celluloid (>= 0.15.2) | ||
| rb-fsevent (>= 0.9.3) | ||
| rb-inotify (>= 0.9) | ||
| lumberjack (1.0.4) | ||
| method_source (0.8.2) | ||
| pry (0.9.12.2) | ||
| coderay (~> 1.0.5) | ||
| method_source (~> 0.8) | ||
| slop (~> 3.4) | ||
| rb-fsevent (0.9.3) | ||
| rb-inotify (0.9.2) | ||
| ffi (>= 0.5.0) | ||
| rspec (2.14.1) | ||
| rspec-core (~> 2.14.0) | ||
| rspec-expectations (~> 2.14.0) | ||
| rspec-mocks (~> 2.14.0) | ||
| rspec-core (2.14.5) | ||
| rspec-expectations (2.14.3) | ||
| diff-lcs (>= 1.1.3, < 2.0) | ||
| rspec-mocks (2.14.3) | ||
| slop (3.4.6) | ||
| thor (0.18.1) | ||
| timers (1.1.0) | ||
|
|
||
| PLATFORMS | ||
| ruby | ||
|
|
||
| DEPENDENCIES | ||
| guard-rspec | ||
| rspec |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
|
|
||
| guard :rspec, cli: "--tag ~@external" do | ||
| watch(%r{^spec/.+_spec\.rb$}) | ||
| watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" } | ||
| watch('spec/spec_helper.rb') { "spec" } | ||
| watch(%r{^spec/support/.+\.rb$}) { "spec" } | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
|
|
||
| class SudokuReader | ||
|
|
||
| def self.reader_from_file(file_path) | ||
| reader = SudokuReader.new | ||
| reader.read(file_path) | ||
| reader | ||
| end | ||
|
|
||
| attr_reader :grid | ||
|
|
||
| def initialize | ||
| @grid = [] | ||
| end | ||
|
|
||
| def read(file_path) | ||
| open(file_path).each do |line| | ||
| parsed_line = parse_line line | ||
| @grid << parsed_line if parsed_line | ||
| end | ||
| end | ||
|
|
||
| def parse_line(line) | ||
| line.split(/[^\d\.]+/) unless separator_line? line | ||
| end | ||
|
|
||
| def separator_line?(line) | ||
| line =~/^-+/ | ||
| end | ||
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,119 @@ | ||
| class SudokuValidator | ||
|
|
||
| attr_reader :grid | ||
| attr_reader :errors | ||
|
|
||
| def initialize(file_path) | ||
| @grid = SudokuReader.reader_from_file(file_path).grid | ||
| @errors = { | ||
| invalid: { | ||
| column: [], | ||
| row: [], | ||
| subgrid: [] | ||
| }, | ||
| incomplete: { | ||
| column: [], | ||
| row: [], | ||
| subgrid: [] | ||
| } | ||
| } | ||
| end | ||
|
|
||
| def valid_array?(array) | ||
| numbers_only(array).uniq.length == numbers_only(array).length | ||
| end | ||
|
|
||
| def complete_array?(array) | ||
| numbers_only(array).length == 9 | ||
| end | ||
|
|
||
| def numbers_only(array) | ||
| array.reject { |el| el == "." } | ||
| end | ||
|
|
||
| def array_is?(validation_type, array) | ||
| if validation_type == :invalid | ||
| not valid_array? array | ||
| else | ||
| not complete_array? array | ||
| end | ||
| end | ||
|
|
||
| def row(i) | ||
| grid[i-1] | ||
| end | ||
|
|
||
| def column(i) | ||
| grid.map { |row| row[i-1] } | ||
| end | ||
|
|
||
| # subgrid is laid out as below | ||
| # 1-based 0-based | ||
| # 1 2 3 0 1 2 <- grid_index for column | ||
| # 1 - 3 4 - 6 7 - 9 0 - 2 3 - 5 6 - 8 | ||
| # 1 . . . | . . . | . . . 0 . . . | . . . | . . . | ||
| # 1 | . 1 . | . 2 . | . 3 . 0 | . 0 . | . 1 . | . 2 . | ||
| # 3 . . . | . . . | . . . 2 . . . | . . . | . . . | ||
| # +-----+-------+-----+ +-----+-------+-----+ | ||
| # 4 . . . | . . . | . . . 3 . . . | . . . | . . . | ||
| # 2 | . 4 . | . 5 . | . 6 . 1 | . 3 . | . 4 . | . 5 . | ||
| # 6 . . . | . . . | . . . 5 . . . | . . . | . . . | ||
| # +-----+-------+-----+ +-----+-------+-----+ | ||
| # 7 . . . | . . . | . . . 6 . . . | . . . | . . . | ||
| # 3 | . 7 . | . 8 . | . 9 . 2 | . 6 . | . 7 . | . 8 . | ||
| # 9 . . . | . . . | . . . 8 . . . | . . . | . . . | ||
| # | ||
| # ^ | ||
| # grid_index for row | ||
| # | ||
| def subgrid(i) | ||
| grid[row_starts_for_grid(i), 3].map do |row| | ||
| row[column_starts_for_grid(i), 3] | ||
| end.flatten | ||
| end | ||
|
|
||
| def row_starts_for_grid(i) | ||
| zero_based(i) / 3 * 3 | ||
| end | ||
|
|
||
| def column_starts_for_grid(i) | ||
| zero_based(i) % 3 * 3 | ||
| end | ||
|
|
||
| def zero_based(i) | ||
| i - 1 | ||
| end | ||
|
|
||
| def validate! | ||
| reset_errors! | ||
| [:invalid, :incomplete].each do |error_type| | ||
| [:row, :column, :subgrid].each do |array_type| | ||
| (1..9).each do |i| | ||
| errors[error_type][array_type] << i if array_is? error_type, send(array_type, i) | ||
| end | ||
| end | ||
| end | ||
| end | ||
|
|
||
| def valid? | ||
| [:row, :column, :subgrid].all? { |array_type| errors[:invalid][array_type].none? } | ||
| end | ||
|
|
||
| def complete? | ||
| [:row, :column, :subgrid].all? { |array_type| errors[:incomplete][array_type].none? } | ||
| end | ||
|
|
||
| def reset_errors! | ||
| [:invalid, :incomplete].each do |error_type| | ||
| [:row, :column, :subgrid].each do |array_type| | ||
| errors[error_type][array_type].clear | ||
| end | ||
| end | ||
| end | ||
|
|
||
| def error_messages(type) | ||
| errors[type].map do |key, vals| | ||
| "#{type} #{key}s: #{vals.join(", ")}" if vals.any? | ||
| end.compact.sort | ||
| end | ||
| end | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| 8 5 9 |6 1 2 |4 3 7 | ||
| 7 2 3 |8 5 4 |1 6 9 | ||
| 1 6 4 |3 7 9 |5 2 8 | ||
| ------+------+------ | ||
| 9 8 6 |1 4 7 |3 5 2 | ||
| 3 7 5 |8 6 2 |9 1 4 | ||
| 2 4 1 |5 9 3 |7 8 6 | ||
| ------+------+------ | ||
| 4 3 2 |9 8 1 |6 7 5 | ||
| 6 1 7 |4 2 5 |8 9 3 | ||
| 5 9 8 |7 3 6 |2 4 1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| 8 5 . |. . 2 |4 . . | ||
| 7 2 . |. 8 . |. . 9 | ||
| . . 4 |. . . |. . . | ||
| ------+------+------ | ||
| . . . |1 . 7 |. . 2 | ||
| 3 . 5 |. . . |9 . . | ||
| . 4 . |. . . |. . . | ||
| ------+------+------ | ||
| . 5 . |. 8 . |. 7 . | ||
| . 1 7 |. . . |. . . | ||
| . . . |. 3 6 |. 4 . |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| 8 5 9 |6 1 2 |4 3 7 | ||
| 7 2 3 |8 5 4 |1 6 9 | ||
| 1 6 4 |3 7 9 |5 2 8 | ||
| ------+------+------ | ||
| 9 8 6 |1 4 7 |3 5 2 | ||
| 3 7 5 |2 6 8 |9 1 4 | ||
| 2 4 1 |5 9 3 |7 8 6 | ||
| ------+------+------ | ||
| 4 3 2 |9 8 1 |6 7 5 | ||
| 6 1 7 |4 2 5 |8 9 3 | ||
| 5 9 8 |7 3 6 |2 4 1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| 8 5 . |. . 2 |4 . . | ||
| 7 2 . |. . . |. . 9 | ||
| . . 4 |. . . |. . . | ||
| ------+------+------ | ||
| . . . |1 . 7 |. . 2 | ||
| 3 . 5 |. . . |9 . . | ||
| . 4 . |. . . |. . . | ||
| ------+------+------ | ||
| . . . |. 8 . |. 7 . | ||
| . 1 7 |. . . |. . . | ||
| . . . |. 3 6 |. 4 . |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| require 'spec_helper' | ||
|
|
||
| describe SudokuReader do | ||
|
|
||
| let(:reader) { SudokuReader.new } | ||
|
|
||
| describe '#parse_line' do | ||
| it 'returns an array' do | ||
| parsed_line = reader.parse_line "8 5 9 |6 1 2 |4 3 7 " | ||
|
|
||
| expect(parsed_line).to eq ["8", "5", "9", "6", "1", "2", "4", "3", "7"] | ||
|
|
||
| parsed_line = reader.parse_line ". . . |. 8 . |. 7 . " | ||
|
|
||
| expect(parsed_line).to eq [".", ".", ".", ".", "8", ".", ".", "7", "."] | ||
|
|
||
| parsed_line = reader.parse_line "------+------+------" | ||
|
|
||
| expect(parsed_line).to be_nil | ||
| end | ||
| end | ||
|
|
||
| describe '#separator_line?' do | ||
| it 'returns true if the line is -----' do | ||
| line = "------+------+------" | ||
|
|
||
| expect(reader.separator_line?(line)).to be_true | ||
|
|
||
| line = "8 5 9 |6 1 2 |4 3 7 " | ||
|
|
||
| expect(reader.separator_line?(line)).to be_false | ||
|
|
||
| line = ". . . |. 8 . |. 7 . " | ||
|
|
||
| expect(reader.separator_line?(line)).to be_false | ||
| end | ||
| end | ||
|
|
||
| describe '#read' do | ||
| it 'reads and stores the file into an array' do | ||
| reader.read fixture_path('valid_incomplete.sudoku') | ||
|
|
||
| expect(reader.grid.length).to eq 9 # rows | ||
| reader.grid.each do |row| | ||
| expect(row.length).to eq 9 # columns | ||
| end | ||
| expect(reader.grid[0][4]).to eq "." | ||
| expect(reader.grid[2][2]).to eq "4" | ||
| end | ||
| end | ||
|
|
||
| describe '#reader_from_file' do | ||
| it 'creates an instance of reader with a grid generated from file' do | ||
| reader = SudokuReader.reader_from_file(fixture_path('valid_incomplete.sudoku')) | ||
|
|
||
| expect(reader.grid.length).to eq 9 | ||
| expect(reader.grid[0][4]).to eq "." | ||
| expect(reader.grid[2][2]).to eq "4" | ||
| end | ||
| end | ||
| end |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
There is a lot of complexity in this method. Extracting functionality into small, well-named private methods would make this a lot easier to read.
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.
improved... take a look at the new implementation. Thanks for pointing this out.