
-----------------------------------
wtd
Thu Sep 29, 2005 6:51 pm

Ruby TYS
-----------------------------------
Let's kick it off with a challenge.

Given a file containing dates in the format:

092203
072105
061704

That is read into an array called 'dates'.  

["092203", "072105", "061704"]

Create a new array called 'new_dates' with each date in the format: mm/dd/yy, rather than mmddyy.  

Don't use regular expressions or slices.  :)

-----------------------------------
Cervantes
Fri Sep 30, 2005 9:17 pm


-----------------------------------

new_dates = File::open("dates.txt").readlines.collect { |d| d
Rather messy block I've got there.  :(

-----------------------------------
wtd
Sat Oct 01, 2005 1:58 pm


-----------------------------------

new_dates = File::open("dates.txt").readlines.collect { |d| d
Rather messy block I've got there.  :(

d[0..1]

Is a slice.  :)

-----------------------------------
wtd
Fri Oct 28, 2005 5:46 pm


-----------------------------------
Write an HTTP server in at most 4 lines of code (no semi-colons) that sits on port 2000 and simply sends "Hello world!" to any clients that connect.

-----------------------------------
rdrake
Fri Nov 18, 2005 9:33 pm


-----------------------------------
Write an HTTP server in at most 4 lines of code (no semi-colons) that sits on port 2000 and simply sends "Hello world!" to any clients that connect.Could only get it down to 5.require 'socket'

socket = TCPServer.new('127.0.0.1', 2000)
newSock = socket.accept
request = newSock.gets
newSock.print "HTTP/1.0 200 OK\r\nContent-type: text/plain\r\n\r\nHello World!\r\n"Any way I can make it shorter?

-----------------------------------
wtd
Fri Nov 18, 2005 10:30 pm


-----------------------------------
Well, that kinda works.  It only connects to one client, though.  :)

On removing extraneous code...  this line doesn't serve any purpose.

request = newSock.gets

-----------------------------------
rdrake
Sat Nov 19, 2005 11:11 am


-----------------------------------
Well, that kinda works.  It only connects to one client, though.  :)The following will connect with an unlimited number of clients, but it's over the limit.require 'socket'
socket = TCPServer.new('127.0.0.1', 2000)
while newSock = socket.accept
    puts newSock.gets
    newSock.print "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\nHello World!Hello world!\r\n"
    newSock.close
end

On removing extraneous code...  this line doesn't serve any purpose.

request = newSock.getsThat line was there so browsers could connect to it too.  After playing around with different telnet clients, I've managed to get the code down to this.require 'socket'
socket = TCPServer.new('127.0.0.1', 2000)
socket.accept
newSock.print "Hello world!"
newSock.closeAny ideas how I could get this down smaller?

-----------------------------------
wtd
Sat Nov 19, 2005 1:38 pm


-----------------------------------
Untested because I'm feeling lazy at the moment.

require 'socket'

socket = TCPServer.new('127.0.0.1', 2000)
loop { Thread.start(server.accept) { |session| session.print "Hello world\n" } }

-----------------------------------
wtd
Wed Nov 23, 2005 8:14 pm


-----------------------------------
Create two classes "Foo" and "Bar".  They should both implement "baz" and "put_baz" methods.  The "baz" method should return a string.  The "put_baz" method should print that string.

You may use the "def" keyword only three times and the class keyword only twice, and Foo and Bar may not share a common base class, other than Object.

-----------------------------------
Cervantes
Wed Nov 23, 2005 9:15 pm


-----------------------------------

module Bazzy
	def baz
		"Bazzy!"
	end
	def put_baz
		puts baz
	end
end

class Foo
	include Bazzy
end

class Bar
	include Bazzy
end

Foo.new.put_baz
Bar.new.put_baz


-----------------------------------
wtd
Wed Nov 23, 2005 9:21 pm

Re: Ruby TYS
-----------------------------------
Let's kick it off with a challenge.

Given a file containing dates in the format:

092203
072105
061704

That is read into an array called 'dates'.  

["092203", "072105", "061704"]

Create a new array called 'new_dates' with each date in the format: mm/dd/yy, rather than mmddyy.  

Don't use regular expressions or slices.  :)

The answer:

new_dates = dates.collect { |date| date.unpack("A2A2A2").join("/") }

-----------------------------------
wtd
Tue Nov 29, 2005 5:53 pm


-----------------------------------
irb(main):006:0> class String
irb(main):007:1>    
irb(main):008:2>      
irb(main):009:2>    
irb(main):010:1> end
=> nil
irb(main):011:0> "hello"
=> *****

Fill in the missing code.  :)

Note that with "hello" we get five stars.  If one input "foo" on the next line, the result should be three stars.

-----------------------------------
wtd
Thu Dec 01, 2005 7:18 pm


-----------------------------------
irb(main):001:0> a = Array.new(4, [])
=> [[], [], [], []]
irb(main):002:0> a[0]  [4]
irb(main):003:0> a
=> [[4], [4], [4], [4]]

Rewrite the first line of code such that the third line yields:

[[4], [], [], []]

You may only remove one character, and add two others.

-----------------------------------
wtd
Mon Dec 05, 2005 1:23 pm


-----------------------------------
irb(main):006:0> class String
irb(main):007:1>    def inspect
irb(main):008:2>       '*' * length  
irb(main):009:2>    end
irb(main):010:1> end
=> nil
irb(main):011:0> "hello"
=> *****

Fill in the missing code.  :)

Note that with "hello" we get five stars.  If one input "foo" on the next line, the result should be three stars.

:)

-----------------------------------
wtd
Mon Dec 05, 2005 1:24 pm


-----------------------------------
irb(main):001:0> a = Array.new(4, [])
=> [[], [], [], []]
irb(main):002:0> a[0]  [4]
irb(main):003:0> a
=> [[4], [4], [4], [4]]

Rewrite the first line of code such that the third line yields:

[[4], [], [], []]

You may only remove one character, and add two others.

irb(main):001:0> a = Array.new(4) { [] }
=> [[], [], [], []]
irb(main):002:0> a[0]  [4]
irb(main):003:0> a
=> [[4], [], [], []]

-----------------------------------
wtd
Tue Dec 20, 2005 12:06 am


-----------------------------------
With using "if", "or", "?" or "unless"...

Create a very simple "Stack" class which holds elements internally in an instance variable "@elements" of type Array.  The class must only have a working "push" method.  It must not include code outside of the definition of the "push" method, including other methods.

-----------------------------------
Cervantes
Wed Dec 21, 2005 9:47 pm


-----------------------------------

class Stack
	def push( *values )
		@elements = [] unless @elments   # unless @elements is not empty
		@elements.push( *values )
	end
end


-----------------------------------
wtd
Wed Dec 21, 2005 9:55 pm


-----------------------------------

class Stack
	def push( *values )
		@elements = [] unless @elments   # unless @elements is not empty
		@elements.push( *values )
	end
end


Good.  Streamlined.

class Stack
   def push(*values)
      @elements ||= []
      @elements.push(*values)
   end
end

-----------------------------------
wtd
Sun Dec 25, 2005 3:00 pm


-----------------------------------
Add a reverse! method to the module Enumerable.  It should be defined in terms of inject.  The method may not contain any code other than a call to inject.  You are not allowed to define "helper methods".  The assignment operator may not occur in the code.

-----------------------------------
wtd
Wed Dec 28, 2005 3:03 am


-----------------------------------
A demonstration.

The following, which was the answer to a previous question, may be reduced by an additional line.

class Stack
   def push(*values)
      @elements ||= []
      @elements.push(*values)
   end
end

Can become:

class Stack
   def push(*values)
      (@elements ||= []).push(*values)
   end
end

How is this possible?

It's possible because:

@elements ||= []

Is not simply a statement.  It is an expression.  An expression which happens to return @elements.

In reality, the code in its original form is probably better, but it's important to realize that the code demonstrated here is possible and Ruby is quite happy to work with it.

-----------------------------------
Cervantes
Wed Dec 28, 2005 10:35 pm


-----------------------------------
Mm mmm!

It's the same reason you can do things like:

a = b = 5

First, we look at the right side: b = 5.  b is set to 5, and (b = 5) returns 5, so a = (b = 5), which is a = 5, so both a and b equal 5.

Hurray!  8-)

-----------------------------------
Cervantes
Fri Jan 13, 2006 5:27 pm


-----------------------------------
The first non-wtd TYS (to the best of my knowledge)!

Given a String object, a:

a = "Hello World"

Call the upcase, index, and sub methods on a, to the same effect as this:

a.upcase
a.index( 'l' )
a.sub( 'o', 'u' )


Do this with one line, and you may use a maximum of two dots (".") or double-colons ("::").

You may print the output of method calls if you like.


edit: wtd has solved the problem, within 6 minutes.  Just as "Chuck Norris once ate three 72 oz. steaks in one hour. He spent the first 45 minutes having sex with his waitress.", wtd spent most of this time away from the computer.  Perhaps wtd is in fact Chuck Norris.  Shockingly, I've just discovered evidence that suggests wtd is actually Chuck Norris, but has changed his name sort of like an anagram.

The TYS is still open to all non-Chuck Norris'.

-----------------------------------
rdrake
Fri Jan 27, 2006 6:19 pm


-----------------------------------
The first non-wtd TYS (to the best of my knowledge)!

Given a String object, a:

a = "Hello World"

Call the upcase, index, and sub methods on a, to the same effect as this:

a.upcase
a.index( 'l' )
a.sub( 'o', 'u' )


Do this with one line, and you may use a maximum of two dots (".") or double-colons ("::").

You may print the output of method calls if you like.Here's the solution:[[:sub, "o", "u"], :upcase, [:index, "l"]].each do |message| p a.send(*message) end


-----------------------------------
Cervantes
Sat Feb 11, 2006 12:42 pm


-----------------------------------
Good, cartoon_shark!

Next:
We can use attr_reader to, in effect, give read access to instance variables, like this:

class Foo
    attr_reader :bar
    def initialize(bar)
        @bar = bar
    end
end

puts Foo.new(42).bar


However, this only works with instance variables.  Trying to use this with a class variable produces a NoMethodError when trying to read the value.

irb(main):001:0> class Foo
irb(main):002:1>   attr_reader :bar
irb(main):003:1>   def Foo.set_bar(value)
irb(main):004:2>     @@bar = value
irb(main):005:2>   end
irb(main):006:1> end
=> nil
irb(main):007:0> Foo.set_bar(42)
=> 42
irb(main):008:0> Foo.bar
NoMethodError: undefined method `bar' for Foo:Class
        from (irb):8
        from :0


Write code that makes the following possible:

class Foo
    class_attr_reader :bar, :baz
    def Foo.set_bar(value)
        @@bar = value
    end
    def Foo.set_baz(value)
        @@baz = value
    end
end

class Bar
    class_attr_reader :foo
    def Bar.set_foo(value)
        @@foo = value
    end
end

Foo.set_bar("Pizza for dinner tonight, wtd.  ;-)")
Foo.set_baz("Onion, red pepper, sausage, diced tomato, and two kinds of cheese.")
Bar.set_foo("And most importantly, green olives!  Mmmm!")

puts Foo.bar
puts Foo.baz
puts Bar.foo

Foo and Bar may contain only the code shown above.  (They may not be re-opened.)

Edit: Solved, by wtd.  20 minutes.  Beast!  Once again, the TYS will remain open for a while.

-----------------------------------
rdrake
Sun Feb 12, 2006 12:34 am


-----------------------------------
Not an easy one at all.  I'll send you the solution when you're on IRC later, mostly likely tomorrow.

Anybody else care to try this one out for themselves?

-----------------------------------
wtd
Tue Feb 14, 2006 2:54 pm


-----------------------------------
As a follow-up to Cervantes' TYS, create a conditional_attr_writer method such that I can write, for example:

conditional_attr_writer :foo => lambda { |self, new_val| new_val > self.foo }. 
                        :bar => lambda { |self, new_val| new_val > 3 }

-----------------------------------
Cervantes
Tue Feb 14, 2006 8:06 pm


-----------------------------------
Nice one, wtd. :)

Although, I had to change "self" in the lambda function to "current".



class Module
    def conditional_attr_writer(hsh)
        hsh.each_pair { |hsh_key, hsh_value|
            class_eval %Q


And to cartoon_shark, Good job, once again!  Hikaru79, you've got some catching up to do. ;)

Edit: Dammit!  It's either white text, or no indented code.  Spoiler tags would be great.
Edit^2: Dammit!  /me removes a single, useless line of code

-----------------------------------
wtd
Tue Feb 14, 2006 8:49 pm


-----------------------------------
Excellent

-----------------------------------
wtd
Sat May 13, 2006 5:49 pm


-----------------------------------
New TYS.

Does Ruby have a case ("switch" in some languages) statement?

-----------------------------------
Cervantes
Sat May 13, 2006 7:16 pm


-----------------------------------
Does Ruby have a case ("switch" in some languages) statement?
No. Trick question: Ruby has a case expression.

-----------------------------------
wtd
Sun May 14, 2006 7:10 am


-----------------------------------
Does Ruby have a case ("switch" in some languages) statement?
No. Trick question: Ruby has a case expression.

Indeed.

-----------------------------------
Cervantes
Sat May 20, 2006 12:27 pm


-----------------------------------
There's quite a few Ruby TYS questions over at Freerange right now. I'll copy the questions only to here. 
Let's start off with a fairly easy one.

irb(main):001:0> true | puts("or")
or
=> true
Explain why "or" is output, despite the fact that the '|' operator should know the whole expression is true after seeing the initial 'true', since true or something is true.

This next TYS is tough, I think, but it's worth it. It's quite fun. :)

In one line of code, write a program that computes the factorial of a given number. I say it in this manner because I'm not asking you to write a function. Indeed, there is to be no use of "def" or "while" or "loop" any other looping structure.

I'm being kind of vague about this because otherwise I'll give too much away. Feel free to post answers; if it's not what I'm looking for, I'll let you know.

Addendum: I want a recursive solution. But keep in mind, you can't define any methods!


In one line (no semi-colon cheating, of course), write a program that loops infinitely. It should not crash due to a stack overflow (ie. we're not using recursion, here). You may not use any keywords.

For discussion and answers, please visit the [url=ttp://freerange.compsci.ca/viewtopic.php?id=40]Freerange Ruby TYS thread.

-----------------------------------
zylum
Thu Jun 01, 2006 11:07 am


-----------------------------------
puts (1..ARV

-----------------------------------
Cervantes
Thu Jun 01, 2006 3:28 pm


-----------------------------------
puts (1..ARV

Since when has zylum been doing Ruby? :)

That's essentially the solution wtd posted on the Freerange forums, which prompted me to add that addendum: I want a recursive solution. 

In any case, the answers to all these are found in the Freerange TYS thread.

Here's two more:

Quit a standard IRB session. You cannot use any irb methods such as (exit, quit, irb_exit, irb_quit...). Things like Ctrl+D and Ctrl+Z do not count. IRB should not exit because of any error. The code you write into IRB that makes it exit must be valid Ruby code.

Write a short amount of code that makes the following possible:
p Rubidium.new
#
(Of course, the 0xb7cf9ed0 will change.)
The code should apply generally; that is, we're not writing an empty Rubidium class, here.

-----------------------------------
zylum
Thu Jun 01, 2006 6:13 pm


-----------------------------------
Since when has zylum been doing Ruby? :)

since two days ago :)

-----------------------------------
wtd
Thu Jun 01, 2006 7:09 pm


-----------------------------------
Since when has zylum been doing Ruby? :)

since two days ago :)

 Excellent... 
