How to generate a random name in Ruby

I need to make a program in ruby ​​to generate a robot name like KU765 or NG274 style and store and validate them to avoid duplication. I also need to do a "reset" method to remove all stored names and rerun. For some reason this program doesn't work. Hope someone can help me find the error. Many thanks.

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

      

+3


source to share


5 answers


def save_name
  stored_names = []
  stored_names << named
end

      

Each time you create a name and call save_name

, you remove all previously created names by assigning an empty arraystored_names

EDIT: There were a few more errors, let me write a working solution first:



class Robot
  attr_accessor :named , :stored_names , :rl

  def initialize()
    @stored_names = []
  end

  @@rl = "_ABCDEFGHIJKLMNOPQRSTUVWXYZ".chars.to_a

  def name
    @named = ""
    @named << @@rl.sample
    @named << @@rl.sample
    @named << rand(100..999).to_s
    save_name 
    check_name
  end

  def save_name
    @stored_names << @named
  end

  def check_name
    @stored_names.uniq!
  end

  def reset
    @stored_names = Array.new
  end
end

      

  • To access the members of your object, you must prefix them @

    .

  • You have called save_name

    and check_name

    on @named

    which is a string and does not provide these methods

  • @stored_names

    must be initialized with an empty array before you can insert elements into it <<

    . This is usually done in the constructor of the classinitialize()

0


source


Here's another way to build a class Robot

that you might want to consider. (My answers are usually not that long or detailed, but I wrote part of this to clarify aspects of the Ruby object model in my own mind. Hopefully this helps others to 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 parsing a class, the class method is created first reset

    , then the string is executed reset

    . How self => Robot

    , when this happens, the class method is executed reset

    , initializing to @bots

    an empty array.

  • It is the responsibility of the Robot

    class to maintain and modify the list of instances . This list is stored in an instance variable of the class @bots

    .

  • An instance Robot

    is created by a call Robot::new

    that allocates memory and then calls a (private) instance method initialize

    . Where new

    ? Since we have not defined it as a class method in Robot

    , there are two possibilities: it inherits from one of the Robot

    ancestors ( Robot.ancestors => [Robot, Object, Kernel, BasicObject]

    ), or it is an instance method of the class Class

    , since it is the class for which it Robot

    is an instance (i.e. Robot.class => Class

    ). Find out that: Class.instance_method(:new) => #<UnboundMethod: Class#new>

    (or Class.instance_methods.include?(:new) => true

    ) Object.method(:new) => #<Method: Class#new>

    . And this! But it makes sense, because all classes are instances Class

    , including Robot

    superclass Object

    . #<Method: Class#new>

    the returned Object.method(:new)

    shows new

    is defined in Class

    (which can alternatively be seen withRobot.method(:new).owner => Class

    ... Very cool, huh? If you didn't already know this and can follow what I said in this paragraph, you just learned the essence of the Ruby Object Model!

  • Suppose we add the class method new

    shown below to Robot

    . super

    calls a class method Object::new

    (which is an instance method Class#new

    ), passing any arguments new

    (not here). Object::new

    returns the instance it creates, which in turn returns Robot::new

    . Hence, this method will simply be a channel and will not affect the results.

    def self.new
      super  
    end
    
          

  • We can make a small change to the above method to add a copy of the instance created Object::new

    to the array @bots

    :

    def self.new
      instance = super
      @bots << instance
      instance
    end
    
          

  • I wrote this a little more compactly like:

    def self.new
      (@bots << super).last
    end
    
          

  • I used Array # sample method to randomly draw PREFACE_SIZE

    characters from PREFACE

    and SUFFIX_SIZE

    characters from SUFFIX_SIZE

    . sample

    samples without replacement, so you will not receive, for example, "UU112". If you want fetch and replace, 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 created a class method bots

    to return the value of a class instance variable @bots

    . This could alternatively be done by specifying a read accessory for @bots

    in the Robots

    'singleton class:

    class << self
      attr_reader :name
    end
    
          

  • When called Robot.reset

    , what happens to all the instances Robot

    it contained? Will they be left to roam the woods, rejected and homeless? In languages ​​like C

    , you need to free memory before discarding them. In Ruby and many other modern languages ​​that are unnecessary (and cannot be done at all). Ruby garbage collection keeps track of all objects and kills (after freeing memory) any objects that are no longer referenced by any other object. Nice, huh?

+3


source


The task itself is not difficult, but I don't like the way your code is organized. This is what I would do in the first step:

class Robot
  class Name < String
    class << self
      def sign
        "#{[*?A..?Z].sample}#{[*?A..?Z].sample}"
      end

      def number
        "#{rand 1..9}#{rand 0..9}#{rand 0..9}"
      end

      def new
        super << sign << number
      end
    end
  end
end

      

And then:

Robot::Name.new

      

When building a list of names, it is easy to verify that they are unique. This is how I would do it:

class Robot
  class Names < Array
    def self.generate n
      new.tap { |array| n.times do array.add_random_name end }
    end

    def add_random_name
      name = Name.new
      include?( name ) ? add_random_name : self << name
    end
  end
end

      

And then:

Robot::Names.generate 7

      

+2


source


I understand this is not efficient, but it will work.

letters = [*'A'..'Z'] => 
numbers = [*100..999]
names = []
2.times{names.push(letters.shuffle.first)} => Randomizing array and choosing element
names.push(numbers.shuffle.first)
names.join => Creates a String object out of the array elements

      

It's not good, but it gets the job done.

+1


source


This is how I can automate Cary's approach with mine y_support/name_magic

:

require 'y_support/all'

class Robot
  β˜… NameMagic

  def name_yourself
    begin
      self.name = "#{[*?A..?Z].sample( 2 ).join}#{rand 100..999}"
    rescue NameError; retry end
  end
end

3.times { Robot.new.name_yourself }
Robot.instances #=> [PR489, NS761, OE663]
Robot.forget "PR489"
Robot.instances #=> [NS761, OE663]
Robot.forget_all_instances
Robot.instances #=> []
Robot.new.name_yourself
Robot.instances #=> [IB573]

      

+1


source







All Articles