Is there a better method to display a number in hex with leading 0? I tried:
i.to_s(16)
but
2.to_s(16) #=> "2"
where I expect "02". I tried the print format:
"%02x" % i
which works for 2, but
"%02x" % 256 #=> "100"
where I want "0100". So I came up with this:
class Integer
def to_hex_string
("%0x" % self).size % 2 == 0 ? "%0x" % self : "%0#{("%0x" % self).size+1}x" % self
end
end
It works:
2.to_hex_string #=> "02"
256.to_hex_string #=> "0100"
It works also with class Bignumber, but it looks strange that such an easy request needs a trick like this. Any better idea?
for 2-digit hex values this works:
def to_hex(int)
int < 16 ? '0' + int.to_s(16) : int.to_s(16)
end
Yes, it bugs:
Let's try this:
class Integer
def to_hex_string
"0#{to_s(16)}"
end
end
class BigNumber
def to_hex_string
"0#{to_s(16)}"
end
end
class String
def to_hex_string
self.unpack('H*').first
end
def to_bytes_string
unless self.size % 2 == 0
raise "Can't translate a string unless it has an even number of digits"
end
raise "Can't translate non-hex characters" if self =~ /[^0-9A-Fa-f]/
[self].pack('H*')
end
def to_bignum
self.bytes.inject { |a,b| (a << 8) + b }
end
end
p a="ff"*192 # => "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
p bytestring=a.to_bytes_string # => "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"
p bytestring.to_hex_string # => "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
p biga=a.to_bytes_string.to_bignum # => 2410312426921032588580116606028314112912093247945688951359675039065257391591803200669085024107346049663448766280888004787862416978794958324969612987890774651455213339381625224770782077917681499676845543137387820057597345857904599109461387122099507964997815641342300677629473355281617428411794163967785870370368969109221591943054232011562758450080579587850900993714892283476646631181515063804873375182260506246992837898705971012525843324401232986857004760339316735
And the BUG is here:
p biga.to_hex_string # => "0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
Where does this 0 come from????
What is even more strange is my complicated solution is working:
p ("%0x" % biga).size % 2 == 0 ? "%0x" % biga : "%0#{("%0x" % biga).size+1}x" % biga # => "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
Maybe a bug in "0#{to_s(16)}"?
Use "%.2x", where 2 is the amount of digits you want.
"%.2x" % 0 # => "00"
"%.2x" % 15 # => "0f"
"%.2x" % 255 # => "ff"
This was the first hit on Google when I was just trying to solve this. I had to find a couple of other posts to finish up my solution but I think this is clean.
class Fixnum
def to_hex(bits)
rjust = (bits/4 + (bits.modulo(4)==0 ? 0 : 1))
"0x" + self.to_s(16).rjust(rjust, "0")
end
end
You are making this way too complicated. If you want to print an integer in hexadecimal with a leading zero, then it is just
class Integer
def to_hex_string
"0#{to_s(16)}"
end
end
2.to_hex_string # => 02
256.to_hex_string # => 0100
Related
# Character Counter
class String
def count_lcases
count(('a'..'z').to_a.join(''))
end
def count_upcases
count(('A'..'Z').to_a.join(''))
end
def count_num
count((0..9).to_a.join(''))
end
def count_spl_chars
length - count_lcases - count_upcases - count_num
end
end
input = ARGV[0]
if ARGV.empty?
puts 'Please provide an input'
exit
end
puts 'Lowercase characters = %d' % [input.count_lcases]
puts 'Uppercase characters = %d' % [input.count_upcases]
puts 'Numeric characters = %d' % [input.count_num]
puts 'Special characters = %d' % [input.count_spl_chars]
I used ranges to count characters but count function is called 3 times.
I can always use loops and count it one by one.I was wondering is there any way to optimize this?...
If you are using Ruby 2.7 you could use tally; the string's chars are just iterated one time.
def classify_char(c)
case c
when /[a-z]/ then :lcase
when /[A-Z]/ then :ucase
when /\d/ then :digit
else :other
end
end
p "asg3456 ERTYaeth".chars.map{|c| classify_char(c) }.tally
# => {:lcase=>7, :digit=>4, :other=>2, :ucase=>4}
If Ruby 2.3...2.7, this will work:
CHAR_CLASSES = {
lcase: ?a..?z,
ucase: ?A..?Z,
digit: ?0..?9,
}
p "asg3456 ERTYaeth".each_char.with_object(Hash.new(0)) { |c, o|
o[CHAR_CLASSES.find { |label, group| group === c }&.first || :other] += 1
}
For < 2.3,
p "asg3456 ERTYaeth".each_char.with_object(Hash.new(0)) { |c, o|
p = CHAR_CLASSES.find { |label, group| group === c }
o[p ? p.first : :other] += 1
}
This question already has answers here:
How do I keep the delimiters when splitting a Ruby string?
(5 answers)
Closed 7 years ago.
This has been asked multiple times around here, but never got a generic answer, so here we go:
Say you have a string, any string, but let's go with "oruh43451rohcs56oweuex59869rsr", and you want to split it with a regular expression. Any regular expression, but let's go with a sequence of digits: /\d+/. Then you'd use split:
"oruh43451rohcs56oweuex59869rsr".split(/\d+/)
# => ["oruh", "rohcs", "oweuex", "rsr"]
That's lovely and all, but I want the digits. So for that we have scan:
"oruh43451rohcs56oweuex59869rsr".scan(/\d+/)
# => ["43451", "56", "59869"]
But I want it all! Is there, say, a split_and_scan? Nope.
How about I split and scan then zip them? Let me stop you right there.
Ok, so how?
If split's pattern contains a capture group, the group will be included in the resulting array.
str = "oruh43451rohcs56oweuex59869rsr"
str.split(/(\d+)/)
# => ["oruh", "43451", "rohcs", "56", "oweuex", "59869", "rsr"]
If you want it zipped,
str.split(/(\d+)/).each_slice(2).to_a
# => [["oruh", "43451"], ["rohcs", "56"], ["oweuex", "59869"], ["rsr"]]
I'm glad you asked… well, there's String#shatter from Facets. I don't love it because it's implemented using trickery (look at the source, it's cute clever trickery, but what if your string actually contains a "\1"?).
So I rolled my own. Here's what you get:
"oruh43451rohcs56oweuex59869rsr".unjoin(/\d+/)
# => ["oruh", "43451", "rohcs", "56", "oweuex", "59869", "rsr"]
And here's the implementation:
class Object
def unfold(&f)
(m, n = f[self]).nil? ? [] : n.unfold(&f).unshift(m)
end
end
class String
def unjoin(rx)
unfold do |s|
next if s.empty?
ix = s =~ rx
case
when ix.nil?; [s , ""]
when ix == 0; [$&, $']
when ix > 0; [$`, $& + $']
end
end
end
end
(verbosier version at the bottom)
And here are some examples of corner cases being handled:
"".unjoin(/\d+/) # => []
"w".unjoin(/\d+/) # => ["w"]
"1".unjoin(/\d+/) # => ["1"]
"w1".unjoin(/\d+/) # => ["w", "1"]
"1w".unjoin(/\d+/) # => ["1", "w"]
"1w1".unjoin(/\d+/) # => ["1", "w", "1"]
"w1w".unjoin(/\d+/) # => ["w", "1", "w"]
And that's it, but here's more…
Or, if you don't like mucking with the built-in classes… well, you could use Refinements… but if you really don't like it, here it is as functions:
def unfold(x, &f)
(m, n = f[x]).nil? ? [] : unfold(n, &f).unshift(m)
end
def unjoin(s, rx)
unfold(s) do |s|
next if s.empty?
ix = s =~ rx
case
when ix.nil?; [s , ""]
when ix == 0; [$&, $']
when ix > 0; [$`, $& + $']
end
end
end
It also occurs to me that it may not always be clear which are the separators and which are the separated bits, so here's a little addition that lets you query a string with #joint? to know what role it played before the split:
class String
def joint?
false
end
class Joint < String
def joint?
true
end
end
def unjoin(rx)
unfold do |s|
next if s.empty?
ix = s =~ rx
case
when ix.nil?; [s, ""]
when ix == 0; [Joint.new($&), $']
when ix > 0; [$`, $& + $']
end
end
end
end
and here it is in use:
"oruh43451rohcs56oweuex59869rsr".unjoin(/\d+/)\
.map { |s| s.joint? ? "(#{s})" : s }.join(" ")
# => "oruh (43451) rohcs (56) oweuex (59869) rsr"
You can now easily reimplement split and scan:
class String
def split2(rx)
unjoin(rx).reject(&:joint?)
end
def scan2(rx)
unjoin(rx).select(&:joint?)
end
end
"oruh43451rohcs56oweuex59869rsr".split2(/\d+/)
# => ["oruh", "rohcs", "oweuex", "rsr"]
"oruh43451rohcs56oweuex59869rsr".scan2(/\d+/)
# => ["43451", "56", "59869"]
And if you hate match globals and general brevity…
class Object
def unfold(&map_and_next)
result = map_and_next.call(self)
return [] if result.nil?
mapped_value, next_value = result
[mapped_value] + next_value.unfold(&map_and_next)
end
end
class String
def unjoin(regex)
unfold do |tail_string|
next if tail_string.empty?
match = tail_string.match(regex)
index = match.begin(0)
case
when index.nil?; [tail_string, ""]
when index == 0; [match.to_s, match.post_match]
when index > 0; [match.pre_match, match.to_s + match.post_match]
end
end
end
end
I have the following code for an assignment. After much debugging I found what was happening
class Integer
def initialize()
#ans = ""
end
def ans
#ans = ""
end
def ans=(value)
#ans = value
end
def to_base(base)
# convert given number into the base
# figure out how to make it the most efficient
num = self
r = 0
loop do
r = num % base # modulus
#ans = r.to_s + #ans.to_s # add to answer
num /= base # division
break unless num != 0
end
english = #ans # return value
end
def to_oct
self.to_base(8)
end
end
puts 8.to_oct
puts 8.to_base(2)
Output:
10
100010
The output for the binary version should be 1000 not 100010
What it did was append the first instance of the class 8.to_oct onto the second call 8.to_base(2)
Is there a way to have this cleared as I want to use the same number (8) in this example and convert it to various base numbers. what am I doing wrong in my class?
Thanks!
One of the pre-work exercises for Dev Bootcamp is an RPN calculator. I made it work but would like refactoring feedback. Any and all help to make this code cleaner is greatly appreciated.
class RPNCalculator
def evaluate(rpn)
a = rpn.split(' ')
array = a.inject([]) do |array, i|
if i =~ /\d+/
array << i.to_i
else
b = array.pop(2)
case
when i == "+" then array << b[0] + b[1]
when i == '-' then array << b[0] - b[1]
when i == '*' then array << b[0] * b[1]
when i == '/' then array << b[0] / b[1]
end
end
end
p array.pop
end
end
calc = RPNCalculator.new
calc.evaluate('1 2 +') # => 3
calc.evaluate('2 5 *') # => 10
calc.evaluate('50 20 -') # => 30
calc.evaluate('70 10 4 + 5 * -') # => 0
class RPNCalculator
def evaluate rpn
array = rpn.split(" ").inject([]) do |array, i|
if i =~ /\d+/
array << i.to_i
else
b = array.pop(2)
array << b[0].send(i, b[1])
end
end
p array.pop
end
end
I tend to prefer avoiding case..when in favor of lookup tables. So I'd change your code to:
class RPNCalculator
def evaluate(rpn)
a = rpn.split(' ')
array = a.inject([]) do |array, i|
if i =~ /\d+/
array << i.to_i
else
array << array.pop(2).reduce(op(i))
end
end
p array.pop
end
private
def op(char)
{'+'=>:+, '-'=>:-, '/'=>:/, '*'=>:*}[char]
end
end
I also don't believe you should only be popping off 2 operands. "1 2 3 +" would be valid RPN, evaluating to 6. The entire stack should be reduced. This also avoids the mutation, which is a good thing, as it follows a more functional style.
class RPNCalculator
def evaluate(rpn)
a = rpn.split(' ')
array = a.inject([]) do |array, i|
if i =~ /\d+/
[*array, i.to_i]
else
[array.reduce(op(i))]
end
end
p array.pop
end
private
def op(char)
{'+'=>:+, '-'=>:-, '/'=>:/, '*'=>:*}[char]
end
end
I removed the other mutation here too, by using [*arr, value] instead of actually modifying the array.
Finally, I'd avoid printing directly from your #evaluate method and just return the number. I'd also (again) avoid the mutation:
class RPNCalculator
def evaluate(rpn)
a = rpn.split(' ')
stack = a.inject([]) do |stack, i|
if i =~ /\d+/
[*stack, i.to_i]
else
[stack.reduce(op(i))]
end
end
stack.last
end
private
def op(char)
{'+'=>:+, '-'=>:-, '/'=>:/, '*'=>:*}[char]
end
end
I renamed 'array' to 'stack', since it is a parser stack and is less generic than just array.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Test if string is a number in Ruby on Rails
Currently I have this (awful) code:
def is_num(num_given)
begin
num_given.to_i
worked = true
rescue
worked = false
ensure
return worked
end
end
Which I refactored to this:
def is_num(num_given)
num_given.to_i.is_a?(Numeric) rescue false
end
This still just doesn't feel right to me, is there a better way to do this?
Both of these implementations work fine for my purposes, I am just looking for some code euphoria.
something.is_a?(Numeric) is the way to go. Referring to your latter example, there's no need to call to_i on the input.
Note that something.is_a?(Numeric) will not work if you're looking to see if a string is a number...
Here's another solution. It's not very Ruby-like, but that's intentional (e.g., while is faster than str.chars.each in this case).
# is a character between 0 and 9? (based on C's isdigit())
def digit?(c)
o = c.ord
o >= 48 && o <= 57 # '0'.ord, '9'.ord
end
# is a string numeric (i.e., represented as an integer or decimal)?
def numeric?(str)
str = str.to_s unless str.is_a?(String)
l = str.length
i = 0
while i < l
c = str[i]
if c == '.' || c == '-'
i += 1
next
end
return false if !digit?(c)
i += 1
end
true
end
Here are the unit tests. Let me know if I missed a case. For other answerers, just change the subject block to your function.
if $0 == __FILE__
require 'minitest/autorun'
describe :digit? do
%w(- + : ? ! / \ ! # $ ^ & *).each do |c|
it "flunks #{c}" do
digit?(c).must_equal false
end
end
%w(0 1 2 3 4 5 6 7 8 9).each do |c|
it "passes #{c}" do
digit?(c).must_equal true
end
end
end
describe :numeric? do
subject { :numeric? }
%w(0 1 9 10 18 123.4567 -1234).each do |str|
it "passes #{str}" do
method(subject).call(str).must_equal true
end
end
%w(-asdf 123.zzz blah).each do |str|
it "flunks #{str}" do
method(subject).call(str).must_equal false
end
end
[-1.03, 123, 200_000].each do |num|
it "passes #{num}" do
method(subject).call(num).must_equal true
end
end
end
end
The functions you listed won't work:
is_num("a") #=> true
The problem is that they don't raise an error for invalid input. What you want is Integer, which will raise an error which you can rescue:
def is_num(num_given)
!!Integer(num_given) rescue false
end
This works:
irb(main):025:0> is_num("a")
=> false
irb(main):026:0> is_num(5)
=> true
irb(main):027:0> is_num((1..2))
=> false
irb(main):028:0> is_num("3")
=> true
(There may be a more natural way to do this, though.)
You can always use a simple regex:
def is_num(num_given)
num_given =~ /\d+(\.\d+)?/
end