I am writing a program that needs to check if the values in each column of a two-dimensional array are equal. The number of columns is also static at five.
Currently I have an if statement that iterates from column to column and compares all of the values in that column in one giant check:
if column[0][i] == column[1][i] && column[0][i] == column[2][i]
Edit: Sorry, I didn't intend for the confusion. The array creates a 5x5 game board. The rows refers to each individual array and the columns refers to the nth digit in each of the arrays.
Your question is somewhat confusing, I think because in most code I've come across that represents a structure with rows and columns using arrays, the "outer" array represents the rows and the "inner" arrays represent the columns. For example:
arr = [ [ a, b ],
[ x, y ] ]
In the usual model, (a, b) is "row" 0, and (x, y) is row 1. That makes (a, x) column 0 and (b, y) column 1.
But your code suggests that your structure is inverted, with row 0 being (a, x) and row 1 being (b, y), which makes (a, b) column 0 and (x, y) column 1, so I'll answer it that way. If we want every value in a column to be equal to every value in the same column (i.e. a == b && x == y), then it's pretty easy. Suppose we have the following data:
arr = [ [ 10, 10, 10, 10 ], # <-- Column 0
[ 11, 11, 11, 11 ], # <-- Column 1
[ 12, 0, 12, 12 ] ] # <-- Column 2
To check if every value in "column" 0 is equal to every other value in column 0, we could do this:
arr[0].all? {|item| item == arr[0][0] } # => true
This just compares every item in the column to the first item arr[0][0] and returns false as soon as it finds one that isn't equal (or true if it doesn't).
In order to do this for the every "row", we can wrap the first all? in another:
arr.all? do |sub_arr|
sub_arr.all? {|item| item == sub_arr.first }
end
# => false
Edit: If your array looks instead like this:
arr = [ [ 10, 11, 12 ],
[ 10, 11, 0 ],
[ 10, 11, 12 ],
[ 10, 11, 12 ] ]
# │ │ └─ Column 2
# │ └─ Column 1
# └─ Column 0
One way to solve it would be this:
first_row, *rest = arr
rest.all? do |row|
row.each_with_index.all? do |item, col_idx|
row[col_idx] == first_row[col_idx]
end
end
The first line assigns the first row to first_row and the rest of the rows to rest. Then for each row in rest we use all? to compare each item to the corresponding item in first_row.
P.S. Another way to solve it would be this:
arr.transpose.all? {|row| row.uniq.size == 1 }
Array#transpose just swaps the rows and columns (i.e. turning [[a,b],[x,y]] into [[a,x],[b,y]]), and then in all? we use count the unique values in each "column" (which is now a row). If there's more than one unique value we know they're not all equal. Of course, this has a lot more overhead: Both transpose and uniq iterate over every value and return a new array, whereas the method above stops as soon as it finds any value that doesn't match. But given only 25 items it might not be so bad, depending on how often you need it to run.
P.P.S. I was curious how much better the first method performs than the second. You can see the code and the result here: https://gist.github.com/jrunning/7168af45c5fa5fb4ddd3 Because the first method "short-circuits"—i.e. it stops as soon as it finds a "wrong" value—it gets faster as the probability of a "wrong" value increases. With a 33% chance of any row having a wrong value, the first method performs 33% faster than the second. With a 75% chance, the first performs 80% faster than the second. I realize that's more information than you require, but I found it interesting.
Related
I am trying to create a method complex_check(n), which will do the following:
Create an array of integers ascending from 0 to n
Check each element of that array against complex criteria.
For example, I have an array from 0..n, and I want to know which elements of the array are both evenly divisible by 3 and not divisible by 4. I can index through to check for single criteria like odd?, etc., but is there a compact way to check each integer against multiple criteria?
This is the best I could come up with, I think this is sort of what you're trying to do:
def complex_check(n)
check_array = (0..n).to_a
check_array.select { |num|
num % 3 == 0 &&
num % 4 != 0
}
end
Then using it:
complex_check(15)
=> [3, 6, 9, 15]
One of the things Ruby is very good at is processing through lists and other regular data structures. The Enumerable extensions common to many things including Array allow you to quickly filter, split, chunk, and otherwise completely rework the data you're dealing with. Often a few quick alterations can do the job.
In this case select can be used to filter out undesirable values from your potential candidates in the range 0 to n:
def complex_check(n)
(0..n).select do |v|
v % 3 == 0 and v % 4 != 0
end
end
The key here is using select where any block that returns a logically true value will be a signal to include the element, and otherwise to exclude it. The opposite of this is reject which works on the same principle, just with inverted logic.
You could also pass these filters in dynamically:
def complex_check(n, *tests)
tests.each_with_object((0..n).to_a) do |test, a|
a.select!(&test)
end
end
Where your test code ends up looking like this:
complex_check(
50,
-> (v) { v % 3 == 0 },
-> (v) { v % 4 != 0 }
)
Then you can plug in tests using lambdas which are little reusable blocks.
create an array of integers ascending from 0 to n
Don't do this if you don't have to, which is almost never.
Use a Range or an Enumerator. They are real easy:
0.upto(n).select do |i| #0.upto(n) results in a Enumerator
#complex criteria
end
#or
def complex_check(n)
0.step(n,3).reject{|n| (n%4).zero?} #0.step(n,3) is an Enumerator
end
p complex_check(15) #= [3, 6, 9, 15]
I have two arrays: fasta_ids & frags_by_density. Both contain the same set of ≈1300 strings.
fasta_ids is ordered numerically e.g. ['frag1', 'frag2', 'frag3'...]
frags_by_density contains the same strings ordered differently e.g. ['frag14', 'frag1000'...]
The way in which frag_by_density is ordered is irrelevant to the question (but for any bioinformaticians, the 'frags' are contigs ordered by snp density).
What I want to do is find the indexes in the frag_by_density array, that contain each of the strings in fasta_ids. I want to end up with a new array of those positions (indexes), which will be in the same order as the fasta_ids array.
For example, if the order of the 'frag' strings was identical in both the fasta_ids and frags_by_density arrays, the output array would be: [0, 1, 2, 3...].
In this example, the value at index 2 of the output array (2), corresponds to the value at index 2 of fasta_ids ('frag3') - so I can deduce from this that the 'frag3' string is at index 2 in frags_by_density.
Below is the code I have come up with, at the moment it gets stuck in what I think is an infinite loop. I have annotated what each part should do:
x = 0 #the value of x will represent the position (index) in the density array
position_each_frag_id_in_d = [] #want to get positions of the values in frag_ids in frags_by_density
iteration = []
fasta_ids.each do |i|
if frags_by_density[x] == i
position_each_frag_id_in_d << x #if the value at position x matches the value at i, add it to the new array
iteration << i
else
until frags_by_density[x] == i #otherwise increment x until they do match, and add the position
x +=1
end
position_each_frag_id_in_d << x
iteration << i
end
x = iteration.length # x should be incremented, however I cannot simply do: x += 1, as x may have been incremented by the until loop
end
puts position_each_frag_id_in_d
This was quite a complex question to put into words. Hopefully there is a much easier solution, or at least someone can modify what I have started.
Update: renamed the array fasta_ids, as it is in the code (sorry if any confusion)
fasta_id = frag_id
Non optimized version. array.index(x) returns index of x in array or nil if not found. compact then removes nil elements from the array.
position_of_frag_id_in_d = frag_ids.map{|x| frag_by_density.index(x)}.compact
a = [1,2,3,4]
a[4,43]
# => []
a[5,43]
# => nil
What is the reason for this anomaly?
Assuming you mean this:
a = [1,2,3,4,5]
a[5,43]
# => []
a[6,43]
# => nil
From http://bugs.ruby-lang.org/issues/4245:
This is per spec.
Think of it this way:
[5..-1]: give me all elements after the 5th one and up to the last
one. There are none, so []
[6..-1]: give me all elements after the 6th
one and up to the last one. Say what? There is no 6th one, so returns
nil as the given request is out of bounds.
I agree with spartacus and the bug reporter from the link by Dylan -- there are indeed inconsistencies and Array#slice could use a change. Although yes, it is the spec; from Array#slice
For start and range cases the starting index is just before an element. Additionally, an empty array is returned when the starting index for an element range is at the end of the array ... Returns nil if the index (or starting index) are out of range.
[ 0, 1, 2, 3 ]
^ ^ ^ ^ ^
0 1 2 3 4
Let's say the array a was constructed as [0,1,2,3] , and the numbers below the hats represent where one would "start" when using the a[start,length] form. So a[0,0] is [], and a[1,0] is [], since we have not "hopped" anywhere. Similarly, a[4,0] is [], and that's fine. Now a[4,x] where x is any nonzero number, should return nil, in my opinion, since a[4] is undefined, and in theory, a[4,x] is asking for an array that would look like [undefined, undefined...]
For ranges, however, it appears that an array is built from all indices that appear in the range, so the "hat" start visualization does not apply. So a[0..2] returns [a[0],a1,a[2]], or [0,1,2] in this case.
a[4..x] should return nil for any x, since there is no a[4].
I tried to see how Array#[]= works, and played around:
enum[int] = obj → obj
enum[start, length] = obj → obj
enum[range] = obj → obj
Question 1
I have one array b holding nil at its 0 index.
b = []
b[0] # => nil
I tried to replace nil with integer 10 in the code below.
b[-1] = 10 # => IndexError: index -1 too small for array; minimum: 0
Why doesn't the code above work, but the ones below do? In case of an array with size 1, why are the indices 0 and -1 treated differently?
b[0] = 5 # => 5
b[-1] = 10 # => 10
Question 2
I created an array of size 2, and did the following:
a = [1,2]
a[-3] = 3 # => IndexError: index -3 too small for array; minimum: -2
a[-3] = [3] # => IndexError: index -3 too small for array; minimum: -2
a[-3..-4] = [3] # => RangeError: -3..-4 out of range
I believe that negative index never increases the size of an array, but I don't know why. Why did the code below succeed?
a[-2..-3] = [3,4] #=> [3, 4]
I would suggest you to take a look at the first para in Array documentation. It surprisingly says: “A negative index is assumed to be relative to the end of the array—that is, an index of -1 indicates the last element of the array, -2 is the next to last element in the array, and so on.”
That means, that you may set a[-N]th element if and only |N| <= a.size. That’s why a = [1,2] ; a[-3] = 3 fails (3 > 2).
On the other hand, there is [likely] not documented feature for ruby arrays: a[INBOUNDS_IDX..NONSENSE_IDX]=SMTH will insert SMTH before INBOUNDS_IDX index:
a=[1,2]
a[2..0]='a'
a[2..1]='b'
a[2..-100]='c'
# ⇒ [1, 2, "c", "b", "a"]
a[2..-1]='q'
# ⇒ [1, 2, "q"]
Nonsense here means “less than INBOUNDS_IDX, and not treatable as index in an negative notation” (that’s why a[2..-1] in the example above is treated as a[2..(a.size - 1)].)
Q1:
An empty array has 0 elements, so when you try to set its element 0, with negative index -1, it will give an error.
Because negative index cycles through the array from the end.
So
a = []; a[-1] = 3 makes it impossible to
a) get the element at last position, since its null
b) set its value. since it was never captured.
a[0] = 5 will work because you are telling the compiler to
a) grab the first element,
b) create one if not present, and then assign that to the value you requested.
See official api doc specifically mentioning positive index can grow size, negative index past the beginning of the array raises an error.
Q2:
The above explanation almost answers the second question as well.
Given a = [1,2]
a[-3] = 3 causes the first point of break. You are trying to access the 3rd element from the end, which does not exist. By design it breaks down.
While a[-2..-3] is within the capture range of the defined array.
You ask the interpreter to capture the second element from the last (1st from the front in this case), and try to invoke a range which is asking it to increase the array's size, and populate it with whatever you requested.
Happily, all is still well and as desired. Good to know.
Observation #1
The -1 index is related to the last element, if the array has no size, [], you can't use it until you initialize it with one or more elements.
Observation #2:
Yes, you are right, the negative index never increases size of the array, it only references a concrete existing position in the array.
Don't think the array is circular—the 0 index clued to the N-1 index—so you can't use any negative index thinking that it's valid.
Given a non-negative integer n and an arbitrary set of inequalities that are user-defined (in say an external text file), I want to determine whether n satisfies any inequality, and if so, which one(s).
Here is a points list.
n = 0: 1
n < 5: 5
n = 5: 10
If you draw a number n that's equal to 5, you get 10 points.
If n less than 5, you get 5 points.
If n is 0, you get 1 point.
The stuff left of the colon is the "condition", while the stuff on the right is the "value".
All entries will be of the form:
n1 op n2: val
In this system, equality takes precedence over inequality, so the order that they appear in will not matter in the end. The inputs are non-negative integers, though intermediary and results may not be non-negative. The results may not even be numbers (eg: could be strings). I have designed it so that will only accept the most basic inequalities, to make it easier for writing a parser (and to see whether this idea is feasible)
My program has two components:
a parser that will read structured input and build a data structure to store the conditions and their associated results.
a function that will take an argument (a non-negative integer) and return the result (or, as in the example, the number of points I receive)
If the list was hardcoded, that is an easy task: just use a case-when or if-else block and I'm done. But the problem isn't as easy as that.
Recall the list at the top. It can contain an arbitrary number of (in)equalities. Perhaps there's only 3 like above. Maybe there are none, or maybe there are 10, 20, 50, or even 1000000. Essentially, you can have m inequalities, for m >= 0
Given a number n and a data structure containing an arbitrary number of conditions and results, I want to be able to determine whether it satisfies any of the conditions and return the associated value. So as with the example above, if I pass in 5, the function will return 10.
They condition/value pairs are not unique in their raw form. You may have multiple instances of the same (in)equality but with different values. eg:
n = 0: 10
n = 0: 1000
n > 0: n
Notice the last entry: if n is greater than 0, then it is just whatever you got.
If multiple inequalities are satisfied (eg: n > 5, n > 6, n > 7), all of them should be returned. If that is not possible to do efficiently, I can return just the first one that satisfied it and ignore the rest. But I would like to be able to retrieve the entire list.
I've been thinking about this for a while and I'm thinking I should use two hash tables: the first one will store the equalities, while the second will store the inequalities.
Equality is easy enough to handle: Just grab the condition as a key and have a list of values. Then I can quickly check whether n is in the hash and grab the appropriate value.
However, for inequality, I am not sure how it will work. Does anyone have any ideas how I can solve this problem in as little computational steps as possible? It's clear that I can easily accomplish this in O(n) time: just run it through each (in)equality one by one. But what happens if this checking is done in real-time? (eg: updated constantly)
For example, it is pretty clear that if I have 100 inequalities and 99 of them check for values > 100 while the other one checks for value <= 100, I shouldn't have to bother checking those 99 inequalities when I pass in 47.
You may use any data structure to store the data. The parser itself is not included in the calculation because that will be pre-processed and only needs to be done once, but if it may be problematic if it takes too long to parse the data.
Since I am using Ruby, I likely have more flexible options when it comes to "messing around" with the data and how it will be interpreted.
class RuleSet
Rule = Struct.new(:op1,:op,:op2,:result) do
def <=>(r2)
# Op of "=" sorts before others
[op=="=" ? 0 : 1, op2.to_i] <=> [r2.op=="=" ? 0 : 1, r2.op2.to_i]
end
def matches(n)
#op2i ||= op2.to_i
case op
when "=" then n == #op2i
when "<" then n < #op2i
when ">" then n > #op2i
end
end
end
def initialize(text)
#rules = text.each_line.map do |line|
Rule.new *line.split(/[\s:]+/)
end.sort
end
def value_for( n )
if rule = #rules.find{ |r| r.matches(n) }
rule.result=="n" ? n : rule.result.to_i
end
end
end
set = RuleSet.new( DATA.read )
-1.upto(8) do |n|
puts "%2i => %s" % [ n, set.value_for(n).inspect ]
end
#=> -1 => 5
#=> 0 => 1
#=> 1 => 5
#=> 2 => 5
#=> 3 => 5
#=> 4 => 5
#=> 5 => 10
#=> 6 => nil
#=> 7 => 7
#=> 8 => nil
__END__
n = 0: 1
n < 5: 5
n = 5: 10
n = 7: n
I would parse the input lines and separate them into predicate/result pairs and build a hash of callable procedures (using eval - oh noes!). The "check" function can iterate through each predicate and return the associated result when one is true:
class PointChecker
def initialize(input)
#predicates = Hash[input.split(/\r?\n/).map do |line|
parts = line.split(/\s*:\s*/)
[Proc.new {|n| eval(parts[0].sub(/=/,'=='))}, parts[1].to_i]
end]
end
def check(n)
#predicates.map { |p,r| [p.call(n) ? r : nil] }.compact
end
end
Here is sample usage:
p = PointChecker.new <<__HERE__
n = 0: 1
n = 1: 2
n < 5: 5
n = 5: 10
__HERE__
p.check(0) # => [1, 5]
p.check(1) # => [2, 5]
p.check(2) # => [5]
p.check(5) # => [10]
p.check(6) # => []
Of course, there are many issues with this implementation. I'm just offering a proof-of-concept. Depending on the scope of your application you might want to build a proper parser and runtime (instead of using eval), handle input more generally/gracefully, etc.
I'm not spending a lot of time on your problem, but here's my quick thought:
Since the points list is always in the format n1 op n2: val, I'd just model the points as an array of hashes.
So first step is to parse the input point list into the data structure, an array of hashes.
Each hash would have values n1, op, n2, value
Then, for each data input you run through all of the hashes (all of the points) and handle each (determining if it matches to the input data or not).
Some tricks of the trade
Spend time in your parser handling bad input. Eg
n < = 1000 # no colon
n < : 1000 # missing n2
x < 2 : 10 # n1, n2 and val are either number or "n"
n # too short, missing :, n2, val
n < 1 : 10x # val is not a number and is not "n"
etc
Also politely handle non-numeric input data
Added
Re: n1 doesn't matter. Be careful, this could be a trick. Why wouldn't
5 < n : 30
be a valid points list item?
Re: multiple arrays of hashes, one array per operator, one hash per point list item -- sure that's fine. Since each op is handled in a specific way, handling the operators one by one is fine. But....ordering then becomes an issue:
Since you want multiple results returned from multiple matching point list items, you need to maintain the overall order of them. Thus I think one array of all the point lists would be the easiest way to do this.