One-Liners (#113)

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

On Feb 9, 2007, at 2:15 PM, James Edward G. 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.

Dan

I guess it is time now :wink:

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

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

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

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©+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.

On Sun, 11 Feb 2007 09:55:59 -0800, Chris S. 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

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’ :stuck_out_tongue:

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

On Sat, 10 Feb 2007 02:00:03 +0900, Ruby Q. 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

On Feb 11, 9:27 am, “Louis J Scoras” [email protected] 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.

My solutions. Be gentle, this is my first quiz :slight_smile: 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®}
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

On Feb 11, 4:40 pm, Alex Y. [email protected] wrote:

One-level flatten().

r=[];quiz.each{|a|r+=[*a]};r

Elegantly small!

Hi,

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

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

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

please kindly insert the string “get” on the appropriate place in my
last
post :wink:

On Feb 12, 1:07 am, “Phrogz” [email protected] wrote:

On Feb 11, 4:40 pm, Alex Y. [email protected] 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

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

I don’t think my solutions contribute much that is new, but you can
see them below and on pastie: Parked at Loopia.

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 D.'s
sort_by{rand} solution to the array shuffle.

cheers,
Krishna


require ‘test/unit’

test setup mostly borrowed from Jamie M.

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=snippet&id=8
# (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

On 2/12/07, Krishna D. [email protected] wrote:

Looking at others’ solutions, I really like Robert D.'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.

Cheers
Robert

Alex Y. wrote:

Robert D. 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/browse_thread/thread/90223b4082d864fa/5eaa58d92745fda3?lnk=gst&q=Re%3A+[QUIZ]+One-Liners+(%23113)&rnum=1&hl=de#5eaa58d92745fda3

ruby-talk-google
http://groups.google.de/group/ruby-talk-google/browse_thread/thread/90223b4082d864fa/b42536dc92412aeb?lnk=gst&q=Re%3A+[QUIZ]+One-Liners+(%23113)&rnum=1&hl=de#b42536dc92412aeb

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

cheers

Simon

Robert D. 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 :slight_smile: