Symbolify (#169)

Here is my solution. It’s not really outstanding on any front, but it
works and
it’s my first Ruby Q. submission.

def symbolify(i)
i.zero?? “??-??”:"-"+("(?(-?))-"*i).chop
end

Also, I added this part for fun:

require ‘mathn’
def symbolify_short(i)
return “??-??” if i.zero?
factors = i.prime_division
factors.inject("") do |string,pair|
string << “(” << symbolify(pair.first) << “)**(” <<
symbolify(pair.last) <<
“)*”
end.chop
end

-Dana

On Jul 11, 2008, at 9:17 AM, Matthew M. wrote:

Symbolify (#169)

a full-on cheat:

cfp:~/src/ruby > cat a.rb

impl

def symbolify i;def (s=i.to_s).delete _;‘’;end;s;end

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!”

cfp:~/src/ruby > time ruby a.rb
Passed!

real 0m0.026s
user 0m0.021s
sys 0m0.005s

a @ http://codeforpeople.com/

Here’s a fairly straightforward solution, this passes the tests and
works
for both positive and negative integers:

def symbolify(i)
digits = [
“?(-?(”,
“?)-?(”,
“?-?(",
"?–?
”,
“(?-?()(?-?()",
“?–?(”,
"(?–?
)(?-?()”,
“(((?-?()(?-?())(?-?())-(?)-?()",
"((?
-?()(?-?())(?-?()”,
“((?-?()(?–?())-(?)-?()”,
“(?-?()(?–?()”
]

if i < 0
“-(#{symbolify(-i)})”
else
if i < 9
digits[i]
else
i.abs.to_s.split(//).map {|digit| digits[digit.to_i]}.inject(nil)
{
|answer, rep| answer ? “((#{rep})–(#{answer})*(#{digits[10]}))”: rep }
end
end
end

The basic approach is to generate an expression which works like a
lexical
scan of the decimal representation of the (positive) integer, i.e. it’s
the
closed form of

val = 0
i.to_s(10).split(//).each |digit|
val = val * 10 + digit.to_i
end

except the the digits are represented by expressions following the
rules.

For the positive integers <= 1000 the longest string generated was 157
characters for i = 777.

For the negative integers >= 1000 the longest string generate was 160
characters for i = -777 (i.e) the same string wrapped in parentheses
preceded by a -

Rick DeNatale

My blog on Ruby
http://talklikeaduck.denhaven2.com/

My previous post didn’t work for i=0, this one does:

def symbolify(i)
“??-??”+"–?)-?("*i
end

Is it awful at this point to say that I just don’t get it? How does
eval on
these curious looking strings end up giving you an interger?

On Jul 13, 2008, at 18:45 , Rick DeNatale wrote:

The basic approach is to generate an expression which works like a
lexical
scan of the decimal representation of the (positive) integer, i.e.
it’s the
closed form of

My first version did roughly the same thing, but against the binary
representation:

15 = 0b1111 = “2**3+4+2+1”.encode

encode would substitute + for – and gsub numbers in from the table.
Powers of 2 were precalculated as were 0-9.

I also benchmarked and figured out that it was more often (roughly 55%
of the time) faster and a smaller result if I subtract the difference
between the next higher power of two and the number in question.

Regardless, answers got messy…

Wow, so ?? gives you the ASCII code for the ? character. That’s
awesome.
Now I understand :slight_smile:

On Mon, Jul 14, 2008 at 10:31 AM, Frederick C. <

On 14 Jul 2008, at 10:25, Paul S. wrote:

Is it awful at this point to say that I just don’t get it? How does
eval on
these curious looking strings end up giving you an interger?

Well you’ve got multiplication, exponentiation and substraction/unary
minus (ie you’ve got addition) and parentheses. So they only thing
missing is getting some actual numbers to multiply together and so on.
Try evaluating ??, ?-, ?* etc… in the console :slight_smile:

Fred

Try evaluating ??, ?-, ?* etc… in the console :slight_smile:

Unfortunately(??), this doesn’t work with ruby19 though. In ruby19, ?
( evaluates to “(”.

irb(main):001:0> ?(.class
=> String

In irb 1.8:
irb(main):001:0> ?(.class
=> Fixnum

Symbolify (#169)

Fairly straightforward; handles negative and positive. I tried for the
shortest resulting encoding but fell a little short compared to some of
the other results . Thats likely due to my use of addition instead of
multiplication.

def symbolify(j)
i = j.abs
add = “–”
unless $nums
code = {?? => “??”, ?- => “?-”, ?) => “?)”, ?( => “?(”, ?* =>
“?"}
$nums = {}
code.keys.each do |x|
code.keys.each do |y|
$nums[x-y] = “%s-%s” % [code[x], code[y]]
$nums[x
y] = “%s*%s” % [code[x], code[y]]
$nums[xy] = "%s%s” % [code[x], code[y]]
end
end
end

if $nums[i]
    eq = "%s%s%s" % [j < 0 ? "-(" : "", $nums[i], j < 0 ? ")" : ""]
    return eq
end

values = {}
remove = 0
$nums.keys.sort.reverse.each do |num|
    next unless num > 1
    if num < i and i % num == 0
        return "%s(%s)*(%s)" % [j<0 ? "-" : 

“”,$nums[num],symbolify(i/num)]
end
pow = 0
pow += 1 while numpow <= i
values[num
(pow-1)] = [num,pow-1]
remove = num**(pow-1) if remove < num**(pow-1)
end

base,pow = values[remove]
equation = "(%s)**(%s)" % [$nums[base], symbolify(pow)]
equation << add + symbolify(i-remove) if i - remove > 0
j < 0 ? "-(" + equation + ")" : equation

end

Still I failed to convince eval() to back my string to original numbers,
but some folks’re talk 'bout ASCII codes

The point is that in ruby 1.8 something like ?( denoted the character
‘(’ but this really is only a fixnum (40) – as it was already
described by others.

The task is: you have
the following symbols/numbers

irb(main):002:0> p ??, ?-, ?*, ?), ?(
63
45
42
41
40

the operations *, - (with – being +)
and parentheses.

Use this to build any number.

E.g. 1:
irb(main):004:0> eval(’?)-?(’) # ~~ 41 - 40
=> 1

This is something slightly different than recoding a decimal number to
base-5 and using symbols instead of digits.

It took me some time to figure this out myself. It was really a nice
idea and an excellent quiz.

Thank you for the explanation

On 2008/07/15, at 0:30, ThoML wrote:

E.g. 1:
irb(main):004:0> eval(’?)-?(’) # ~~ 41 - 40
=> 1

ASCII code themselves are good old familiar things but
the idea that the numbers also operate as Operators
is quite over my head ;-(

I’m pretty confident on Context Switching, but
this one is too fine grained…(to me)

It was really a nice idea and an excellent quiz.

Yes, I agree. Good education to me: impressed;
still some sorrow to me
it’ll took quite long to digest&utilize…

=============================
ContextSwitcher

     Shindo  Motoakira
<[email protected]>

=============================

Excuse me again(^_^;)

Thanks to the post;
–> On 2008/07/14, at 10:45, Rick DeNatale wrote:
being inspired&encouraged, I made refinements to my code;

Still I failed to convince eval() to back my string to original numbers,
but some folks’re talk 'bout ASCII codes, I’m not too far to the punch
line.

but after long long the other-way-'round, sigh…

Making wish this help somebody.

I’m now going to sleep…

== source follows ==
#!/usr/bin/env ruby -Ku
Base = 5

def i_to_penta(i, penta)

think of only Positive numbers

p = i / Base
if 0 < i
q = i % Base
penta << q
if p < Base
penta << p
else
i_to_penta(p, penta)
end
end
end

def penta_to_sym(penta)
outlet = []

penta.reverse.each { |msd|

penta.each { |msd|
case msd
when 0

outlet << ‘(’

outlet << ‘-’

  outlet << '?'
when 1

outlet << ‘)’

  outlet << '*'
when 2

outlet << ‘(’

outlet << ‘*’

  outlet << '-'
when 3

outlet << ‘?’

outlet << ‘-’

outlet << ‘*’

  outlet << '('

outlet << ‘)’

when 4

outlet << ‘(’

  outlet << ')'

outlet << ‘?’

outlet << ‘-’

else
  outlet << '!'
end

}
outlet
end

def symb1(i)
penta = Array.new
i_to_penta(i, penta)
outlet = penta_to_sym(penta)
end

def symbolify(i)
outlet = symb1(i)
#outlet
s = outlet.to_s
end

puts symbolify(ARGV[0].to_i)

== source ends ==

=============================
ContextSwitcher

     Shindo  Motoakira
<[email protected]>

=============================

Here’s mine solution (CHEATING)

def symbolify(i)
k = String.new("#{i}")
def k.is_a?©; true; end;
def k.delete(s); [] end;
return k;
end

On Fri, Jul 11, 2008 at 6:12 PM, ara.t.howard [email protected]
wrote:
Great Quiz indeed, but just coming back from vacations the fun stuff
has already be done.

BTW Ara ?* forever :wink:

Cheers
Robert

On 7/14/08, -j b- [email protected] wrote:

Symbolify (#169)

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

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

Fairly straightforward; handles negative and positive. I tried for the
shortest resulting encoding but fell a little short compared to some of
the other results .

My solution tries for the absolute shortest encoding without cheating.
That makes it pretty slow, so I added some optional optimizations to
help it run faster.
Without the ** operator, I get

(0…1000).inject(‘’){|s,i|s+=symbolify(i)}.length == 16001

-Adam

---- symbolify.rb —
class Symbolifier
def initialize opt_lvl=0,max=nil
@strings={} # @strings[n] = [symbolify(n),t]
@values = {} # @values[x] = [all n such that symbolify(n).size == x]
@todo = {}
@newlengths = {}
@optimization = opt_lvl
@max = max&&max2 #store values 2x as big as max so we can subtract
insert(%w{ ?? ?- ?
?) ?(}.map{|s|[s,:digit]})
update_todo
end

def [] x
rec = @strings[x]
p :EXP,rec if rec&&rec[1]==:exp

return rec[0] if rec
rec = @strings[-x]
if rec
  r=(rec[1]==:add) ? '-('+rec[0]+')' : '-'+rec[0]
  return r.sub(/^--/,'')
end
return rec if rec=gen_alternates(x) if @optimization>=2
until (rec=generate(x))
  return rec if rec=gen_alternates(x) if @optimization>=1
end
return rec

end

private
def add_syms s1,s2
[((s2[0]==?-)? “%s%s”:“%s–%s”)%[s1,s2],:add]
end
def sub_syms s1,s2,t2
[((t2==:add)? “%s-(%s)”:“%s-%s”)%[s1,s2],:add]
end
def mul_syms s1,s2,t1,t2
ss=“%s*%s”
ss = “(%s)*%s” if (t1==:add)
ss[-2…-1]=“(%s)” if (t2==:add)
[ss%[s1,s2],:mul]
end
def exp_syms s1,s2
[“(%s)**(%s)”%[s1,s2],:exp]
end

def store v,rep
(@values[rep[0].size]||=[])<<v
@strings[v] = rep
@newlengths[rep[0].size]=true
#~ p :EXP,rep if rep[1]==:exp
end

def insert newsyms
newsyms.each{|s|
if (0 > v=eval(s[0]))
v=-v
s[0]=(s[1]==:add) ? ‘-(’+s[0]+‘)’ : ‘-’+s[0]
end
next if @max && v>@max
if !@strings[v]
store(v,s)
elsif (@strings[v][0].size > s[0].size)
@values[@strings[v][0].size].delete(v)
store(v,s)
end
}
end

def generate(target)
a_idx,b_idx,newlen = 0,0,Float::MAX
@todo.each{|k,a| if (k+a[0]<newlen)
a_idx,b_idx = k,a[0]
newlen = a_idx+b_idx
end
}
@todo[a_idx].delete(b_idx)
p “generating strings of length>= #{newlen+1} (#{a_idx}+#{b_idx}+1)”
newvals=[]
@values[a_idx].each{|v1|
@values[b_idx].each{|v2|
s1,t1 = @strings[v1]
s2,t2 = @strings[v2]
newvals<< add_syms(s1,s2)
newvals<< sub_syms(s1,s2,t2)
newvals << mul_syms(s1,s2,t1,t2)

REMOVE following line for significant speedup

    newvals <<exp_syms(s1,s2)
  }
}
insert(newvals)
update_todo
f=@strings[target]
p :EXP,f if f&&f[1]==:exp

return f[0] if f

end

def gen_alternates(x)
newvals=[]
len,alt = 3e30,nil
(1…5).each{|i|
s1,t1=@strings[i]
if (s1)
s2,t2 = @strings[x-i]
newvals<< add_syms(s1,s2) if (s2)
s2,t2 = @strings[x+i]
newvals<< sub_syms(s2,s1,t1) if (s2)
s2,t2 = @strings[x/i]
m,tm=@strings[x%i]
if (s2 && m)
s3,t3 = mul_syms(s1,s2,t1,t2)
newvals<< add_syms(s2,m)
end
end
}
insert(newvals)
update_todo
f=@strings[x]
return f[0] if f
end

def update_todo
@newlengths.keys.each{|len|@todo[len]||=[]
@todo.each{|k,a| a<<len if k<=len;a.sort!.uniq!}
}
@newlengths={}
end
end

def symbolify x
$ymbolifier ||= Symbolifier.new

CHANGE TO

$ymbolifier ||= Symbolifier.new opt_level_1_or_2,max_input

for faster performance

return $ymbolifier[x]
end

On Sun, Jul 13, 2008 at 6:08 PM, Matthew M. [email protected]
wrote:

But this is brilliant Matt, why cheat, we can do this without cheating
too :wink:

@digits = %w{ ??-?? ?)-?( ?-?( ?–? ?–?) ?–?( }

def symbolify i
s = i.to_s( 5 ).split( // )
f = s.shift
s.inject( @digits[f.to_i] ){ |so_far, b|
“(#{so_far})*(” << @digits[ 5 ] << “)–” << @digits[ b.to_i ]
}
end

Cheers
Robert

Robert D. wrote:

On Fri, Jul 11, 2008 at 6:12 PM, ara.t.howard [email protected] wrote:
Great Quiz indeed, but just coming back from vacations the fun stuff
has already be done.

BTW Ara ?* forever :wink:

Define forever :stuck_out_tongue:

$ ruby19 -v -e 'p ?
ruby 1.9.0 (2007-12-25 revision 14709) [i686-linux]
"
"