Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate a random name in Ruby

Tags:

random

ruby

I need to make a program in ruby to generate a robot name like KU765 or NG274 style and to store them and check it to avoid repetition. I also need to make a "reset" method to delete all stored names and start again. This program is not working for some reason. I hope somebody helps me to find the mistake. Thanks a lot.

class Robot
  attr_accessor :named , :stored_names , :rl
  def self.name
    new.name
  end

  @@rl = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ"

  def name
    named = ""
    named << @@rl[rand(26).to_i]
    named << @@rl[rand(26).to_i]
    named << rand(100..999).to_s
    named.save_name 
    named.check_name
  end

  def save_name
    stored_names = []
    stored_names << named
  end

  def check_name
    stored_names.uniq!
  end

  def reset
    stored_names = Array.new
  end
end
like image 785
RadW2020 Avatar asked Feb 12 '23 14:02

RadW2020


1 Answers

Here's another way to construct the Robot class that you may wish to consider. (My answers are not normally this long or detailed, but I wrote this in part to clarify aspects of Ruby's object model in my own mind. I hope it might help others do the same.)

Code

PREFACE      = ('A'..'Z').to_a << ?_
SUFFIX       = ('0'..'9').to_a
PREFACE_SIZE = 2
SUFFIX_SIZE  = 3

class Robot
  def self.reset()     @bots = []               end
  reset    
  def self.new()       (@bots << super).last    end
  def self.bots()      @bots                    end
  def self.delete(bot) @bots.delete(bot)        end
  def self.bot_names() @bots.map { |b| b.name } end

  attr_reader :name

  def initialize()     @name = add_name         end

  private

  def add_name
    loop do
      @name = gen_name 
      return @name unless self.class.bot_names.include?(@name)
    end
  end

  def gen_name
    PREFACE.sample(PREFACE_SIZE).join << SUFFIX.sample(SUFFIX_SIZE).join
  end
end

Example

Robot.bots           #=> []
robbie = Robot.new   #=> #<Robot:0x000001019f4988 @name="AP436">
robbie.name          #=> "AP436"
Robot.bots           #=> [#<Robot:0x000001019f4988 @name="AP436">]
r2d2 = Robot.new     #=> #<Robot:0x000001019cd450 @name="KL628">
r2d2.name            #=> "KL628"
Robot.bots           #=> [#<Robot:0x000001019f4988 @name="AP436">,
                     #   #<Robot:0x000001019cd450 @name="KL628">]
Robot.bot_names      #=> ["AP436", "KL628"]
Robot.delete(robbie) #=> #<Robot:0x000001019f4988 @name="AP436">
Robot.bots           #=> [#<Robot:0x000001019cd450 @name="KL628">]
Robot.bot_names      #=> ["KL628"]
Robot.reset          #=> []
c3po = Robot.new     #=> #<Robot:0x000001018ff8c0 @name="VO975">
Robot.bots           #=> [#<Robot:0x000001018ff8c0 @name="VO975">]

Explanation

  • When the class is parsed, the class method reset is first created, then the line reset is executed. As self => Robot when that occurs, the class method reset is executed, initializing @bots to an empty array.

  • The responsibility for saving and modifying a list of instances of Robot lies with the class. This list is held in the class instance variable @bots.

  • Instance of Robot are created by invoking Robot::new, which allocates memory and then invokes the (private) instance method initialize. Where is new? Since we have not defined it as a class method in Robot, there are two possibilities: it is inherited from one of Robot's ancestors (Robot.ancestors => [Robot, Object, Kernel, BasicObject]) or it is an instance method of the class Class, as that is the class for which Robot is an instance (i.e., Robot.class => Class) Let's find out which: Class.instance_method(:new) => #<UnboundMethod: Class#new> (or Class.instance_methods.include?(:new) => true), Object.method(:new) => #<Method: Class#new>. It's both! But that makes sense, because all classes are instances of Class, including Robot's superclass, Object. #<Method: Class#new> returned by Object.method(:new) shows new is defined in Class (which can alternatively be seen with Robot.method(:new).owner => Class. Very cool, eh? If you didn't know this already, and can follow what I've said in this paragraph, you've just learned the essence of Ruby's object model!

  • Suppose we add the class method new, shown below, to Robot. super invokes the class method Object::new (which is the instance method Class#new), passing any arguments of new (here there aren't any). Object::new returns the instance that it creates, which Robot::new in turn returns. Therefore, this method would simply be a conduit and and have no effect on the results.

    def self.new
      super  
    end
    
  • We can make a small change to the above method to add a copy of the instance that is created by Object::new to the array @bots:

    def self.new
      instance = super
      @bots << instance
      instance
    end
    
  • I have written this a little more compactly as:

    def self.new
      (@bots << super).last
    end
    
  • I've used the method Array#sample to randomly draw PREFACE_SIZE characters from PREFACE and SUFFIX_SIZE characters from SUFFIX_SIZE. sample samples without replacement, so you will not get, for example, "UU112". If you want to sample with replacement, replace the method gen_name with the following:

    def gen_name
      str = PREFACE_SIZE.times.with_object('') { |_,s| s << PREFACE.sample }
      SUFFIX_SIZE.times { str << SUFFIX.sample }
      str
    end
    
  • I have created a class method bots to return the value of the class instance variable @bots. This could alternatively be done by defining a read accessor for @bots on Robots' singleton class:

    class << self
      attr_reader :name
    end
    
  • When Robot.reset is invoked, what happens to all the instances of Robot it had contained? Will they be left to wander the forest, rejected and homeless? In languages like C you need to release their memory before casting them aside. In Ruby and many other modern languages that's not necessary (and generally can't be done). Ruby's "garbage collection" keeps track of all objects, and kills off (after releasing memory) any that are no longer referenced by any other object. Nice, eh?

like image 102
Cary Swoveland Avatar answered Feb 14 '23 05:02

Cary Swoveland