Related
I'm learning Rust and I wanted to write program that would take a (randomly generated) bowling sheet and generate the score. I now know that I will have to use Rusts Vecs instead of arrays but I got stuck at accessing the value from the nested arrays so I would like to find the solution before I re-write it.
What I wanted to do is access the individual values and run some logic on them, but I got stuck at the "accessing values" part, this is what I came up with (but it doesn't work):
let sheet: [[u32; 2]; 10] = [[1, 3], [0, 6], [9, 0], [0, 5], [5, 3], [4, 2], [1, 4], [2, 3], [3, 0], [4, 4]];
for frame in 0..sheet.len() {
for score in 0..sheet[frame].len() {
println!("{}", sheet[frame[score]]);
}
}
You should clarify what exactly do you mean by 'accessing individual values', but from your code i'd assume that you just want to iterate over every score. Here's how you do it with for loops:
let sheet = [[1, 3], [0, 6], [9, 0], [0, 5], [5, 3], [4, 2], [1, 4], [2, 3], [3, 0], [4, 4]];
for frame in sheet {
// On the first iteration frame will be == [1, 3], then [0, 6], etc
for score in frame {
// on first iteration score will be == 1, then 3, then 0, etc
println!("{}", score);
}
}
Suppose I have an array of unique integers that contains 9 elements.
array = [3,5,7,9,2,4,8,1,6]
How do I return an array of indexs that tell me the position of the original array of integers from largest to smallest?
index_of_largest_to_smallest = [3,6,2,8,1,5,0,4,7]
So this would tell me the largest number is at position 3, and the second largest is at position 6 etc.
I tried array.sort, but that sorts the array from largest to smallest.
I also tried array.each_with_index but couldn't get it to return another array.
Via each_with_index, sort, map, last and reverse:
[3,5,7,9,2,4,8,1,6].each_with_index #=> [[3, 0], [5, 1], [7, 2], [9, 3], [2, 4], [4, 5], [8, 6], [1, 7], [6, 8]]
.sort #=> [[1, 7], [2, 4], [3, 0], [4, 5], [5, 1], [6, 8], [7, 2], [8, 6], [9, 3]]
.map(&:last) #=> [7, 4, 0, 5, 1, 8, 2, 6, 3]
.reverse #=> [3, 6, 2, 8, 1, 5, 0, 4, 7]
array.each_index.sort_by { |i| -array[i] }
#=> [3, 6, 2, 8, 1, 5, 0, 4, 7]
See the form of Array#each_index and Enumerable#sort_by. Note that Array#each_index returns an enumerator when, as here, no block is given.
I am given an array arr of integers that is sorted in ascending or descending order. If arr contains at least two distinct elements, I need to find the longest arr.last(n) that has exactly two distinct elements (i.e., with the largest n). Otherwise, it should return arr. Some examples are:
arr = [6, 4, 3, 2, 2], then [3, 2, 2] is to be returned
arr = [6, 4, 3, 3, 2], then [3, 3, 2] is to be returned
arr = [1], then arr is to be returned.
I would be grateful for suggestions on how to compute the desired result.
Here's a fairly inefficient approach that uses take_while:
def last_non_dupe(array, count = 2)
result = [ ]
array.reverse.take_while do |n|
result << n
result.uniq.length <= count
end.reverse
end
It can be improved on by using a Set which is automatically unique:
require 'set'
def last_non_dupe(array, count = 2)
result = Set.new
array.reverse.take_while do |n|
result << n
result.length <= count
end.reverse
end
Where in either case you do:
last_non_dupe([6, 4, 3, 2, 2])
# => [3, 2, 2]
The count argument can be changed as necessary for longer or shorter lists.
def last_two_different(arr, count)
arr.reverse_each.
lazy.
chunk(&:itself).
first(count).
flat_map(&:last).
reverse
end
last_two_different [6, 4, 3, 2, 2], 2 #=> [3, 2, 2]
last_two_different [3, 4, 3, 3, 2], 2 #=> [3, 3, 2]
last_two_different [3, 4, 3, 3, 2], 3 #=> [4, 3, 3, 2]
last_two_different [3, 4, 3, 3, 2], 4 #=> [3, 4, 3, 3, 2]
last_two_different [1, 2], 2 #=> [1, 2]
last_two_different [1, 1], 2 #=> [1, 1]
last_two_different [1], 2 #=> [1]
last_two_different [], 2 #=> []
The steps are as follows.
arr = [6, 4, 3, 2, 2]
count = 2
enum0 = arr.reverse_each
#=> #<Enumerator: [6, 4, 3, 2, 2]:reverse_each>
We can convert this enumerator to an array to see the values it will generate.
enum0.to_a
#=> [2, 2, 3, 4, 6]
First, suppose we wrote the following.
enum1 = enum0.chunk(&:itself)
#=> #<Enumerator: #<Enumerator::Generator:0x00005c29be132b00>:each>
enum1.to_a
#=> [[2, [2, 2]], [3, [3]], [4, [4]], [6, [6]]]
We want the first count #=> 2 elements generated by enum1, from which we could extract the desired result. That tells us that we want a lazy enumerator.
enum2 = enum0.lazy
#=> #<Enumerator::Lazy: #<Enumerator: [6, 4, 3, 2, 2]:reverse_each>>
enum3 = enum2.chunk(&:itself)
#=> #<Enumerator::Lazy: #<Enumerator:
# #<Enumerator::Generator:0x00005c29bdf48cb8>:each>>
enum3.to_a
#=> [[2, [2, 2]], [3, [3]], [4, [4]], [6, [6]]]
a = enum3.first(count)
#=> [[2, [2, 2]], [3, [3]]]
b = a.flat_map(&:last)
#=> [2, 2, 3]
b.reverse
#=> [3, 2, 2]
Not sure about the efficiency, but here is another way to do it:
arr = [6, 4, 3, 2, 2]
uniq = arr.uniq.last(2) # => [3, 2]
arr.select{|e| uniq.include?(e)} # => [3, 2, 2]
I am trying to generate all possible combinations of certain values in an array of 15 which add up to 50.
$a = [3, 4, 1, 2, 5]
print $a.repeated_permutation(15).to_a
In this case,
[2,2,2,2,4,4,4,4,4,4,4,4,4,3,3]
[2,2,2,4,2,4,4,4,4,4,4,4,4,3,3]
[2,2,4,2,2,4,4,4,4,4,4,4,4,3,3]
are all possible answers.
After some investigation I realize the code to do this is a bit over my head, but I will leave the question up if it might help someone else.
For some reference as to what I am working on, Project Euler, problem 114. It's pretty difficult, and so I am attempting to solve only a single case where my 50-space-long grid is filled only with 3-unit-long blocks. The blocks must be separated by at least one blank, so I am counting the blocks as 4. This (with some tweaking, which I have left out as this is confusing enough already) allows for twelve blocks plus three single blanks, or a maximum of fifteen elements.
Approach
I think recursion is the way to go here, where your recursive method looks like this:
def recurse(n,t)
where
n is the number of elements required; and
t is the required total.
If we let #arr be the array of integers you are given, recurse(n,t) returns an array of all permutations of n elements from #arr that sum to t.
Assumption
I have assumed that the elements of #arr are non-negative integers, sorted by size, but the method can be easily modified if it includes negative integers (though performance will suffer). Without loss of generality, we can assume the elements of #arr are unique, sorted by increasing magnitude.
Code
def recurse(n,t)
if n == 1
#arr.include?(t) ? [[t]] : nil
else
#arr.each_with_object([]) do |i,a|
break if i > t # as elements of #arr are non-decreasing
if (ret = recurse(n-1,t-i))
ret.each { |b| a << [i,*b] }
end
end
end
end
Examples
#arr = [3, 4, 1, 2, 5].sort
#=> [1, 2, 3, 4, 5]
recurse(1,4)
#=> [[4]]
recurse(2,6)
#=> [[1, 5], [2, 4], [3, 3], [4, 2], [5, 1]]
recurse(3,10)
#=> [[1, 4, 5], [1, 5, 4], [2, 3, 5], [2, 4, 4], [2, 5, 3],
# [3, 2, 5], [3, 3, 4], [3, 4, 3], [3, 5, 2], [4, 1, 5],
# [4, 2, 4], [4, 3, 3], [4, 4, 2], [4, 5, 1], [5, 1, 4],
# [5, 2, 3], [5, 3, 2], [5, 4, 1]]
recurse(3,50)
#=> []
Improvement
We can do better, however, by first computing all combinations, and then computing the permutations of each of those combinations.
def combo_recurse(n,t,last=0)
ndx = #arr.index { |i| i >= last }
return nil if ndx.nil?
arr_above = #arr[ndx..-1]
if n == 1
arr_above.include?(t) ? [[t]] : nil
else
arr_above.each_with_object([]) do |i,a|
break if i > t # as elements of #arr are non-decreasing
if (ret = combo_recurse(n-1,t-i,i))
ret.each { |b| a << [i,*b] }
end
end
end
end
combo_recurse(1,4)
#=> [[4]]
combo_recurse(2,6)
#=> [[1, 5], [2, 4], [3, 3]]
combo_recurse(3,10)
#=> [[1, 4, 5], [2, 3, 5], [2, 4, 4], [3, 3, 4]]
combo_recurse(3,50)
#=> []
combo_recurse(15,50).size
#=> 132
combo_recurse(15,50).first(5)
#=> [[1, 1, 1, 1, 1, 1, 4, 5, 5, 5, 5, 5, 5, 5, 5],
# [1, 1, 1, 1, 1, 2, 3, 5, 5, 5, 5, 5, 5, 5, 5],
# [1, 1, 1, 1, 1, 2, 4, 4, 5, 5, 5, 5, 5, 5, 5],
# [1, 1, 1, 1, 1, 3, 3, 4, 5, 5, 5, 5, 5, 5, 5],
# [1, 1, 1, 1, 1, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5]]
We can then compute the permutations from the combinations:
combo_recurse(2,6).flat_map { |a| a.permutation(a.size).to_a }.uniq
#=> [[1, 5], [5, 1], [2, 4], [4, 2], [3, 3]]
combo_recurse(3,10).flat_map { |a| a.permutation(a.size).to_a }.uniq
#=> [[1, 4, 5], [1, 5, 4], [4, 1, 5], [4, 5, 1], [5, 1, 4],
# [5, 4, 1], [2, 3, 5], [2, 5, 3], [3, 2, 5], [3, 5, 2],
# [5, 2, 3], [5, 3, 2], [2, 4, 4], [4, 2, 4], [4, 4, 2],
# [3, 3, 4], [3, 4, 3], [4, 3, 3]]
We can approximate the number of permutations for (15,50) (it will be somewhat high because uniq is not applied):
def factorial(n)
(1..n).reduce :*
end
Math.log10 combo_recurse(15,50).reduce(1) { |t,a| t*factorial(a.size) }
#=> 1599.3779486682888
That is, the result has about 1,600 digits. What platform will you be running this on?
I've been scanning the forums and haven't found an answer yet that I can apply to my situation. I need to be able to take an n by n array and transpose it in Python-3. The example given is that I have this list input into the function:
[[4, 2, 1], ["a", "a", "a"], [-1, -2, -3]] and it needs to be transposed to read:
[[4, 'a', -1], [2, 'a', -2], [1, 'a', -3]] So basically reading vertically instead of horizontally.
I CANNOT use things like zip or numpy, I have to make my own function.
Been rattling my brain at this for two nights and it's a huge headache. If anyone could help and then provide an explanation so I can learn it, I'd be grateful.
Edit:
I should add for reference sake that the argument variable is M. The function we're supposed to write is trans(M):
A one-liner:
def trans(M):
return [[M[j][i] for j in range(len(M))] for i in range(len(M[0]))]
result:
>>> M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> trans(M)
[[1, 4, 7], [2, 5, 8], [3, 6, 9]
# or for a non-square matrix:
>>> N = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
>>> trans(N)
[[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]
Additional Note: If you look up the tutorial on list comprehension, one of the examples is in fact transposition of a matrix array.
A variant that should work for matrices with irregular row lengths:
m=[[3, 2, 1],
[0, 1],
[2, 1, 0]]
m_T = [ [row[c] for row in m if c < len(row)] for c in range(0, max([len(row) for row in m])) ]
Here is an in place solution that works for square matrices:
def trans(M):
n = len(M)
for i in range(n - 1):
for j in range(i + 1, n):
M[i][j], M[j][i] = M[j][i], M[i][j]
Example Usage:
def print_matrix(M):
for row in M:
for ele in row:
print(ele, end='\t')
print()
M = [[4, 2, 1], ["a", "a", "a"], [-1, -2, -3]]
print('Original Matrix:')
print_matrix(M)
trans(M)
print('Transposed Matrix:')
print_matrix(M)
Output:
Original Matrix:
4 2 1
a a a
-1 -2 -3
Transposed Matrix:
4 a -1
2 a -2
1 a -3
y=([1,2], [3,4], [5,6])
transpose=[[row[i] for row in y] for i in range(len(y[0]))]
the output is
[[1, 3, 5], [2, 4, 6]]
You can also use the function in numpy to transpose - if you need the answer as a list it is straightforward to convert back using tolist:
from numpy import transpose
M = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
transpose(M).tolist()
the output is
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Haven't timed it (no time!) but I strongly suspect this will be a lot faster than iterators for large arrays, especially if you don't need to convert back to a list.