I have a nested array representing an "image" (a map of 0's and 1's). My end goal is to transform the 4 numbers surrounding any "1" to also be 1's.
The approach I've taken is to map the x,y coordinates of any existing 1 in the initial grid and add those coordinates to a new array so I can later use them to perform the transformation on the original.
To simplify, I'm trying to get this to work, initially, on an array that includes only one "1" — however, the result is unexpected in that it's storing multiple sets of x,y coordinates for the one "1" in the array, instead of a single set. I'm sure the solution is simple, but as a beginner, I'm stumped as to why this is happening.
(Please ignore the commented code; it's the beginnings of the transformation, but I'll bring it back once I solve this issue.)
class Image
def initialize(image)
#image = image
end
def output_image
x_size = #image.first.length
y_size = #image.length
edit = []
#image.each_with_index do | row , y |
row.each_with_index do |cell, x |
edit << [x,y] if cell == 1
end
# edit.each do |pair|
# x = pair.first
# y = pair.last
# #image[x-1][y] = 1 if x > 0
# #image[x+1][y] = 1 if x < (x_size - 1)
# #image[x][y-1] = 1 if y > 0
# #image[x][y+1] = 1 if y < (y_size - 1)
# end
puts edit.inspect
#puts #image.inspect
# #image.each { |x| puts x.join }
end
end
end
image = Image.new([
[0, 0, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 0],
[0, 0, 0, 0]
])
image.output_image
This results in:
[]
[[2, 1]]
[[2, 1]]
[[2, 1]]
Rather than the expected:
[]
[[2,1]]
[]
[]
You're not clearing the edit variable before each run of the outer loop. So each time you print it, it's still storing the initial coordinate where you found a 1.
You'll get the expected result if you insert edit = [] after puts edit.inspect.
This does what you want:
def output_image
x_size = #image.first.length
y_size = #image.length
edit = []
#image.each_with_index do | row , y |
row.each_with_index do |cell, x |
edit << [x,y] if cell == 1
end
end
edit.each do |pair|
y = pair.first
x = pair.last
#image[x-1][y] = 1 if x > 0
#image[x+1][y] = 1 if x < (x_size - 1)
#image[x][y-1] = 1 if y > 0
#image[x][y+1] = 1 if y < (y_size - 1)
end
#image.each { |x| puts x.join }
puts edit.inspect
end
Thanks again to Rob for the help. This was the solution I was looking for:
def output_image
x_size = #image.first.length
y_size = #image.length
edit = []
#image.each_with_index do | row , x |
row.each_with_index do |cell, y |
edit << [x,y] if cell == 1
end
end
edit.each do |x,y|
#image[x-1][y] = 1 if x > 0
#image[x+1][y] = 1 if x < (x_size - 1)
#image[x][y-1] = 1 if y > 0
#image[x][y+1] = 1 if y < (y_size - 1)
end
#image.each { |x| puts x.join }
end
Related
currently I'm making a comparison between the Prim's Algorithm and Kruskal's Algorithm. Both codes are from GeeksforGeeks, however only the Kruskal's algorithm has the total calculated weight in finding the MST. The Prim's algorithm doesn't have one, and I don't have any idea on how can I output the total weight. I hope you can help me.
Here's the code for the Kruskal's Algorithm (from GeeksforGeeks):
class Graph:
def __init__(self, vertices):
self.V = vertices
self.graph = []
def addEdge(self, u, v, w):
self.graph.append([u, v, w])
def find(self, parent, i):
if parent[i] == i:
return i
return self.find(parent, parent[i])
def union(self, parent, rank, x, y):
xroot = self.find(parent, x)
yroot = self.find(parent, y)
if rank[xroot] < rank[yroot]:
parent[xroot] = yroot
elif rank[xroot] > rank[yroot]:
parent[yroot] = xroot
else:
parent[yroot] = xroot
rank[xroot] += 1
def KruskalMST(self):
result = []
i = 0
e = 0
self.graph = sorted(self.graph,
key=lambda item: item[2])
parent = []
rank = []
for node in range(self.V):
parent.append(node)
rank.append(0)
while e < self.V - 1:
u, v, w = self.graph[i]
i = i + 1
x = self.find(parent, u)
y = self.find(parent, v)
if x != y:
e = e + 1
result.append([u, v, w])
self.union(parent, rank, x, y)
minimumCost = 0
print("Edges in the constructed MST")
for u, v, weight in result:
minimumCost += weight
print("%d -- %d == %d" % (u, v, weight))
print("Minimum Spanning Tree", minimumCost)
g = Graph(4)
g.addEdge(0, 1, 10)
g.addEdge(0, 2, 6)
g.addEdge(0, 3, 5)
g.addEdge(1, 3, 15)
g.addEdge(2, 3, 4)
g.KruskalMST()
The code for Prim's Algorithm (also from GeeksforGeeks):
import sys
class Graph():
def __init__(self, vertices):
self.V = vertices
self.graph = [[0 for column in range(vertices)]
for row in range(vertices)]
minimumcost = 0
def printMST(self, parent):
print ("Edge \tWeight")
for i in range(1, self.V):
print (parent[i], "-", i, "\t", self.graph[i][parent[i]])
def minKey(self, key, mstSet):
min = sys.maxsize
for v in range(self.V):
if key[v] < min and mstSet[v] == False:
min = key[v]
min_index = v
return min_index
def primMST(self):
key = [sys.maxsize] * self.V
parent = [None] * self.V
key[0] = 0
mstSet = [False] * self.V
parent[0] = -1
for cout in range(self.V):
u = self.minKey(key, mstSet)
mstSet[u] = True
for v in range(self.V):
if self.graph[u][v] > 0 and mstSet[v] == False and key[v] > self.graph[u][v]:
key[v] = self.graph[u][v]
parent[v] = u
self.printMST(parent)
g = Graph(5)
g.graph = [ [0, 2, 0, 6, 0],
[2, 0, 3, 8, 5],
[0, 3, 0, 0, 7],
[6, 8, 0, 0, 9],
[0, 5, 7, 9, 0]]
g.primMST();
I am attempting to solve an edge case to a task related to a personal project.
It is to determine the unit price of a service and is made up of the total_amount and cost.
Examples include:
# 1
unit_price = 300 / 1000 # = 0.3
# 2
unit_price = 600 / 800 # = 0.75
# 3
unit_price = 500 / 1600 # = 0.3125
For 1 and 2, the unit_prices can stay as they are. For 3, rounding to 2 decimal places will be sufficient, e.g. (500 / 1600).round(2)
The issue arises when the float becomes long:
# 4
unit_price = 400 / 56000 # = 0.007142857142857143
What's apparent is that the float is rather long. Rounding to the first significant figure is the aim in such instances.
I've thought about using a regular expression to match the first non-zero decimal, or to find the length of the second part and apply some logic:
unit_price.match ~= /[^.0]/
unit_price.to_s.split('.').last.size
Any assistance would be most welcome
One should use BigDecimal for this kind of computation.
require 'bigdecimal'
bd = BigDecimal((400.0 / 56000).to_s)
#⇒ 0.7142857142857143e-2
bd.exponent
#⇒ -2
Example:
[10_000.0 / 1_000, 300.0 / 1_000, 600.0 / 800,
500.0 / 1_600, 400.0 / 56_000].
map { |bd| BigDecimal(bd.to_s) }.
map do |bd|
additional = bd.exponent >= 0 ? 0 : bd.exponent + 1
bd.round(2 - additional) # THIS
end.
map(&:to_f)
#⇒ [10.0, 0.3, 0.75, 0.31, 0.007]
You can detect the length of the zeros string with regex. It's a bit ugly, but it works:
def significant_round(number, places)
match = number.to_s.match(/\.(0+)/)
return number unless match
zeros = number.to_s.match(/\.(0+)/)[1].size
number.round(zeros+places)
end
pry(main)> significant_round(3.14, 1)
=> 3.14
pry(main)> significant_round(3.00014, 1)
=> 3.0001
def my_round(f)
int = f.to_i
f -= int
coeff, exp = ("%e" % f).split('e')
"#{coeff.to_f.round}e#{exp}".to_f + int
end
my_round(0.3125)
#=> 0.3
my_round(-0.3125)
#=> -0.3
my_round(0.0003625)
#=> 0.0004
my_round(-0.0003625)
#=> -0.0004
my_round(42.0031)
#=> 42.003
my_round(-42.0031)
#=> -42.003
The steps are as follows.
f = -42.0031
int = f.to_i
#=> -42
f -= int
#=> -0.0031000000000034333
s = "%e" % f
#=> "-3.100000e-03"
coeff, exp = s.split('e')
#=> ["-3.100000", "-03"]
c = coeff.to_f.round
#=> -3
d = "#{c}e#{exp}"
#=> "-3e-03"
e = d.to_f
#=> -0.003
e + int
#=> -42.003
To instead keep only the most significant digit after rounding, change the method to the following.
def my_round(f)
coeff, exp = ("%e" % f).split('e')
"#{coeff.to_f.round}e#{exp}".to_f
end
If f <= 0 this returns the same as the earlier method. Here is an example when f > 0:
my_round(-42.0031)
#=> -40.0
I have a following programm
def calc_res(a)
n = a.length
result = 0
for i in 0 .. (n - 1)
for j in i .. (n - 1)
if (a[i] != a[j] && j - i > result) then
result = j - i
end
end
end
return result
end
which return following output
irb(main):013:0> calc_res([4, 6, 2, 2, 6, 6, 4])
=> 5
but it is taking time if array size is too large e.g. [0,1,2,3,.....70000]
can any one suggest me how can I optimize it.
Thanks
If I have understood the problem you are trying to solve (from code)
def calc_res(a)
last_index = a.length - 1
index = 0
while a[index] == a.last do
index = index + 1
break if index == last_index
end
last_index - index
end
It checks items from start if they are equal to items from end, end it moves the index toward the last element. As I understood you search for max length between different elements.
For you problem with [4, 6, 2, 2, 6, 6, 4] it will have one iteration and return 5, for the problem with [1...70000] it will have zero iterations and will return the difference in positions for those two (size of the array - 1)
My understanding is that the problem is to find two unique elements in the array whose distance apart (difference in indices) is maximum, and to return the distance they are apart. I return nil if all elements are the same.
My solution attempts to minimize the numbers of pairs of elements that must be examined before an optimal solution is identified. For the example given in the question only two pairs of elements need be considered.
def calc_res(a)
sz = a.size-1
sz.downto(2).find { |n| (0..sz-n).any? { |i| a[i] != a[i+n] } }
end
a = [4,6,2,2,6,6,4]
calc_res a
#=> 5
If sz = a.size-1, sz is the greatest possible distance two elements can be apart. If, for example, a = [1,2,3,4], sz = 3, which is the number of positions 1 and 4 are apart.
For a, sz = a.size-1 #=> 6. I first determine if any pair of elements that are n = sz positions apart are unique. [a[0], a[6]] #=> [4,4] is the only pair of elements 6 positions apart. Since they are not unique I reduce n by one (to 5) and examine all pairs of elements n positions apart, looking for one whose elements are unique. There are two pairs 5 positions apart: [a[0], a[5]] #=> [4,6] and [a[1], a[6]] #=> [6,4]. Both of these meet the test, so we are finished, and return n #=> 5. In fact we are finished after testing the first of these two pairs. Had neither these pairs contained unique values n would have been reduced by 1 to 4 and the three pairs [a[0], a[4]] #=> [4,6], [a[1], a[5]] #=> [6,6] and [a[2], a[6]] #=> [2,6] would have been searched for one with unique values, and so on.
See Integer#downto, Enumerable#find and Enumerable#any?.
A more rubyesque versions include:
def calc_res(a)
last = a.last
idx = a.find_index {|e| e != last }&.+(1) || a.size
a.size - idx
end
def calc_res(a)
last = a.last
a.size - a.each.with_index(1).detect(->{[a.size]}) {|e,_| e != last }.last
end
def calc_res(a)
last = a.last
a.reduce(a.size) do |memo, e|
return memo unless e == last
memo -= 1
end
end
def calc_res(a)
return 0 if b = a.uniq and b.size == 1
a.size - a.index(b[-1]).+(1)
end
I'm trying to test certain variables on a grid made out of nested tables. However no matter what I try it wont give me the values stored within the variables only the data type or a nil value
y = {}
for _y = 0,16 do
for _x = 0,16 do
x = {}
x.x = _x
x.y = _y
x.v = flr(rnd(2))
if x.x < 1 or x.x > 14 then
x.v = 3
end
if x.v == 0 then
x.v = "."
elseif x.v ==1 then
x.v = ","
else
x.v = "0"
end
add(y,x)
end
end
I've tried accessing the value using
print(t[1][3])
But this only prints back a nil value, how would I code this to show whats stored within the value within these two tables?
You have the nesting as follows:
y = {x_1, x_2, x_3, ...}
where, each of x_i is of the form:
x = {
x = p,
y = q,
v = r
}
so, you will have the indexing for each x element as y[i], and each y[i] contains 3 attributes:
print(y[1].x)
will give you x_1.x
You want to create a 2-dimensional table, but only create a 1-dimensional one.
Fix your code to look somewhat like this
y = {}
for _y=1,16 do
y[_y] = {}
for _x=1,16 do
y[_y][_x]= "your data"
end
end
Below I have posted the instructions for this problem along with my solution. A few test case scenarios have failed, but seem to be working for most. Can anybody help out at which point I've gone wrong? Any help is much appreciated!!
Using the Ruby language, have the function ArithGeo(arr) take the array of numbers stored in arr and return the string "Arithmetic" if the sequence follows an arithmetic pattern or return "Geometric" if it follows a geometric pattern.
If the sequence doesn't follow either pattern return -1.
An arithmetic sequence is one where the difference between each of the numbers is consistent
Arithmetic example: [2, 4, 6, 8]
In a geometric sequence, each term after the first is multiplied by some constant or common ratio.
Geometric example: [2, 6, 18, 54]
Negative numbers may be entered as parameters, 0 will not be entered, and no array will contain all the same elements.
Code:
def arithGeo(num)
idx = 0
while idx < num.length
if ((num[idx] - num[idx + 1]) == (num[idx + 1] - num[idx + 2]))
return "Arithmetic"
elsif ((num[idx + 1] / num[idx]) == (num[idx + 2] / num[idx + 1]))
return "Geometric"
else
return "-1"
end
idx += 1
end
end
#Test Cases that Failed
p arithGeo([1, 2, 3, 4, 5, 10, 20])
p arithGeo([1, 2, 3, 4, 5, 6, 7, 88, 2])
p arithGeo([10, 110, 210, 310, 410, 511])
OK, lets do a much more "ruby like" way:
def arith?(arr)
check_arr = []
arr.reverse.inject {|memo, num| check_arr << (memo - num); num}
#loop through from highest to lowest, subtracting each from the next and store in check_arr
check_arr.all? {|num| num == check_arr[-1]}
#check that all results are the same in the arr i.e. [2,2,2,2,2]
end
This returns true if all of the operations return the same result, thus a linear progression.
def geo?(arr)
check_arr = []
arr.reverse.inject {|memo, num| check_arr << (memo / num); num}
#loop through from highest to lowest, dividing each by the next and store in check_arr
check_arr.all? {|x| x == check_arr[-1]}
#check that all products are the same in the arr i.e. [3,3,3,3,3]
end
This returns true if all of the operations return the same result, thus a geometric progression.
Now use those methods in your other method
def arith_geo?(arr)
if arith?(arr)
'Arithmetic'
elsif geo?(arr)
'Geometric'
else
-1
end
end
You did use a while but you do not loop over the data, because you write return you will only ever look at the first three numbers and then immediately return the result. You will have to keep the previous result, and make sure the result stays the same to return either geometric or arithmetic.
This should help you to complete the exercise :)
I was able to do the solution in JavaScript and this is what I came up with:
function algoGeo(arr){
var algo = true;
var geo = true;
//first check algo
for(var k = 1; k < arr.length; k++){
if( (arr[0] + (arr[1] - arr[0]) * k) !== arr[k] && algo ){
algo = false;
}
if( arr[0] * Math.pow(arr[1] / arr[0], k) !== arr[k] && geo){
geo = false;
}
}
return algo ? "Arithmetic" : geo ? "Geometric" : -1;
}
var arr = [5,12,19,26];
console.log(algoGeo(arr));
def ArithGeo(arr)
diff1 = []
diff2 = []
arr.each_index do |x|
if(x + 1 < arr.length)
diff1 << arr[x + 1] - arr[x]
diff2 << arr[x + 1] / arr[x]
end
end
diff1.uniq.size == 1 ? "Arithmetic" : diff2.uniq.size == 1 ? "Geometric" : -1
end
A little late but this is what i came up with when trying to solve this same question.