Checking the Credits, y'all!
def valid?(card_number) | |
digits = card_number | |
.split("") | |
.map { |number| number.to_i } | |
numbers = [] | |
digits.each_with_index do |digit, index| | |
if index.even? | |
numbers << digit * 2 | |
else | |
numbers << digit | |
end | |
end | |
summed_digits = [] | |
numbers.each do |number| | |
if number > 9 | |
# sum of the digits | |
summed_digits << 1 + number - 10 | |
else | |
summed_digits << number | |
end | |
end | |
# add them all together | |
sum = summed_digits.reduce(:+) | |
valid = (0 == sum % 10) | |
valid | |
end | |
if valid?("4929735477250543") | |
puts "The number is valid!" | |
else | |
puts "The number is invalid!" | |
end | |
# valid | |
['5541808923795240', '4024007136512380', '6011797668867828'] | |
.map { |number| valid?(number) } # => [true, true, true] | |
# invalid | |
['5541801923795240', '4024007106512380', '6011797668868728'] | |
.map { |number| valid?(number) } # => [false, false, false] | |
# >> The number is valid! |
def valid?(card_number) | |
identifier = card_number.reverse.chars.map(&:to_i) | |
with_doubles = identifier.map.with_index { |n, i| i.even? ? n : n*2 } | |
single_digits = with_doubles.map { |n| n > 9 ? n.to_s.chars.map(&:to_i).inject(0, :+) : n } | |
sum = single_digits.inject(0, :+) | |
mod_10 = sum % 10 | |
valid = mod_10 == 0 | |
valid | |
end | |
# valid | |
['79927398713', '5541808923795240', '4024007136512380', '6011797668867828'] | |
.map { |num| valid? num } # => [true, true, true, true] | |
# invalid | |
['5541801923795240', '4024007106512380', '6011797668868728'] | |
.map { |num| valid? num } # => [false, false, false] | |
# process the example | |
if valid? "4929735477250543" | |
puts "The number is valid!" | |
else | |
puts "The number is invalid!" | |
end | |
# >> The number is valid! |
# split across lines more than I otherwise would so that we can see how the data gets transformed as it progresses | |
# not saying this is best, just where I wound up :) | |
# I tend to prefer chains of transformations a lot more than most people :P | |
def valid?(card_number) | |
sum = card_number # => "4929735477250543" | |
.reverse # => "3450527745379294" | |
.chars # => ["3", "4", "5", "0", "5", "2", "7", "7", "4", "5", "3", "7", "9", "2", "9", "4"] | |
.map { |char| char.to_i } # => [3, 4, 5, 0, 5, 2, 7, 7, 4, 5, 3, 7, 9, 2, 9, 4] | |
.map.with_index { |n, i| maybe_double n, i } # => [3, 8, 5, 0, 5, 4, 7, 14, 4, 10, 3, 14, 9, 4, 9, 8] | |
.map { |n| sum_digits n } # => [3, 8, 5, 0, 5, 4, 7, 5, 4, 1, 3, 5, 9, 4, 9, 8] | |
.inject(0, :+) # => 80 | |
0 == sum % 10 # => true | |
end | |
def sum_digits(number) | |
number.to_s # => "3", "8", "5", "0", "5", "4", "7", "14", "4", "10", "3", "14", "9", "4", "9", "8" | |
.chars # => ["3"], ["8"], ["5"], ["0"], ["5"], ["4"], ["7"], ["1", "4"], ["4"], ["1", "0"], ["3"], ["1", "4"], ["9"], ["4"], ["9"], ["8"] | |
.map { |digit| digit.to_i } # => [3], [8], [5], [0], [5], [4], [7], [1, 4], [4], [1, 0], [3], [1, 4], [9], [4], [9], [8] | |
.inject(0, :+) # => 3, 8, 5, 0, 5, 4, 7, 5, 4, 1, 3, 5, 9, 4, 9, 8 | |
end | |
def maybe_double(number, index) | |
if index.even? | |
number | |
else | |
number * 2 | |
end | |
end | |
# # valid | |
# ['79927398713', '5541808923795240', '4024007136512380', '6011797668867828'] | |
# .map { |num| valid? num } # => [true, true, true, true] | |
# | |
# # invalid | |
# ['5541801923795240', '4024007106512380', '6011797668868728'] | |
# .map { |num| valid? num } # => [false, false, false] | |
# process the example | |
if valid? "4929735477250543" | |
puts "The number is valid!" | |
else | |
puts "The number is invalid!" | |
end | |
# >> The number is valid! |
# I took your philosophy of method chaining to its logic conclusion, | |
# removing the local variable `sum` from the `valid?` method. | |
# I was able to remove both instances of .map { |char| char.to_i } | |
# by doing the the integer conversion in the subsequent step, saving | |
# both time and space. I also reversed the conditional statement in | |
# `maybe_double`, since I think it makes it clearer when it doubles. | |
def valid?(card_number) | |
card_number # => "4929735477250543" | |
.reverse # => "3450527745379294" | |
.chars # => ["3", "4", "5", "0", "5", "2", "7", "7", "4", "5", "3", "7", "9", "2", "9", "4"] | |
.map.with_index { |n, i| maybe_double(n.to_i, i) } # => [3, 8, 5, 0, 5, 4, 7, 14, 4, 10, 3, 14, 9, 4, 9, 8] | |
.inject { |s, n| s + sum_digits(n) } # => 80 | |
.modulo(10) # => 0 | |
.zero? # => true | |
end | |
def sum_digits(number) | |
number # => 3, 8, 5, 0, 5, 4, 7, 14, 4, 10, 3, 14, 9, 4, 9, 8 | |
.to_s # => "3", "8", "5", "0", "5", "4", "7", "14", "4", "10", "3", "14", "9", "4", "9", "8" | |
.chars # => ["3"], ["8"], ["5"], ["0"], ["5"], ["4"], ["7"], ["1", "4"], ["4"], ["1", "0"], ["3"], ["1", "4"], ["9"], ["4"], ["9"], ["8"] | |
.inject(0) { |s, n| s + n.to_i } # => 3, 8, 5, 0, 5, 4, 7, 5, 4, 1, 3, 5, 9, 4, 9, 8 | |
end | |
def maybe_double(number, index) | |
if index.odd? | |
number * 2 | |
else | |
number | |
end | |
end | |
# # valid | |
# ['79927398713', '5541808923795240', '4024007136512380', '6011797668867828'] | |
# .map { |num| valid? num } # => [true, true, true, true] | |
# | |
# # invalid | |
# ['5541801923795240', '4024007106512380', '6011797668868728'] | |
# .map { |num| valid? num } # => [false, false, false] | |
# process the example | |
if valid? "4929735477250543" | |
puts "The number is valid!" | |
else | |
puts "The number is invalid!" | |
end | |
# >> The number is valid! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment