I have this little password generating program, I want the method print_password to call the generate_password method, but it just doesn't work
require 'digest'
class Challenge
KEY = [
'4', '5', '6', '7',
'8', '9', 'A', 'B',
'C', 'D', 'E', 'F',
'0', '1', '2', '3'
]
def initialize(email)
#email = email # && raise
puts 'This object was initialized!'
end
def print_password
puts %(Password 1: {generate_password}) # Here I want to call generate_password method
end
private
def generate_password
#hash = Digest::SHA1.hexdigest(#email)
#id = #hash.scan(/\d+/).map(&:to_i).inject(:+)
#prng = Random.new(#id)
prepare_map
apply_map
end
def prepare_map
#map = []
id_string = #id.to_s
id_size = id_string.size
map_string = id_string * (KEY.size.to_f / id_size).ceil
0.upto(15) do |i|
#map[i] = map_string[i].to_i
end
#map
end
end
def apply_map
calculated_key = KEY.shuffle(random: #prng).map.with_index do |char, i|
(char.bytes[0] + #map[i]).chr
end
calculated_key.join
end
me = Challenge.new('me#gmail.com') # Initialize new object
me.print_password # Here I want to print the password
So here at the end, it initializes a new object and then where I use me.print_password it just prints out Password 1: {generate_password}
Don't know exactly what I am doing wrong here, thanks for your help in advance.
You need to use a hash character before your curly brackets (same notation as for double quotes):
puts %(Password: #{generate_password})
puts "Password: #{generate_password}"
Related
I have a hash of arrays through which I need to fetch certain data from it by iterating with each key matching value from an another array. The below code is working if I have only one matching criteria and If am using multiple keys it is throwing an error. How can I fetch if there are multiple key matches?
Below is the code for the above problem:
class Sample
def check_inspection_data
data = [{"FL"=>"F", "IN"=>"?", "Circ-7"=>"HM562"}, {"FL"=>"...", "IN"=>"I", "Circ-7"=>"HM563"}, {"FL"=>"F", "IN"=>"O", "Circ-7"=>"HM564"}, {"FL"=>"F", "IN"=>"S", "Circ-7"=>"HM565"}]
inspections = ['I', 'O', 'B', 'H', 'G', 'S']
puts inspections.each { |i| data.find { |d| d['IN'] == i }.fetch('Circ-7') } --> But it throws an error
# puts data.find { |d| d['IN'] == 'I' }.fetch('Circ-7') --> This is working
end
end
sample = Sample.new
sample.check_inspection_data
Below is the error am getting for the above code:
NoMethodError: undefined method `fetch' for nil:NilClass
block in check_inspection_data at sample.rb:5
each at org/jruby/RubyArray.java:1801
check_inspection_data at sample.rb:5
<main> at sample.rb:10
When the inspections iteration reaches the element B, it results in nil, because there are no elements in data where the value of its key IN is B:
p [{"FL"=>"F", "IN"=>"?", "Circ-7"=>"HM562"},
{"FL"=>"...", "IN"=>"I", "Circ-7"=>"HM563"},
{"FL"=>"F", "IN"=>"O", "Circ-7"=>"HM564"},
{"FL"=>"F", "IN"=>"S", "Circ-7"=>"HM565"}].find { |e| e['IN'] == 'B' }
# nil
Similar to any other element in inspections that doesn't exist as a key in data.
Alternatively you can get the common "IN" values between inspections and data, iterate over each element in data and push to an array the values of "Circ-7":
DATA = [{"FL"=>"F", "IN"=>"?", "Circ-7"=>"HM562"},
{"FL"=>"...", "IN"=>"I", "Circ-7"=>"HM563"},
{"FL"=>"F", "IN"=>"O", "Circ-7"=>"HM564"},
{"FL"=>"F", "IN"=>"S", "Circ-7"=>"HM565"}].freeze
INSPECTIONS = ['I', 'O', 'B', 'H', 'G', 'S'].freeze
def check_inspection_data
common_in_values = DATA.map { |d| d['IN'] } & INSPECTIONS
DATA.each_with_object([]) do |e, arr|
next unless common_in_values.include?(e['IN'])
arr << e['Circ-7']
end
end
p check_inspection_data # ["HM563", "HM564", "HM565"]
So I am working on a small assignment to transcribe DNA strands to RNA strands. My current code looks like this:
class Complement
def self.of_dna(str)
dna_rna = { 'G' => 'C', 'C' => 'G', 'T' => 'A', 'A' => 'U' }
rna = []
str.scan(/[GCTA]/).each do |x|
rna << dna_rna[x]
end
rna.join('')
end
end
It works perfectly, except for in one situation. If a DNA strand is passed that is partially correct, for example ACGTXXXCTTAA, my method will translate the DNA to RNA and just leave out the X's, giving me a result of UGCAGAAUU rather than just "". How can I make it so the loop will fail and exit when it receives a letter that isn't DNA related?
EDIT:
The test I am trying to get to pass looks like this:
def test_dna_correctly_handles_partially_invalid_input
# skip
assert_equal '', Complement.of_dna('ACGTXXXCTTAA')
end
I attempted #Holger Just's idea from below, and received this error:
1) Error:
ComplementTest#test_dna_correctly_handles_completely_invalid_input:
ArgumentError: ArgumentError
/Users/LukasBarry/exercism/ruby/rna-transcription/rna_transcription.rb:6:in `block in of_dna'
/Users/LukasBarry/exercism/ruby/rna-transcription/rna_transcription.rb:5:in `each'
/Users/LukasBarry/exercism/ruby/rna-transcription/rna_transcription.rb:5:in `of_dna'
rna_transcription_test.rb:43:in `test_dna_correctly_handles_completely_invalid_input'
The usual failure I've been getting from the above method is this:
1) Failure:
ComplementTest#test_dna_correctly_handles_partially_invalid_input [rna_transcription_test.rb:48]:
Expected: ""
Actual: "UGCAGAAUU"
Any help would be greatly appreciated.
Try this
class Complement
def self.of_dna(str)
return "" if str =~ /[^GCTA]/
...
end
end
Fun fact, you don't even need a loop to replace characters
str = 'GATTACA'
str.tr('ATCG', 'UAGC')
# => 'CUAAUGU'
Is all you need.
You can also match X in your regex and perform some erorr handling if it is found in the string. This could look something like this:
class Complement
def self.of_dna(str)
dna_rna = { 'G' => 'C', 'C' => 'G', 'T' => 'A', 'A' => 'U' }
rna = []
str.scan(/[GCTAX]/).each do |x|
return '' if x == 'X'
rna << dna_rna[x]
end
rna.join('')
end
end
I prefer using Hash#fetch for this because it'll raise a KeyError for you on mismatch, allowing you to write less code that validates inputs (i.e., less defensive programming), which I think is more valuable than cleverness (in which case I would recommend String#tr).
class DNA
TranslationMap = { 'G' => 'C', 'C' => 'G', 'T' => 'A', 'A' => 'U' }
attr_reader :dna
def initialize(dna)
#dna = dna
end
def to_rna
dna.each_char.map do |nucleotide|
TranslationMap.fetch(nucleotide)
end.join('')
rescue KeyError
return false
end
end
Feel free to adapt what happens when the error is rescued to fit your needs. I recommend raising a more specific exception (e.g. DNA::InvalidNucleotide) for the caller to handle.
In use:
dna = DNA.new 'GCTA'
# => #<DNA:0x007fc49e903818 #dna="GCTA">
dna.to_rna
# => "CGAU"
dna = DNA.new 'ACGTXXXCTTAA'
# => #<DNA:0x007fc49f064800 #dna="ACGTXXXCTTAA">
dna.to_rna
# => false
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I am trying to ask the user for a name so we can create a fake name.
Fake name will:
Swap the first and last name
Change all the vowels (a,e,i,o,u) to next vowel, So 'a' would become 'e','u' would become 'a'
Change all the consonants to (besides the vowels) to the next consonant in the alphabet, So 'd' would become 'f', 'n' would become 'p'
I am unable to get the first and last name capitalized at the end of the program. Any advice on how to do this?
I am also trying to Use a data structure to store the fake names as they are entered. When the user exits the program, iterate through the data structure and print all of the data the user entered. A sentence like "Vussit Gimodoe is actually Felicia Torres" or "Felicia Torres is also known as Vussit Gimodoe
# ---- Swap First and Last Name ----
def name_swap(name)
name.split.reverse.join(' ')
end
# ---- Change all the vowels ----
def vowel_change(name)
vowels = ['a', 'e', 'i', 'o', 'u']
name = name.downcase.split('')
new_name = name.map do |vow|
if vowels.include?(vow)
vowels.rotate(1)[vowels.index(vow)]
elsif vowels == 'u'
vowels.replace('a')
else
vow
end
end
new_name.join
end
# ---- Change the constant ----
def constant_change(name)
constants = ['b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z']
name = name.downcase.split('')
new_name = name.map do |letter|
if constants.include?(letter)
constants.rotate(1)[constants.index(letter)]
elsif constants == 'z'
constants.replace('b')
else
letter
end
end
new_name.join.capitalize!
end
# ---- User Interface and Data Storage----
valid_input = false
agents ={}
user_input = ""
secret_name = ""
until valid_input
puts "Hello Secret Agent, to begin please enter the name you would like to change. When you are finished, type 'quit' !"
user_input = gets.chomp.downcase
if user_input == "quit"
puts "Thank You!"
valid_input = true
else
secret_name = name_swap(vowel_change(constant_change(user_input)))
puts "Your secret name is #{secret_name} "
end
agents[user_input] = secret_name
end
agents.each do |name, scramble|
puts"#{name} is also known #{scramble}"
end
The problem is when I return the final agent name the name is lower case and I need both the first name and last name capitalized. It is also taking quit to exit the until loop as a name.
Have a look at this: https://ruby-doc.org/core-2.2.0/String.html#method-i-capitalize-21
You could do this before you print the secret name:
output = output.split.each { |name| name.capitalize! }.join(' ')
and the same for the original name:
original_name = original_name.split.each { |name| name.capitalize! }.join(' ')
Examples from Ruby docs:
a = "hello"
a.capitalize! #=> "Hello"
a #=> "Hello"
a.capitalize! #=> nil
Or use Rails' titleize method if you are using Rails.
http://apidock.com/rails/String/titleize
In rails, you have a method called titleize
that said, give this a try
output = name_swap(vowel_change(constant_change(original_name))).titleize
original_name = original_name.titleize
Reference Answer: https://stackoverflow.com/a/15005638/2398387
my_hash = Hash.new{|h,k| h[k] = []}
name = 'John'
my_hash[name] << '7'
my_hash[name] << '9'
name = 'Jane'
my_hash[name] << '7'
my_hash[name] << 'J'
array_info = my_hash.values_at('John')
puts array_info.class => array
array_info.each do |ele|
puts ele => 7, 9
end
removed = array_info.include?('7')
puts removed => false ??!?!?????
array_info just printed 7 as an element in the array, so we know that it exists. So why would array_info.include?('7') not return true??
Take a look at array_info. Puts-ing it shows that your ele values are indeed in that array, but your array is nested inside another array.
removed = array_info.first.include?('7')
Will return true.
for fun I am creating in ruby a simple leet (1337) generator
so i am doing something like this, which works but doesn't look very efficient, i am sure it can be accomplished with one line only...
def leet
words = words.gsub(/a/, '4')
words = words.gsub(/e/, '3')
words = words.gsub(/i/, '1')
words = words.gsub(/o/, '0')
words = words.gsub(/s/, '5')
words = words.gsub(/t/, '7')
puts words
end
Can you give me a help here? :) thanks!
def leet(word)
puts word.gsub(/[aeiost]/,'a'=>'4','e'=>'3','i'=>'1','o'=>'0','s'=>'5','t'=>'7')
end
def leet s
s.tr 'aeiost', '431057'
end
A more general version of megas's:
class Leet
##map = {
'a' => '4',
'e' => '3',
'i' => '1',
'o' => '0',
's' => '5',
't' => '7'
}
##re = Regexp.union(##map.keys)
def self.speak(str)
str.gsub(##re, ##map)
end
end
puts Leet.speak('leet')
# l337
Adjust ##map as needed and away you go.