I'm using this simple function:
def print_players(players):
tot = 1
for p in players:
print '%2d: %15s \t (%d|%d) \t was: %s' % (tot, p['nick'], p['x'], p['y'], p['oldnick'])
tot += 1
and I'm supposing nicks are no longer than 15 characters.
I'd like to keep each "column" aligned, is there a some syntactic sugar allowing me to do the same but keeping the nicknames column left-aligned instead of right-aligned, without breaking column on the right?
The equivalent, uglier, code would be:
def print_players(players):
tot = 1
for p in players:
print '%2d: %s \t (%d|%d) \t was: %s' % (tot, p['nick']+' '*(15-len(p['nick'])), p['x'], p['y'], p['oldnick'])
tot += 1
Thanks to all, here is the final version:
def print_players(players):
for tot, p in enumerate(players, start=1):
print '%2d:'%tot, '%(nick)-12s (%(x)d|%(y)d) \t was %(oldnick)s'%p
To left-align instead of right-align, use %-15s instead of %15s.
Slightly off topic, but you can avoid performing explicit addition on tot using enumerate:
for tot, p in enumerate(players, start=1):
print '...'
Or if your using python 2.6 you can use the format method of the string:
This defines a dictionary of values, and uses them for dipslay:
>>> values = {'total':93, 'name':'john', 'x':33, 'y':993, 'oldname':'rodger'}
>>> '{total:2}: {name:15} \t ({x}|{y}\t was: {oldname}'.format(**values)
'93: john \t (33|993\t was: rodger'
Seeing that p seems to be a dict, how about:
print '%2d' % tot + ': %(nick)-15s \t (%(x)d|%(y)d) \t was: %(oldnick)15s' % p
Related
I'm tasked with creating a Caesar cipher for a project I am working on. A Caesar cipher takes each letter in a string of text and replaces it with a letter a fixed number of places away from it (dictated by the cipher key). For instance if my text is "cat" and my cipher key is 3, my new word would be "fdw" (I'm assuming positive numbers move the letters to the right). I've been able to get my code to solve correctly for most strings of text, but I am finding that if my string includes > ? or # it will not work. Their ASCii codes are 62,63 and 64 if that helps. Any input is appreciated!
def caesar_cipher(str, num)
strArray = str.split('')
cipherArray = strArray.collect do |letter|
letter = letter.ord
if (65...90).include?(letter + num) || (97...122).include?(letter + num)
letter = letter + num
elsif (91...96).include?(letter + num) || (123...148).include?(letter + num)
letter = (letter - 26) + num
else
letter
end
end
cipherArray = cipherArray.collect {|x| x.chr}
cipher = cipherArray.join('')
end
caesar_cipher("Am I ill-prepared for this challenge?", 3)
#ord 62-64 DON'T work >, ?, #
You should create an alphabet variable, just think in if you use both ends then you will have 2 problems: negative numbers and an ASCii number that doesn't exist. You can handle this with module operator % or with a single subtraction.
alphabet = "abcde"
text_to_cipher= "aaee" => 0044 #number based in his position at aphabet var
key = 3
result will be 3377 => dd¡? or any other symbol since 7 is out of the string length "abcde" same happens with ASCii at its ends.
With module operator, you can restrict that.
size_of_your_alphabet = 5 # For this case
7%size_of_your_alphabet = 2
The Ruby builtin tr is ideal to implement substitution ciphers.
Step 1: assemble the characters you wish to transform.
chars = ["A".."Z", "a".."z", ">".."#"].flat_map(&:to_a)
Step 2: create a 1:1 array of the transformed characters
transformed = chars.map{|c| (c.ord + 3).chr}
Step 3: apply tr to transform the string.
str.tr(chars.join, transformed.join)
Full working example:
def caesar_cipher(str, num)
chars = ["A".."Z", "a".."z", ">".."#"].flat_map(&:to_a)
transformed = chars.map{|c| (c.ord + num).chr}
str.tr(chars.join, transformed.join)
end
Output:
> caesar_cipher("Am I ill-prepared for this challenge?", 3)
#=> "Dq L mpp-tvitevih jsv xlmw gleppirkiC"
Notes:
Most substitution ciphers actually rely on letter rotation, not ASCII values. My inital assumption was that you wanted a rotation, e.g. ("a".."z").to_a.rotate(num). See prior edit for a working example of that.
You can use ranges in tr() to create a really simple Caesar cipher: str.tr('A-Za-z','B-ZAb-za')
Edit: Also, because of the range specification feature, the \ is an escape character so that you can use literals like -. See this SO answer for details. I think the above exhibits a bug due to this, because it contains a \ which should be escaped by another \.
Hi I want to add a space before and after the special characters in the string
Frozen/Chilled/Ambient (Please state)
I want the result like
Frozen / Chilled / Ambient ( Please state )
Are there any possibilities to add the space in ruby regexp?
Don't need to use complex regex
You can make use of block syntax of gsub
"Frozen/Chilled/Ambient (Please state)".gsub(/\W+/) {|w| " #{w} "}
#=> "Frozen / Chilled / Ambient ( Please state ) "
If you want to remove the duplicate spaces you can use squish
"Frozen/Chilled/Ambient (Please state)".gsub(/\W+/) {|w| " #{w} "}.squish
#=> "Frozen / Chilled / Ambient ( Please state )"
NOTE:
\W - matches any non-word character
squish - Removes surrounding white spaces and change multiple spaces to 1
EDIT:
As per the comment if can also make use of /[[:punct:]]/
[[:punct:]] => [!"\#$%&'()*+,\-./:;<=>?#\[\\\]^_`{|}~]
Try this:
sample = "Frozen/Chilled/Ambient (Please state)"
sample.gsub(/([^\w\s])/, ' \1 ')
It is getting everything is not a \w (\w is a-z, A-Z, 0-9 and the undescore _) or space \s. Then gsub replaces the element found by itself with space before and after.
Try String#gsub:
> sample = "Frozen/Chilled/Ambient (Please state)"
#=> "Frozen/Chilled/Ambient (Please state)"
> sample.gsub!("/", " / ")
#=> "Frozen / Chilled / Ambient (Please state)"
Note: gsub! will override variable's value itself
Update:
as per your comment you want to add space before and after each special characters:
> pattern = /[^a-zA-Z0-9|(|)|_|\s\-]/
> sample.gsub(pattern){|match|" #{match} "}
#=> "Frozen / Chilled / Ambient (Please state)"
Note: pattern covers all special characters
This might be a quick solution.
"Frozen/Chilled/Ambient (Please state)".split("/").join(" / ")
# => "Frozen / Chilled / Ambient (Please state)"
A few minutes after, Cary Swoveland will come and comment, "Hey son, there are enough string methods to solve this problem, your solution is quite ineffective" -))
For that case, below snippet uses string methods, and matches everythin except
letters digit and space.
q = "Frozen/Chilled/Ambient (Please state)"
puts q.gsub(/[^a-zA-Z0-9. ]/){|s| " #{s} "}
#=> Frozen / Chilled / Ambient ( Please state )
without blocks.
q.gsub(/([^a-zA-Z0-9.])/, ' \1 ')
#=> Frozen / Chilled / Ambient ( Please state )
I'm attempting to simplify a script, and my attempts are failing. I'm making a function that will pass the given arguments and turn them into an indexed table, but I want to be able to pass quoted and non-quoted alike and have the function recognize that quoted arguments are considered one value while also respecting non-quoted arguments.
For example:
makelist dog "brown mouse" cat tiger "colorful parrot"
should return an indexed table like the following:
list_table = {"dog", "brown mouse", "cat", "tiger", "colorful parrot"}
The code I have works for quoted, but it's messing up on the non-quoted, and on top of that, adds the quoted arguments a second time. Here's what I have:
function makelist(str)
require 'tprint'
local list_table = {}
for word in string.gmatch(str, '%b""') do
table.insert(list_table, word)
end
for word in string.gmatch(str, '[^%p](%a+)[^%p]') do
table.insert(list_table, word)
end
tprint(list_table)
end
I'm not understanding why the omission of quotes is being ignored, and also is chopping off the first letter. That is, this is the output I receive from tprint (a function that prints a table out, not relevant to the code):
makelist('dog "brown mouse" cat tiger "colorful parrot"')
1=""brown mouse""
2=""colorful parrot""
3="og"
4="rown"
5="mouse"
6="cat"
7="tiger"
8="olorful"
9="parrot"
As you can see, 'd', 'b', and 'c' are missing. What fixes do I need to make so that I can get the following output instead?
1="brown mouse"
2="colorful parrot"
3="dog"
4="cat"
5="tiger"
Or better yet, have them retain the same order they were dictated as arguments, if that's possible at all.
local function makelist(str)
local t = {}
for quoted, non_quoted in ('""'..str):gmatch'(%b"")([^"]*)' do
table.insert(t, quoted ~= '""' and quoted:sub(2,-2) or nil)
for word in non_quoted:gmatch'%S+' do
table.insert(t, word)
end
end
return t
end
It may be easier to simply split on whitespaces and concatenate those elements that are inside quotes. Something like this may work (I added few more test cases):
function makelist(str)
local params, quoted = {}, false
for sep, word in str:gmatch("(%s*)(%S+)") do
local word, oquote = word:gsub('^"', "") -- check opening quote
local word, cquote = word:gsub('"$', "") -- check closing quote
-- flip open/close quotes when inside quoted string
if quoted then -- if already quoted, then concatenate
params[#params] = params[#params]..sep..word
else -- otherwise, add a new element to the list
params[#params+1] = word
end
if quoted and word == "" then oquote, cquote = 0, oquote end
quoted = (quoted or (oquote > 0)) and not (cquote > 0)
end
return params
end
local list = makelist([[
dog "brown mouse" cat tiger " colorful parrot " "quoted"
in"quoted "terminated by space " " space started" next "unbalanced
]])
for k, v in ipairs(list) do print(k, v) end
This prints the following list for me:
1 dog
2 brown mouse
3 cat
4 tiger
5 colorful parrot
6 quoted
7 in"quoted
8 terminated by space
9 space started
10 next
11 unbalanced
First thanks for your question, got me to learn the basics of Lua!
Second, so I think you went with your solution in a bit of misdirection. Looking at the question I just said why don't you split once by the quotes (") and than choose where you want to split by space.
This is what I came up with:
function makelist(str)
local list_table = {}
i=0
in_quotes = 1
if str:sub(0,1) == '"' then
in_quotes = 0
end
for section in string.gmatch(str, '[^"]+') do
i = i + 1
if (i % 2) == in_quotes then
for word in string.gmatch(section, '[^ ]+') do
table.insert(list_table, word)
end
else
table.insert(list_table, section)
end
end
for key,value in pairs(list_table) do print(key,value) end
end
The result:
1 dog
2 brown mouse
3 cat
4 tiger
5 colorful parrot
ruby 2.1.3
rails 4.1.7
I want to generate a unordered list from textarea. So I have to preserve all line breaks for each item and remove leading and trailing spaces.
Well, I'm trying to remove all leading and trailing spaces from each line of textarea with no success.
I'm using a regex:
string_from_textarea.gsub(/^[ \t]+|[ \t]+$/, '')
I've tried strip and rstrip rails methods with no luck too (they are working with the same result as regex):
Leading spaces for each line are removed perfectly.
But with trailing spaces only the last space from string is removed. But I wanna for each line.
What am I missing here? What is the deal with textarea and trailing spaces for each line?
UPDATE
Some code example:
I'm using a callback to save formated data.
after_validation: format_ingredients
def format_ingredients
self.ingredients = #ingredients.gsub(/^[ \t]+|[ \t]+$/, "")
end
Form view:
= f.text_area :ingredients, class: 'fieldW-600 striped', rows: '10'
You can use String#strip
' test text with multiple spaces '.strip
#=> "test text with multiple spaces"
To apply this to each line:
str = " test \ntext with multiple \nspaces "
str = str.lines.map(&:strip).join("\n")
"test\ntext with multiple\nspaces"
This isn't a good use for a regexp. Instead use standard String processing methods.
If you have text that contains embedded LF ("\n") line-ends and spaces at the beginning and ends of the lines, then try this:
foo = "
line 1
line 2
line 3
"
foo # => "\n line 1 \n line 2\nline 3\n"
Here's how to clean the lines of leading/trailing white-space and re-add the line-ends:
bar = foo.each_line.map(&:strip).join("\n")
bar # => "\nline 1\nline 2\nline 3"
If you're dealing with CRLF line-ends, as a Windows system would generate text:
foo = "\r\n line 1 \r\n line 2\r\nline 3\r\n"
bar = foo.each_line.map(&:strip).join("\r\n")
bar # => "\r\nline 1\r\nline 2\r\nline 3"
If you're dealing with the potential of having white-space that contains other forms of white-space like non-breaking spaces, then switching to a regexp that uses the POSIX [[:space:]] character set, that contains white-space used in all character sets. I'd do something like:
s.sub(/^[[:space:]]+/, '').sub(/[[:space:]]+$/, '')
I think #sin probably intimated the problem in his/her first comment. Your file was probably produced on a Windows machine that puts a carriage return/life feed pair ("\r\n") at the end of each line other than (presumably) the last, where it just writes \n. (Check line[-2] on any line other than the last.) That would account for the result you are getting:
r = /^[ \t]+|[ \t]+$/
str = " testing 123 \r\n testing again \n"
str.gsub(r, '')
#=> "testing 123 \r\ntesting again\n"
If this theory is correct the fix should be just a slight tweak to your regex:
r = /^[ \t]+|[ \t\r]+$/
str.gsub(r, '')
#=> "testing 123\ntesting again\n"
You might be able to do this with your regex by changing the value of the global variable $/, which is the input record separator, a newline by default. That could be a problem for the end of the last line, however, if that only has a newline.
I think you might be looking for String#lstrip and String#rstrip methods:
str = %Q^this is a line
and so is this
all of the lines have two spaces at the beginning
and also at the end ^`
`> new_string = ""
> ""
str.each_line do |line|
new_string += line.rstrip.lstrip + "\n"
end
> "this is a line\n and so is this \n all of the lines have two spaces at the beginning \n and also at the end "
2.1.2 :034 > puts new_string
this is a line
and so is this
all of the lines have two spaces at the beginning
and also at the end
> new_string
`> "this is a line\nand so is this\nall of the lines have two spaces at the beginning\nand also at the end\n"`
This question already has an answer here:
Anyone can comment this ruby code? [closed]
(1 answer)
Closed 8 years ago.
I don't know ruby language. I was reading a very interesting article which contain a following 2 line ruby code which i need to understand.
(0..0xFFFFFFFFFF).each do |i|
puts "#{"%010x" % i}"
end
By googling, i get the 1st line. But i am not able to understand 2nd line. Can someone please explain its meaning?
puts "#{"%010x" % i}" has actually two parts - string interpolation (which G.B tells you about), and string format using %:
Format—Uses str as a format specification, and returns the result of
applying it to arg. If the format specification contains more than one
substitution, then arg must be an Array or Hash containing the values
to be substituted. See Kernel::sprintf for details of the format
string.
"%05d" % 123 #=> "00123"
"%-5s: %08x" % [ "ID", self.object_id ] #=> "ID : 200e14d6"
"foo = %{foo}" % { :foo => 'bar' } #=> "foo = bar"
So "%010x" % i formats the integer in hex format (x) with at least 10 digits (10), padding with zeros (the leading 0):
"%010x" % 150000
# => "00000249f0"
Actually
puts "#{"%010x" % i}"
is exactly the same as
puts "%010x" % i
since the interpolation simply puts the resulting value (a string) within a string....
Puts key word is used to print the data on the console.
for example
puts "writing data to console"
above line will print exact line to the console "writing data to console"
#a = "this is a string"
puts #a
this will print "this is a test string"
puts "My variable a contains #{#a}"
this will print "My variable a contains this is a string" and this merging technique is called string interpolation.
this first argument in puts "#{"%010x" % i}" specifies the format and second represents the value.
and for your exact question and further details see this link
it's string interpolation and sprintf
documents:
http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Literals#Interpolation
http://www.ruby-doc.org/core-2.1.2/Kernel.html#method-i-sprintf
http://batsov.com/articles/2013/06/27/the-elements-of-style-in-ruby-number-2-favor-sprintf-format-over-string-number-percent/
"%010x" % i is same as sprintf("%010x", i)
puts "#{"%010x" % i}"
This line print the content. and if you want o interpolated the string please used single quote inside the double quote. like this "#{'%010x' % i }"
and %x means convert integer into hexadecimal and %010x means make it 10 place value means if out is 0 then make it like this 0000000000.
Print
puts is the equivalent of echo in PHP and printf in C
When included in either a command-line app, or as part of a larger application, it basically allows you to output the text you assign to the method:
puts "#{"%010x" % i}"
This will basically print the contents of "#{"%010x" % i}" on the screen - the content of which means that ruby will output the calculaton of what's inside the curly braces (which has been explained in another answer)