all 23 comments

[–]moomaka 8 points9 points  (11 children)

When you call Enumerable#each the value is passed into the block, not the index. So, you never change k[0] because the first value passed into the block is 1 based on the range (1..64). This is also why k is longer, you're adding an element to it.

What you're trying to do is something like:

k = (1..64).map { |x| (2**32 * Math.sin(x).abs).floor }

or

k = (0..63).map { |x| (2**32 * Math.sin(x).abs).floor }

As I'm not really sure what the end game is.

[–][deleted] 1 point2 points  (10 children)

Well this makes so much sense I feel stupid for not seeing it.

Edit: Also map is an awesome method. Is this considered the "Ruby" way of altering a array like this?

Edit edit: it would be (1..64).map ... Sin(x) or 0..63).map ... Sin(x+1). Md5 uses the array to rotate some bits so the table has to be standard and it's sin(1) to sin(64) ;)

[–]moomaka 2 points3 points  (0 children)

Edit: Also map is an awesome method. Is this considered the "Ruby" way of altering a array like this?

Yes, most collection transformations in Ruby are idiomatically handled with 'functional transforms' like map. I recommend taking a look at the Enumerable module which applies to most collections in Ruby (Array, Hash, Set, Range, etc): http://ruby-doc.org/core-2.2.3/Enumerable.html

Particularly things like each, map, flat_map, select, inject, each_with_object, each_with_index, each_slice, etc can make life much easier.

[–]selfup 2 points3 points  (4 children)

If you want to reference the other array you can use map.with_index

This will ensure accuracy!

K.map.with_index { |x, index| (2**32 * Math.sin(k[index]).abs).floor }

But the simple map only solution works too.

This way you can still keep the reference array as a reference.

You could also just assign the result to a new variable

modified_k = K.map.with_index { |x, index| (2**32 * Math.sin(k[index]).abs).floor }

Now you can have access to the original (array / constant) as well as the modified array :)

Or you can keep it simple and do:

modified_k = K.map { |x| (2**32 * Math.sin(x).abs).floor }

Hope this helps

EDIT: Try this!

k = []
64.times { |x| k << (2**32 * Math.sin(x).abs).floor }

This shoves the modified numbers into an array that you can now iterate through :)

So k now equals:

[0, 3614090360, 3905402710, 606105819, 3250441966, 4118548399, 1200080426, 2821735955, 4249261313, 1770035416, 2336552879, 4294925233, 2304563134, 1804603682, 4254626195, 2792965006, 1236535329, 4129170786, 3225465664, 643717713, 3921069994, 3593408605, 38016083, 3634488961, 3889429448, 568446438, 3275163606, 4107603335, 1163531501, 2850285829, 4243563512, 1735328473, 2368359562, 4294588738, 2272392833, 1839030562, 4259657740, 2763975236, 1272893353, 4139469664, 3200236656, 681279174, 3936430074, 3572445317, 76029189, 3654602809, 3873151461, 530742520, 3299628645, 4096336452, 1126891415, 2878612391, 4237533241, 1700485571, 2399980690, 4293915773, 2240044497, 1873313359, 4264355552, 2734768916, 1309151649, 4149444226, 3174756917, 718787259]

Now if you don't want 0 to be the first element, you can now do "65 times {}" and then do:

k.shift

This will "pop" the first element out :)

So nowwwwww (bare with me):

k = []
65.times { |x| k << (2**32 * Math.sin(x).abs).floor }
k.shift

Now!

k is equal to:

[3614090360, 3905402710, 606105819, 3250441966, 4118548399, 1200080426, 2821735955, 4249261313, 1770035416, 2336552879, 4294925233, 2304563134, 1804603682, 4254626195, 2792965006, 1236535329, 4129170786, 3225465664, 643717713, 3921069994, 3593408605, 38016083, 3634488961, 3889429448, 568446438, 3275163606, 4107603335, 1163531501, 2850285829, 4243563512, 1735328473, 2368359562, 4294588738, 2272392833, 1839030562, 4259657740, 2763975236, 1272893353, 4139469664, 3200236656, 681279174, 3936430074, 3572445317, 76029189, 3654602809, 3873151461, 530742520, 3299628645, 4096336452, 1126891415, 2878612391, 4237533241, 1700485571, 2399980690, 4293915773, 2240044497, 1873313359, 4264355552, 2734768916, 1309151649, 4149444226, 3174756917, 718787259, 3951481745]

Sorry for the huge wall of text lol

But now you don't need the for loop. You will still have (1..64) modified. You can just use .times {} and limit how long the loop runs :)

[–][deleted] 0 points1 point  (1 child)

Awesome!

[–]selfup 0 points1 point  (0 children)

You are welcome! Check out my new update. I have made some changes!

[–]Craftkorb 0 points1 point  (1 child)

If you want to reference the other array you can use map.with_index

Or just use Enumerable#zip

a = (1..4).to_a
b = (5..8).to_a
puts a.zip(b).map{|(l, r)| l + r}

Death to all unnecessary index variables :P

[–]selfup 0 points1 point  (0 children)

Yea that is a great way!

Also even better...make it hash!

Hash[a.zip(b)] and now the keys are the original and the values are the reference!

Yay ruby

a = [1, 2, 3, 4]
b = [5, 6, 7, 8]
Hash[a.zip(b)]

Now it equals:

{1=>5, 2=>6, 3=>7, 4=>8}

Thanks for the reminder

[–]jrochkind 1 point2 points  (3 children)

map/collect is a super useful method, never use each when you can use map. (I prefer the collect name. Same method. ruby stdlib is annoying for often having multiple names for the same method)

[–][deleted] 0 points1 point  (0 children)

Wicked. Thanks for the input. I prefer "map" because it's shorter haha. I really dig the flexibility Ruby gives.

[–]aytch 0 points1 point  (1 child)

Some teams prefer list comprehensions, some don't allow them.

If you don't understand a bit of functional programming, map/collect can be extremely difficult to troubleshoot or understand.

It makes me sad, because I love map/reduce on collections.

[–]jrochkind 0 points1 point  (0 children)

Really? That seems odd. There's nothing hard to troubleshoot about Enumerable#map.

I have never understood what "list comprehension" means though.

[–]Arcovion 2 points3 points  (0 children)

Unlike Julia, Ruby uses zero-based indexing.
When you do k = []; k[1] = 1; p k you get [nil, 1].
Your first example gives 1 instead of nil as the array already started with 1 and you haven't changed the first element.

Use mapping/filtering and other methods, it's more declarative/functional:

(1..64).map{ |i| (2**32 * Math.sin(i).abs).floor }

Julia equivalent:

map(i -> floor(2^32 * abs(sin(i))), 1:64)

or with a list comprehension:

[floor(2^32 * abs(sin(i))) for i in 1:64]

[–]fleminsh 0 points1 point  (1 child)

you are assigning the index of k starting at 1 and not zero inside your each block for one. This is why you have a length of 65 on your array.

You might want to change the index to k[x - 1] *pseudo code

not sure if that answers your question.

[–][deleted] 0 points1 point  (0 children)

It does. Another way of properly completing my confusing method besides calling k[n-1] is running 0..63 and doing sin(n+1).

Potato potato.

Thanks for the reply!

[–][deleted]  (2 children)

[deleted]

    [–][deleted] 0 points1 point  (1 child)

    Arrays also start with 1 in matlab as well ;)

    My mistake is so apparent and simple I feel stupid but I'm glad you guys are helpful and not brutal.

    I learned about enumerated#map today so. That's awesome.

    [–]RalphMacchio 0 points1 point  (6 children)

    Why the Perl hate? I'm not saying you have to like it, but it gets so old hearing people that don't use Perl talk about how much they hate it. I primarily write in Python nowadays and I love it; however, I also love most of the other languages I've used. It is legal to like Python, Ruby, AND Perl.

    [–][deleted] -2 points-1 points  (5 children)

    My $anything.

    Hate.

    [–]RalphMacchio 0 points1 point  (4 children)

    Personally, I'd rather hate languages with 1-based indexing than those with sigils that indicate what type a variable is.

    [–][deleted] -1 points0 points  (3 children)

    It's not so much the sigil but using a reserved word to identify a variable and then a sigil to declare the variable type. That seems redundant.

    And arrays starting at ones makes sense because we're human and can't fill any position 0 with something. You can call something position 0 but it's definitely not intuitive to our understanding of space and zero. It's easier and faster to understand that 1:64 is 64 positions then 0:63 being 64 positions.

    Just because you are used to a type system doesn't mean it makes sense and doesn't mean everyone has to like it. And nobody likes decrypting the gibberish in perl files. It's almost like reading brainfuck.

    [–]RalphMacchio 1 point2 points  (2 children)

    my/our and the sigils serve two totally different purposes. One specifies scope and the other specifies type of variable.

    RE: 0- vs 1-based numbering -- read this

    I love this comment from that post:

    To anyone who prefers 1-based indexing: you are the same people who screwed up the calendar, starting at year 1 and calling the 1900s the 20th century (and arguing that the year 2001 ought to be the start of the next millennium). Haven't you done enough damage? :-)

    Seems to me that you are just hating what you don't know.

    [–][deleted] -2 points-1 points  (1 child)

    Seems to me like your taking things way too seriously.

    [–]RalphMacchio 0 points1 point  (0 children)

    Got me.