Is it heavier to iterate through an empty table in Lua? - lua

Case1: iterating through a pre-sized table
local t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
for i = 1, 10 do
t[i] = i * 2
end
Case2: iterating through an empty table
local t = {}
for i = 1, 10 do
t[i] = i * 2
end
Would there be any performance difference between performing the two loops?
Does Lua internally resize the table before assigning a value?

Related

How to get the next and previous element in an array, Ruby

I have this array and need to replace its elements by the multiplication of its previous and next.
I do the following:
array.each_with_index{|element, index|
next_element = array[index+1]
previous_element = array[index-1]
}
array.map! {|a|
if a == array.first
a = a * next_element
elsif a == array.last
a = a * previous_element
else
a = next_element * previous_element
end
}
I expect the following result:
array = [4, 1, 6, 7, 9, 3, 0] #given array
array = [4, 24, 7, 54, 21, 0, 0] #array replaced
I get the following error:
undefined local variable or method `next_element' for Arrays:Class
Is there a easy way of getting the previous and next element of a given array element?
Am I using the array.map! method right?
This would work:
array = [4, 1, 6, 7, 9, 3, 0]
[nil, *array, nil].each_cons(3).map { |l, m, r| (l || m) * (r || m) }
#=> [4, 24, 7, 54, 21, 0, 0]
The array is surrounded by nil values, so each element has neighbors. each_cons(3) then yiels each element along with its neighbors to map which multiplies the left (l) with the right (r) neighbor, falling back to the middle element (m) if one of the neighbors happens to be nil.
You can do as following,
[array[0..1].inject(:*)] + array[0..-2].map.with_index { |x,i| x * (array[i+2] || array[i+1]) }
# => [4, 24, 7, 54, 21, 0, 0]
You defined next_element and previous_element inside the loop, so they become undefined at the end. This is a simple work around of your code, I'll assume that
you want to keep first and last element unchanged. You dont need to use map
array.each_with_index do |element, index|
if element != array.first && element != array.last
array[index] = array[index+1] * array[index-1]
end
end
array => [4, 24, 168, 1512, 4536, 0, 0]
This is not what you expected, why? Because your element, array[index] will change after each iteration you can print array after each iteration to see the result
I would suggest you to use another array to save the value of array, like this
b =[]
array.each_with_index do |element, index|
b[index] = array[index]
if element != array.first && element != array.last
b[index] = array[index+1] * array[index-1]
end
end
Seems like each_cons would be a good fit here:
[array.first] + array.each_cons(3).map { |p, _, n| p * n } + [array.last]
#=> [4, 24, 7, 54, 21, 0, 0]
This needs some more work (e.g. if the array is empty this will return [nil, nil]) but I'm sure you can figure out these edge cases.

How to remove array elements and append it to the front of the array in ruby without using any inbuilt methods?

I have an array say [1,2,3,4,5,6,7,8]. I need to take an input from the user and remove the last input number of array elements and append it to the front of the array. This is what I have achieved
def test(number, array)
b = array - array[0...(array.length-1) - number]
array = array.unshift(b).flatten.uniq
return array
end
number = gets.chomp_to_i
array = [1,2,3,4,5,7,8,9]
now passing the argument to test gives me the result. However, there are two problems here. first is I want to find a way to do this append on the front without any inbuilt method.(i.e not using unshift).Second, I am using Uniq here, which is wrong since the original array values may repeat. So how do I still ensure to get the correct output? Can some one give me a better solution to this.
The standard way is:
[1, 2, 3, 4, 5, 7, 8, 9].rotate(-3) #=> [7, 8, 9, 1, 2, 3, 4, 5]
Based on the link I supplied in the comments, I threw this together using the answer to that question.
def test(number, array)
reverse_array(array, 0, array.length - 1)
reverse_array(array, 0, number - 1)
reverse_array(array, number, array.length - 1)
array
end
def reverse_array(array, low, high)
while low < high
array[low], array[high] = array[high], array[low]
low += 1
high -= 1
end
end
and then the tests
array = [1,2,3,4,5,7,8,9]
test(2, array)
#=> [8, 9, 1, 2, 3, 4, 5, 7]
array = [3, 4, 5, 2, 3, 1, 4]
test(2, array)
#=> [1, 4, 3, 4, 5, 2, 3]
Which I believe is what you're wanting, and I feel sufficiently avoids ruby built-ins (no matter what way you look at it, you're going to need to get the value at an index and set a value at an index to do this in place)
I want to find a way to do this append on the front without any inbuilt method
You can decompose an array during assignment:
array = [1, 2, 3, 4, 5, 6, 7, 8]
*remaining, last = array
remaining #=> [1, 2, 3, 4, 5, 6, 7]
last #=> 8
The splat operator (*) gathers any remaining elements. The last element will be assigned to last, the remaining elements (all but the last element) are assigned to remaining (as a new array).
Likewise, you can implicitly create an array during assignment:
array = last, *remaining
#=> [8, 1, 2, 3, 4, 5, 6, 7]
Here, the splat operator unpacks the array, so you don't get [8, [1, 2, 3, 4, 5, 6, 7]]
The above moves the last element to the front. To rotate an array n times this way, use a loop:
array = [1, 2, 3, 4, 5, 6, 7, 8]
n = 3
n.times do
*remaining, last = array
array = last, *remaining
end
array
#=> [6, 7, 8, 1, 2, 3, 4, 5]
Aside from times, no methods were called explicitly.
You could create a new Array with the elements at the correct position thanks to modulo:
array = %w[a b c d e f g h i]
shift = 3
n = array.size
p Array.new(n) { |i| array[(i - shift) % n] }
# ["g", "h", "i", "a", "b", "c", "d", "e", "f"]
Array.new() is a builtin method though ;)

How to read nested table

I am new to lua and want to learn about nested table
This is what I have been trying:
t = {};
t[1] = 22, {1, 22, 3};
t[2] = 44, {4, 5, 6};
t[3] = 66, {4, 5, 6};
for k, v in ipairs(t) do
print(k,v)
end
This does not work for me.
This is the result I want:
Example:
1 2 5
2 5 66
3 6 33
4 2 1
5 4 12
6 4 3
7 2 44
8 3 1
9 2 44
10 3 99
How do I read a nested table like this and
how do I table.insert in the right column?
I believe the misunderstanding lies in this code:
t[1] = 22, {1, 22, 3}
The 2nd value, the one after the comma, {1, 22, 3} is being assigned to nothing, it is dropped in the ether.
Perhaps what you meant was a table of tables:
t[1] = {22, {1, 22, 3}}
This would create an entry at [1] in t that is itself..a table
t[1][1] == 22
t[1][2] == {1, 22, 3}
Then to iterate this setup you could use:
local t = {}
t[1] = {22, {1, 22, 3}}
t[2] = {44, {4, 5, 6}}
t[3] = {66, {4, 5, 6}}
for _,entry in ipairs(t) do
local key = entry[1]
io.write(key .. ' ')
for _,value in ipairs(entry[2]) do
io.write(value .. ' ')
end
io.write('\n')
end
But to be honest, I'm not sure what you're asking as your "expected output" is significantly different than your sample data set.
Replying to Qualmos' comment in payo's answer:
local t = {}
t[1] = {22,3}
t[2] = {44,6}
t[3] = {66,63}
for _,v in pairs(table) do
print(_,v[1],v[2])
end
Would print something like this:
1,22,3
2,44,6
3,66,63
Btw, you can make the table look like this:
local t = {
{22,3};
{44,6};
{66,63};
}

Insert after every nth comma in a string [duplicate]

This question already has answers here:
Inserting an array into every nth element of another
(3 answers)
Closed 6 years ago.
I have the following string and array:
a = '1, 2, 3, 4, 5, 6, 7, 8'
b = ['9', '10', '11', '12']
I need to insert an element of b after every nth comma (2 for this example) into a, resulting in:
a = '1, 2, 9, 3, 4, 10, 5, 6, 11, 7, 8, 12'
I've been playing around with various forms of scan but can't seem to produce the desired result.
Is there an easy way for me to do this?
Use a.split(', '), any solution from your previous question, and join(', ').
With credits to #Stefan :
a = '1, 2, 3, 4, 5, 6, 7, 8'
b = ['9', '10', '11', '12']
enum = Enumerator.new do |y|
e1 = a.split(',').each
e2 = b.each
loop do
y << e1.next.strip << e1.next.strip << e2.next
end
end
puts enum.to_a.join(', ')
#=> 1, 2, 9, 3, 4, 10, 5, 6, 11, 7, 8, 12
You could also use this if you are sure that every number is separated by a comma and a space :
enum = Enumerator.new do |y|
e1 = a.split(', ').each
e2 = b.each
loop do
y << e1.next << e1.next << e2.next
end
end

How to compare more than 3 array to find the one with highest priority

I have following array set holding priorities,
array1 = [1, 2, 1, 2, 3]
array2 = [1, 1, 1, 2, 3]
|
|
|
arrayn = [1, 3, 1, 2, 3]
I want to find out easiest way to find out the array variable which having highest priority i.e 1
It should check in a following way,
If last element of any array is lowest that should be return.
If last element of more than one array is same then previous element of that array should be matched
In above given example last 3 values of all the 3 array are same so it will check for the 2nd last element
array1 = 2
array2 = 1
array3 = 3
So it should return array2.
Please let me know if any one fail to understand the question
More Examples
Example 1
arr1 = [1,1,1,1,3]
arr2 = [3,3,3,3,2]
should return arr2
Example 2
arr1 = [2,2,2,1,3]
arr2 = [1,2,1,3,3]
should return arr1, as arr1.last == arr2.last (i.e. 3)
but arr1[3] < arr2[3] i.e. (1 < 3)
For equal sized arrays (and if I understand the question right) this should work:
arrays = [
[1, 2, 1, 1, 3],
[1, 3, 1, 2, 3],
[1, 1, 1, 2, 3],
[1, 3, 1, 1, 3]
]
p arrays[arrays.transpose.reverse.map{|el|
next if el.count(el.min) != 1
el.rindex(el.min)
}.compact[0]]
Result:
#=> [1, 1, 1, 2, 3]
Step by step: Transpose arrays and start to check from last chunk. If there is not one minimal priority skip this chunk (put nil in output), if only one - get it's index. Remove all nil elements and use first found index to print desired array.
UPDATED
If you wish to handle the case when initial array of arrays doesn't have answer you could change the code in this way:
idx = arrays.transpose.reverse.map{|el|
next if el.count(el.min) != 1
el.rindex(el.min)
}.compact[0]
p idx ? arrays[idx] : "no answer"
The result for [[1,1,1,1,1], [1,1,1,1,2], [2,1,1,1,1], [2,1,1,1,2]] will be:
#=> "no answer"
tab = [array1, array2, array3, arrayn]
i = -1
while tab.count != 1 && tab.count + i >= 0
tab = tab.select { |t| t[i] == tab.map { |j| j[i] }.min }
i = i - 1
end
result = tab[0]

Resources