Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion exercises/allergies/allergies_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ def test_allergic_to_lots_of_stuff
def test_allergic_to_everything
skip
allergies = Allergies.new(255)
# rubocop:disable Metrics/LineLength
expected = %w(eggs peanuts shellfish strawberries tomatoes chocolate pollen cats)
assert_equal expected, allergies.list
end
Expand Down
163 changes: 100 additions & 63 deletions exercises/alphametics/example.rb
Original file line number Diff line number Diff line change
@@ -1,98 +1,135 @@
module BookKeeping
VERSION = 3
VERSION = 4
end

class Alphametics
def solve(puzzle)
letters = Hash.new(0)
puzzle.scan(/[a-zA-Z]/) { |w| letters[w] += 1 }

possible_values(letters.keys) do |letters_values|
return letters_values if valid?(puzzle, letters_values)
end
def self.solve(equation)
new.solve(equation)
end

nil
def solve(equation)
@prime_solver = AlphaSolver.new(equation)
solve_using_partials
end

private

def possible_values(letters)
(0..9).to_a.combination(letters.length) do |combined_integers|
combined_integers.permutation do |permutated_integers|
yield permutated_integers.map.with_index { |integer, index|
[letters[index], integer]
}.to_h
end
attr_accessor :prime_solver

def solve_using_partials
prime_solver.partial_solutions.each do |partial_solution|
sub_solver = AlphaSolver.new(prime_solver.partial_equation(partial_solution))
sub_solution = sub_solver.first_solution
return sub_solution.merge(partial_solution) if sub_solution
end
{}
end

def valid?(puzzle, letters_values)
equation = puzzle.gsub(/[a-zA-Z]/, letters_values)
Equation.new(equation).valid?
end
end

class Equation
attr_reader :equation
class AlphaSolver

def initialize(equation)
@equation = equation
def initialize(input_equation)
@input_equation = input_equation.gsub('^', '**')
@puzzle = Puzzle.new(input_equation)
end

def valid?
return false if has_leading_zeros?
def partial_solutions
AlphaSolver.new(puzzle.simplified).all_solutions
end

expression, result = equation.split('==')
def all_solutions
numeric_permutations.map { |values| result_table if solution?(values) }.compact
end

numbers = []
operators = []
def first_solution
numeric_permutations.each { |values| return result_table if solution?(values) }
nil
end

expression.scan(/\d+|\+|\-|\*|\/|\^/).each do |token|
case token
when /^\d+$/
numbers.push(token.to_i)
when '+', '-', '*', '/', '^'
calculate_last(numbers, operators) if has_precedence?(operators, token)
operators.push(token)
end
end
def partial_equation(partial_solution)
input_equation.tr(partial_solution.keys.join, partial_solution.values.join)
end

until operators.empty?
calculate_last(numbers, operators)
end
private

attr_reader :input_equation, :puzzle
attr_accessor :proposed_values

numbers.last == result.to_i
def solution?(values)
self.proposed_values = values.join
proposed_equation_qualified? && proposed_equation_evaluates?
end

private
def proposed_equation
input_equation.tr(puzzle_letters, proposed_values)
end

def has_leading_zeros?
equation.match(/^0\d+|\D0\d+/)
def numeric_permutations
puzzle.numeric_permutations
end

def has_precedence?(operators, token)
return false if operators.empty?
prev_operator = operators.last
def puzzle_letters
puzzle.letters
end

case token
when '+', '-'
prev_operator == '*' || prev_operator == '/' || prev_operator == '^'
when '*', '/'
prev_operator == '^'
else
false
end
def proposed_equation_qualified?
(proposed_equation =~ /\b0\d+/).nil?
end

def calculate_last(numbers, operators)
right = numbers.pop
left = numbers.pop
operator = as_ruby_operator(operators.pop)
result = left.send(operator, right)
numbers.push(result)
def proposed_equation_evaluates?
eval(proposed_equation)
end

def as_ruby_operator(operator)
operator == '^' ? '**' : operator
def result_table
Hash[puzzle_letters.chars.zip(result_numbers)]
end

def result_numbers
proposed_values.chars.map(&:to_i)
end

end

class Puzzle

PATTERNS = {mod_10: ' % 10',
adjacent_letters: /(\b)([A-Z]{1,})([A-Z])/,
equation_left_side: /(.*)( == )/}

def initialize(string_equation)
@string_equation = string_equation
end

def letters
@letters ||= string_equation.scan(/[A-Z]/).uniq.join
end

def numeric_permutations
@numeric_permutations ||= unused_numbers.to_a.permutation(letter_count)
end

def simplified
@simplified ||= string_equation
.gsub(PATTERNS[:adjacent_letters], "\\1\\3")
.gsub(PATTERNS[:equation_left_side], "(\\1)#{PATTERNS[:mod_10]}\\2")
end

private

attr_reader :string_equation

def letter_count
@letter_count ||= letters.length
end

def unused_numbers
@unused_numbers ||= (0..9).to_a.map(&:to_s) - used_numbers
end

def used_numbers
@used_numbers ||= string_equation.gsub(PATTERNS[:mod_10], '').scan(/\d/).uniq
end

end
1 change: 0 additions & 1 deletion exercises/atbash-cipher/atbash_cipher_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
require 'minitest/autorun'
require_relative 'atbash_cipher'

# rubocop:disable Style/MethodName
class AtbashTest < Minitest::Test
def test_encode_no
assert_equal 'ml', Atbash.encode('no')
Expand Down
3 changes: 1 addition & 2 deletions exercises/beer-song/beer_song_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
require 'minitest/autorun'
require_relative 'beer_song'

# rubocop:disable Metrics/LineLength
class BeerSongTest < Minitest::Test
def test_the_first_verse
expected = "99 bottles of beer on the wall, 99 bottles of beer.\n" \
Expand Down Expand Up @@ -62,7 +61,7 @@ def test_a_few_verses
assert_equal expected, BeerSong.new.verses(2, 0)
end

def test_the_whole_song # rubocop:disable Metrics/MethodLength
def test_the_whole_song
skip
expected = <<-SONG
99 bottles of beer on the wall, 99 bottles of beer.
Expand Down
2 changes: 1 addition & 1 deletion exercises/binary-search-tree/binary_search_tree_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_inserting_right
assert_equal 5, four.right.data
end

def test_complex_tree # rubocop:disable Metrics/MethodLength
def test_complex_tree
skip
four = Bst.new 4
four.insert 2
Expand Down
1 change: 0 additions & 1 deletion exercises/binary/example.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ def to_decimal

private

# rubocop:disable Style/WordArray
def valid?(s)
s.chars.all? { |char| ['0', '1'].include?(char) }
end
Expand Down
2 changes: 0 additions & 2 deletions exercises/circular-buffer/circular_buffer_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,6 @@ def test_forced_writes_to_non_full_buffer_should_behave_like_writes
assert_raises(CircularBuffer::BufferEmptyException) { buffer.read }
end

# rubocop:disable Metrics/MethodLength
def test_alternate_read_and_write_into_buffer_overflow
skip
buffer = CircularBuffer.new(5)
Expand All @@ -108,5 +107,4 @@ def test_alternate_read_and_write_into_buffer_overflow
assert_equal 'B', buffer.read
assert_raises(CircularBuffer::BufferEmptyException) { buffer.read }
end
# rubocop:enable Metrics/MethodLength
end
2 changes: 0 additions & 2 deletions exercises/clock/example.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ def initialize(hours=0, minutes=0)
@internal = hours * 60 + minutes
end

# rubocop:disable Style/OpMethod
def +(hours=0, minutes)
@internal += hours * 60 + minutes
self
Expand All @@ -21,7 +20,6 @@ def +(hours=0, minutes)
def -(*args)
self.+(*args.map(&:-@))
end
# rubocop:enable Style/OpMethod

def ==(other)
to_s == other.to_s
Expand Down
1 change: 0 additions & 1 deletion exercises/connect/connect_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ def test_x_wins_using_a_convoluted_path
assert_equal 'X', game.winner, 'X wins using a convoluted path'
end

# rubocop:disable MethodLength
def test_x_wins_using_a_spiral_path
skip
board = [
Expand Down
1 change: 0 additions & 1 deletion exercises/custom-set/custom_set_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,6 @@ def test_intersection_of_two_sets_with_no_shared_elements_is_an_empty_set
assert_equal expected, set2.intersection(set1)
end

# rubocop:disable Metrics/LineLength
def test_intersection_of_two_sets_with_shared_elements_is_a_set_of_the_shared_elements
skip
set1 = CustomSet.new [1, 2, 3, 4]
Expand Down
1 change: 0 additions & 1 deletion exercises/diamond/diamond_test.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# rubocop:disable Metrics/MethodLength
# !/usr/bin/env ruby
gem 'minitest', '>= 5.0.0'
require 'minitest/autorun'
Expand Down
2 changes: 1 addition & 1 deletion exercises/etl/etl_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_more_keys
assert_equal expected, ETL.transform(old)
end

def test_full_dataset # rubocop:disable Metrics/MethodLength
def test_full_dataset
skip
old = {
1 => %w(A E I O U L N R S T),
Expand Down
1 change: 0 additions & 1 deletion exercises/house/house_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
require 'minitest/autorun'
require_relative 'house'

# rubocop:disable Metrics/MethodLength
class HouseTest < Minitest::Test
def test_rhyme
expected = <<-RHYME
Expand Down
3 changes: 0 additions & 3 deletions exercises/largest-series-product/example.tt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ require_relative 'largest_series_product'

# Test data version:
# <%= sha1 %>
# Rubocop directives
# rubocop:disable Style/NumericLiterals
# rubocop:disable Metrics/LineLength
#
class Seriestest < Minitest::Test<% test_cases.each do |test_case| %>
def <%= test_case.name %><% if test_case.skipped? %>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@
# Test data version:
# deb225e Implement canonical dataset for scrabble-score problem (#255)

# Rubocop directives
# rubocop:disable Style/NumericLiterals
# rubocop:disable Metrics/LineLength
#
class Seriestest < Minitest::Test
def test_can_find_the_largest_product_of_2_with_numbers_in_order
assert_equal 72, Series.new('0123456789').largest_product(2)
Expand Down
2 changes: 1 addition & 1 deletion exercises/linked-list/linked_list_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def test_unshift_pop
assert_equal 20, deque.pop
end

def test_example # rubocop:disable Metrics/MethodLength
def test_example
skip
deque = Deque.new
deque.push(10)
Expand Down
1 change: 0 additions & 1 deletion exercises/meetup/meetup_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
# and a method day(weekday, schedule)
# where weekday is one of :monday, :tuesday, etc
# and schedule is :first, :second, :third, :fourth, :last or :teenth.
# rubocop:disable Style/AlignParameters
class MeetupTest < Minitest::Test
def test_monteenth_of_may_2013
assert_equal Date.new(2013, 5, 13),
Expand Down
2 changes: 0 additions & 2 deletions exercises/nth-prime/example.tt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ require_relative 'nth_prime'

# Test data version:
# <%= sha1 %>
# Rubocop directives
# rubocop:disable Style/NumericLiterals
#
class NthPrimeTest < Minitest::Test<% test_cases.each do |test_case| %>
def <%= test_case.name %><% if test_case.skipped? %>
Expand Down
2 changes: 0 additions & 2 deletions exercises/nth-prime/nth_prime_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@

# Test data version:
# bb79e10
# Rubocop directives
# rubocop:disable Style/NumericLiterals
#
class NthPrimeTest < Minitest::Test
def test_first_prime
Expand Down
3 changes: 1 addition & 2 deletions exercises/ocr-numbers/ocr_numbers_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
require_relative 'ocr_numbers'

class OCRTest < Minitest::Test
# rubocop:disable Style/TrailingWhitespace
def test_recognize_zero
text = <<-NUMBER.chomp
_
Expand Down Expand Up @@ -169,7 +168,7 @@ def test_identify_1234567890
assert_equal '1234567890', OCR.new(text).convert
end

def test_identify_123_456_789 # rubocop:disable Metrics/MethodLength
def test_identify_123_456_789
skip
text = <<-NUMBER.chomp
_ _
Expand Down
1 change: 0 additions & 1 deletion exercises/protein-translation/protein_translation_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
require 'minitest/autorun'
require_relative 'protein_translation'

# rubocop:disable Style/MethodName
class TranslationTest < Minitest::Test
def test_AUG_translates_to_methionine
assert_equal 'Methionine', Translation.of_codon('AUG')
Expand Down
Loading