-
-
Notifications
You must be signed in to change notification settings - Fork 36
Initial check-in of solution. #6
base: master
Are you sure you want to change the base?
Changes from all commits
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,2 @@ | ||
| --color | ||
| --format progress |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| source 'https://rubygems.org' | ||
|
|
||
| gem 'rspec' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| GEM | ||
| remote: https://rubygems.org/ | ||
| specs: | ||
| diff-lcs (1.2.4) | ||
| 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) | ||
|
|
||
| PLATFORMS | ||
| ruby | ||
|
|
||
| DEPENDENCIES | ||
| rspec |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| require 'Matrix' | ||
|
|
||
| class SudokuValidator | ||
| def initialize(file=nil) | ||
| return if file.nil? | ||
|
|
||
| puzzle = [] | ||
| open(file).each do |line| | ||
| row = line.gsub(/[|\-+]/, "") | ||
| unless row.strip.empty? | ||
| puzzle.push(row.split(' ').map{|x| x == '.' ? nil : x.to_i}) | ||
| end | ||
| end | ||
|
|
||
| @puzzle = Matrix.rows(puzzle) | ||
|
Contributor
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. 👍 for using |
||
| end | ||
|
|
||
| def valid? | ||
| return false if @puzzle.nil? | ||
| return validate(@puzzle) | ||
| end | ||
|
|
||
| def complete? | ||
| @puzzle.row_vectors.each do |row| | ||
|
Contributor
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. You could say: def complete?
@puzzle.row_vectors.all?(&:all?)
end
The line above checks that all the vectors have all non-nil values. |
||
| return false if row.include? nil | ||
| end | ||
| true | ||
| end | ||
|
|
||
| def validate(puzzle) | ||
| valid_puzzle?(puzzle) && valid_rows?(puzzle) && valid_columns?(puzzle) && valid_submatricies?(puzzle) | ||
| end | ||
|
|
||
| def valid_puzzle?(puzzle) | ||
| puzzle.square? && (puzzle.row_count % 3) == 0 | ||
| end | ||
|
|
||
| def valid_rows?(puzzle) | ||
| puzzle.row_vectors.each do |row| | ||
|
Contributor
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. You probably want to use def valid_rows(puzzle)
puzzle.row_vectors.all? do |row|
grouping_valid?(row)
end
endThis checks that all rows have a valid grouping. |
||
| return false unless grouping_valid?(row) | ||
| end | ||
|
|
||
| true | ||
| end | ||
|
|
||
| def valid_columns?(puzzle) | ||
| puzzle.column_vectors.each do |column| | ||
| return false unless grouping_valid?(column) | ||
| end | ||
|
|
||
| true | ||
| end | ||
|
|
||
| def valid_submatricies?(puzzle) | ||
| (puzzle.row_count / 3).times do |row| | ||
| (puzzle.column_count / 3).times do |column| | ||
| subpuzzle = puzzle.minor(3*row..(3*row)+2, 3*column..(3*column)+2) | ||
| flattened = [] | ||
| subpuzzle.row_vectors.each do |subrow| | ||
| flattened += subrow.to_a | ||
| end | ||
| return false unless grouping_valid?(flattened) | ||
| end | ||
| end | ||
|
|
||
| true | ||
| end | ||
|
|
||
| def grouping_valid?(set) | ||
| values = Hash.new(0) | ||
| set.each do |value| | ||
|
Contributor
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. You are looking to see there are any duplicates in a def grouping_valid?(set)
set.to_a.length == set.to_a.uniq.length
end
Author
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. Nice! I really like this way of doing it -- very clean. |
||
| values[value] += 1 unless value == nil | ||
| end | ||
|
|
||
| values.find{|k, v| v > 1 } == nil | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| # This file was generated by the `rspec --init` command. Conventionally, all | ||
| # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. | ||
| # Require this file using `require "spec_helper"` to ensure that it is only | ||
| # loaded once. | ||
| # | ||
| # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration | ||
| RSpec.configure do |config| | ||
| config.treat_symbols_as_metadata_keys_with_true_values = true | ||
| config.run_all_when_everything_filtered = true | ||
| config.filter_run :focus | ||
|
|
||
| # Run specs in random order to surface order dependencies. If you find an | ||
| # order dependency and want to debug it, you can fix the order by providing | ||
| # the seed, which is printed after each run. | ||
| # --seed 1234 | ||
| config.order = 'random' | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| require 'sudoku_validator' | ||
|
|
||
| describe SudokuValidator do | ||
| before (:each) do | ||
| @validator = SudokuValidator.new | ||
| end | ||
|
|
||
| it "has no duplicates in a row" do | ||
| validPuzzle = Matrix[[1,2,3],[nil,nil,nil],[nil,nil,nil]] | ||
| @validator.validate(validPuzzle).should be_true | ||
|
|
||
| invalidPuzzle = Matrix[[1,1,2],[nil,nil,nil],[nil,nil,nil]] | ||
| @validator.validate(invalidPuzzle).should be_false | ||
| end | ||
|
|
||
| it "has no duplicates in a column" do | ||
| validPuzzle = Matrix[[1,nil,nil],[2,nil,nil],[3,nil,nil]] | ||
| @validator.validate(validPuzzle).should be_true | ||
|
|
||
| invalidPuzzle = Matrix[[1,nil,nil], [1,nil,nil], [2,nil,nil]] | ||
| @validator.validate(invalidPuzzle).should be_false | ||
| end | ||
|
|
||
| it "has no duplicates in a sub-grid" do | ||
| validPuzzle = Matrix[[1,2,3],[4,5,6],[7,8,9]] | ||
| @validator.validate(validPuzzle).should be_true | ||
|
|
||
| invalidPuzzle = Matrix[[1,2,3],[4,5,6],[7,8,1]] | ||
| @validator.validate(invalidPuzzle).should be_false | ||
| end | ||
|
|
||
| it "validates files" do | ||
| vc = SudokuValidator.new("valid_complete.sudoku") | ||
| vc.valid?.should be_true | ||
| vc.complete?.should be_true | ||
|
|
||
| vi = SudokuValidator.new("valid_incomplete.sudoku") | ||
| vi.valid?.should be_true | ||
| vi.complete?.should be_false | ||
|
|
||
| ic = SudokuValidator.new("invalid_complete.sudoku") | ||
| ic.valid?.should be_false | ||
| ic.complete?.should be_true | ||
|
|
||
| ii = SudokuValidator.new("invalid_incomplete.sudoku") | ||
| ii.valid?.should be_false | ||
| ii.complete?.should be_false | ||
| end | ||
| end |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| #!/usr/bin/env ruby | ||
| require_relative 'lib/sudoku_validator' | ||
|
|
||
| validator = SudokuValidator.new(ARGV[0]) | ||
| puts "This sudoku is #{!validator.valid? ? "in" : ""}valid#{validator.valid? && !validator.complete? ? ", but incomplete" : ""}." |
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.
String#splitcan accept a regex.