Ruby reverse histogram - ruby

So I'm new to ruby and while I was reading about histograms I had a thought. Is there was a way to have a histogram convert a number into a line of symbols? For example, 12 would be converted into ############.

You can multiply a string by an integer in Ruby.
value = 12
result = '#' * value
=> "############"
So for [1, 3, 5, 4] you could do
[1, 3, 5, 4].map{|value| '#' * value}
=> ["#", "###", "#####", "####"]

Related

Turn one string of multiple numbers separated by commas into array of integers in ruby

How to turn "1,2,3,4,500,645" into [1,2,3,4,500,645] in Ruby.
.to_i only returns the first number
if commas just divide integers
"1,2,3,4,500,645".split(',').map(&:to_i)
=> [1, 2, 3, 4, 500, 645]
if you are not sure what's in the string and you want everything breaks if something not expected is there
"1,2,3,4,500,645".split(',').map { |i| Integer(i) }
=> [1, 2, 3, 4, 500, 645]

Arithmetic sequence Ruby

It is a code to find the missing sequence of an arithmetic sequence and finding common difference and also checking is it is an increasing or decreasing sequence. Take user input for further operation
For Ex: enter array elements
2 4 6 10 12 14
missing number is 8 instead of
enter array elements
2
4
6
10
12
14
missing number is 8
puts "enter arithmetic sequence"
o = Array.new
x = gets.chomp
item = x.split(" ")
o.push(item)
puts "#{o}"
len = o.length
sum = (len + 1) * (o[0] + o[len - 1]) / 2
summ = 0
o.each { |a| summ+=a }
res = sum - summ
if(o[1]>o[0])
puts "its an increasing sequence"
else
puts "its a decreasing sequence"
end
common_difference = o[1] - o[0]
puts "Common difference is #{common_difference}"
puts "missing number is #{res}"
The operations like sum common difference are working, but requirement is that we need to take user input in a single line instead of taking in multiple line, split that and store in an array.
For taking sum I used actual sum - target sum method.
Main issue is that it rise an error
`*': Array can't be coerced into Integer
How to convert array elements that is in string format to int using to_i method or Integer method
Expected Output
i/p 2 4 6 8 12 14
o/p
missing number 10
requirement is that we need to take user input in a single line instead of taking in multiple line, split that and store in an array
gets.chomp returns a string with trailing newline removed, e.g. (the 2nd line being user input)
x = gets.chomp
2 4 6 8 12 14
x #=> "2 4 6 8 12 14"
split converts that string to an array:
x.split
#=> ["2", "4", "6", "8", "12", "14"]
what's missing is the conversion to integer. To convert each element of an array, there's map:
x.split.map { |s| s.to_i }
#=> => [2, 4, 6, 8, 12, 14]
or its short-hand notation:
x.split.map(&:to_i)
#=> => [2, 4, 6, 8, 12, 14]
applied to your code:
puts "enter arithmetic sequence"
x = gets.chomp
o = x.split.map(&:to_i)
puts "#{o}"
# ...
Note that there's no need to create an empty array. You can just assign the result of map to o.
The rest of your code seems to work as expected. But you should check out Cary Swoveland's answer for more succinct way of finding the missing element.
Try this:
def missing_number(arr)
((arr.size + 1) * (arr.first + arr.last))/2 - arr.sum
end
missing_number [2, 4, 6, 10, 12, 14] #=> 8
missing_number [11, 8, 5, 2, -4, -7] #=> -1
missing_number [1.2, 2.0, 2.4, 2.8, 3.2] #=> 1.6000000000000014
Suppose arr were not missing any values. For example,
arr = [2, 4, 6, 8, 10, 12, 14]
Then:
arr.sum
#=> 56
which, because it is an arithmetic series, we could alternatively compute as follows:
(arr.size * (arr.first + arr.last))/2
#=> 56
In fact,
arr = [2, 4, 6, 10, 12, 14]
and
arr.sum
#=> 48
As I explained above, we can calculate the sum of the values of arr after the missing value has been inserted as follows:
((arr.size + 1) * (arr.first + arr.last))/2
#=> 56
The missing value therefore equals 56 - 48 #=> 8.
Here is another way to find the missing value that is slightly less efficient.
def missing_number(arr)
arr.each_cons(2).max_by { |a,b| (b-a).abs }.sum/2
end
missing_number [2, 4, 6, 10, 12, 14] #=> 8
missing_number [11, 8, 5, 2, -4, -7] #=> -1
missing_number [1.2, 2.0, 2.4, 2.8, 3.2] #=> 1.6
Suppose
arr = [11, 8, 5, 2, -4, -7]
The steps are as follows.
enum = arr.each_cons(2)
#=> #<Enumerator: [11, 8, 5, 2, -4, -7]:each_cons(2)>
We can see the (5) values that the enumerator will generate and pass to Enumerable#max_by by converting enum to an array:
enum.to_a
#=> [[11, 8], [8, 5], [5, 2], [2, -4], [-4, -7]]
Next let's look at the values that max_by will compare:
enum.map { |a,b| (b-a).abs }
#=> [3, 3, 3, 6, 3]
We therefore obtain the following:
c = enum.max_by { |a,b| (b-a).abs }
#=> [2, -4]
The last two steps calculate the average of 2 and -4:
d = c.sum
#=> -2
d/2
#=> -1

Select specific character positions from string

I'm looking for a way to select pseudo random characters from a string.
For example, I have a 64 character string. I would like to pick positions 0, 1, 4, 5, 8, 9.
Or a harder one would be with the same string, I would pick positions 0, 1, 2, 4, 6, 8, 10, 11, 12 and so on.
Is there a quick way to do this?
Here's something that may work well for you:
#!/usr/bin/env ruby
# Returns a string whose length is a random number between 0
# and the string length, and whose values are characters from
# random positions in the input string.
def random_string_char_subset(string)
chars = string.chars.shuffle
char_count = Random.rand(string.length + 1)
subset = ''
char_count.times { subset << chars.pop }
subset
end
puts random_string_char_subset 'hello' # => lhl
puts random_string_char_subset '0123456789' # => 821097634
puts random_string_char_subset 'bye' # => b
Yes, you could use Array#values_at
> "64charstring".chars.values_at(*[0, 1, 4])
=> ["6", "4", "a"]
Update:
And if you'd like to get string result - join the result.
> "64charstring".chars.values_at(*[0, 1, 4]).join
=> "64a"
This can be done using []
a = 'test string'
a[1] #=>e, assuming you are using a known value
a[Random.rand(a.length)] #assuming you want a random value

Ruby : Can you please explain why reverse range not giving expected result in ruby

why the below given [] for a reverse order range in ruby
(0..5).to_a
# => [0, 1, 2, 3, 4, 5]
(5..0).to_a
# => []
I am new on ruby PL
what is the best way to use a reverse range in ruby
The best way to use a reverse range for iteration
I know .reverse of array
But can I inherit the range and make a custom method of it and use it as a range
I also try
class Range
def r
to_a.reverse
end
end
# => :r
(5..0).r
# => []
You asked why (5..0).to_a doesn't give the "expected result", by which I assume you mean [5,4,3,2,1].
If a range is a..b that means it includes all values x such that a <= x <= b.1 If a > b, no values are included, so nil is returned. There is no such thing as an "empty" range, as there is an empty array ([]), hash ({}), string ("") and so on. (1..1 is a range, but it is not empty.) That's why 5..3 cannot return a Range object, and therefore returns nil.
Ruby does not support the concept of a "reversed range". If you just want to step down from 3 to 1 there are many ways to do that without involving a range.
Note also that ranges, unlike arrays, for example, may contain an infinite number of values. 1.0..3.0 is one such example.
1 The range a...b (three dots) includes all values x such that a <= x < b.
what should I do if I need a reverse range
(0..5).to_a.reverse
#=> [5, 4, 3, 2, 1, 0]
or
(0..5).reverse_each.to_a
#=> [5, 4, 3, 2, 1, 0]
Here's a way to do it that might more closely express they way you're thinking about it:
(5.downto 0).to_a
=> [5, 4, 3, 2, 1, 0]
Try:
[*0..5].reverse
#=> [5, 4, 3, 2, 1, 0]
OR
> r = Proc.new {|x| x.reverse}
> r.call((0..5).to_a)
#=> [5, 4, 3, 2, 1, 0]

ruby convert array into function arguments

Say I have an array. I wish to pass the array to a function. The function, however, expects two arguments. Is there a way to on the fly convert the array into 2 arguments?
For example:
a = [0,1,2,3,4]
b = [2,3]
a.slice(b)
Would yield an error in Ruby. I need to input a.slice(b[0],b[1]) I am looking for something more elegant, as in a.slice(foo.bar(b))
Thanks.
You can turn an Array into an argument list with the * (or "splat") operator:
a = [0, 1, 2, 3, 4] # => [0, 1, 2, 3, 4]
b = [2, 3] # => [2, 3]
a.slice(*b) # => [2, 3, 4]
Reference:
Array to Arguments Conversion
Use this
a.slice(*b)
It's called the splat operator

Resources