Coding challenge: Space-separated constants

I’m issuing this challenge because I’m
too lazy to do this myself. :wink:

Perhaps no one will be interested. But
I have a feeling someone could do this
with some trick I haven’t seen yet.

Problem: Given an input line consisting
of Ruby constants separated by whitespace,
return an array of those constants.

Hashes and arrays are allowed as long as
their contents are constants. Regexes are
allowed. Fancy strings are allowed, but
not here-docs. Proc objects and other
esoteric things are not allowed.

Have I left any holes in this problem? I’m
sure I have, and I’m sure the language
lawyers will be all over me. :wink:

Example:

str = <<EOF
123 4.567 “John Smith” %w[a b c] [1,2,3] {5=>6} true nil
EOF

values = str.parse

values should now be:

[123, 4.567, “John Smith”, [“a”, “b”, “c”], [1,2,3],

{5=>6}, true, nil]

What I’m after is a CSV-like line-oriented
data format, but simpler and prettier.

Note: I don’t think regexes will work for this.
Will need a parser. Perhaps Rockit (or lift C code
from Ruby interp)?

Thoughts?

Cheers,
Hal

Hi,

···

At Mon, 24 Feb 2003 12:53:54 +0900, Hal E. Fulton hal9000@hypermetrics.com wrote:

Hashes and arrays are allowed as long as
their contents are constants. Regexes are
allowed. Fancy strings are allowed, but
not here-docs. Proc objects and other
esoteric things are not allowed.

What about #{}?


Nobu Nakada

Hal E. Fulton wrote:

str = <<EOF
123 4.567 “John Smith” %w[a b c] [1,2,3] {5=>6} true nil
EOF

values = str.parse

values should now be:

[123, 4.567, “John Smith”, [“a”, “b”, “c”], [1,2,3],

{5=>6}, true, nil]

Inefficient, but it seems to work…

result =
until str.empty?
n = 1

loop do
begin
eval str[0…n]
rescue Exception
else
break if str[n,1] == " " or n == str.length
end
n += 1
end

result << eval(str.slice!(0…n))
end

p result

You could tighten it up a bit by not eval-ing unless the substring is
followed by a space or the end of the string.

Good question. My hesitant response is no.

I am thinking of this as a data format. So
there should be no variables used – nothing
that would require the presence or maintenance
of a certain context.

But what about something like #{rand} or
#{Time.now}? Truthfully I haven’t thought
about it.

Hal

···

----- Original Message -----
From: nobu.nokada@softhome.net
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, February 24, 2003 1:15 AM
Subject: Re: Coding challenge: Space-separated constants

Hi,

At Mon, 24 Feb 2003 12:53:54 +0900, > Hal E. Fulton hal9000@hypermetrics.com wrote:

Hashes and arrays are allowed as long as
their contents are constants. Regexes are
allowed. Fancy strings are allowed, but
not here-docs. Proc objects and other
esoteric things are not allowed.

What about #{}?

Inefficient as you say, but very clever. A good
example of something I would not have thought of. :slight_smile:

Hal

···

----- Original Message -----
From: “Joel VanderWerf” vjoel@PATH.Berkeley.EDU
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, February 24, 2003 1:17 AM
Subject: Re: Coding challenge: Space-separated constants

Inefficient, but it seems to work…

result =
until str.empty?
n = 1

loop do
begin
eval str[0…n]
rescue Exception
else
break if str[n,1] == " " or n == str.length
end
n += 1
end

result << eval(str.slice!(0…n))
end

p result

You could tighten it up a bit by not eval-ing unless the substring is
followed by a space or the end of the string.

[snip Joel’s code]

I based this on Joel Vanderwerf’s idea and made
the following adjustments.

  1. I divide the whole string into “pieces” that
    are each either whitespace or “blackspace” :slight_smile:
  2. I work a piece at a time instead of a char
    at a time

I’ll bet this is faster, though I haven’t tried
a speed comparison.

I also added detection of malformed constants.

Code below. Improvement/critique welcome.

Hal

class String
def values
pieces = self.scan(/[ \t]+|[^ \t]+/)
vals =
str = “”
while pieces[0] do
piece = pieces.shift
str << piece
if str =~ /[1]+$/ # whitespace only
str = “”
next
end
begin
vals << eval(str)
str = “”
rescue Exception
if pieces[0]
next
else
raise “Bad value near #{str}”
end
end
end
vals
end
end

line1 = <<EOF
234 3.14 “John Smith” “Jane Doe” ‘Bob Dole’ true nil
EOF
p line1.values

line2 = <<EOF
%w[alpha beta gamma] %q[This’" is’" “” ‘’ only a test.]
EOF
p line2.values

line3 = " 234 345.678 'John" # Unterminated quote
p line3.values

···

----- Original Message -----
From: “Joel VanderWerf” vjoel@PATH.Berkeley.EDU
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, February 24, 2003 1:17 AM
Subject: Re: Coding challenge: Space-separated constants

Inefficient, but it seems to work…


  1. \t ↩︎

Hi –

···

On Mon, 24 Feb 2003, Hal E. Fulton wrote:

----- Original Message -----
From: nobu.nokada@softhome.net
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, February 24, 2003 1:15 AM
Subject: Re: Coding challenge: Space-separated constants

Hi,

At Mon, 24 Feb 2003 12:53:54 +0900, > > Hal E. Fulton hal9000@hypermetrics.com wrote:

Hashes and arrays are allowed as long as
their contents are constants. Regexes are
allowed. Fancy strings are allowed, but
not here-docs. Proc objects and other
esoteric things are not allowed.

What about #{}?

Good question. My hesitant response is no.

I am thinking of this as a data format. So
there should be no variables used – nothing
that would require the presence or maintenance
of a certain context.

But what about something like #{rand} or
#{Time.now}? Truthfully I haven’t thought
about it.

Presumably they would be inside quotation marks:

str = ‘123 4.5 “#{rand}” “and so on”’

so if your solution is eval-based, the interpolation should just sort
of happen.

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

[snip code]

Simplified scan, moved error check outside loop, added eval binding
context, and wrote a haiku.

class String
def values (bind=nil)
res =
str = ‘’
scan(/\S+\s*/).each { |tok|
begin
res << eval(str << tok, bind)
str = ‘’
rescue Exception
end
}
str.empty? or raise “Bad value near: #{str}”
res
end
end

a = “I n c r e m e n t a l”

a = <<EOF.values binding
111 proc do |x| x.to_i.chr end <<-1
82
117 Refactoring code
98 Insert seven syllables
121 One line at a time
1
33 callcc {|x| x} print(a[0].chr,a[-2,2])
EOF

a.size < a[0] and a[4].call or puts “ve #{a[2].map(&a[1])}” << a[3]

···

“Hal E. Fulton” hal9000@hypermetrics.com wrote:

Code below. Improvement/critique welcome.


Tabby

Surely. As long as illegal things such as
“#{undefinedvar}” are caught and handled
appropriately. Whatever that means.

Hal

···

----- Original Message -----
From: dblack@candle.superlink.net
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, February 24, 2003 8:48 AM
Subject: Re: Coding challenge: Space-separated constants

What about #{}?

Good question. My hesitant response is no.

I am thinking of this as a data format. So
there should be no variables used – nothing
that would require the presence or maintenance
of a certain context.

But what about something like #{rand} or
#{Time.now}? Truthfully I haven’t thought
about it.

Presumably they would be inside quotation marks:

str = ‘123 4.5 “#{rand}” “and so on”’

so if your solution is eval-based, the interpolation should just sort
of happen.

Simplified scan, moved error check outside loop, added eval binding
context, and wrote a haiku.

[snip code]

Worthy changes, thanks very much!

My favorite part is the haiku. :wink:

a = “I n c r e m e n t a l”

a = <<EOF.values binding
111 proc do |x| x.to_i.chr end <<-1
82
117 Refactoring code
98 Insert seven syllables
121 One line at a time
1
33 callcc {|x| x} print(a[0].chr,a[-2,2])
EOF

a.size < a[0] and a[4].call or puts “ve #{a[2].map(&a[1])}” << a[3]

For those who are too lazy to run this themselves,
the output is:

I looooooooooooooooooooooooooooooooooooooooooooooooooooove Ruby!

Thanks much for the refactoring and entertainment. The
code snippet above makes my brain itch.

I don’t recall seeing you post before… are you
a long-time lurker or have I just not been
paying attention?

Hal

···

----- Original Message -----
From: “Sabby and Tabby” sabbyxtabby@yahoo.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Saturday, March 01, 2003 10:07 AM
Subject: Re: Coding challenge: Space-separated constants

My favorite part is the haiku. :wink:

Yay~! :slight_smile:

I don’t recall seeing you post before… are you
a long-time lurker or have I just not been
paying attention?

Neither. Just a newbie here.

···

“Hal E. Fulton” hal9000@hypermetrics.com wrote:


Tabby