is there a data structure in python that is equivalent to array in cpp?
one that some elements are initialized and some are not?
for example, in python list: [1,2,3], elements have to be sequentially filled
in cpp array can be a[0] == 0, a1 -- arbitrary, uninitialized, a[2] == 2
is there an cpp-array equivalent structure in python?
ps, python array doesn't seem to be equivalent, all elements have to be filled sequentially too
Perhaps this answer here on StackOverflow may be what you are looking for?
How to create a fix size list in python?
You can probably put together some kind of wrapper using a dictionary:
class CppArray:
def __init__(self, value):
if value == None:
self.data = {}
self.length = 0
else:
self.data = { 0: value }
self.length = 1
def insert(self, index, value):
while index in self.data:
tmp = self.data[index]
self.data[index] = value
value = tmp
index = index + 1
self.data[index] = value
if index >= self.length:
self.length = index + 1
def __getitem__(self, index):
if (index < 0 or index >= self.length):
# must create IndexException
raise IndexException("Index out of range")
if index in self.data:
return self.data[index]
else:
return None
x = CppArray("i")
x.insert(0,10)
x.insert(200,30)
x[1]
Obviously this quick sketch is missing many details which would make the class more useful.
For other ideas on special methods you could use, check:
https://docs.python.org/3/reference/datamodel.html
Related
My program orders arrays 1 and 2, and iterates to check whether each element in 1 is the sqrt of each element in 2. I've tested the comparison without the loop and it works fine, so I don't think that there's an uninitialised variable.
def comp(array1, array2)
order1 = array1.sort
order2 = array2.sort
i = 0
while i < order1.length
if order1[i] * order1[i] == order2[i]
i += 1
else
false
end
end
order1[i] * order1[i] == order2[i]
end
Can you point me in the direction of the issue? I've also not used Math.sqrt because it times out on my interface.
Your i equals order1.length, after your loop, so the last line of your method is basically
order1[order1.length] * order1[order1.length] == order2[order1.length]
which is (assuming your arrays are the same length):
nil * nil == nil
which throws an error. Not sure why you need the last line, if you remove it and simply return a counter, your method works as expected if you use a dedicated counter, for the elements which match your condition, instead of using index for that (your index has to be incremented always):
def comp(array1, array2)
order1 = array1.sort
order2 = array2.sort
i = 0
counter = 0
while i < order1.length
if order1[i] * order1[i] == order2[i]
counter += 1
end
i += 1
end
counter
end
In Ruby it is pretty common to use proper enumerators for iterating over collections, so your while can be nicely substituted by Enumerable#each_with_index:
def comp(array1, array2)
order1 = array1.sort
order2 = array2.sort
counter = 0
order1.each_with_index do |el, i|
if el * el == order2[i]
counter += 1
end
end
counter
end
And as the last step, we can also Array#count how many elements in an array meet a certain condition without needing to specify a local variable, like so:
def comp(array1, array2)
order2 = array2.sort
array1.sort.each_with_index.count { |el, i| el ** 2 == order2[i] }
end
I've been learning some algorithms and I can't find the reason why my method is failing. if you could look at the code and shed some light as to why that is happening. I would truly appreciate it.
I'm trying to write a method that would binary search an array recursively and so far that is all my code.
def recursive_binary_search(arr, target)
max_index = arr.length - 1
mid_index = max_index / 2
if arr[mid_index] > target
new_arr = arr[0..(mid_index - 1)]
recursive_binary_search(new_arr, target)
elsif arr[mid_index] < target
new_arr = arr[(mid_index + 1)..max_index]
recursive_binary_search(new_arr, target)
else
return mid_index
end
end
The error I keep getting is undefined method '>' for nil:NilClass
I was unable to reproduce the exception reported by the OP (as the data that produced the exception was not given in the question), but the main problem is that, because max_index is computed from arr, and arr is constantly getting smaller, the index returned by the method will have no relation to the correct index in the initial array arr.
Suppose, for example, that arr = [1,2,3,4,5,6] and target = 6. In this case the method will return 0 (rather than 5) as the index of the target element. That's because arr will progressively become arr[3..6], arr[4..6], arr[5..6] and arr[6], at which point index 0 will be returned.
Here is one way the method could be written, using a case statement. The method assumes that target is an element of arr and (as required by binary searches) the elements of arr are ordered, smallest to largest.
def recursive_binary_search(arr, target, min_index=0, max_index=arr.size-1)
mid_index = (min_index+max_index)/2
case arr[mid_index] <=> target
when 0 # arr[mid_index] == target
mid_index
when -1 # arr[mid_index] < target
min_index = mid_index + 1
recursive_binary_search(arr, target, min_index, max_index)
when 1 # arr[mid_index] > target
max_index = mid_index - 1
recursive_binary_search(arr, target, min_index, max_index)
end
end
arr = [1,2,3,4,5,6]
arr.each { |target| puts "#{target}: #{recursive_binary_search(arr, target)}" }
1: 0
2: 1
3: 2
4: 3
5: 4
6: 5
If your arrays are sorted you could try something like this:
def search(arr, target)
return nil if array.empty?
mid_index = array.length / 2
case target <=> array[mid_index]
when -1
search(array.take(mid_index), target)
when 0
mid_index
when 1
subs = search(array.drop(mid_index + 1), target)
subs.nil? ? nil : (mid_index + 1) + subs
end
end
I'm trying to create a recursive method sum_of_digits(i) that takes the sum of integers, i.e. '456' = 4+5+6 = 15
However, I receive a NoMethodError for chr.to_i in the following code:
def sum_of_digits(i)
input = i.to_s
if i == 0
return 0
elsif input.length == 1
return i
else
for n in 1..input.length
sum += input[i].chr.to_i % 10^(n-1)
end
end
return sum
end
Thank you!
String indexes are zero-based in ruby. The problem is here:
for n in 1..input.length
it should be written as
for n in 0..input.length-1
BTW, call to chr is superfluous as well, since you already have a string representation of a digit there. As well, sum must be declared in advance and set to zero.
Also, the whole code is not ruby idiomatic: one should avoid using unnecessary returns and for-loop. The modified version (just in case) would be:
def sum_of_digits(i)
input = i.to_s
case
when i == 0 then 0 # return zero
when input.length == 1 then i # return i
else
sum = 0
input.length.times do |index|
sum += input[index].to_i % 10^index
end
sum
end
end
or, even better, instead of
sum = 0
input.length.times do |index|
sum += input[index].to_i % 10^index
end
sum
one might use inject:
input.length.times.inject(0) do |sum, index|
sum += input[index].to_i % 10^index
end
In one of my algorithms I use Ruby's combination and permutation methods. I have to discuss this algorithms complexity. Where could I find information about their complexity/implementation?
I've tried implementing a simple 'hand made' function but the Ruby ones seem to run in near constant time!
Any information about where to look would be much appreciated.
Implementation can be shown on the same pages you linked. Hover your mouse over the name of the combination/permutation methods, and select click to toggle source.
You can view the latest and different versions of source here at the main repo: http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/
You can read the revision history of array.c to see perhaps why/when any changes were made to the combination/permutation methods. http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/trunk/array.c?view=log. This may give you some indication into complexity and design choices made by the developers.
You may even be able to ask certain contributors to the source for reasons as to why they made XYZ change to the method, they may/may not help.
There is nothing in the Ruby Language Specification that requires implementors to guarantee a certain algorithmic complexity, and there is most certainly nothing that forces a particular implementation.
Every Ruby Execution Engine has their own implementation, and they may or may not have the same algorithmic complexity.
For example, here is Rubinius's implementation of Array#combination, located in kernel/common/array.rb#L360-394:
def combination(num)
num = Rubinius::Type.coerce_to num, Fixnum, :to_int
return to_enum(:combination, num) unless block_given?
if num == 0
yield []
elsif num == 1
each do |i|
yield [i]
end
elsif num == size
yield self.dup
elsif num >= 0 && num < size
stack = Rubinius::Tuple.pattern num + 1, 0
chosen = Rubinius::Tuple.new num
lev = 0
done = false
stack[0] = -1
until done
chosen[lev] = self.at(stack[lev+1])
while lev < num - 1
lev += 1
chosen[lev] = self.at(stack[lev+1] = stack[lev] + 1)
end
yield chosen.to_a
lev += 1
begin
done = lev == 0
stack[lev] += 1
lev -= 1
end while stack[lev+1] + num == size + lev + 1
end
end
self
end
And Array#permutation, located in kernel/common/array.rb#L935-969:
def permutation(num=undefined, &block)
return to_enum(:permutation, num) unless block_given?
if undefined.equal? num
num = #total
else
num = Rubinius::Type.coerce_to num, Fixnum, :to_int
end
if num < 0 || #total < num
# no permutations, yield nothing
elsif num == 0
# exactly one permutation: the zero-length array
yield []
elsif num == 1
# this is a special, easy case
each { |val| yield [val] }
else
# this is the general case
perm = Array.new(num)
used = Array.new(#total, false)
if block
# offensive (both definitions) copy.
offensive = dup
Rubinius.privately do
offensive.__permute__(num, perm, 0, used, &block)
end
else
__permute__(num, perm, 0, used, &block)
end
end
self
end
As you can see, it delegates to a private helper method named Array#__permute__, defined in kernel/common/array.rb#L971-994:
def __permute__(num, perm, index, used, &block)
# Recursively compute permutations of r elements of the set [0..n-1].
# When we have a complete permutation of array indexes, copy the values
# at those indexes into a new array and yield that array.
#
# num: the number of elements in each permutation
# perm: the array (of size num) that we're filling in
# index: what index we're filling in now
# used: an array of booleans: whether a given index is already used
#
# Note: not as efficient as could be for big num.
#total.times do |i|
unless used[i]
perm[index] = i
if index < num-1
used[i] = true
__permute__(num, perm, index+1, used, &block)
used[i] = false
else
yield values_at(*perm)
end
end
end
end
So I'm trying to learn how to sort an array without using the .sort method, this is what I have so far, but the middle number is dropping out.
def my_sort(num)
for j in 1...num.length
key = num[j]
i = j - 1
while i > 0 and num[i] = key
num[i+1] = num[i]
i = i - 1
end
num[i+1] = key
end
end
then I run the method
my_sort([3,1,2])
I get
=> 1...3
but I want
=> 1,2,3
What am I doing wrong?
You're not returning the modified array, but instead the object fed into your for iterator.
What you're missing is simply leaving the array as the last thing in the method:
def my_sort(num)
# ...
num
end
As a note it's usually bad form to wreck the arguments you're given. A more polite function would return a copy.
Actual implementation of insertion sort must look like:
def my_sort(arr)
for j in 1...arr.length
key = arr[j]
i = j-1
while i>=0 and arr[i] > key # You used arr[i] = key here instead
arr[i+1] = arr[i]
i = i-1
end
arr[i+1] = key
end
arr #return the array
end