How to change the element part of an array while iterating - ruby

An array xs consists of numbers from 0 to 9:
xs = [*0..9]
Test parity, and store result in place:
xs.map!(&:odd?)
puts xs.join(" ")
# => false, true, ..., true
xs changed as expected. But I just want to change a part of the array
xs[5..-1].map!(&:odd?)
puts xs.join(" ")
# => 0 1 2 3 4 5 6 7 8 9
I guess the slice operation returns a copy. Or some other reasons.
xs[...] = xs[...].some_operation is a solution, but is there any way to do this without assignment?

Here is a way to do this:
xs.fill(5..-1) { |i| xs[i].odd? }
#=> 0 1 2 3 4 true false true false true

Related

Elixir: Return value from for loop

I have a requirement for a for loop in Elixir that returns a calculated value.
Here is my simple example:
a = 0
for i <- 1..10
do
a = a + 1
IO.inspect a
end
IO.inspect a
Here is the output:
warning: variable i is unused
Untitled 15:2
2
2
2
2
2
2
2
2
2
2
1
I know that i is unused and can be used in place of a in this example, but that's not the question. The question is how do you get the for loop to return the variable a = 10?
You cannot do it this way as variables in Elixir are immutable. What your code really does is create a new a inside the for on every iteration, and does not modify the outer a at all, so the outer a remains 1, while the inner one is always 2. For this pattern of initial value + updating the value for each iteration of an enumerable, you can use Enum.reduce/3:
# This code does exactly what your code would have done in a language with mutable variables.
# a is 0 initially
a = Enum.reduce 1..10, 0, fn i, a ->
new_a = a + 1
IO.inspect new_a
# we set a to new_a, which is a + 1 on every iteration
new_a
end
# a here is the final value of a
IO.inspect a
Output:
1
2
3
4
5
6
7
8
9
10
10

Bitmasking in Ruby: Get numbers which generated the bitmask

Currently I am storing a combination of a group of items as a single integer (bitmasked value) as in the example below:
Example:
1 - Orange
2 - Banana
4 - Cherry
8 - Apple
And then if the user selects Orange (1) and Apple (8) then the sum of those is 9.
And it is always and only when those two items are combined this value is 9.
And you are able to recover the original two numbers which were used to generate this number.
Here is an example website which does the trick:
http://www.tfxsoft.com/playground/calc.php
What I need:
I need an algoritm (preferrably in Ruby) which would take the sum (9) of those two bitmask values and return the values which it "contains" ( 1 and 4).
I think this might be what you're looking for:
FRUIT = { 1 => 'Orange', 2 => 'Banana', 4 => 'Cherry', 8 => 'Apple' }
def mask_fruit(a, b) a | b end
def unmask_fruit(masked)
FRUIT.select { |k, _| (masked | k) == masked }
end
mask = mask_fruit 1, 8 # => 9
unmask_fruit mask # => {1=>"Orange", 8=>"Apple"}
As I understand you want to find position of bits. Here is simple but not optimal solution:
2.1.5 :033 > 9.to_s(2).reverse.chars.map.with_index { |b, i| b == "1" ? i + 1 : nil }.compact
=> [1, 4]

Print numbers in a range

I am trying to print all numbers between 1 and 50, using the following code:
[1..50].each{|n| puts n}
but the console print
[1..50]
I want to print something like this
1
2
3
4
...
50
Try the following code:
(1..50).each { |n| puts n }
The problem is that you're using [] delimiter instead of () one.
You can use [1..10] with a minor tweak:
[*1..10].each{ |i| p i }
outputs:
1
2
3
4
5
6
7
8
9
10
The * (AKA "splat") "explodes" the range into its components, which are then used to populate the array. It's similar to writing (1..10).to_a.
You can also do:
puts [*1..10]
to print the same thing.
So, try:
[*1..10].join(' ') # => "1 2 3 4 5 6 7 8 9 10"
or:
[*1..10] * ' ' # => "1 2 3 4 5 6 7 8 9 10"
To get the output you want.
The error here is that you are creating an Array object with a range as its only element.
> [1..10].size
=> 1
If you want to call methods like each on a range, you have to wrap the range in parentheses to avoid the method being called on the range's last element rather than on the range itself.
=> (1..10).each { |i| print i }
12345678910
Other ways to achieve the same:
(1..50).each { |n| print n }
1.up_to(50) { |n| print n }
50.times { |n| print n }
You can cast your range (in parentheses) to an array ([1 2 3 4 5 6... 48 49 50]) and join each item (e.g. with ' ' if you want all items in one line).
puts (1..50).to_a.join(' ')
# => 1 2 3 4 5 6 7 ... 48 49 50

how to describe this series in code?

i would like to find a formula describing this series.
i need to set a boolean depending on a positive integer.
it's pretty simple but i am stuck and feel a bit stupid.
0 false
1 true
2 true
3 false
4 false
5 true
6 true
7 false
8 false
9 true
10 true
11 false
12 false
...
so the flag changes at every odd number
Well, for the flag changing at every odd number, it looks like your boolean should be true if and only if (n+3)%4 <= 1, where % is the modulo operator:
n (n+3)%4 Boolean
-- ------- -------
0 3 false
1 0 true
2 1 true
3 2 false
4 3 false
5 0 true
6 1 true
7 2 false
8 3 false
9 0 true
10 1 true
11 2 false
12 3 false
:: : : :
I've deliberately added three instead of subtracting one, since some languages have different ideas of what the modulo operator should do for negative numbers. And keep in mind that this is language-agnostic. If you're specifically looking for a C or C-like language solution, see the excellent answer here from Christoffer Hammarström ((n + 1) & 2 just in case it ever disappears) - this is far more succinct in those particular languages.
In C and other languages where non-zero is true: (n + 1) & 2, and in other languages: (n + 1) & 2 != 0.
You can first divide the int value by 2 and then check if it is even or odd.
boolean flag = ((i+1)/2)%2!=0;
Maybe there is an off-by-one error, so check this.
N (N+1)/2 ((N+1)/2)%2 compare != 0
0 0 0 false
1 1 1 true
2 1 1 true
3 2 0 false
4 2 0 false
5 3 1 true
6 3 1 true
7 4 0 false
8 4 0 false
9 5 1 true
...
Flag changes at every odd number, means the last bit is set to 1.
1 => 01, 3 => 11, ... 9 => 1001, 11 => 1011
and so on..
so, u can just check the last bit at each step and whenever it is 1, flip the flag.

Auto complete an array according a vector

I have an array of 16 squares and I would like to auto complete it with integers values depending of the position in the array and the vector TOP_RIGHT.
TOP_RIGHT = 3
# Build the array...
#top_right = Array.new(16, 0)
#top_right.each_index do |square|
#top_right[square] = square / TOP_RIGHT if (0...16).include?(square - TOP_RIGHT)
end
# Print the array...
i = 0
#top_right.each do |square|
puts if i % 4 == 0
print "#{square} "
i += 1
end
My code seems to be okay, but after testing the result is:
0 0 0 1
1 1 2 2
2 3 3 3
4 4 4 5
I would like to get this array:
0 0 0 0
1 1 1 0
2 2 1 0
3 2 1 0
Do you think it is possible, using array and simple Ruby methods?
Thanks, and happy end year!
Edit:
In the previous example, TOP_RIGHT is a vector like and its value is the number of cases that we can add or sub in order to go from the source square to the destination square (which is on top-right).
For example if I get this other vector: TOP, its value is 4 and the generated array can be:
# print_array(4)
0 0 0 0
1 1 1 1
2 2 2 2
3 3 3 3
...and if the vector is RIGHT, its value is -1 and the array can be:
# print_array(-1)
3 2 1 0
3 2 1 0
3 2 1 0
3 2 1 0
Isn't it a little beat tricky? :)
I don't see how to process for designing a constructor which can build such arrays, by passing a value of a vector.
If you use an array to hold an array, and don't try to do it in a vector, it's not too bad:
#!/usr/bin/ruby1.8
top_right = 3
array_size = 4
a = (0...array_size).collect do |i|
(0...array_size).collect do |j|
[i, j].collect do |e|
top_right - e
end.min
end
end.reverse
a.each do |e|
p e
end
=> [0, 0, 0, 0]
=> [1, 1, 1, 0]
=> [2, 2, 1, 0]
=> [3, 2, 1, 0]
And if you really need the array squished into a vector, then:
v = a.flatten

Resources