I'm very new to ruby at the moment but I came from a PHP background and must say that I enjoy doing ruby, alot. It's a really nice language and the community is strict but helpful.
Today I was looking at stackoverflow and checked one of my answers to a question to generate a random string using PHP. I had actually written a script for this so I thought, why not share it!
This script has some modifiers which allow you to choose wether you want to include the following sets
So in this PHP script I physically typed each set into an array e.g.:
$charSubSets = array(
'abcdefghijklmnopqrstuvwxyz',
'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
'0123456789',
'!@#$%^&*()_+{}|:">?<[]\\\';,.`~',
'µñ©æáßðøäåé®þüúíóö'
);
and this was basically my way of being able to define complexity right there.
Now this looks alright, even in the code but ruby has ranges and ranges are something new and shiny for me to play with so I was thinking of building a random string generator later today just to get some more experience with it.
Now for my question, I know that you can do the following things with a range including:
'a'..'z'
'A'..'Z'
0..9
etc.. But I was thinking, could you also make a range with special characters? as in, only special characters? and if that is possible, would you also be able to do the same for the crazy voodooh?
The reason I'm asking is because there is no example in the docs or anything on SO explaining this.
Check out Range#to_a
which is gotten from Enumerable. Note that on the left hand side of the docs it says that Range includes Enumerable, which means that the methods in Enumerable can be called on Ranges. If you can't find a method in a class, see what modules the docs say are included and click on the link to the included module.
Check out Array#shuffle
.
Check out Array#join
Check out Array#[]
, which will take a range as a subscript, so you can take a slice of an array of random characters.
A two dot Range includes the end. A three dot Range doesn't include the end:
p (1...5).to_a #=> [1, 2, 3, 4]
Putting it all together:
chars = (0..9).to_a + ('A'..'z').to_a + ('!'..'?').to_a
10.times do
puts chars.shuffle[0..5].join
end
--output:--
I(m,E.
%_;i(3
rb=_ef
kJrA9n
YA`e.K
89qCji
Ba1x3D
acp)=8
2paq3I
U0>Znm
(Shakespeare will appear there eventually.)
Yes - this is certainly possible.
Fire up your console e.g. irb
or pry
.
1. for the special characters:
('!'..'?').to_a
# => [
# "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-",
# ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":",
# ";", "<", "=", ">", "?"
# ]
2. for the 'voodooh' characters:
('µ'..'ö').to_a
# => [
# "µ", "¶", "·", "¸", "¹", "º", "»", "¼", "½", "¾", "¿", "À", "Á",
# "Â", "Ã", "Ä", "Å", "Æ", "Ç", "È", "É", "Ê", "Ë", "Ì", "Í", "Î",
# "Ï", "Ð", "Ñ", "Ò", "Ó", "Ô", "Õ", "Ö"
# ]
This is trivial to just try tho, the position (and kb index of the key) on your keyboard for the end special character defines what characters come inbetween, if I'd pick a ~
instead of a ?
for the end it would look like this:
('!'..'~').to_a
# => [
# "`", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",",
# "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
# ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F",
# "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S",
# "T", "U", "V", "W", "X", "Y", "Z", "[", "\\", "]", "^", "_", "a",
# "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
# "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{",
# "|", "}", "~"
# ]
basically if character a
is 65
and z
is 90
then all characters inbetween like b
which is 66
will be included, it works like that for anything you put in a range and since in ruby everything is an object, you can use anything in a range as long as it implements certain methods as explained by the docs!
After doing some playing around in my console I came to this solution which "mimics" the given PHP example and perhaps even completes it.
def rng(length = 10, complexity = 4)
subsets = [("a".."z"), ("A".."Z"), (0..9), ("!".."?"), ("µ".."ö")]
chars = subsets[0..complexity].map { |subset| subset.to_a }.flatten
# => [
# "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l",
# "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
# "y", "z", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
# "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
# "W", "X", "Y", "Z", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, "!", "\"",
# "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".",
# "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":",
# ";", "<", "=", ">", "?", "µ", "¶", "·", "¸", "¹", "º", "»",
# "¼", "½", "¾", "¿", "À", "Á", "Â", "Ã", "Ä", "Å", "Æ", "Ç",
# "È", "É", "Ê", "Ë", "Ì", "Í", "Î", "Ï", "Ð", "Ñ", "Ò", "Ó",
# "Ô", "Õ", "Ö"
# ]
chars.sample(length).join
end
Now calling rng
will produce results like this:
rng # => "·boÇE»Ñ¼Á¸"
rng(10, 2) # => "nyLYAsxJi9"
rng(20, 2) # => "EOcQdjZa0t36xCN8TkoX"
As pointed out below in the comments, I did not even provide a documentation link to the relevant concept, in Ruby this is called a Range
and can be found here (2.5.0).
If you need docs for your specific version, try googling for ruby range [your ruby version]
. You can find out what your version is by running ruby -v
in the terminal. Happy rubying :D
all dates are in dd-mm-yyyy format
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With