Working through some "puzzles" to learn ruby. However lost on this one. Help?

Basically, I am working through some puzzles to learn ruby. I just
finished an online class learning this stuff, and want to test my
knowledge.

Basically, I am working through puzzles based off of “test driven
development”.

I have basically been tested by making methods do things in the past
puzzles.

However, this current puzzle “puzzles” me in a way.

Here is the test:

result = reverse do
“hello world”
end
result.should == “olleh dlrow”
end

It’s basically rspec. I understand what it is doing on some level. Its
basically taking in a string. It’s breaking down the string with
probably a method .each.

Most likely its implementing something like this

(string).each do |word|
word.reverse
end

Problem is, I could make the above work if it was asking for me to make
a method that takes in an argument.

However, it’s not asking for it to take in an argument. So, I am
completely lost.

Can someone help me make sense of how to make this test pass? How do I
make this work? I really am not familiar with this topic 100%. I’m
sure I learned about this, but if someone could help me in the right
direction I would really appreciate it :).

Dear JD JD,

I’m not sure I got what you willing to accomplish.

But… try this.

“hello world”.split.map(&:reverse).join(" ")

Step by step would be:

“hello world”.split
=> [“hello”, “world”]

“hello world”.split.map { |word| word.reverse}
=> [“olleh”, “dlrow”]

“hello world”.split.map { |word| word.reverse}.join(" ")
=> “olleh dlrow”

Is it what you’re looking for?

Best regards,
Abinoam Jr.

On Mon, Dec 16, 2013 at 9:10 PM, Abinoam Jr. [email protected] wrote:

“hello world”.split
Best regards,

I have basically been tested by making methods do things in the past
end


Posted via http://www.ruby-forum.com/.

Given the exercise, it looks at though they want to introduce you to
working blocks. What you typically do with blocks (the do-end or {}
single-line form) is yield them. In this case, take the result of the
yield, then do the word reversal. You might want to check to make sure
the
result of the yield is a String, or can be duck typed as one.

I don’t want to just give the answer, as what’s the fun of that, right?
But
the basic structure would look something like this:

def reverse(&block)
result = yield if block_given?

do something with result to get the reversed words

end

However, this current puzzle “puzzles” me in a way.
basically taking in a string. It’s breaking down the string with

I think you are looking for something like this

def reverse
test_string = yield

your code to reverse it goes here

end

The ‘yield’ executes a block of code (in this case just returning your
string).
Assign it to a variable and then you can use it for you reversing logic.

Michael Hansen

Hi,

What website are you using for the ruby puzzles?

This was the solution I came up with, and it appears to have made it
work:

def reverse
sentence=yield.split

sentence.map do |word|
word.reverse!
end

sentence.join(" ")
end

Basically, from my understanding yield is split and made into an array
and put into sentence. Then sentence uses map to iterate over each
element in the array and .reverse! is used to reverse each element. I
used reverse! instead of reverse (without the ! point) to keep the
change permanent. Playing around with it in irb it showed that it would
just change back without the !.

Then I used .join(" ") to turn the array into a string and join the
words with a space.

However, I am still semi lost. I don’t understand the difference
between .map and .each. All I know is using .each doesn’t seem to make
the thing pass. Could someone explain me the difference between the
two?

Also, I am still really confused about this. You are correct, tamouse
m, this was to introduce blocks. However, this set up really confuses
me. How does yield take in the “hello world”? I find it really
confusing. Could someone explain this set up a little more? It appears
it is blocks, but I am used to using blocks in a different context and I
find this set up/thing really confusing. Although, I will be honest,
I’m not super familiar with blocks really. I could probably use a good
refresher (or maybe even a site that explains them if that would be
easier).

Thanks again for any help with the above.

PS: To the last poster, I got these puzzles a while ago. I don’t know
where they are from though or how to get them now (again, got them a
while back). They have some out there on the the net though I’m sure.
Various sites seem to provide them without even having to download them
if you search around. I’m sure someone knows a good site, but I’m not
familiar with the best site to use really. Sorry I’m not being very
helpful here I guess.

Are you sure you aren’t overcomplicating this?

def reverse
yield.reverse
end

Ah, I failed to read the spec properly. Let my error be a warning to
all!

JD JD wrote in post #1130915:

def reverse
sentence=yield.split

sentence.map do |word|
word.reverse!
end

sentence.join(" ")
end

However, I am still semi lost. I don’t understand the difference
between .map and .each. All I know is using .each doesn’t seem to make
the thing pass. Could someone explain me the difference between the
two?

The difference between #map and #each is what they return. #map is used
to create a new array whose elements are mapped from the original array;
e.g:

a1 = [1, 2, 3]
a2 = a1.map {|x| x * 2 }
p a1 #=> [1, 2, 3]
p a2 #=> [2, 4, 6]

There’s a version called #map! which updates the array; e.g:

a1 = [1, 2, 3]
a1.map! {|x| x * 2 }
p a1 #=> [2, 4, 6]

While #each is used to iterate through the elements without mapping
them, and usually you wouldn’t modify the array from inside the block;
e.g:

a3 = [1, 2, 3]
a3.each {|x| puts x }

Your solution is a valid mixture, even though you used #map instead of
#each; there are two or three alternatives you could do if you want to
make your code look a bit more “correct”:

  1. use #each ; this one works* because you’re using String#reverse! to
    modify each element of the ‘sentence’ array, without changing the array
    itself.

def reverse
sentence = yield.split
sentence.each do |word|
word.reverse!
end
sentence.join(" ")
end

  • at least, it works for me, in Ruby 1.9.1 and up.
  1. use the return value from #map ; this works because you’re creating a
    second array whose elements are mapped from the first array.

def reverse
sentence = yield.split
backwrds = sentence.map do |word|
word.reverse
end
backwrds.join(" ")
end

  1. similar to #2, but use #map! so you don’t need a second array
    variable.

def reverse
sentence = yield.split
sentence.map! do |word|
word.reverse
end
sentence.join(" ")
end

Also, I am still really confused about this. You are correct, tamouse
m, this was to introduce blocks. However, this set up really confuses
me. How does yield take in the “hello world”? I find it really
confusing. Could someone explain this set up a little more? It appears
it is blocks, but I am used to using blocks in a different context and I
find this set up/thing really confusing. Although, I will be honest,
I’m not super familiar with blocks really. I could probably use a good
refresher (or maybe even a site that explains them if that would be
easier).

I can give you a slightly more complicated example, which might help; it
assumes you have defined any of the #reverse methods listed above:

reverse do
File.open(‘some_words.txt’,‘r’){|f| f.read }
end

When #reverse yields, the block reads the words from a text file. If
you invoked ‘yield’ twice, it would read the file twice. There’s no
limit to the complexity you could add inside that block; the reason it’s
useful is that #reverse doesn’t care how complex the block is, once it
works it will keep on working.

If you’re familiar with javascript’s habit of passing functions as
objects (or the concept of Lambda functions in general) you could even
do this:

get_words = lambda {
words = File.open(‘some_words.txt’,‘r’){|f| f.read }
# blah blah, extra processing
return words
}

obfuscated_words = reverse &get_words

I added a redundant ‘return’ in there, because sometimes people like
that sort of thing. It’s just to demonstrate that ‘get_words’ is a
fully-fledged Lambda function, which you can pass as the block parameter
to #reverse.

Ok, I think I’ve found an alternative method:

def reverse
yield.gsub(/\b(\w+)\b/) { $1.reverse }
end

reverse { ‘hello world’ }
=> “olleh dlrow”

Ah yes, this looks like a neater way to do it:
yield.gsub(/\S+/){|s|s.reverse}

Nice code :slight_smile:

How about this?
yield.gsub(/\S+/, &:reverse)

Hello everyone,

I’m a newbie rails developer too and would like to know what are the
best
websites ruby code challenges?

Dear Angela,

Sorry but most people don’t like thread hijacking over here.

Please, just start a new thread and the others will be pleased to help
you.

Abinoam Jr.

We had fun with this on irc yesterday. I guess it’s safe for jdjd to
check
out my gists now. :wink:

https://gist.github.com/phluid61/7999234

Sent from my phone, so excuse the typos.

I wasnt aware that asking a question constituted a hijack in your book
and
why are you being so aggressive?

If you cant answer the question, then it doesnt apply to you.

My question relates to this topic.

Hello Angela,

People can be a bit uppity about their ‘rules’. Try
http://iwanttolearnruby.com if you’re looking for some challenges, and
don’t let the sassy nerds discourage you.

Jonan

Sorry meant jonan!

:slight_smile:

Thank you jonathan and well said!

Dear Angela,

I’m sorry, I didn’t meant to be aggressive or offend you.

I wish you the best experience learning this wonderful language that I
love so much.

Best regards,
Abinoam Jr.

@Matthew K., Thanks for this response. I am going to try to read
your response for a bit and try to understand it more. I may respond
back later with questions though. Also, thanks for the git file to look
at your answer, lol :). I will also try to read that and understand it
when I have a bit more time.

@anglea, people are recommending you respond in another thread for a
good reason and it is understandable why they are making this request.
It does sidetrack the original thread and you won’t get as many answers
because people didn’t come to this thread seeking to answer your
question. It’s not saying your question is a bad question. It is just
saying that you may get more responses by making a separate thread.
Also, having two “conversations” going on in the same thread can confuse
things and needlessly complicate them. I would agree with the other
poster in saying that it would probably be more helpful if you started a
new thread with that question (again, just so you can get a better
response and also because it can sidetrack a thread if a million side
topics are going on in it).

Thank you JD,

You have understand my intention.
I’m not a native english speaker and sometimes I sound rude when I
didn’t want to.
I just notice that there was something wrong in “the way” I wrote when
people overreact to it.
Then I come back and read it again and try to find what was wrong.
In this case I used words like “dear”, “sorry”, “help” but they were
not enough to express myself correctly.
Sorry again for that. I’m trying to improve my english skills.

About the thread thing, it’s all pretty simple.

  1. Somebody creates a thread with a subject like “Working through some
    “puzzles” to learn ruby. However lost on this one. Help?”
  2. I look at the first e-mail and just don’t have any interest in it
  3. The subsequently e-mails that will come and go “under” that thread
    will be ignored by myself. Just because I didn’t have interest in the
    whole thread.
    (That’s how a lot of people do. Myself included).

So if an e-mail with somebody asking for what are the best websites
ruby code challenges arrives it will be completly ignored because I
lost interest on this thread at the first e-mail.
So, even if I am that guy that knows what are the best websites, that
asking for help will never come to me just because I have ignored it
because it was hidden inside a thread that didn’t raise my attention.
But, if a new thread pops up with a clear subject stating “What are
the best websites for code chalenge?” chances a higher that it get
answered.

So, at first, thread hijacking/sidetracking is BAD for people doing
it. Less chances of good answers.
At second, yes, there’s lots of people that don’t like and get upset
when get distracted to a thread side subject.
At third, if lots of people decide to do it at the same time…
welll… no chance of having any kind of productive discussion.

So, sorry again Angela. It all was with the best of intentions.
Thank you again JD.

Sincerely,
Abinoam Jr.