[QUIZ] One-Liners (#113)

R

Ruby Quiz

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"}}}}.
 
J

James Edward Gray II

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
 
J

James Edward Gray II

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
 
J

James Edward Gray II

* 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].
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
 
J

Jamie Macey

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 = {:eek: => {:t => {:t => {:f => :f}}}}
assert_equal hash, OneLiner.nested_hash([:eek:, :t, :t, :f, :f])
end
end
 
J

James Edward Gray II

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
 
P

Phrogz

* 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
 
C

Chris Shea

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

Phrogz

* 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
 
J

Jamie Macey

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

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
 
P

Phrogz

* 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]]
]

}
 
P

Phrogz

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

}

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

James Edward Gray II

# 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
 
P

Phrogz

# 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. ;)

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.
 
P

Phrogz

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." ]
]
 
J

James Edward Gray II

# 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. ;)

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.

My solution handles either.

James Edward Gray II
 
D

Dan Uznanski

* 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].
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
 
L

Louis J Scoras

# 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 = ([email protected]).to_a
x = -1

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

specify "should sort randomly w/ shuffle" do
shuffle(@a).should == @rands[[email protected]]
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
 
C

Chris Shea

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=;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.
 
K

Ken Bloom

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)
# 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

89 characters
# Wondrous sequence
b=quiz;a=;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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,906
Latest member
SkinfixSkintag

Latest Threads

Top