In Ruby 2.1.2, I can successfully compare the result of Time.parse and Time.utc for the same time, and it returns the expected true:
Time.parse("2015-02-09T22:38:43Z") == Time.utc(2015, 2, 9, 22, 38, 43)
=> true
However, this same comparison counterintuitively returns false when the second value is not an integer:
Time.parse("2015-02-09T22:38:43.1Z") == Time.utc(2015, 2, 9, 22, 38, 43.1)
=> false
This is despite the fact that the second values are still integers and are still equivalent:
Time.parse("2015-02-09T22:38:43.1Z").sec
=> 43
Time.utc(2015, 2, 9, 22, 38, 43.1).sec
=> 43
Time.parse("2015-02-09T22:38:43.1Z").sec == Time.utc(2015, 2, 9, 22, 38, 43.1).sec
=> true
Moreover, the comparison results in true between successive calls of the same methods:
Time.parse("2015-02-09T22:38:43.1Z") == Time.parse("2015-02-09T22:38:43.1Z")
=> true
Time.utc(2015, 2, 9, 22, 38, 43.1) == Time.utc(2015, 2, 9, 22, 38, 43.1)
=> true
Why is this so? Is this a bug, or am I missing something?
Ruby compares fractional seconds as well as seconds when comparing times. For some reason your times receive different fractional seconds:
Time.parse("2015-02-09T22:38:43.1Z").subsec
# => (1/10)
Time.utc(2015, 2, 9, 22, 38, 43.1).subsec
# => (14073748835533/140737488355328)
I believe you are running into an issue with precision. The reason the integer seconds compare works is due to the precision of integers, and Ruby performed a .to_i on the parsed version for you.
Underlying the Time class is an integer that represents a very precise integer number, and parsing and explicit values might be treated just differently enough to cause problems. If sub-second precision is not important to you, then it would be best to compare seconds:
Time.parse("2015-02-09T22:38:43.1Z").to_i == Time.utc(2015, 2, 9, 22, 38, 43.1).to_i
In the above case you are comparing seconds since the Unix epoch (Jan 1, 1970)
Another option would be to create a function to compare two times within a certain precision. Many unit testing frameworks provide that feature. Essentially if T1 == T2 within 0.1 seconds, it's good enough.
The easiest way to do a "within" comparison would be like this:
def within(time1, time2, precision)
return (time1 - time2).abs < precision
end
NOTE: the above works with time, floating points, and fractions.
Related
I have a paradigm where the purpose is to calculate "the total accumulated from 'variable from' to 'variable to'". I got two methods, but I don't know exactly what steps they go through.
The first is the times method. I don't understand what (to - from +1) produces and why (i + from)? Also, this code throws syntax error, unexpected end, expecting end-of-input, I don't know where I am going wrong .
from = 10
to = 20
sum = 0
(to - from +1).times to |i|
sum = sum + (i + from)
end
puts sum
Then there is the for loop. I can't understand what is the "total sum accumulated from 'variable from' to 'variable to'", what is the process of adding it?
from = 10
to = 20
sum = 0
for i in from..to
sum = sum + i
end
puts sum
I'm bad at math, thank you all.
Using the IRB you can create an array that represents all the numbers from to to:
irb(main):043:0> from=10
=> 10
irb(main):044:0> to=20
=> 20
irb(main):047:0> a=(from..to).to_a
=> [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
You can get a sum of that array:
irb(main):048:0> a.sum
=> 165
And, actually, you don't need to make an array at all:
irb(main):049:0> (from..to).sum
=> 165
Side note. If you have three dots the last value of to is not included and that is a different sum obviously:
irb(main):053:0> (from...to).to_a
=> [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
irb(main):054:0> (from...to).sum
=> 145
So upto should really be called uptoandincluding:
irb(main):055:0> from.upto(to).to_a
=> [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
You can also use reduce or the alias inject either with a block or symbol to an operation to reduct a list the the pairwise application of the operator.
Example (reduce and inject are the same, but I usually use inject with a block or reduce with the parenthesis):
# block form where n is repeatedly added to an accumulator
irb(main):058:0> (from..to).inject{|sum, n| sum+n}
=> 165
# the operator + is repeated applied from the left to right
irb(main):059:0> (from..to).reduce(:+)
=> 165
Here are a few idiomatic ways of solving this problem in Ruby. They might be a little easier to follow than the solution you proposed.
sum = 0
10.upto(20) do |i|
sum = sum + i
end
For the first iteration of loop, i will = 10, the second, i will = 11 and so "up to" 20. Each time it will add the value of i to sum. When it completes, sum will have a value of 165.
Another way is this:
10.upto(20).sum
The reason this works is that 10.upto(20) returns an Enumerator. You can call sum on an Enumerator.
I don't even know how to explain this... I've been looking for algos but no luck.
I need a function that would return an array of incrementally bigger numbers (not sure what kind of curve) from two numbers that I'd pass as parameters.
Ex.:
$length = 20;
get_numbers(1, 1000, $length);
> 1, 2, 3, 5, 10, 20, 30, 50, 100, 200, 500... // let's say that these are 20 numbers that add up to 1000
Any idea how I could do this..? I guess I'm not smart enough to figure it out.
How about an exponential curve? Sample Python implementation:
begin = 1
end = 1000
diff = end - begin
length = 10
X = diff**(1.0/(length-1))
seq = []
for i in range(length):
seq.append(int(begin+X**i))
print seq
(note: ** is the Python operator for exponentiation. Other languages may or may not use ^ instead)
Result:
[2, 3, 5, 10, 22, 47, 100, 216, 464, 999]
I have a function like this:
(0..Float::INFINITY).lazy.take_while {|n|(n**2+ 1*n+41).prime?}.force[-1]
I'm using this as an optimisation exercise. This works fine, but it has a memory order O(n) as it will create the entire array and then take the last element.
I am trying to get this without building the entire list, hence the lazy enumerator. I can't think of anything other than using a while loop.
(0..Float::INFINITY).lazy.take_while {|n|(n**2+ 1*n+41).prime?}.last.force
Is there a way to do this in space order O(1) rather than O(n) with enumerators?
EDIT: lazy isn't necessary here for the example to work, but I thought it might be more useful to reduce the space complexity of the function?
If you just don't want to save the entire array:
(0..1.0/0).find {|n| !(n**2+n+41).prime?} - 1
1.0/0 is the same as Float::INFINITY. I used it in case you hadn't seen it. So far as I know, neither is preferable.
My first thought clearly was overkill:
def do_it
e = (0..1.0/0).to_enum
loop do
n = e.peek
return e.inspect unless (n**2+n+41).prime?
e.next
end
end
do_it
Solution
Use inject to hold on to the current value instead of building an array.
(0..Float::INFINITY).lazy.take_while {|n|(n**2+ 1*n+41).prime?}.inject{|acc,n| n }
Note that you must use lazy otherwise inject will build an intermediate array.
Verifying
To see what happens if you don't use lazy, run the following after restarting ruby & running the non-lazy version. It will return arrays that "look like" the intermediate array.
ObjectSpace.enum_for(:each_object, Array).each_with_object([]) {|e, acc|
acc << e if e.size == 40 and e.first == 0
}
The non-lazy version will return:
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39]]
Re-doing the test with lazy will return an empty array.
I'm trying to figure out if there's a way to split a string that contains numbers with different digit sizes without having to use if/else statements. Is there an outright method for doing so. Here is an example string:
"123456789101112131415161718192021222324252627282930"
So that it would be split into an array containing 1-9 and 10-30 without having to first split the array into single digits, separate it, find the 9, and iterate through combining every 2 elements after the 9.
Here is the current way I would go about doing this to clarify:
single_digits, double_digits = [], []
string = "123456789101112131415161718192021222324252627282930".split('')
single_digits << string.slice!(0,9)
single_digits.map! {|e| e.to_i}
string.each_slice(2) {|num| double_digits << num.join.to_i}
This would give me:
single_digits = [1,2,3,4,5,6,7,8,9]
double_digits = [10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30]
As long as you can be sure that every number is greater than its predecessor and greater than zero, and every length of number from a single digit to the maximum is represented at least once, you could write this
def split_numbers(str)
numbers = []
current = 0
str.each_char do |ch|
current = current * 10 + ch.to_i
if numbers.empty? or current > numbers.last
numbers << current
current = 0
end
end
numbers << current if current > 0
numbers
end
p split_numbers('123456789101112131415161718192021222324252627282930')
output
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
For Anon's example of 192837453572 we get
[1, 9, 28, 37, 45, 357, 2]
Go through each character of the string, collecting single 'digits', until you find a 9 (set a controlling value and increment it by 1), then continue on collecting two digits, until you find 2 consecutive 9's, and continue on.
This can then be written to handle any sequence of numbers such as your example string.
You could do this:
str = "123456789101112131415161718192021222324252627282930"
result = str[0..8].split('').map {|e| e.to_i }
result += str[9..-1].scan(/../).map {|e| e.to_i }
It's essentially the same solution as yours, but slightly cleaner (no need to combine the pairs of digits). But yeah, if you want a generalizable solution to an arbitrary length string (including more than just 2 digits), that's a different question than what you seem to be asking.
UPDATE:
Well, I haven't been able to get this question out of my mind, because it seems like there could be a simple, generalizable solution. So here's my attempt. The basic idea is to keep a counter so that you know how many digits the number you want to slice out of the string is.
str = "123456789101112131415161718192021222324252627282930"
result = []
i = 1
done = str.length < 1
str_copy = str
while !done do
result << str_copy.slice!(0..i.to_s.size-1).to_i
done = true if str_copy.size == 0
i += 1
end
puts result
This generates the desired output, and is generalizable to a string of consecutive positive integers starting with 1. I'd be very interested to see other people's improvements to this -- it's not super succinct
I have a perfectly square 64x64 2D array of integers that will never have a value greater than 64. I was wondering if there is a really fast way to compare all of the elements with each other and display the ones that are the same, in a unique way.
At the current moment I have this
2D int array named array
loop from i = 0 to 64
loop from j = 0 to 64
loop from k = (j+1) to 64
loop from z = 0 to 64
if(array[i][j] == array[k][z])
print "element [i][j] is same as [k][z]
As you see having 4 nested loops is quite a stupid thing that I would like not to use. Language does not matter at all whatsoever, I am just simply curious to see what kind of cool solutions it is possible to use. Since value inside any integer will not be greater than 64, I guess you can only use 6 bits and transform array into something fancier. And that therefore would require less memory and would allow for some really fancy bitwise operations. Alas I am not quite knowledgeable enough to think in that format, and therefore would like to see what you guys can come up with.
Thanks to anyone in advance for a really unique solution.
There's no need to sort the array via an O(m log m) algorithm; you can use an O(m) bucket sort. (Letting m = n*n = 64*64).
An easy O(m) method using lists is to set up an array H of n+1 integers, initialized to -1; also allocate an array L of m integers each, to use as list elements. For the i'th array element, with value A[i], set k=A[i] and L[i]=H[k] and H[k]=i. When that's done, each H[k] is the head of a list of entries with equal values in them. For 2D arrays, treat array element A[i,j] as A[i+n*(j-1)].
Here's a python example using python lists, with n=7 for ease of viewing results:
import random
n = 7
m = n*n
a=[random.randint(1,n) for i in range(m)]
h=[[] for i in range(n+1)]
for i in range(m):
k = a[i]
h[k].append(i)
for i in range(1,n+1):
print 'With value %2d: %s' %(i, h[i])
Its output looks like:
With value 1: [1, 19, 24, 28, 44, 45]
With value 2: [3, 6, 8, 16, 27, 29, 30, 34, 42]
With value 3: [12, 17, 21, 23, 32, 41, 47]
With value 4: [9, 15, 36]
With value 5: [0, 4, 7, 10, 14, 18, 26, 33, 38]
With value 6: [5, 11, 20, 22, 35, 37, 39, 43, 46, 48]
With value 7: [2, 13, 25, 31, 40]
class temp {
int i, j;
int value;
}
then fill your array in class temp array[64][64], then sort it by value (you can do this in Java by implementing a comparable interface). Then the equal element should be after each other and you can extract i,j for each other.
This solution would be optimal, categorizing as a quadratic approach for big-O notation.
Use quicksort on the array, then iterate through the array, storing a temporary value of the "cursor" (current value you're looking at), and determine if the temporary value is the same as the next cursor.
array[64][64];
quicksort(array);
temp = array[0][0];
for x in array[] {
for y in array[][] {
if(temp == array[x][y]) {
print "duplicate found at x,y";
}
temp = array[x][y];
}
}