Retain 0's when incrementing number - ruby

If I increment integer 003 by 1, I get 4.
num = 003
num += 1
# => 4
I want it to be 004. How can I retain the 0's in this?

You can convert an integer to a String and give it a fixed amount of padding using String#rjust, where the first argument is the total width of the resulting String, and the second argument is the character to use for padding:
>> int = 3
>> str = int.to_s.rjust(3, '0')
#=> "003"
And then you can increment that string using String#next:
>> str.next
#=> "004"

First of all, the leading zero in 003 makes that an octal integer literal in Ruby, not a decimal. Of course, it doesn't matter with 3 but it does matter for 009 (which is a SyntaxError), 030, etc. Presumably you really mean to say:
num = 3
as the leading zeroes aren't really part of the number, they're just formatting that you want on output. To format the number, you'd use String#% or sprintf:
> '%03d' % 3
=> "003"
> sprintf('%03d', 3)
=> "003"

Related

Convert a two-letter String to a 3-digit number

I am working on a software problem and I found myself needing to convert a 2-letter string to a 3-digit number. We're talking about English alphabet only (26 letters).
So essentially I need to convert something like AA, AR, ZF, ZZ etc. to a number in the range 0-999.
We have 676 combinations of letters and 1000 numbers, so the range is covered.
Now, I could just write up a map manually, saying that AA = 1, AB = 2 etc., but I was wondering if maybe there is a better, more "mathematical" or "logical" solution to this.
The order of numbers is of course not relevant, as long as the conversion from letters to numbers is unique and always yields the same results.
The conversion should work both ways (from letters to numbers and from numbers to letters).
Does anyone have an idea?
Thanks a lot
Treat A-Z as 1-26 in base 27, with 0 reserved for blanks.
E.g. 'CD' -> 3 * 27 + 4 = 85
85 -> 85 / 27, 85 % 27 = 3, 4 = C, D
If you don’t have to use consecutive numbers, you can view a two-letter string as a 36-based number. So, you can just use the int function to convert it into an Integer.
int('AA', 36) # 370
int('AB', 36) # 371
#...
int('ZY', 36) # 1294
int('ZZ', 36) # 1295
As for how to convert the number back to a string, you can refer to the method on How to convert an integer to a string in any base?
#furry12 because the diff between the first number and the last one is 1295-370=925<999. It is quite lucky, so you can minus every number for like 300, the results will be in the range of 0-999
def str2num(s):
return int(s, 36) - 300
print(str2num('AA')) # 70
print(str2num('ZZ')) # 995

`to_i` method with base value as parameter in ruby

Can anyone explain how base parameter works when calling to_i with the following examples?
'2'.to_i(2) #=> 0
'3'.to_i(2) #=> 0
'12'.to_i(2) #=> 1
'122'.to_i(2) #=> 1
'20'.to_i(2) #=> 0
'21'.to_i(2) #=> 0
I do not understand how it's actually working. Can anyone explain please?
It is the same reason that '54thousand'.to_i is 54: to_i reads until it finds end of string or an invalid digit.
In binary (base 2), the only valid digits are 0 and 1. Thus, because 2 is invalid, '122'.to_i(2) is identical to '1'.to_i(2). Also, '2'.to_i(2) is identical to ''.to_i(2), which is rather intuitively 0.
base, in other word Radix means the number of unique digits in a numeral system.
In Decimal, we have 0 to 9, 10 digits to represent numbers.
You are using 2 as parameter, that means Binary, so there're only 0 and 1 working.
From the Doc of to_i:
Returns the result of interpreting leading characters in str as an
integer base base (between 2 and 36). Extraneous characters past the
end of a valid number are ignored. If there is not a valid number at
the start of str, 0 is returned. This method never raises an
exception when base is valid.
You can use these number representations directly in Ruby:
num_hex = 0x100
#=> 256
num_bin = 0b100
#=> 4
num_oct = 0o100
#=> 64
num_dec = 0d100
#=> 100

Why does Ruby return for `str[-1..1]` what it does?

Suppose we have a string str. If str contains only one character, for example, str = "1", then str[-1..1] returns 1.
But if the size (length) of str is longer than one, like str = "anything else", then str[-1..1] returns "" (empty string).
Why does Ruby interpret string slicing like this?
This behaviour is just how ranges of characters work.
The range start is -1, which is the last character in the string. The range end is 1, which is the second position from the start.
So for a one character string, this is equivalent to 0..1, which is that single character.
For a two character string, this is 1..1, which is the second character.
For a three character string, this is 2..1, which is an empty string. And so on for longer strings.
To get a non-trivial substring, the start position has to represent a position earlier than the end position.
For a single-length string, index -1 is the same as index 0, which is smaller than 1. Thus, [-1..1] gives a non-trivial substring.
For a string longer than a single character, index -1 is larger than index 0. Thus, [-1..1] cannot give a non-trivial substring, and by default, it returns an empty string.
Writing down the indices usually helps me:
# 0 1 2 3 4 5 6 7 8 9 10 11 12
str = 'a' 'n' 'y' 't' 'h' 'i' 'n' 'g' ' ' 'e' 'l' 's' 'e' #=> "anything else"
# -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1
You can refer to each character by either its positive or negative index. For example, you can use either 3 or -10 to refer to "t":
str[3] #=> "t"
str[-10] #=> "t"
and either 7 or -6 to refer to "g":
str[7] #=> "g"
str[-6] #=> "g"
Likewise, you can use each of these indices to retrieve "thing" via a range:
str[3..7] #=> "thing"
str[3..-6] #=> "thing"
str[-10..7] #=> "thing"
str[-10..-6] #=> "thing"
str[-1..1] however would return an empty string, because -1 refers to the last character and 1 refers to the second. It would be equivalent to str[12..1].
But if the string consists of a single character, that range becomes valid:
# 0
str = '1'
# -1
str[-1..1] #=> "1"
In fact, 1 refers to an index after the first character, so 0 would be enough:
str[-1..0] #=> "1"

Understanding this snippet 'D' * (num % 1000 / 500)

Can anyone explain how to read this code and what it will do?
'D' * (num % 1000 / 500)
It is from a method for converting integers to Roman numerals. I don't understand how it functions.
It is pretty obfuscated indeed. I guess the idea was to put one or zero Ds depending on if you get a number greater than 500 after you get the remainder of division by 1000.
The order of the operations:
num % 1000
num modulo 1000. Will leave the last three digits.
/ 500
Will see if the last three digits are greater than 500.
String#* repeats a string:
'x' * 5 # => "xxxxx"
The reason that is needed is because D is the letter for 500. You will have only one or zero of these as M is the letter for 1000.
The expression (num % 1000 / 500) means "if you have in your last 3 digits a number greater than 500 then evaluate to 1 otherwise evaluate to 0"
"D" * (0 or 1) is determining whether to put "D" on the roman number or not.
What it Does
The expression is a way of building the Roman numeral five-hundreds digit, which is 'D'.
It takes any number, extracts only the three rightmost digits (values 0 through 999), and returns a 'D' only if the value is 500 or greater. Otherwise it returns an empty string ''
How to Read it
In Ruby, the multiply *, divide /, and modulus % symbols have equal precedence and are processed in order from left to right. Parentheses, however, have a higher precedence than these three operators.
To help visualize the processing order, you can add optional parentheses:
'D' * ( ( num % 1000 ) / 500 )
num % 1000:
extracts the three rightmost digits of a number, resulting in values 0 - 999
{0-999} / 500:
determines if value is 500 or greater, or not.
Returns 1 if so, 0 if not.
In Ruby, integer division does not automatically convert to decimals.
'D' * {1 or 0}:
In Ruby, multiplying a string by 1 returns the string, multiplying by 0 returns an empty string
Examples
For a number 35,045:
35045 % 1000 #=> 45
45 / 500 #=> 0
'D' * 0 #=> ""
For a number 468,987:
468987 % 1000 #=> 987
987 / 500 #=> 1
'D' * 1 #=> "D"
For a number 670:
670 % 1000 #=> 670
670 / 500 #=> 1
'D' * 1 #=> "D"
For a number 7:
7 % 1000 #=> 7
7 / 500 #=> 0
'D' * 0 #=> ""
See this page and scroll down to Ruby Operators Precedence.
Multiplication, division, and modular arithmetic are all together, so precedence is left to right IIRC.
First, num % 1000 is evaluated. Then, that is divided by 500. That's then multiplied by 'D'.
The modulus % and division / operators have the same precedence.
So associativity, which is from left to right for these operators, comes into play.
Therefore the expression is equivalent to 'D' * ((num % 1000) / 500): you are multiplying 'D' by the last 3 digits of num divided by 500.

how to insert char at multiple position from end of the string

input like this:
100000000
1000
100
100000
10000
i need to start inserting char (,) from end of the string.first time after three char from end and then repeat the insert (,) after every 2 char
output
10,00,00,000
1,000
100
1,00,000
10,000
any hint guys how can i do this, i need to start inserting char(',') from end of the string.
thanks!
Here are two ways, the first using a regular expression, the last just inserting commas in a loop.
a = %w| 100000000 1000 100 100000 10000 |
#=> ["100000000", "1000", "100", "100000", "10000"]
#1 Use a regex
r = /
(?<=\d) # match digit in positive lookbehind
\d{2} # match two digits
(?= # begin positive lookahead
(?:\d{2})* # match two digits, repeated zero or more times
\d # match last digit
\z # match end of string
) # end positive lookahead
/x # extended mode
a.each { |s| puts "#{s} -> #{ s.gsub(r) { |ss| ',' + ss } }" }
100000000 -> 10,00,00,000
1000 -> 1,000
100 -> 100
100000 -> 1,00,000
10000 -> 10,000
This regex is similar to the one given earlier by #Avinish, but I chose to use a positive lookbehind and no capture group, and presented it in extended mode to help readers understand how it worked. I would use a regular expression here.
#2 Insert commas
If you do not wish to use a regular expression, you could determine the position of the last comma to insert (p below), the number of commas to insert (n below) and then insert them, back to front:
def insert_commas(string)
sz = string.size
str = string.dup
p = sz - 3
n = (sz - 2)/2
n.times { str.insert(p, ','); p -= 2 }
str
end
a.each { |s| puts "#{s} -> #{insert_commas(s)}" }
100000000 -> 10,00,00,000
1000 -> 1,000
100 -> 100
100000 -> 1,00,000
10000 -> 10,000
I duped string on the assumption you did not want to mutate string.
Alternatively,
def insert_commas(string)
sz = string.size
return string if sz < 4
p = sz.even? ? 1 : 2
string[0,p] + string[p..-2].gsub(/\d{2}/) { |s| ",#{s}" } + string[-1]
end
Use the below positive lookahead based regex.
gsub(/(\d)(?=(?:\d{2})*\d{3}$)/, "$1,")
DEMO

Resources