0
x = 16
while x != 1 do
  if x % 2 == 0
    x = x / 2
    print "#{x} "
  end
  break if x < 0
end

Hi, the result I get from above is 8 4 2 1 . Is there any way to remove the space at the end?

8
  • 3
    Don't print the values into the loop. Put them into a list (array) then, after the loop, join the array items using space as glue. Commented Jul 27, 2017 at 8:45
  • 1
    @axiac: A good idea but the extra storage required for this always needs to be considered, however small. Commented Jul 27, 2017 at 8:46
  • 2
    By running the script I have the 8 4 2 1 result Commented Jul 27, 2017 at 8:47
  • 1
    @Bathsheba, storage is not an issue you should consider in Ruby at this level. Ruby is made for beautiful code, it is not the main objective to win at performance Commented Jul 27, 2017 at 8:49
  • 2
    @roppo aside from the white space annoyance, are you aware that this code enters an infinite loop if x is not a power of 2? Commented Jul 27, 2017 at 10:38

4 Answers 4

4

One of Rubys main features is its beauty - you can shorten that loop to a nice one liner when using an array:

x = 16
arr = []

arr.push(x /= 2) while x.even?
puts arr.join(' ')
# => "8 4 2 1"

* As sagarpandya82 suggested x.even? is the same as using x % 2 == 0, leading to even more readable code

Sign up to request clarification or add additional context in comments.

4 Comments

Honestly, it looks like PHP. In Ruby the upfront declaration of the local variable is considered to be code smell, as well as while loop.
@mudasobwa on a second thought, you are right. I am curious how a pure Ruby solution, unaffected by PHP thinking, looks like :-)
@mudasobwa, I assume the code is part of a study exercise. It's readable and Rubyish enough for that context. Of course you would add a method when actually doing something with the code....
I think this is the most elegant solution. In a similar vein you could also use until x.odd?.
3

Don't print the values into the loop. Put them into a list (array) then, after the loop, join the array items using space as glue.

x = 16
a = []
while x != 1 do
  if x % 2 == 0
    x = x / 2
    a << x
  end
  break if x < 0
end
puts '<' + a.join(' ') + '>'

The output is:

<8 4 2 1>

As @Bathsheba notes in a comment, this solution uses extra memory (the array) to store the values and also the call to Array#join generates a string that doubles the memory requirements. This is not an issue for small lists as the one in the question but needs to be considered the list becomes very large.

2 Comments

I think the break line is superfluous here:)
@sagarpandya82 it was in the original code. I only changed the part that handles the output, didn't even try to make it look good.
3
loop.reduce([[], 16]) do |(acc, val), _|
  break acc if val <= 1

  acc << val / 2 if val.even?
  [acc, val / 2]
end.join ' '

2 Comments

Suggestion to use even? here instead of val % 2 == 0. +1 for using loop which I believe is more idiomatic.
No offense, but this version reminds me of Lisp & Prolog ;-) +1
0
if x != 0
    print " "
end

is one way, having dropped the suffixed space from the other print. I/O will always be the performance bottleneck; an extra if will have a negligible effect on performance, and the extra print will merely contribute to the output stream which is normally buffered.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.