Forum: Ruby One-Liners (#113)

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2007-02-09 18:01
(Received via mailing list)
The three rules of Ruby Quiz:

1.  Please do not post any solutions or spoiler discussion for this quiz
until
48 hours have passed from the time on this message.

2.  Support Ruby Quiz by submitting ideas as often as you can:

http://www.rubyquiz.com/

3.  Enjoy!

Suggestion:  A [QUIZ] in the subject of emails about the problem helps
everyone
on Ruby Talk follow the discussion.  Please reply to the original quiz
message,
if you can.

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

This week's Ruby Quiz is in pop quiz format.  For each of the scenarios
below,
send in a one line (80 characters or less) solution that performs the
task.  You
may use any legal Ruby syntax including require statements and
semicolons, but
the goal in finesse more than golfing.

Any input described in the problem is in a local variable called quiz.
Assigning to this variable is assumed to have happened earlier in the
program
and is not part of your submitted solution.

Your line just needs to evaluate to the expected result.  You do not
have to
store the result in a variable or create any output.

Any edge cases not covered by the provided examples are left to your
best
judgement.

* Given a Numeric, provide a String representation with commas inserted
between
each set of three digits in front of the decimal.  For example,
1999995.99
should become "1,999,995.99".

* Given a nested Array of Arrays, perform a flatten()-like operation
that
removes only the top level of nesting.  For example, [1, [2, [3]]] would
become
[1, 2, [3]].

* Shuffle the contents of a provided Array.

* Given a Ruby class name in String form (like
"GhostWheel::Expression::LookAhead"), fetch the actual class object.

* Insert newlines into a paragraph of prose (provided in a String) so
lines will
wrap at 40 characters.

* Given an Array of String words, build an Array of only those words
that are
anagrams of the first word in the Array.

* Convert a ThinkGeek t-shirt slogan (in String form) into a binary
representation (still a String).  For example, the popular shirt "you
are dumb"
is actually printed as:

  111100111011111110101
  110000111100101100101
  1100100111010111011011100010

* Provided with an open File object, select a random line of content.

* Given a wondrous number Integer, produce the sequence (in an Array).
A
wondrous number is a number that eventually reaches one, if you apply
the
following rules to build a sequence from it.  If the current number in
the
sequence is even, the next number is that number divided by two.  When
the
current number is odd, multiply that number by three and add one to get
the next
number in the sequence.  Therefore, if we start with the wondrous number
15, the
sequence is [15, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8,
4, 2,
1].

* Convert an Array of objects to nested Hashes such that %w[one two
three four
five] becomes {"one" => {"two" => {"three" => {"four" => "five"}}}}.
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-02-09 20:41
(Received via mailing list)
On 2/9/07, Ruby Quiz <james@grayproductions.net> wrote:
>
> The three rules of Ruby Quiz:
>
> <snip>
>
Sounds like fun,
Now the stupid question of the day: will a comment before the line be a
problem for your tools, I guess they are counting ;)

Cheers
Robert
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2007-02-09 20:47
(Received via mailing list)
On Feb 9, 2007, at 1:40 PM, Robert Dober wrote:

> On 2/9/07, Ruby Quiz <james@grayproductions.net> wrote:
>>
>> The three rules of Ruby Quiz:
>>
>> <snip>
>>
> Sounds like fun,
> Now the stupid question of the day: will a comment before the line
> be a
> problem for your tools, I guess they are counting ;)

I don't have any tools.  Someone should build a test suite and post
it though, if they feel motivated to do so.

For my solutions though, I put the questions as comments before each
solution.

James Edward Gray II
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-02-09 21:43
(Received via mailing list)
On 2/9/07, James Edward Gray II <james@grayproductions.net> wrote:
> > Now the stupid question of the day: will a comment before the line
> > be a
> > problem for your tools, I guess they are counting ;)
>
> I don't have any tools.  Someone should build a test suite and post
> it though, if they feel motivated to do so.
>
> For my solutions though, I put the questions as comments before each
> solution.


You read (Past Tense) me perfectly ;)
Thx

Robert
2017657725dd1bce83dc8a1e2e991d04?d=identicon&s=25 Luke Ivers (Guest)
on 2007-02-09 22:01
(Received via mailing list)
So, does the quiz variable that we're getting have to remain unmodified,
or
does it matter?
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2007-02-09 22:06
(Received via mailing list)
On Feb 9, 2007, at 3:01 PM, Luke Ivers wrote:

> So, does the quiz variable that we're getting have to remain
> unmodified, or
> does it matter?

Either way is fine with me.

James Edward Gray II
2017657725dd1bce83dc8a1e2e991d04?d=identicon&s=25 Luke Ivers (Guest)
on 2007-02-09 22:11
(Received via mailing list)
> 4, 2,
> 1].
>
>
One final question: you say "given a wondrous number"... does this mean
that
the input is guaranteed to be wondrous, and we therefore don't need to
check
it, or does the solution need to include a check to make sure that it is
indeed a wondrous number?
2017657725dd1bce83dc8a1e2e991d04?d=identicon&s=25 Luke Ivers (Guest)
on 2007-02-09 22:14
(Received via mailing list)
On 2/9/07, Luke Ivers <technodolt@gmail.com> wrote:
> > current number is odd, multiply that number by three and add one to get
> the input is guaranteed to be wondrous, and we therefore don't need to
> check
> it, or does the solution need to include a check to make sure that it is
> indeed a wondrous number?
>


Never mind.
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2007-02-09 22:15
(Received via mailing list)
On Feb 9, 2007, at 3:10 PM, Luke Ivers wrote:

>> to get
> One final question: you say "given a wondrous number"... does this
> mean that
> the input is guaranteed to be wondrous, and we therefore don't need
> to check
> it...

Correct.

James Edward Gray II
5c2285f675ad99d67216b8d4f547ac8a?d=identicon&s=25 Jamie Macey (Guest)
on 2007-02-09 22:20
(Received via mailing list)
On 2/9/07, James Edward Gray II <james@grayproductions.net> wrote:
> Someone should build a test suite and post
> it though, if they feel motivated to do so.

Okay.  The only one I'm taking significant liberties with is the
random-line-from-a-file - the test is expecting that the contents of
the file be loaded using File#read, and uses OpenStruct to provide a
test stub with that functionality.  Other than that, these tests are a
pretty direct translation from the initial description.  Method stubs
for the implementation are also provided.

require 'test/unit'
require 'ostruct'

class OneLiner
  class << self
    def commaize(number)
    end

    def flatten_once(ary)
    end

    def shuffle(ary)
    end

    def get_class(name)
    end

    def wrap_text(paragraph)
    end

    def find_anagrams(words)
    end

    def binarize(slogan)
    end

    def random_line(file)
    end

    def wondrous_sequence(n)
    end

    def nested_hash(ary)
    end
  end
end

class TestOneLiner < Test::Unit::TestCase
  # Given a Numeric, provide a String representation with commas
inserted
  # between each set of three digits in front of the decimal.  For
example,
  # 1999995.99 should become "1,999,995.99".
  def test_commaize
    assert_equal "1,999,995.99", OneLiner.commaize(1999995.99)
  end

  # Given a nested Array of Arrays, perform a flatten()-like operation
that
  # removes only the top level of nesting.  For example, [1, [2, [3]]]
would
  # become [1, 2, [3]].
  def test_flatten_once
    ary = [1, [2, [3, 4]]]
    flatter_ary = [1, 2, [3, 4]]
    assert_equal flatter_ary, OneLiner.flatten_once(ary)
  end

  # Shuffle the contents of a provided Array.
  def test_shuffle
    ary = [3,1,4,1,5,9]
    shuffled_ary = OneLiner.shuffle(ary)
    assert_not_equal ary, shuffled_ary
    assert_equal ary.sort, shuffled_ary.sort
  end

  # Given a Ruby class name in String form (like
  # "GhostWheel::Expression::LookAhead"), fetch the actual class object.
  def test_get_class
    assert_equal Test::Unit::TestCase,
                 OneLiner.get_class("Test::Unit::TestCase")
  end

  # Insert newlines into a paragraph of prose (provided in a String) so
  # lines will wrap at 40 characters.
  def test_wrap_text
    wrapped = "Insert newlines into a paragraph of " + "\n" +
              "prose (provided in a String) so lines " + "\n" +
              "will wrap at 40 characters."
    paragraph = "Insert newlines into a paragraph of " +
                "prose (provided in a String) so lines " +
                "will wrap at 40 characters."
    assert_equal wrapped, OneLiner.wrap_text(paragraph)
  end

  # Given an Array of String words, build an Array of only those words
that
  # are anagrams of the first word in the Array.
  def test_find_anagrams
    anagrams = %w(cat act)
    assert_equal anagrams, OneLiner.find_anagrams(%w(tac bat cat rat
act))
  end


  # Convert a ThinkGeek t-shirt slogan (in String form) into a binary
  # representation (still a String).  For example, the popular shirt
  # "you are dumb" is actually printed as:
         # 111100111011111110101
         # 110000111100101100101
         # 1100100111010111011011100010
  def test_binarize
    output = "111100111011111110101" + "\n" +
             "110000111100101100101" + "\n" +
             "1100100111010111011011100010"
    assert_equal output, OneLiner.binarize("you are dumb")
  end

  # Provided with an open File object, select a random line of content.
  #
  # NOTE: This test assumes you're using File#read to get the string
data
  #       from the file - if doing otherwise, update the test?
  def test_random_line
    file = OpenStruct.new(:read => "development:
  adapter: mysql
  database: redvase_development
  host: localhost
  username: root
  password:")
    lines = file.read.split("\n")
    line = OneLiner.random_line(file)
    assert_equal true, lines.include?(line)
  end

  # Given a wondrous number Integer, produce the sequence (in an Array).
A
  # wondrous number is a number that eventually reaches one, if you
apply
  # the following rules to build a sequence from it.  If the current
number
  # in the sequence is even, the next number is that number divided by
two.
  # When the current number is odd, multiply that number by three and
add
  # one to get the next number in the sequence.  Therefore, if we start
with
  # the wondrous number 15, the sequence is [15, 46, 23, 70, 35, 106,
53,
  # 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1].
  def test_wondrous_sequence
    seq = [23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1]
    assert_equal seq, OneLiner.wondrous_sequence(23)
  end

  # Convert an Array of objects to nested Hashes such that %w[one two
three
  # four five] becomes {"one" => {"two" => {"three" => {"four" =>
"five"}}}}.
  def test_nested_hash
    hash = {:o => {:t => {:t => {:f => :f}}}}
    assert_equal hash, OneLiner.nested_hash([:o, :t, :t, :f, :f])
  end
end
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2007-02-09 22:27
(Received via mailing list)
On Feb 9, 2007, at 3:19 PM, Jamie Macey wrote:

> On 2/9/07, James Edward Gray II <james@grayproductions.net> wrote:
>> Someone should build a test suite and post
>> it though, if they feel motivated to do so.
>
> Okay.  The only one I'm taking significant liberties with is the
> random-line-from-a-file - the test is expecting that the contents of
> the file be loaded using File#read...

What if it's a file too big to read into memory?  ;)

James Edward Gray II
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-02-09 22:56
(Received via mailing list)
On Feb 9, 10:00 am, Ruby Quiz <j...@grayproductions.net> wrote:
> * Given a wondrous number Integer, produce the sequence (in an Array).  A
> wondrous number is a number that eventually reaches one, if you apply the
> following rules to build a sequence from it.  If the current number in the
> sequence is even, the next number is that number divided by two.  When the
> current number is odd, multiply that number by three and add one to get the next
> number in the sequence.  Therefore, if we start with the wondrous number 15, the
> sequence is [15, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2,
> 1].

Here are a few more test cases, both to help others and to be sure
that mine is right:

def test_wondrous( str )
  maps = [
    [1, [1]],
    [3,[3,10,5,16,8,4,2,1]],
    [5,[5,16,8,4,2,1]],
    [8,[8,4,2,1]],
    [15,[15,46,23,70,35,106,53,160,80,40,20,10,5,16,8,4,2,1]],
    [31,
[31,94,47,142,71,214,107,322,161,484,242,121,364,182,91,274,137,412,206,103,310,155,466,233,700,350,175,526,263,790,395,1186,593,1780,890,445,1336,668,334,167,502,251,754,377,1132,566,283,850,425,1276,638,319,958,479,1438,719,2158,1079,3238,1619,4858,2429,7288,3644,1822,911,2734,1367,4102,2051,6154,3077,9232,4616,2308,1154,577,1732,866,433,1300,650,325,976,488,244,122,61,184,92,46,23,70,35,106,53,160,80,40,20,10,5,16,8,4,2,1]]
  ]
  raise "Solution too long (#{str.length} characters)" unless
str.length <= 80
  maps.each{ |pair|
    quiz = pair[0]
    expected = pair[1]
    output = eval( str )
    unless expected==output
      raise "quiz=#{quiz}; expected #{expected.inspect}, got
#{output.inspect}"
    end
  }
end
017e05d1a49ffa59ea03e149e7af720b?d=identicon&s=25 Chris Shea (Guest)
on 2007-02-09 23:10
(Received via mailing list)
[snip]
>   # Given an Array of String words, build an Array of only those words that
>   # are anagrams of the first word in the Array.
>   def test_find_anagrams
>     anagrams = %w(cat act)
>     assert_equal anagrams, OneLiner.find_anagrams(%w(tac bat cat rat act))
>   end
[snip]

I changed anagrams to %w(tac cat act). I'm the sort of person that
thinks a word is an anagram of itself (although, I have a feeling
"tac" isn't a word).
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-02-09 23:15
(Received via mailing list)
On Feb 9, 10:00 am, Ruby Quiz <j...@grayproductions.net> wrote:
> * Given a Numeric, provide a String representation with commas inserted between
> each set of three digits in front of the decimal.  For example, 1999995.99
> should become "1,999,995.99".

More test cases:
def test_commify( str )
  maps = [
    [1, "1"],
    [-1, "-1"],
    [0.001, "0.001"],
    [-0.001, "-0.001"],
    [999, "999"],
    [-999, "-999"],
    [999.1, "999.1"],
    [-999.1, "-999.1"],
    [999.12, "999.12"],
    [-999.12, "-999.12"],
    [999.123, "999.123"],
    [-999.123, "-999.123"],
    [9999, "9,999"],
    [-9999, "-9,999"],
    [9999.1, "9,999.1"],
    [-9999.1, "-9,999.1"],
    [9999.12, "9,999.12"],
    [-9999.12, "-9,999.12"],
    [9999.123, "9,999.123"],
    [-9999.123, "-9,999.123"],
    [12, "12"],
    [123, "123"],
    [1234, "1,234"],
    [12345, "12,345"],
    [123456, "123,456"],
    [1234567, "1,234,567"],
    [12345678, "12,345,678"],
    [-12, "-12"],
    [-123, "-123"],
    [-1234, "-1,234"],
    [-12345, "-12,345"],
    [-123456, "-123,456"],
    [-1234567, "-1,234,567"],
    [-12345678, "-12,345,678"]
  ]
  raise "Solution too long (#{str.length} characters)" unless
str.length <= 80
  maps.each{ |pair|
    quiz = pair[0]
    expected = pair[1]
    output = eval( str )

    unless expected==output
      raise "quiz=#{quiz}; expected #{expected.inspect}, got
#{output.inspect}"
    end
  }
end
5c2285f675ad99d67216b8d4f547ac8a?d=identicon&s=25 Jamie Macey (Guest)
on 2007-02-09 23:17
(Received via mailing list)
On 2/9/07, Chris Shea <cmshea@gmail.com> wrote:
> thinks a word is an anagram of itself (although, I have a feeling
> "tac" isn't a word).

Neither did I, I was just looking for an easy test.  And yet, lo and
behold:

http://cancerweb.ncl.ac.uk/cgi-bin/omd?query=tac
A kind of customary payment by a tenant; a word used in old records.
Origin: Cf. Tack, 4.
Source: Websters Dictionary
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-02-09 23:45
(Received via mailing list)
On Feb 9, 10:00 am, Ruby Quiz <j...@grayproductions.net> wrote:
> * Given a nested Array of Arrays, perform a flatten()-like operation that
> removes only the top level of nesting.  For example, [1, [2, [3]]] would become
> [1, 2, [3]].

Yet more test cases (and a new way that I'm testing them). Used like:
s = 'your 80 char solution here'
test_solution( :flatten_once, s )


def test_solution( map_set, str )
  raise "Solution too long (#{str.length} chars)" unless str.length <=
80
  maps = MAPS[ map_set ]
  maps.each{ |pair|
    quiz = pair[0]
    expected = pair[1]
    output = eval( str )

    unless expected==output
      raise "quiz=#{quiz}; expected #{expected.inspect}, got
#{output.inspect}"
    end
  }
end

MAPS = {
  :commify => [
    [1, "1"],
    [-1, "-1"],
    [0.001, "0.001"],
    [-0.001, "-0.001"],
    [999, "999"],
    [-999, "-999"],
    [999.1, "999.1"],
    [-999.1, "-999.1"],
    [999.12, "999.12"],
    [-999.12, "-999.12"],
    [999.123, "999.123"],
    [-999.123, "-999.123"],
    [9999, "9,999"],
    [-9999, "-9,999"],
    [9999.1, "9,999.1"],
    [-9999.1, "-9,999.1"],
    [9999.12, "9,999.12"],
    [-9999.12, "-9,999.12"],
    [9999.123, "9,999.123"],
    [-9999.123, "-9,999.123"],
    [12, "12"],
    [123, "123"],
    [1234, "1,234"],
    [12345, "12,345"],
    [123456, "123,456"],
    [1234567, "1,234,567"],
    [12345678, "12,345,678"],
    [-12, "-12"],
    [-123, "-123"],
    [-1234, "-1,234"],
    [-12345, "-12,345"],
    [-123456, "-123,456"],
    [-1234567, "-1,234,567"],
    [-12345678, "-12,345,678"]
  ],

  :flatten_once => [
    [ [], [] ],
    [ [1], [1] ],
    [ [1,2], [1,2] ],
    [ [1,[2]], [1,2] ],
    [ [[1],2], [1,2] ],
    [ [[1,2]], [1,2] ],
    [ [1,2,3], [1,2,3] ],
    [ [1,[2,3]], [1,2,3] ],
    [ [[1,2,3]], [1,2,3] ],
    [ [1, [2, [3]]], [1, 2, [3]] ],
    [ [1, [[2], 3]], [1, [2], 3] ],
    [ [1,[2,[3,[4]]]], [1, 2, [3,[4]]] ],
    [ [[[[[[6]]]]]], [[[[[6]]]]] ]
  ],

  :wondrous => [
    [1, [1]],
    [3,[3,10,5,16,8,4,2,1]],
    [5,[5,16,8,4,2,1]],
    [8,[8,4,2,1]],
    [15,[15,46,23,70,35,106,53,160,80,40,20,10,5,16,8,4,2,1]],
    [31,
[31,94,47,142,71,214,107,322,161,484,242,121,364,182,91,274,137,412,206,103,310,155,466,233,700,350,175,526,263,790,395,1186,593,1780,890,445,1336,668,334,167,502,251,754,377,1132,566,283,850,425,1276,638,319,958,479,1438,719,2158,1079,3238,1619,4858,2429,7288,3644,1822,911,2734,1367,4102,2051,6154,3077,9232,4616,2308,1154,577,1732,866,433,1300,650,325,976,488,244,122,61,184,92,46,23,70,35,106,53,160,80,40,20,10,5,16,8,4,2,1]]
  ]

}
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-02-10 00:36
(Received via mailing list)
>     [999.12, "999.12"],
>     [-9999.123, "-9,999.123"],
>     [-12345, "-12,345"],
>     [ [[1],2], [1,2] ],
>   :wondrous => [
>     [1, [1]],
>     [3,[3,10,5,16,8,4,2,1]],
>     [5,[5,16,8,4,2,1]],
>     [8,[8,4,2,1]],
>     [15,[15,46,23,70,35,106,53,160,80,40,20,10,5,16,8,4,2,1]],
>     [31,
> 
[31,94,47,142,71,214,107,322,161,484,242,121,364,182,91,274,137,412,206,103,310,155,466,233,700,350,175,526,263,790,395,1186,593,1780,890,445,1336,668,334,167,502,251,754,377,1132,566,283,850,425,1276,638,319,958,479,1438,719,2158,1079,3238,1619,4858,2429,7288,3644,1822,911,2734,1367,4102,2051,6154,3077,9232,4616,2308,1154,577,1732,866,433,1300,650,325,976,488,244,122,61,184,92,46,23,70,35,106,53,160,80,40,20,10,5,16,8,4,2,1]]
>   ]
>
> }

  # Built-in classes for testing #4
  :class_from_string => [
    ["OpenSSL", OpenSSL ],
    ["OpenSSL::Digest", OpenSSL::Digest ],
    ["OpenSSL::Digest::DigestError", OpenSSL::Digest::DigestError ],
  ],
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2007-02-10 00:47
(Received via mailing list)
On Feb 9, 2007, at 5:35 PM, Phrogz wrote:

>   # Built-in classes for testing #4
>   :class_from_string => [
>     ["OpenSSL", OpenSSL ],
>     ["OpenSSL::Digest", OpenSSL::Digest ],
>     ["OpenSSL::Digest::DigestError", OpenSSL::Digest::DigestError ],
>   ],

Technically those are constants, not classes.  For example, OpenSSL
is a module.  That neatly foils a solution someone sent me off list
today.  ;)

James Edward Gray II
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-02-10 01:01
(Received via mailing list)
On Feb 9, 4:46 pm, James Edward Gray II <j...@grayproductions.net>
wrote:
> is a module.  That neatly foils a solution someone sent me off list
> today.  ;)

I had wondered about that. The wording of the quiz says "class", but I
figure that:
a) Given the number of modules-as-namespaces over classes-as-
namespaces, a good solution to the problem allows module stops along
the way, and thus
b) If you're going to allow non-classes along the way, you generally
want the "resolve this as though I typed it" functionality, which may
end in constants.

BUT...if the quiz has the wrinkle that only Classes should be returned
(and thus you should get  nil for the cases above), that would be
interesting to program, too.
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2007-02-10 01:09
(Received via mailing list)
On Feb 9, 2007, at 6:00 PM, Phrogz wrote:

>>
> want the "resolve this as though I typed it" functionality, which may
> end in constants.
>
> BUT...if the quiz has the wrinkle that only Classes should be returned
> (and thus you should get  nil for the cases above), that would be
> interesting to program, too.

My solution handles either.

James Edward Gray II
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-02-10 01:11
(Received via mailing list)
Some interesting edge cases, assuming that exactly 40 characters may
fit on a line:
(My one-liner still doesn't handle the 2nd and 3rd ones)

MAPS[ :paragraph_wrapping ] = [
  [ "One\nTwo\nThree", "One\nTwo\nThree" ],

  [ "It's the end of the world as we know it.",
    "It's the end of the world as we know it." ],

  [ "It is the end of the world as we know it",
    "It is the end of the world as we know it" ],

  [ "It is the end of the world as we know it and I feel fine.",
    "It is the end of the world as we know it\nand I feel fine." ],

  [ "It's the end of the world as we know it, and I feel fine.",
    "It's the end of the world as we know it,\nand I feel fine." ],

  [ "It is the end of the world as we know it, and I feel fine.",
    "It is the end of the world as we know\nit, and I feel fine." ],

  [ "It is not the end of the world as we know it, and I feel fine.",
    "It is not the end of the world as we\nknow it, and I feel
fine." ]
]
822f398dd085da080bbe6c7e7b53d3ba?d=identicon&s=25 Dan Uznanski (Guest)
on 2007-02-11 00:58
(Received via mailing list)
On Feb 9, 2007, at 2:15 PM, James Edward Gray II wrote:

>>> When the
>>>
>>>
>> One final question: you say "given a wondrous number"... does this
>> mean that
>> the input is guaranteed to be wondrous, and we therefore don't need
>> to check
>> it...
>
> Correct.
>
Not that there are any known positive numbers that are not wondrous...
indeed, it would be wondrous to find such a number.  Brute force
attacks from eight years ago place any non-wondrous number, should it
exist, above 2E16.

That said, there are three known cycles of /negative/ non-wondrous
numbers.

The real name of this problem is the Collatz Problem.

http://mathworld.wolfram.com/CollatzProblem.html

Dan
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-02-11 17:22
(Received via mailing list)
I guess it is time now ;)


This was a great quiz and it thought me that I did not *know anything
about
Regexps*.
Now I know a little bit:
I also got acquainted with an old enemy of mine, #inject :)


# Given an Array of String words, build an Array of only those words
that
are
# anagrams of the first word in the Array.
quiz.select{ |ele| ele.split("").sort == quiz.first.split("").sort }
# I left the first word in the list one could discard it within the 80
chars
limit be deleting WS in my solution.

# Given a Ruby class name in String form (like
# "GhostWheel::Expression::LookAhead"), fetch the actual class object.
#
x=quiz.split("::").inject(self.class){|k,m|k.const_get(m)};Class===x ? x
:
nil

# * Given a Numeric, provide a String representation with commas
inserted
between
# each set of three digits in front of the decimal.  For example,
1999995.99
# should become "1,999,995.99".
m=/[^\.]*/.match(quiz.to_s
);p=$';m[0].reverse.gsub(/\d{3}\B/,'\&,').reverse+p
# I could not believe how tough this one was for me!!!!

# * Given a nested Array of Arrays, perform a flatten()-like operation
that
# removes only the top level of nesting.  For example, [1, [2, [3]]]
would
become
# [1, 2, [3]].
#
quiz.inject( [] ) { |a,e| a + ( Array === e ? e : [e] ) }

# Convert a ThinkGeek t-shirt slogan (in String form) into a binary
# representation (still a String).  For example, the popular shirt "you
are
dumb"
# is actually printed as:
#
#        111100111011111110101
#        110000111100101100101
#        1100100111010111011011100010
#
quiz.split.map{ |w| s=""; w.each_byte{ |b| s<<b.to_s(2)}; s}.join("\n")

# * Convert an Array of objects to nested Hashes such that %w[one two
three
four
# five] becomes {"one" => {"two" => {"three" => {"four" => "five"}}}}.
quiz[0..-3].reverse.inject( { quiz[-2] => quiz[-1] } ){ |h,e| { e => h }
}
# I found a fitting solution with a recursive method in 80 chars but
eventually
# I was saved by #inject from ridiculing myself.

# Provided with an open File object, select a random line of content.
q=quiz.readlines; q[ rand( q.size ) ].chomp

# * Shuffle the contents of a provided Array.
#
quiz.sort_by{ rand }
# This was a great Quiz but this problem was somehow an anticlimax for
me,
did I miss something?

# Given a wondrous number Integer, produce the sequence (in an Array).
A
# wondrous number is a number that eventually reaches one, if you apply
the
# following rules to build a sequence from it.  If the current number in
the
# sequence is even, the next number is that number divided by two.  When
the
# current number is odd, multiply that number by three and add one to
get
the next
# number in the sequence.  Therefore, if we start with the wondrous
number
15, the
# sequence is [15, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16,
8,
4, 2,
# 1].
q=quiz; x=[q]; until x[-1]==1 do x << ( q= q%2==0 ? q/2 : 3 * q + 1 );
end;
x
# Maybe not  very challenging but a good read on Google:)

# Insert newlines into a paragraph of prose (provided in a String) so
lines
will
# wrap at 40 characters.
#
quiz.gsub(/(.{1,40})(\b|\z)/){$1+"\n"}.gsub(/\s*\n\s*/,"\n").chomp
# tougher than I thought I am not sure about all edge cases

I attached a test suite and the solutions

Cheers
Robert
51a34236538906ab994cf9f2e533d14d?d=identicon&s=25 Lou Scoras (ljscoras)
on 2007-02-11 17:28
(Received via mailing list)
# Largely just to play around with rspec a bit.
# The random_line solution too long as well.

require 'rubygems'
require 'spec'

def commify(quiz)
 quiz.to_s.reverse.gsub(/(\d{3})(?=\d)(?!\d*\.)/) {"#$1,"}.reverse
end

context "integers to strings" do
 specify "should get commas every three digits from the right" do
   commify(123).should      == '123'
   commify(1234).should     == '1,234'
   commify(123456).should   == '123,456'
   commify(-12345).should   == '-12,345'
   commify(-1001001).should == '-1,001,001'
 end
end

context "floats to strings" do
 specify "should not get commas after decimal" do
   commify(123.456).should     == '123.456'
   commify(123.456789).should  == '123.456789'
   commify(123456.789).should  == '123,456.789'
   commify(-123456.789).should == '-123,456.789'
 end
end

def flatten1(quiz)
  quiz.inject([]){|r,n| n.respond_to?(:each) ? n.each {|i| r<< i} : (r<<
n) ; r}
end

context "arrays nested arrays only one level deep" do
 setup do
   @ary = [[1],2,[:symbol],'foo']
   @random = []
   10.times do
     n = rand(100)
     @random << (rand > 0.5 ? n : [n] )
   end
 end

 specify "should flatten1 the same as flatten" do
   flatten1(@ary).should    == @ary.flatten
   flatten1(@random).should == @random.flatten
 end
end

context "arrays nested multiple levels" do
 specify "should only loose 1 level of arrays" do
   flatten1([1, [2, [3]]]).should == [1,2,[3]]
   flatten1([[[[[1]]]]]).should   == [[[[1]]]]
 end
end

def shuffle(quiz)
  quiz.sort_by { rand }
end

context "An array with several elements" do
  setup do
    @rands = [3,2,1,6,5,4,9,8,7,10]
    @a     = (1..@rands.length).to_a
    x      = -1

    self.stub!(:rand).and_return { @rands[x+= 1] }
  end

  specify "should sort randomly w/ shuffle" do
    shuffle(@a).should == @rands[0..@a.length-1]
  end
end


module GhostWheel
 module Expression
   class LookAhead
   end
 end
end

def to_class(quiz)
 quiz.split(/::/).inject(Object) {|s,c| s.const_get(c.to_sym)}
end

context %{given a "class expression"} do
  specify "to_class should return that class" do
    GhostWheel.should_receive(:const_get).with(:Expression).and_return(GhostWheel::Expression)
    GhostWheel::Expression.should_receive(:const_get).with(:LookAhead).and_return(GhostWheel::Expression::LookAhead)

    to_class("GhostWheel::Expression::LookAhead")
  end

  specify "to_class should work for built-in classes" do
    to_class("Net::HTTP").should == Net::HTTP
  end
end

def wrap(quiz)
  quiz.gsub(/(.{1,40})\s+/){ "$1\n" }
end

context "A paragraph of text w/ less than 40 lines" do
  setup do
    @text = 'f' * 40
  end

  specify "should not be changed by wrap" do
    wrap(@text).should == @text
  end
end

context "A paragraph with more than 40 characters" do
  setup do
    @paragraph = <<-END_PARA.gsub(/\s+/, ' ').strip
       Given a wondrous number Integer, produce the sequence (in an
       Array).  A wondrous number is a number that eventually
       reaches one, if you apply the following rules to build a
       sequence from it.  If the current number in the sequence is
       even, the next number is that number divided by two.  When
       the current number is odd, multiply that number by three and
       add one to get the next number in the sequence.  Therefore,
       if we start with the wondrous number 15, the sequence is
       [15, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8,
       4, 2, 1].
    END_PARA
  end

  specify "should have no lines longer than 40 wide after wrapping" do
    wrap(@paragraph).split(/\n/).each do |line|
      line.length.should_not > 40
    end
  end
end

context "An paragraph with a word longer than 40 characters" do
  setup do
    @text = 'f' * 60
  end

  specify "should not be split mid word" do
    wrap(@text).should_not_include '\n'
  end
end

def anagrams(quiz)
  n=quiz[0].split(//).sort; quiz.select {|i| i.split(//).sort == n }
end

context "An array of words" do
  setup do
    @a = %w/silly lilsi looloo yllis yuf silly2 islyl/
  end

  specify "anagrams should contain words with same letters same number
of times" do
    anagrams(@a).should == %w/silly yllis islyl/
  end
end

def to_bin(quiz)
  quiz.scan(/\w/).collect {|c| sprintf "%b", c[0] }.join('')
end

context "A ascii string" do
  setup do
    @str = "you are dumb"
  end

  specify "should be converted to binary by to_bin" do
    to_bin(@str).should == '111100111011111110101' +
                           '110000111100101100101' +
                           '1100100111010111011011100010'
  end
end

def rand_line(quiz)
  z=0;quiz.each{z+=1};quiz.seek 0;n=rand
z;quiz.each_with_index{|x,i|;return x if i==n}
end

context "an open file handle" do
  setup do
    require 'stringio'
    @fh = StringIO.new <<-END
      one
      two
      three
      four
    END
  end

  specify "should return a random line" do
    line = rand_line(@fh).strip
    %w/one two three four/.should_include(line)
  end
end

def wonder(quiz)
  @a=[quiz];until quiz==1;@a<< quiz=quiz%2==0?quiz/2: quiz*3+1 end;@a
end

context "The wonderous sequence for 15" do
  setup { @w = wonder(15) }
  specify "should end with 1" do
    @w[@w.length-1].should == 1
  end
  specify "should match the test data" do
    @w.should == [15, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5,
16, 8, 4, 2, 1]
  end
end

def hashify(quiz)
  quiz.reverse.inject(){|m,i|{i=>m}}
end

context "An array of strings" do
  specify "should return nested hashes when hashified" do
    hashify(%w/one two three four five/).should ==
        {"one" => {"two" => {"three" => {"four" => "five"}}}}
  end
end
017e05d1a49ffa59ea03e149e7af720b?d=identicon&s=25 Chris Shea (Guest)
on 2007-02-11 19:00
(Received via mailing list)
I wasn't able to get down to less than 80 chars on two of the items.
For commaizing numbers and getting a random line from a file (assuming
loading the whole file into memory is against the rules) I think I was
just barking up the wrong path.  I like my nested hash solution (which
I wrote in both golf and non-golf modes.

# Commaize (works for both floats and integers)
a=quiz.to_s.split('.');a[0].reverse.gsub(/
(\d{3})/,'\1,').chomp(',').reverse+"#{'.'+a[1] if a[1]}"

# Flatten once
a=[];quiz.each{|i| if i.is_a? Array;i.each{|j| a<<j};else;a<<i;end};a

# Randomize array (the obvious way)
quiz.sort_by {rand}

# Class from String (fails for some)
begin eval "#{quiz}.allocate.class" rescue nil end

# Wrap lines (no newline at the end!)
a='';b=quiz;until b.size<=40;a<<b.slice!(0..b.rindex(' ',
40))<<"\n";end;a<<b

# Find anagrams
quiz.find_all {|x| x.split('').sort == quiz[0].split('').sort}

# Binarize
a=''; quiz.each_byte {|b| a << (b == 32 ? "\n" : "%b" % b)}; a

# Random line (kludge, reads the whole file twice)
f=quiz;c=0;f.each{c+=1};r=rand(c)+1;f.pos=0;c=0;a='';f.each{|line|c
+=1;a=line if c==r};a

# Wondrous sequence
b=quiz;a=[b];while b>1;if b%2==1;b=3*b+1;else;b=b/2;end;a<<b;end;a

# Nested hash (golf and non-golf, and my best answer (I think))
a=quiz.pop;quiz.reverse_each{|i|a={i=>a}};a
hash = quiz.pop; quiz.reverse_each { |item| hash = { item => hash } };
hash

Thanks for the good time.
5c2285f675ad99d67216b8d4f547ac8a?d=identicon&s=25 Jamie Macey (Guest)
on 2007-02-11 19:02
(Received via mailing list)
Basic test case attached, code should be stuffed in one_liner.rb for
tests to pass.  Solutions are class methods that take a parameter
usually not named 'quiz' :P

I probably could have got smaller solutions with inject instead of
more manual iteration, but they are all under 80, so I'm happy leaving
them as is.

- Jamie


class OneLiner; class << self
  # Convert to string, work backwards from . (or end of string) to add
commas
  def commaize(number)
    s = number.to_s; while s.gsub!(/^(-?\d+)(\d{3})([,.]\d+|$)/,
'\1,\2\3'); end; s
  end

  # Single elements appended to array, arrays added together
  def flatten_once(ary)
    a = []; ary.each{|e| e.kind_of?(Array) ? a += e : a << e }; a
  end

  # Random sort, block evaluates to 1, 0, or -1.
  def shuffle(ary)
    ary.sort{|a,b|1-rand(3)}
  end

  # Traverse class hierarchy looking up constant names
  def get_class(name)
    name.split("::").inject(Object){|klass, name| klass.const_get(name)}
  end

  # Find up to 40 chars including the space, and add a \n following.
  def wrap_text(paragraph)
    paragraph.gsub(/(.{1,39}( |$))/, "\\1\n")
  end

  # Sort the first word's chars, if current word's chars sort same, is
anagram
  def find_anagrams(words)
    word = words.shift.split(//).sort; words.select{|w|w.split(//).sort
== word}
  end

  # Unpack char as 8bit binary, but only grab the (important) last 7
bits
  # Would likely be easier with a sprintf %7b
  def binarize(slogan)
    slogan.split('
').map{|w|w.unpack('B8'*w.size).map{|b|b[1..7]}.join}.join("\n")
  end

  # Split lines, grab one at random
  def random_line(file)
    lines = file.read.split("\n"); lines[rand(lines.size)]
  end

  # Generate sequence, terminating on a 1
  def wondrous_sequence(n)
    a = [n]; while n != 1; n = (n%2>0) ? n*3+1 : n/2; a << n; end; a
  end
  # Recursive version, using a lambda for the recursive function
  def wondrous_sequence_r(n)
    r=lambda{|i| i==1 ? [1] : [i] + r.call((i%2>0) ? i*3+1 : i/2)};
r.call(n)
  end

  # Pop keys off the end of the array, create a new hash around it
  def nested_hash(ary)
    hsh = ary.pop; while key = ary.pop; hsh = {key => hsh}; end; hsh
  end
  # Recursive version, using a lambda for the recursive function
  def nested_hash_r(ary)
    r=lambda{|a|a.size == 1 ? a.first : {a.shift => r.call(a)}};
r.call(ary)
  end
end; end
851acbab08553d1f7aa3eecad17f6aa9?d=identicon&s=25 Ken Bloom (Guest)
on 2007-02-11 20:10
(Received via mailing list)
On Sun, 11 Feb 2007 09:55:59 -0800, Chris Shea wrote:

> I wasn't able to get down to less than 80 chars on two of the items.
> For commaizing numbers and getting a random line from a file (assuming
> loading the whole file into memory is against the rules) I think I was
> just barking up the wrong path.  I like my nested hash solution (which
> I wrote in both golf and non-golf modes.
>
> # Commaize (works for both floats and integers)
> a=quiz.to_s.split('.');a[0].reverse.gsub(/
> (\d{3})/,'\1,').chomp(',').reverse+"#{'.'+a[1] if a[1]}"

Too long: 96 characters (but I couldn't get it under 80 either)

> a='';b=quiz;until b.size<=40;a<<b.slice!(0..b.rindex(' ',
> +=1;a=line if c==r};a
89 characters
851acbab08553d1f7aa3eecad17f6aa9?d=identicon&s=25 Ken Bloom (Guest)
on 2007-02-11 20:11
(Received via mailing list)
On Sat, 10 Feb 2007 02:00:03 +0900, Ruby Quiz wrote:
#In all of this, +i+ is the input. Some solutions don't behave exactly
the
same as the requested sample output, and some are too long. I think I
noted all such instances.

# * Given a Numeric, provide a String representation with commas
inserted between
# each set of three digits in front of the decimal.  For example,
1999995.99
# should become "1,999,995.99".

#this takes 83 characters
a=i.to_s.split('.');a[0]=a[0].reverse.scan(/.{1,3}/).join(',').reverse;a.join('.')

# * Given a nested Array of Arrays, perform a flatten()-like operation
that
# removes only the top level of nesting.  For example, [1, [2, [3]]]
would become
# [1, 2, [3]].

i.inject([]){|cur,val| Array===val ? cur+val : cur << val}
#or
i.inject([]){|cur,val| cur+val rescue cur << val}
#(cur+val throws an error if val isn't an array)

# * Shuffle the contents of a provided Array.

i.inject([]){|cur,val| cur.insert(rand(cur.length+1),val)}

# * Given a Ruby class name in String form (like
# "GhostWheel::Expression::LookAhead"), fetch the actual class object.

eval(i)
#or
i.split("::").inject(Object){|c,v| c.const_get(v)}

# * Insert newlines into a paragraph of prose (provided in a String) so
# lines will wrap at 40 characters.

#clearly doesn't fit within 80 characters
i.split.inject([[]]){|r,w| (r[-1].inject(0){|a,b| a+b.size}+w.size)<40 ?
r[-1] << w : r << [w]; r}.map{|x| x.join(' ')}.join("\n")


# * Given an Array of String words, build an Array of only those words
# that are  anagrams of the first word in the Array.

i.select{|x| x.split(//).sort==i.first.split(//).sort}

# * Convert a ThinkGeek t-shirt slogan (in String form) into a binary
# representation (still a String).  For example, the popular shirt "you
are dumb"
# is actually printed as:
#
#   111100111011111110101
#   110000111100101100101
#   1100100111010111011011100010

i.unpack("B*")[0]
#this doesn't give me the same answer that you gave me though
#or
r="";i.each_byte{|x| r << x.to_s(2)};r

# * Provided with an open File object, select a random line of content.
x=i.readlines;x[rand(x.length)]
#or
i.find{rand<.0005 || i.eof?}
#the rules didn't say anything about the random distribution used.
#adjust the threshold as necessary

# * Given a wondrous number Integer, produce the sequence (in an Array).
A
# wondrous number is a number that eventually reaches one, if you apply
the
# following rules to build a sequence from it.  If the current number in
the
# sequence is even, the next number is that number divided by two.  When
the
# current number is odd, multiply that number by three and add one to
get the next
# number in the sequence.  Therefore, if we start with the wondrous
number 15, the
# sequence is [15, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16,
8, 4, 2,
# 1].

r=[i];while i!=1 do r << (i= i%2==0?i/2:i*3+1); end; r

#
# * Convert an Array of objects to nested Hashes such that %w[one two
three four
# five] becomes {"one" => {"two" => {"three" => {"four" => "five"}}}}.

#neither of these gives the same answer asked for here
p=lambda{|h,k| h[k] =
Hash.new(&p)};z=Hash.new(&p);i.inject(z){|ha,co|ha[co]};z
#or
z={};i.inject(z){|ha,co| ha[co]={}};z
D86ec78a7a258246684d15e09e51a170?d=identicon&s=25 Sharon Phillips (Guest)
on 2007-02-11 20:44
(Received via mailing list)
Hi,

I liked this quiz. Bite sized pieces I could attempt between chasing
kids :)

Here's what I came up with. Note that #6 is just a bit over the 80
char limit.

Cheers,
Dave


TEXT_FILE= '/Users/sharon/Documents/Dave/RubyQuiz/english.txt'

#* Given a Numeric, provide a String representation with commas
inserted between
#each set of three digits in front of the decimal.  For example,
1999995.99
#should become "1,999,995.99".
puts "-- 01 --"
quiz="1234567.89"
# soln
a=quiz.gsub(/(\d)(?=\d{3}+(\.\d*)?$)/,'\1,')
# \soln
puts a

#* Given a nested Array of Arrays, perform a flatten()-like operation
that
#removes only the top level of nesting.  For example, [1, [2, [3]]]
would become
#[1, 2, [3]].
puts "\n-- 02 --"
quiz= [3, [4, 5], [2, [3]], [3, [4, 5]]]
# soln
a=quiz.inject([]){|a,q|a[a.size..a.size]=q;a}
# \soln
puts a.inspect

#* Shuffle the contents of a provided Array.
puts "\n-- 03 --"
quiz=(1..20).entries
# soln
1.upto(50){x=rand(quiz.size);quiz[x],quiz[0]=quiz[0],quiz[x]}
# \soln
puts quiz.inspect

#* Given a Ruby class name in String form (like
#"GhostWheel::Expression::LookAhead"), fetch the actual class object.
puts "\n-- 04 --"
require 'ostruct'
quiz= "OpenStruct"
# soln
a= eval(quiz).new
# \soln
puts a.class

#* Insert newlines into a paragraph of prose (provided in a String)
so lines will
#wrap at 40 characters.
puts "\n-- 05 --"
puts "---------|---------|---------|---------|"

quiz= "* Insert newlines into a paragraph of prose (provided in a
String) so lines will wrap at 40 characters."
# soln
a= quiz.gsub(/.{1,40}(?:\s|\Z)/){$&+"\n"}
# \soln
puts a

#* Given an Array of String words, build an Array of only those words
that are
#anagrams of the first word in the Array.
puts "\n-- 06 --"
quiz= %w[cat dog tac act sheep cow]
# soln
a=[];quiz[1...quiz.size].each{|x|a<<x if quiz[0].split
(//).sort==x.split(//).sort}
# /soln
puts a.inspect

#* Convert a ThinkGeek t-shirt slogan (in String form) into a binary
#representation (still a String).  For example, the popular shirt
"you are dumb"
#is actually printed as:
#
#  111100111011111110101
#  110000111100101100101
#  1100100111010111011011100010
puts "\n-- 07 --"
quiz= "you are dumb"
# soln
quiz.unpack('c*').each{|c| print c==32 ? "\n" : "%b"%[c]};
# /soln

#* Provided with an open File object, select a random line of content.
puts "\n\n-- 08 --"
quiz= File.open(TEXT_FILE)
# soln
x=[];quiz.each{|line|x<<line};puts x[rand(x.size)];quiz.close
# \soln

#* Given a wondrous number Integer, produce the sequence (in an
Array).  A
#wondrous number is a number that eventually reaches one, if you
apply the
#following rules to build a sequence from it.  If the current number
in the
#sequence is even, the next number is that number divided by two.
When the
#current number is odd, multiply that number by three and add one to
get the next
#number in the sequence.  Therefore, if we start with the wondrous
number 15, the
#sequence is [15, 46, 23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5,
16, 8, 4, 2,
#1].
puts "\n-- 09 --"
quiz=[15]
# soln
a=quiz.last; while a>1; quiz << (a=a%2==0 ? a/2 : a==1 ? 1 : a*3+1) end
# \soln
puts quiz.inspect

#* Convert an Array of objects to nested Hashes such that %w[one two
three four
#five] becomes {"one" => {"two" => {"three" => {"four" => "five"}}}}.
puts "\n-- 10 --"
quiz= %w[one two three four five]
# soln
a=quiz.reverse[1...quiz.size].inject(quiz.last){|b,c| {c=> b}}
# \soln
puts a.inspect
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-02-11 23:26
(Received via mailing list)
On Feb 11, 9:27 am, "Louis J Scoras" <louis.j.sco...@gmail.com> wrote:
> def anagrams(quiz)
>   n=quiz[0].split(//).sort; quiz.select {|i| i.split(//).sort == n }
> end

Argh! #select is exactly what I should have used. Nice.

> def hashify(quiz)
>   quiz.reverse.inject(){|m,i|{i=>m}}
> end

How very elegant. I kept thinking there should be a way to bootstrap
the inner pair to be like all the outers, but couldn't find it. Well
done.
Ad7805c9fcc1f13efc6ed11251a6c4d2?d=identicon&s=25 Alex Young (regularfry)
on 2007-02-12 00:41
(Received via mailing list)
My solutions.  Be gentle, this is my first quiz :-)  I haven't checked
these against any of the test cases that were posted, but I think a
couple of them are interesting.

# Commify numbers.
def one(quiz)
   quiz.to_s.reverse.gsub(/(\d{3})(?=\d)/,'\1,').reverse
end

# Commify numbers again, but ignore any before the decimal point.
def one_alternate(quiz)
a,b=quiz.to_s.split('.');[a.reverse.gsub(/(\d{3})(?=\d)/,'\1,').reverse,b].join('.')
end

# One-level flatten().
def two(quiz)
   r=[];quiz.each{|a|r+=[*a]};r
end

# Array shuffling the noddy way.
def three(quiz)
   r={};quiz.each{|a|r[a]=nil};r.keys
end

# Array shuffling the proper way.
def three_alternate(quiz)
   r=[];quiz.size.times{r<<quiz.delete_at(rand(quiz.size))};r
end

# Getting classes from strings.
def four(quiz)
   quiz.split('::').inject(Object){|m,r|m=m.const_get(r)}
end

# Line wrapping.
def five(quiz)
   r='';quiz.size.times{|i|r<<quiz[i].chr;i%40==39?r<<"\n":1};r
end

# Finding anagrams.
def six(quiz)
(c=quiz.map{|a|[a,a.split('').sort.join]}).select{|b|b[1]==c[0][1]}.map{|d|d[0]}
end

# Binary strings.
def seven(quiz)
   quiz.split(' ').map{|s|s.unpack('B*')[0][1..-1]}*$/
end

# Random lines.
def eight(quiz)
   (a=quiz.readlines)[rand(a.size)]
end

# Wondrous numbers
def nine(quiz)
   a=quiz;r=[a];r<<(a=a%2==0?a/2:1+a*3)while a!=1;r
end

# Hash construction
def ten(quiz)
   (a = quiz.pop;quiz).reverse.inject(a){|m,r| m = {r => m}}
end
852a62a28f1de229dc861ce903b07a60?d=identicon&s=25 Gavin Kistner (phrogz)
on 2007-02-12 12:41
(Received via mailing list)
On Feb 11, 4:40 pm, Alex Young <a...@blackkettle.org> wrote:
> # One-level flatten().
>    r=[];quiz.each{|a|r+=[*a]};r

Elegantly small!
B09f99b655b96fd4130aafd04531f6f1?d=identicon&s=25 Eric I. (Guest)
on 2007-02-12 14:22
(Received via mailing list)
On Feb 12, 1:07 am, "Phrogz" <g...@refinery.com> wrote:
> On Feb 11, 4:40 pm, Alex Young <a...@blackkettle.org> wrote:
>
> > # One-level flatten().
> >    r=[];quiz.each{|a|r+=[*a]};r
>
> Elegantly small!

When I saw that, I thought that it could definitely be shortened by
using an inject.  After all, there'd be no assignments of r, no final
returning of r, no semicolons.  But when all was said and done, it
ended up being the same length.  Compare:

    quiz.inject([]){|r,a|r+[*a]}
    r=[];quiz.each{|a|r+=[*a]};r

Oh well....

Eric
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-02-12 14:59
(Received via mailing list)
On 2/12/07, Eric I. <rubytraining@gmail.com> wrote:
> using an inject.  After all, there'd be no assignments of r, no final
> returning of r, no semicolons.  But when all was said and done, it
> ended up being the same length.  Compare:
>
>     quiz.inject([]){|r,a|r+[*a]}
>     r=[];quiz.each{|a|r+=[*a]};r
>
> Oh well....
>
> Eric


Comparing this with James' solution we can it down to
quiz.inject{|r,a|[*r]+[*a]}
=================
I think this quiz is just lovely!!!

Robert
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-02-12 15:00
(Received via mailing list)
please kindly insert the string "get" on the appropriate place in my
last
post ;)
2017657725dd1bce83dc8a1e2e991d04?d=identicon&s=25 Luke Ivers (Guest)
on 2007-02-12 15:26
(Received via mailing list)
class OneLiner
 class << self
   def commaize(quiz)
     quiz.to_s.reverse.gsub(/(\d\d\d)(?=\d)(?!\d*\.)/, '\1,').reverse
   end

   def flatten_once(quiz)
     t=[];quiz.each{|x|(Array===x)?x.each{|y|t<<y}:t<<x};t
   end

   def shuffle(quiz)
     quiz.sort{rand(2)}
   end

   def get_class(quiz) #this one was really hard to figure out.
     name.split("::").inject(Object){|klass, name|klass.const_get(name)}
   end

   def wrap_text(quiz)
     quiz.gsub(/(.{1,40})( +|$\n?)|(.{1,40})/, "\\1\\3\n")
   end

   def find_anagrams(quiz)
     t=[];quiz[1..-1].each{|v|(v.scan
(/./).sort==quiz[0].scan(/./).sort)?t<<v:nil};t
   end

   def binarize(quiz)
     s='';quiz.split.each{|v|v.each_byte{|x|s<<'%b'%x};s<<"\n"};s
   end

   def random_line(quiz)
     s='';quiz.readlines.each{|v|rand(2)==0?eval('s=v;break'):s=v};s
   end

   def wondrous_sequence(quiz)
     t=[quiz];until quiz==1;t<<(quiz=(quiz%2==0?quiz/2:quiz*3+1));end;t
   end

   def nested_hash(quiz)

h={};t=h;quiz[0..-3].each{|v|t[v]={};t=t[v]};t.store(quiz[-2],quiz[-1]);h
   end
 end
end
8222471351de475ccbc18f42350a04d8?d=identicon&s=25 Krishna Dole (Guest)
on 2007-02-12 18:15
(Received via mailing list)
I don't think my solutions contribute much that is new, but you can
see them below and on pastie: http://pastie.caboo.se/39741.

I thought it was interesting that many previous solutions to the
commify problem posted on lists and on RubyForge fail for numbers like
0.23423423.

Looking at others' solutions, I really like Robert Dober's
sort_by{rand} solution to the array shuffle.

cheers,
Krishna

----------------------------------------------------------------
require 'test/unit'
# test setup mostly borrowed from Jamie Macey

class OneLiner
  class << self

    # this was the hardest one for me. this answer is not
    # entirely my own, as it was inspired by
    # http://rubyforge.org/snippet/detail.php?type=snipp...
    # (which does not work for numbers like 0.234234234234)
    def commaize(quiz)
      quiz.to_s.sub(/^(-*)(\d+)/){|m| $1 + $2.gsub(/(\d)(?=\d{3}+$)/,
'\1,')}
    end

    def flatten_once(quiz)
      quiz.inject([]){|n, e| e.is_a?(Array) ? n + e : n << e }
    end

    def shuffle(quiz)
      a = quiz.dup; Array.new(a.size).map{|i| a.delete_at(rand(a.size))
}
    end

    def get_class(quiz)
      require quiz.downcase.split("::")[0..-2].join("/"); eval quiz
    end

    def wrap_text(quiz)
      quiz.gsub(/(.{1,40}(\s|$))/, '\1' + "\n").chop
    end

    def find_anagrams(quiz)
      quiz.select{|w| w.scan(/./).sort == quiz[0].scan(/./).sort}
    end

    def binarize(quiz)
      s = ""; quiz.each_byte {|c| c == 32 ? s << "\n" : s << "%b" % c};
s
    end

    # using #readlines would be easiest, but unlike that, this solution
    # should work fine on files that are too big to hold in memory.
    # unfortunately, it is more than 80 chars when using a variable
    # named 'quiz'
    def random_line(quiz)
      i = rand(quiz.each{|l|}.lineno); quiz.rewind; quiz.each{|l|
return l if quiz.lineno == i+1}
    end

    # i know. it's 6 lines, not one. and more than 80 chars :(
    def wondrous_sequence(quiz)
      a = [n = quiz]; while n != 1; n = (n % 2 > 0 ? n * 3 + 1 : n /
2); a << n; end; a
    end

    # i guess it is cheating to use recursion (two lines)
    # but it worked too nicely to resist here.
    def nested_hash(quiz)
      quiz.size > 1 ? {quiz[0] => nested_hash(quiz[1..-1])} : quiz[0]
    end
  end
end

require 'tempfile'
class TestOneLiner < Test::Unit::TestCase
 # Given a Numeric, provide a String representation with commas inserted
 # between each set of three digits in front of the decimal.  For
example,
 # 1999995.99 should become "1,999,995.99".
 def test_commaize
   assert_equal "995", OneLiner.commaize(995)
   assert_equal "1,995", OneLiner.commaize(1995)
   assert_equal "12,995", OneLiner.commaize(12995)
   assert_equal "123,995", OneLiner.commaize(123995)
   assert_equal "1,234,995", OneLiner.commaize(1234995)
   assert_equal "1,234,567,890,995", OneLiner.commaize(1234567890995)
   assert_equal "99,995.992349834", OneLiner.commaize(99995.992349834)
   assert_equal "0.992349834", OneLiner.commaize(0.992349834)
   assert_equal "-0.992349834", OneLiner.commaize(-0.992349834)
   assert_equal "999,995.99", OneLiner.commaize(999995.99)
   assert_equal "-1,999,995.99", OneLiner.commaize(-1999995.99)
 end

 # Given a nested Array of Arrays, perform a flatten()-like operation
that
 # removes only the top level of nesting.  For example, [1, [2, [3]]]
would
 # become [1, 2, [3]].
 def test_flatten_once
   ary = [1, [2, [3, 4]]]
   flatter_ary = [1, 2, [3, 4]]
   assert_equal flatter_ary, OneLiner.flatten_once(ary)
 end

 # Shuffle the contents of a provided Array.
 def test_shuffle
   ary = [3,1,4,1,5,9]
   shuffled_ary = OneLiner.shuffle(ary)
   assert_not_equal ary, shuffled_ary
   assert_equal ary.sort, shuffled_ary.sort
 end

 # Given a Ruby class name in String form (like
 # "GhostWheel::Expression::LookAhead"), fetch the actual class object.
 def test_get_class
   assert_equal Test::Unit::TestCase,
                OneLiner.get_class("Test::Unit::TestCase")
 end

 # Insert newlines into a paragraph of prose (provided in a String) so
 # lines will wrap at 40 characters.
 def test_wrap_text
   wrapped = "Insert newlines into a paragraph of " + "\n" +
             "prose (provided in a String) so lines " + "\n" +
             "will wrap at 40 characters."
   paragraph = "Insert newlines into a paragraph of " +
               "prose (provided in a String) so lines " +
               "will wrap at 40 characters."
   assert_equal wrapped, OneLiner.wrap_text(paragraph)
 end

 # Given an Array of String words, build an Array of only those words
that
 # are anagrams of the first word in the Array.
 def test_find_anagrams
   anagrams = %w(tac cat act)
   assert_equal anagrams, OneLiner.find_anagrams(%w(tac bat cat rat
act))
 end


 # Convert a ThinkGeek t-shirt slogan (in String form) into a binary
 # representation (still a String).  For example, the popular shirt
 # "you are dumb" is actually printed as:
        # 111100111011111110101
        # 110000111100101100101
        # 1100100111010111011011100010
 def test_binarize
   output = "111100111011111110101" + "\n" +
            "110000111100101100101" + "\n" +
            "1100100111010111011011100010"
   assert_equal output, OneLiner.binarize("you are dumb")
 end

 # Provided with an open File object, select a random line of content.
 #
 # NOTE: This test assumes you're using File#read to get the string data
 #       from the file - if doing otherwise, update the test?
 def test_random_line
   f = Tempfile.new("foo")
   f.print("development:
 adapter: mysql
 database: redvase_development
 host: localhost
 username: root
 password:")
   f.flush
   f.rewind
   lines = f.readlines
   line = OneLiner.random_line(f)
   assert_equal true, lines.include?(line)

 end

 # Given a wondrous number Integer, produce the sequence (in an Array).
A
 # wondrous number is a number that eventually reaches one, if you apply
 # the following rules to build a sequence from it.  If the current
number
 # in the sequence is even, the next number is that number divided by
two.
 # When the current number is odd, multiply that number by three and add
 # one to get the next number in the sequence.  Therefore, if we start
with
 # the wondrous number 15, the sequence is [15, 46, 23, 70, 35, 106, 53,
 # 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1].
 def test_wondrous_sequence
   seq = [23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1]
   assert_equal seq, OneLiner.wondrous_sequence(23)
 end

 # Convert an Array of objects to nested Hashes such that %w[one two
three
 # four five] becomes {"one" => {"two" => {"three" => {"four" =>
"five"}}}}.
 def test_nested_hash
   hash = {:o => {:t => {:t => {:f => :f}}}}
   assert_equal hash, OneLiner.nested_hash([:o, :t, :t, :f, :f])
 end
end
Ad7805c9fcc1f13efc6ed11251a6c4d2?d=identicon&s=25 Alex Young (regularfry)
on 2007-02-12 18:18
(Received via mailing list)
Robert Dober wrote:
>> When I saw that, I thought that it could definitely be shortened by
>> using an inject.  After all, there'd be no assignments of r, no final
>> returning of r, no semicolons.  But when all was said and done, it
>> ended up being the same length.  Compare:
>>
>>     quiz.inject([]){|r,a|r+[*a]}
Given the equal lengths, I prefer this - the r=[];...;r idiom strikes me
as rather ugly.

>>     r=[];quiz.each{|a|r+=[*a]};r
>>
>> Oh well....
>>
>> Eric
>
>
> Comparing this with James' solution we can it down to
> quiz.inject{|r,a|[*r]+[*a]}
Wow :-)
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-02-12 22:48
(Received via mailing list)
On 2/12/07, Krishna Dole <dontfall@gmail.com> wrote:

<cut>

> Looking at others' solutions, I really like Robert Dober's
> sort_by{rand} solution to the array shuffle.


That is kind of you but there is a funny story behind it.

Many others came up with it and it is a known idiom.

But yet I got so confused that I failed to post this solution.

I was about to post, DO NOT LAUGH

sort{ rand <=> rand} (which works BTW)

and eventually there was a thread about the issue and I (not even so
kindly)
asked the people to wait for the spoiler period and it was my full
intention
to tell them later that
sort_by { rand } was stupid when I found out -in time- that sort {rand}
was
stupid and not sort_by{ rand }.

Actually I really do not deserve credit for this one.
<cut>

Cheers
Robert
A9c4658e9e475e13d790ae419acf01b6?d=identicon&s=25 Simon Kröger (Guest)
on 2007-02-13 20:30
(Received via mailing list)
Alex Young wrote:
> Robert Dober wrote:

Hi All! Hi James! Hi Robert!

just wanted to note that there seems to be not a single message
from Robert on the newsgroup side of life.

(i'm not using googles interface, but to clarify)

comp.lang.ruby
http://groups.google.de/group/comp.lang.ruby/brows...

ruby-talk-google
http://groups.google.de/group/ruby-talk-google/bro...

If this is old news, feel free to ignore me.

cheers

Simon
4299e35bacef054df40583da2d51edea?d=identicon&s=25 James Gray (bbazzarrakk)
on 2007-02-13 20:45
(Received via mailing list)
On Feb 13, 2007, at 1:30 PM, Simon Kröger wrote:

> Alex Young wrote:
>> Robert Dober wrote:
>
> Hi All! Hi James! Hi Robert!
>
> just wanted to note that there seems to be not a single message
> from Robert on the newsgroup side of life.

Yes, Robert's messages are sent as multipart/alternative.  Here's the
header from his latest one:

Content-Type:   multipart/alternative;  boundary="----
=_Part_86388_20605457.1171389368901"

The Gateway's current Usenet host doesn't support this message
format.  (It's not technically a legal Usenet post.)  You can read
more about this at:

http://blog.grayproductions.net/articles/2006/12/0...
talk-gateway

James Edward Gray II
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-02-13 21:37
(Received via mailing list)
On 2/13/07, James Edward Gray II <james@grayproductions.net> wrote:
>
> http://blog.grayproductions.net/articles/2006/12/0...
> talk-gateway
>
> James Edward Gray II
>
>
> Thx a lot to both of you for this vital info. I'll try to twist my
gmail...

Cheers
Robert
A9c4658e9e475e13d790ae419acf01b6?d=identicon&s=25 Simon Kröger (Guest)
on 2007-02-13 23:51
(Received via mailing list)
James Edward Gray II schrieb:
> Yes, Robert's messages are sent as multipart/alternative.  Here's the
>
>
> James Edward Gray II

Sorry for not reading that before, i wasn't aware of that resource.

So Robert, would you please configure your mail-client?
(I would really like to read your posts)

cheers

Simon
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-02-14 07:52
(Received via mailing list)
On 2/13/07, Simon Kröger <SimonKroeger@gmx.de> wrote:
> >
> > http://blog.grayproductions.net/articles/2006/12/0...
>
> Simon
>
>
Thanx
Did you get this one?

I just switched off "Rich formatting" I did not find much else to do :(

Robert
A9c4658e9e475e13d790ae419acf01b6?d=identicon&s=25 Simon Kröger (Guest)
on 2007-02-14 08:55
(Received via mailing list)
Robert Dober wrote:

> Thanx
> Did you get this one?

Yes!

> I just switched off "Rich formatting" I did not find much else to do :(

You do not have to do any more than that. Thanks.

> Robert

cheers

Simon
703fbc991fd63e0e1db54dca9ea31b53?d=identicon&s=25 Robert Dober (Guest)
on 2007-02-14 09:10
(Received via mailing list)
On 2/14/07, Simon Kröger <SimonKroeger@gmx.de> wrote:
>
> > Robert
>
> cheers
>
> Simon
>
>
Great; great, thx to you and apologies to the list for the noise.
But it might be a good thing to know for all fellow g-mailers  :)

Cheers
Robert
This topic is locked and can not be replied to.