I need to generate a unique six digit alpha-numeric code. To save in my database as voucher no: for every transaction.
I used this
require 'sha1'
srand
seed = "--#{rand(10000)}--#{Time.now}--"
Digest::SHA1.hexdigest(seed)[0,6]
How to generate a random string in Ruby This link was useful
A better way is to let the database handle the ids(incrementing). But if you insisting on generating them your self, you can use a random generator to generate an code, check it against db for uniqueness. then either accept or regenerate
I'd use the database to generate unique keys, but if you insist on doing it the hard way:
class AlnumKey
def initialize
#chars = ('0' .. '9').to_a + ('a' .. 'z').to_a
end
def to_int(key)
i = 0
key.each_char do |ch|
i = i * #chars.length + #chars.index(ch)
end
i
end
def to_key(i)
s = ""
while i > 0
s += #chars[i % #chars.length]
i /= #chars.length
end
s.reverse
end
def next_key(last_key)
to_key(to_int(last_key) + 1)
end
end
al = AlnumKey.new
puts al.next_key("ab")
puts al.next_key("1")
puts al.next_key("zz")
Of course, you'll have to store your current key somewhere, and this is in no way thread / multisession-safe etc.
With the following restrictions:
Valid only until 2038-12-24 00:40:35 UTC
Generates no more than once within a second
you can use this simple code:
Time.now.to_i.to_s(36)
# => "lks3bn"
class IDSequence
attr_reader :current
def initialize(start=0,digits=6,base=36)
#id, #chars, #base = start, digits, base
end
def next
s = (#id+=1).to_s(#base)
#current = "0"*(#chars-s.length) << s
end
end
id = IDSequence.new
1234.times{ id.next }
puts id.current
#=> 0000ya
puts id.next
#=> 0000yb
9876543.times{ id.next }
puts id.current
#=> 05vpqq
This would eleviate the time collision issue by getting the milli seconds
(Time.now.to_f*1000.0).to_i
Related
Hello I'm new to programming and I started with ruby. I'm trying to do my first program. I found online this code that generate a dice roll
class Die
def initialize(sides)
#sides = sides
end
def generate_die_roll
rand(#sides) + 1
end
def roll(number=1)
roll_array = []
number.times do
roll_array << generate_die_roll
end
total = 0
roll_array.each do |roll|
new_total = total + roll
total = new_total
end
total
end
end
and I would like to use in they way that if the number generated is inferior o equal to another print something otherwise something else.
It's probably very easy but i'm trying in every way and now I will need some help please.
that's my code:
require "./newdado.rb"
energia_vitale = 30
puts "Lancia un dado scrivendo (D) da sommare alla tua Energia Vitale iniziale di #{energia_vitale} punti"
scelta = gets.chomp
case scelta
when "D"
SIX_SIDED_DIE = "#{Die.new(6)}"
values = Array[]
values.push(SIX_SIDED_DIE.roll)
puts values
if values < 2
puts "c"
else puts "b"
end
end
when I run it i receive this error
C:/Users/fix/workspace/D&D Ruby/energia vitale.rb:11:in <main>': undefined methodroll' for "#":String (NoMethodError)
Sorry to bother the community with this beginner problem
Why as string?
this line
SIX_SIDED_DIE = "#{Die.new(6)}"`
should be something like
die = Die.new(6)
then you can do die.roll
The below combined programs should ask for a number remove the first digit (lets call this new number x) and then compute x % 7. Ex: (1121546 % 7) = 5
This all appears to be working except that the number entered in will always compute to 0. modulo_7.rb works by itself and will print the correct outcome when passed a parameter.
The question is am I not passing the variables/ parameters properly or is there something else that is getting in the way?
class Number_check_interface
def get_cert_number
print "You are about to check receive the check number for a policy/cert id."
#cert_id = nil
until #cert_id.is_a?(Fixnum) do
puts " Enter the policy/cert ID. "
begin
#cert_id = Integer(gets)
rescue ArgumentError
end
end
end
end
class Run_number_check_interface
def run
load 'modulo_7.rb'
n = Number_check_interface.new
n.get_cert_number
checking_policy_number = Get_policy_check_digit.new(#cert_id)
checking_policy_number.create_check_digit
end
end
run = Run_number_check_interface.new
run.run
modulo_7.rb
This program removes the first digit (index 0) of a 7 digit number and returns the difference 7%18 is 4 since 4 is remainder of how many times 7 can fit into 18.
class Get_policy_check_digit
def initialize(cert_id)
#instance variable
#cert = cert_id
end
def create_check_digit
cert_id_6 = #cert.to_s
cert_id_6.slice!(0)
puts cert_id_6
check_digit = cert_id_6.to_i % 7
puts "Your check digit is #{check_digit}"
end
end
# n = Get_policy_check_digit.new(1121546) When uncommented this will create a new instance
# of Get_policy_check_digit with the parameter 1121546
# n.create_check_digit This will run the method create_check_digit with the
# parameter 1121546
Instance variables are scoped to an individual instance of a class. So when you say #cert_id = Integer(gets) inside Number_check_interface, you are only setting #cert_id for that particular instance of Number_check_interface. Then, when you later write Get_policy_check_digit.new(#cert_id) inside Run_number_check_interface, you are referring to an entirely different #cert_id, one which is specific to that particular instance of Run_number_check_interface, and not to the Number_check_interface you stored in n earlier.
The simple solution is to return #cert_id from Number_check_interface#get_cert_number, and then pass the returned value to Get_policy_check_digit.new:
class Number_check_interface
def get_cert_number
print "You are about to check receive the check number for a policy/cert id."
#cert_id = nil # This is an instance variable. It's only accessible
# from inside this instance of `Number_check_interface`
until #cert_id.is_a?(Fixnum) do
puts " Enter the policy/cert ID. "
begin
#cert_id = Integer(gets)
rescue ArgumentError
end
end
return #cert_id # Return the contents of #cert_id
end
end
class Run_number_check_interface
def run
load 'modulo_7.rb'
n = Number_check_interface.new
cert_number = n.get_cert_number # Here we call `get_cert_number` and
# set `cert_number` to it's return
# value.
# Notice how we use `cert_number` here:
checking_policy_number = Get_policy_check_digit.new(cert_number)
checking_policy_number.create_check_digit
end
end
Other tips:
Convention in Ruby is to name classes with CamelCase.
Require dependencies at the top of your files, not in the middle of method calls.
Unless you have a very good reason not to, use require, not load
You might want to think a bit harder about what purpose these classes serve, and what behavior they are intending to encapsulate. The API seems a bit awkward to me right now. Remember, tell, don't ask.
Why are these separate classes? The design here seems strange, is this ported from another language? It's more complicated than it needs to be. Without changing your structure, here's what's wrong:
In Run_number_check_interface you are reading #cert_id, it doesn't have an instance variable named that, but Number_check_interface does. Just return it from get_cert_number:
class Number_check_interface
def get_cert_number
print "You are about to check receive the check number for a policy/cert id."
cert_id = nil
until cert_id.is_a?(Fixnum) do
puts " Enter the policy/cert ID. "
begin
cert_id = Integer(gets)
rescue ArgumentError
end
end
cert_id # <-- returing the value here
end
end
class Run_number_check_interface
def run
load 'modulo_7.rb'
n = Number_check_interface.new
cert_id = n.get_cert_number # <-- saving here
checking_policy_number = Get_policy_check_digit.new(cert_id) # <-- no longer an ivar
checking_policy_number.create_check_digit
end
end
run = Run_number_check_interface.new
run.run
I'm creating a reverse polish notation calculator as a 'warm-up test' for school. I've almost nailed it. The issue I'm coming across is when I run this myself, I see just the integer returned (which is desired). When I plug this into the school's RSpec checker it returns my data in an array, so it's flagged as incorrect.
To fix, I just built the queue.each statement on the end. I tried this in a few different positions, but it does not seem to matter. Is there a bigger concept to extract my answer out of the array format when evaluate returns an answer?
class RPNCalculator
def evaluate(string)
holding = []
queue = []
string = string.split(" ").to_a #jam string into an array - break on spaces
string.each do |x|
if x.match(/\d/) #number checker. if true throw it in queue.
queue << x.to_i #convert to number from string
elsif x.match(/\+/) #math operator checker
holding << queue[-2] + queue[-1] #grab queue's last 2 & replace w/ result
queue.pop(2)
queue << holding[-1]
elsif x.match(/\-/)
holding << queue[-2] - queue[-1]
queue.pop(2)
queue << holding[-1]
elsif x.match(/\*/)
holding << queue[-2] * queue[-1]
queue.pop(2)
queue << holding[-1]
else
end
end
return queue.each { |x| puts x.to_i} # by [-1] in string, queue holds answer
end
end
Thank you in advance for your time,
Your method (without queue.each) is returning the result of string.each.
If you want to return queue, you need to do that.
class RPNCalculator
def evaluate(string)
holding = []
queue = []
string = string.split(" ").to_a #jam string into an array - break on spaces
string.each do |x|
#...
end
queue[0] # return the final result, stored in queue
end
end
I am trying to replace characters in a string with a shift in the ord by some number. I am thinking the best way to do this is with regex, but running into some problems.
This is the flawed code I do have
def cipher(coded_message)
coded_message=coded_message.downcase.split("")
new_message=[]
coded_message.each do |x|
x=x.gsub(/[a-d][e-z]/, '\1x.ord+22\2x.ord-4')
new_message<<x
end
p new_message.join
end
I know that my problem is with the regex and probably the replacement text, but not sure where to go on this one. Any help would be appreciated.
Ok so I took a different approach to solving your problem. Here is a solution which doesn't involve a regex, and is very flexible.
def cipher(coded_message)
new_message=[]
coded_message.downcase.each_char do |x|
case x
when ("a".."d")
new_message << (x.ord+22).chr
when ("e".."z")
new_message << (x.ord-4).chr
end
end
new_message.join
end
cipher("Code this string")
#=> "ykzapdeoopnejc"
Not much point coding a message if you can't decode it:
#code_key = 123.times.with_object({}) do |i,h|
c = i.chr
h[c] =
case c
when /[a-dA-D]/
(i+22).chr
when /[e-zE-Z]/
(i-4).chr
else
c
end
end
#decode_key = #code_key.invert
def code(message)
#code_key.values_at(*message.chars).join
end
def decode(message)
#decode_key.values_at(*message.chars).join
end
message = "Is 42 an important number?"
coded_message = code(message) # => "Eo 42 wj eilknpwjp jqixan?"
decoded_message = decode(coded_message) # => "Is 42 an important number?"
My new method for a string object in ruby is supposed to return a hash of the count of each character within a string (loaded in from a .txt file) and I am probably trying to go about it the easy way, however I can't seem to make it work without passing the object. I was wondering if there was a way to do this without passing a string. Any help would be appreciated.
Here is my code
class String
def frequency
Object.downcase
Object.gsub("\n", " ")
h = {}
h["A:"] = Object.count('a')
h["B:"] = Object.count('b')
h["C:"] = Object.count('c')
h["D:"] = Object.count('d')
h["E:"] = Object.count('e')
h["F:"] = Object.count('f')
h["G:"] = Object.count('g')
h["H:"] = Object.count('h')
h["I:"] = Object.count('i')
h["J:"] = Object.count('j')
h["K:"] = Object.count('k')
h["L:"] = Object.count('l')
h["M:"] = Object.count('m')
h["N:"] = Object.count('n')
h["O:"] = Object.count('o')
h["P:"] = Object.count('p')
h["Q:"] = Object.count('q')
h["R:"] = Object.count('r')
h["S:"] = Object.count('s')
h["T:"] = Object.count('t')
h["U:"] = Object.count('u')
h["V:"] = Object.count('v')
h["W:"] = Object.count('w')
h["K:"] = Object.count('x')
h["Y:"] = Object.count('y')
h["Z"] = Object.count('z')
return h
end
end
Sounds like you are talking about self, which is the ruby keyword that refers to the current object. Note that self is implied if you just call the method. So to use your example
class String
def frequency
count('a')
end
end
would return the number of as in the string
"asdfa".frequency #=> 2
Just a note, but your current method is very repetitive, and you might want to think about taking advantage of a loop to reduce the amount of code. Also you are not counting capital letters :)
Rather than a very long, un-DRY method that iterates your object 26 times, how about using some Ruby:
def frequency
Hash[downcase.gsub(/[^a-z]/,'').chars.group_by(&:to_s).map{|char, group| ["#{char.upcase}:", group.size]}]
end
You can break this apart onto separate lines if you find it easier to read (and to look up the methods in the API [1]):
def frequency
intermediate_variable = downcase
intermediate_variable = intermediate_variable.gsub(/[^a-z]/,'') # only keep a-z characters
intermediate_variable = intermediate_variable.chars.group_by(&:to_s) # split the string into its component characters and then group that array by the characters (run this on an array to see what it does :-) could also have written it `.group_by{|e|e}`
intermediate_variable = intermediate_variable.map{|char, group| ["#{char.upcase}:", group.size]} # map the array of grouped characters into an array of character and counts (formatting the 'character' how you would like your hash key configured
Hash[intermediate_variable] # make a hash of the characters and their counts
end
[1] http://ruby-doc.org/core-2.0.0/Enumerable.html http://ruby-doc.org/core-2.0.0/String.html
Here is the version I used which is a complete copy of the Rosetta Letter Frequency:
#!/usr/bin/env ruby
def letter_frequency(string)
freq = Hash.new(0)
string.each_char.lazy.grep(/[[:alpha:]]/).map(&:upcase).each_with_object(freq) do |char, freq_map|
freq_map[char] += 1
end
end
In ruby you can just open the class and add the method, like:
class String
def my_method
my_method_code
end
end
Then you just call the method string.my_method. However in your case I would rather use a Ruby module. Here is a code sample, very similar to a class but cleaner imho:
#!/usr/bin/env ruby
module MyString
def self.letter_frequency(string)
freq = Hash.new(0)
string.each_char.lazy.grep(/[[:alpha:]]/).map(&:upcase).each_with_object(freq) do |char, freq_map|
freq_map[char] += 1
end
return freq
end
end
p MyString.letter_frequency('absd')
Modules are more suited for adding your own classes into projects avoiding name colliding and creating mixins.
I would just create a hash like this:
class String
def frequency
chars.each_with_object(Hash.new(0)) do |char, h|
h["#{char.upcase}:"] += 1 if char[/[[:alpha:]]/]
end
end
end