[QUIZ] Symbolify (#169)

M

Matthew Moss

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

The three rules of Ruby Quiz 2:

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 2 by submitting ideas as often as you can! (A
permanent, new website is in the works for Ruby Quiz 2. Until then,
please visit the temporary website at

<http://splatbang.com/rubyquiz/>.

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.

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

## Symbolify (#169)

Your task this week is to count. Yup, that's it.

Oh, by the way... You may only use the characters `?`, `*`, `(`, `)` and `-`.

Specifically, define a function `symbolify` that accepts an integer
and returns a string composed of only the five characters shown above.
The string, when evaluated, will equal the original number passed in.

That is, the following test code should raise no exceptions:

1000.times do |i|
s = symbolify(i)
raise "Not a string!" unless s.is_a? String
raise "Invalid chars!" unless s.delete("?*()-").empty?

x = eval(s)
raise "Decode failed!" unless i == x
end


There are at least a few different approaches that come to mind, so
don't expect everyone to have the same output. Well, not before the
output is passed through `eval`, that is.

I am not requiring that you produce the shortest string (though you
are welcome to attempt such a thing). The only thing I _do_ ask is
that you not produce megabytes of data to represent a simple integer.

P.S. Cheating is encouraged (except that you may not write code
outside of `symbolify`).
 
A

ara.t.howard

That is, the following test code should raise no exceptions:

1000.times do |i|
s = symbolify(i)
raise "Not a string!" unless s.is_a? String
raise "Invalid chars!" unless s.delete("?*()-").empty?

x = eval(s)
raise "Decode failed!" unless i == x
end

i've got one line - tests pass.

a @ http://codeforpeople.com/
 
J

James Gray

## Symbolify (#169)

Your task this week is to count. Yup, that's it.

Oh, by the way... You may only use the characters `?`, `*`, `(`, `)`
and `-`.

Excellent quiz. Full marks Matthew. ;)

James Edward Gray II
 
J

James Gray

Mine was 28 characters, with normal whitespace usage.

Of course, using my solution, the following code causes Ruby to
Segfault:

eval(symbolify(1200))

James Edward Gray II
 
A

Alex LeDonne

Mine was 28 characters, with normal whitespace usage.

James Edward Gray II

I managed to golf one char out of my first solution; it's 28 with
"normal whitespace usage", 24 without. The output is ugly and long,
though.


I also have a longer solution that produces relatively compact
representations relatively quickly such that

symbolify(999).length == 145
symbolify(9999).length == 145
symbolify(999999).length == 389
symbolify(12345678901234567890).length == 1290
symbolify(("9"*2100).to_i).length == 402035

-A
 
M

Matthew Moss

## Symbolify (#169)
Excellent quiz. =A0Full marks Matthew. =A0;)

Somehow, with all the comparisons of how small solutions are, methinks
there are other techniques that I hadn't considered. Mine own solution
is short, but not *that* short.

Though I haven't attempted to shrink it yet, so maybe I can make it
smaller... Let's see...

Okay, I can see how this can be seriously abused. But I guess I asked
for it when I said "cheating encouraged!" No worries; it will be
interesting to see how people do. I just wonder if anyone will write a
solution that doesn't cheat. Or perhaps I'm still underestimating your
solutions? Guess I'll see on Monday.
 
J

James Gray

Okay, I can see how this can be seriously abused. But I guess I asked
for it when I said "cheating encouraged!" No worries; it will be
interesting to see how people do. I just wonder if anyone will write a
solution that doesn't cheat. Or perhaps I'm still underestimating your
solutions? Guess I'll see on Monday.

Mine builds strings using just the characters mentioned, so I doubt it
would be classified as cheating.

James Edward Gray II
 
M

Matthew Moss

This is not required extra work... just for a little more fun. I have
some suspicions about some techniques, what I call "ugly" cheats (as
opposed to the "pretty" cheats who ignored you in high school... umm,
ignore that last part).

Anyway, here's another test:

nums = (0...1000).sort_by { rand }
strs = nums.map { |n| symbolify(n) }

strs.zip(nums).sort_by { rand }.each do |str, num|
res = eval(str)
raise "Not a string!" unless str.is_a? String
raise "Invalid chars!" unless str.delete("?*()-").empty?
raise "Decode failed!" unless res == num
end

puts "Passed!"


This might affect some, maybe not others. I wrote two solutions, one
classified as "pretty" while the other is "ugly" (i.e. fails this
test). Again, you're not required to pass this... Looking at some ugly
solutions will certainly be okay.

Interestingly, my pretty solution confuses IRB. If I run on the
command line:
ruby -r moss test.rb
Passed!

However, if I start up irb:
require 'moss' => true
symbolify(60)

Then I get a nice stack crawl (not gonna show yet, spoiler) that ends
in "Maybe IRB bug!!!". (I imagine you guys can guess what I'm
doing...)
 
M

Matthew Moss

Shortly after posting this, I realize that there could easily be ugly
cheats that pass this test as well...

You'd think I know Ruby a little better at this point in time... =)
 
A

Alex LeDonne

I managed to golf one char out of my first solution; it's 28 with
"normal whitespace usage", 24 without. The output is ugly and long,
though.


I also have a longer solution that produces relatively compact
representations relatively quickly such that

symbolify(999).length == 145
symbolify(9999).length == 145
symbolify(999999).length == 389
symbolify(12345678901234567890).length == 1290
symbolify(("9"*2100).to_i).length == 402035

After clearing a "duh" moment, I've improved these encoded lengths...
symbolify(999).length == 127
symbolify(9999).length == 127
symbolify(999999).length == 337
symbolify(12345678901234567890).length == 1112
symbolify(("9"*2100).to_i).length == 350265

-A
 
W

Wouter Smeenk

2008/7/11 James Gray said:
Mine was 28 characters, with normal whitespace usage.

James Edward Gray II

I managed to squeeze my solution in 19 characters and 23 with normal
whitespace usage.

Wouter Smeenk
 
C

Chris Shea

Anyway, here's another test:

  nums = (0...1000).sort_by { rand }
  strs = nums.map { |n| symbolify(n) }

  strs.zip(nums).sort_by { rand }.each do |str, num|
    res = eval(str)
    raise "Not a string!"  unless str.is_a? String
    raise "Invalid chars!" unless str.delete("?*()-").empty?
    raise "Decode failed!" unless res == num
  end

  puts "Passed!"

I've done some translating of these tests into test/unit (and some
meta-programming to help me test multiple solutions easily. Here's
what the end of my solution file looks like:

###
require 'test/unit'

class TestSymbolify < Test::Unit::TestCase
@test_number = 1

def self.solution_test(module_name, range, test=:delayed_eval_tests)
class_eval <<-EOD
def test_#{@test_number}_#{module_name.to_s.gsub('::','_')}
Object.send:)include, #{module_name})
#{test}(#{range})
end
EOD
@test_number += 1
end

def symbolify_assertions_for(string, integer)
assert_kind_of(String, string)
assert_match(/\A[?*()-]*\Z/, string)
assert_equal(integer, eval(string))
end

def cheat_friendly_tests(range)
range.each do |i|
s = symbolify(i)
symbolify_assertions_for(s,i)
end
end

def delayed_eval_tests(range)
nums = range.sort_by { rand }
strs = nums.map { |n| symbolify(n) }

strs.zip(nums).sort_by { rand }.each do |s, i|
symbolify_assertions_for(s,i)
end
end

# The actual tests
solution_test(Symbolify::Integers, -1000..1000)
solution_test(Symbolify::NaturalNumbers, 0..1000)
solution_test(Symbolify::Cheating,
-1000..1000, :cheat_friendly_tests)
end
###

It might be a little much... but I *was* having fun.

Chris
 

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,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top