I have strings that consist of two lots of numbers. I am trying to split them into two substrings so that there are two decimal places after each decimal.
I have this code:
if homeodds.length == 10 then
homeoddsp = homeodds[0,5].to_f
bookieh = homeodds[5,5].to_f
else
homeoddsp = homeodds[0,4].to_f
bookieh = homeodds[4,4].to_f
end
It handles an eight figure string fine:
"1.211.90" translates to "1.21" and "1.90".
and a ten figure string also works:
"12.2113.00" translates to "12.21" and "13.00".
When I have a nine figure string like "9.1110.00" or "10.119.55", I need to find out where the first decimal is, and take two digits after that so that the remainder becomes the second substring. These cases, I can't consistently do.
You could use String#scan for this particular problem
def decimal_splits(string)
string.scan(/\d+\.\d{2}/)
end
To break down the regular expression:
\d+ 1 or more number of digits
\. the decimal point
\d{2} two digits
The result will be an array of matches for the expression.
decimal_splits("9.1110.00")
#=> ["9.11", "10.00"]
decimal_splits("12.2113.00")
#=> ["12.21", "13.00"]
decimal_splits("1.211.90")
#=> ["1.21", "1.90"]
decimal_splits("10.119.55")
#=> ["10.11", "9.55"]
Related
I have a string and need to extract all palindrome substrings (minimum length is 3 characters) using regular expression
Is this possible?
I want a solution like below
str = "abcbd"
puts sub_str_palindrome(str)
# output
["bcb"]
str = "abcde"
puts sub_str_palindrome(str)
# output
[]
Here are some clues for regexp
to match 3-4 characters palindrome:
(.)(.)\2?\1
5-6 characters (add (?:(.)\3?\2| and ) after \2?:
(.)(.)(?:(.)\3?\2|\2?)\1
7-8 characters (add (?:(.)\4?\3| and ) after \3?):
(.)(.)(?:(.)(?:(.)\4?\3|\3?)\2|\2?)\1
etc.
I hope this algorithm will help you to implement the method
I have a long string which contains only decimal numbers with two signs after comma
str = "123,457568,22321,5484123,77"
The numbers in string only decimals with two signs after comma. How I can separate them in different numbers like that
arr = ["123,45" , "7568,22" , "321,54" , "84123,77"]
You could try a regex split here:
str = "123,457568,22321,5484123,77"
nums = str.split(/(?<=,\d{2})/)
print nums
This prints:
123,45
7568,22
321,54
84123,77
The logic above says to split at every point where a comma followed by two digits precedes.
Scan String for Commas Followed by Two Digits
This is a case where you really need to know your data. If you always have floats with two decimal places, and commas are decimals in your locale, then you can use String#scan as follows:
str.scan /\d+,\d{2}/
#=> ["123,45", "7568,22", "321,54", "84123,77"]
Since your input data isn't consistent (which can be assumed by the lack of a reliable separator between items), you may not be able to guarantee that each item has a fractional component at all, or that the component has exactly two digits. If that's the case, you'll need to find a common pattern that is reliable for your given inputs or make changes to the way you assign data from your data source into str.
I have to get the exact amount of decimal digits of pi, so I tried using this method:
require "bigdecimal/math"
include BigMath
input = 9
output = BigMath.PI(input).to_s
puts output
but instead of getting this as a result:
output: 3.141592653 # Which are the first 9 decimal digits of PI
I get this:
output: 0.3141592653589793238462643313830947690870926e1
What am I doing wrong?
Since π is an irrational number, its decimal representation never ends and never settles into a permanently repeating pattern.
Therefore, algorithms for calculation of π can find only results with specified precision.
BigMath.PI - is not an exception.
Parameter prec which we pass as a first argument, means precision (that is the number of accurate digits after the decimal point).
When we execute BigMath.PI(9), we obtain a BigDecimal instance, which string representation is 0.3141592653589793238462643313830947690870926e1.
If we look more closely at this string we can see e1 in the end.
Such notation is common in math and it means:
Hence, in our case
0.3141592653589793238462643313830947690870926e1
is the same as
0.3141592653589793238462643313830947690870926 * 10 = 3.141592653589793238462643313830947690870926
Since we passed 9 to BigMath.PI, we have at least 9 accurate digits after the decimal dot
3.141592653589793238462643313830947690870926
3.141592653_________________________________
(Actually, when we pass 9 to BigMath.PI, it returns more than 9 accurate digits after the decimal dot, but we should not rely on this fact. You can try to compare if you like).
And probably the last thing to mention: we can't just convert BigDecimal to Float, if we care about accuracy, because Float in general stores only 15 digits after the decimal dot.
So, if your goal is to be able to show π with an arbitrary number of digits after the decimal dot, you can use the following method:
require 'bigdecimal/math'
##
# Returns PI as a string with number_of_digits_after_decimal_dot.
#
def pi(number_of_digits_after_decimal_dot: 2)
# Let's assume presicion equals to 2 as an example
precision = number_of_digits_after_decimal_dot
result = BigMath.PI(precision)
# => ВigDecimal 0.31415926535897932384671233672993238432e1
result = result.truncate(precision).to_s
# => String 0.314e1
# Remove '0.'
result = result[2..-1]
# => String 3141e1
# Remove 'e1'
result = result.split('e').first
# => String 3141
result = result.insert(1, '.')
# => String 3.141
result
end
If not, then, please, update your question to make it less ambiguous.
So, say I have an array of strings such as:
["74712 Don", "48342 Cindy", "50912 Nick"]
and I want to sort them by the number in front of the name. How would I sort by only the first 5 characters of each element (while also evaluating them as numbers)?
Thanks
Assuming you wish to sort by the leading digits of the strings, you can do the following:
["74712 Don", "48342 Cindy", "50912 Nick"].sort_by(&:to_i)
#=> ["48342 Cindy", "50912 Nick", "74712 Don"]
This works because String#to_i ignores "extraneous characters past the end of a valid number".
If some elements of the array may have more than five leading digits, but only the first five are to be considered, one would use
["74712 Don", "48342 Cindy", "209124 Nick"].sort_by { |s|
s[0,5].to_i }
#=> ["209124 Nick", "48342 Cindy", "74712 Don"]
How can I generate an n-character pseudo random string containing only A-Z, 0-9 like SecureRandom.base64 without "+", "/", and "="? For example:
(0..n).map {(('1'..'9').to_a + ('A'..'Z').to_a)[rand(36)]}.join
Array.new(n){[*"A".."Z", *"0".."9"].sample}.join
An elegant way to do it in Rails 5 (I don't test it in another Rails versions):
SecureRandom.urlsafe_base64(n)
where n is the number of digits that you want.
ps: SecureRandom uses a array to mount your alphanumeric string, so keep in mind that n should be the amount of digits that you want + 1.
ex: if you want a 8 digit alphanumeric:
SecureRandom.urlsafe_base64(9)
Even brute force is pretty easy:
n = 20
c = [*?A..?Z + *?0..?9]
size = c.size
n.times.map { c[rand(size)] }.join
#=> "IE210UOTDSJDKM67XCG1"
or, without replacement:
c.sample(n).join
#=> "GN5ZC0HFDCO2G5M47VYW"
should that be desired. (I originally had c = [*(?A..?Z)] + [*(?0..?9)], but saw from #sawa's answer that that could be simplified quite a bit.)
To generate a random string from 10 to 20 characters including just from A to Z and numbers, both always:
require 'string_pattern'
puts "10-20:/XN/".gen
You can do simply like below:
[*'A'..'Z', *0..9].sample(10).join
Change the number 10 to any number to change the length of string