One-Liners (#113)

The three rules of Ruby Q.:

  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 Q. by submitting ideas as often as you can:

http://www.rubyquiz.com/

  1. Enjoy!

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

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

This week’s Ruby Q. 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”}}}}.

On 2/9/07, Ruby Q. [email protected] wrote:

The three rules of Ruby Q.:

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 :wink:

Cheers
Robert

On Feb 9, 2007, at 1:40 PM, Robert D. wrote:

On 2/9/07, Ruby Q. [email protected] wrote:

The three rules of Ruby Q.:

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 :wink:

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 G. II

On 2/9/07, James Edward G. II [email protected] 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 :wink:

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 :wink:
Thx

Robert

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

On Feb 9, 2007, at 3:01 PM, Luke I. 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 G. II

On 2/9/07, Luke I. [email protected] 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.

On Feb 9, 2007, at 3:10 PM, Luke I. 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 G. II

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?

On Feb 9, 2007, at 3:19 PM, Jamie M. wrote:

On 2/9/07, James Edward G. II [email protected] 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? :wink:

James Edward G. II

On 2/9/07, James Edward G. II [email protected] 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

[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).

On Feb 9, 10:00 am, Ruby Q. [email protected] 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

On 2/9/07, Chris S. [email protected] 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

On Feb 9, 10:00 am, Ruby Q. [email protected] 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

On Feb 9, 10:00 am, Ruby Q. [email protected] 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]]
]

}

[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 ],
],

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. :wink:

James Edward G. II

On Feb 9, 4:46 pm, James Edward G. II [email protected]
wrote:

is a module. That neatly foils a solution someone sent me off list
today. :wink:

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.

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 G. II