Skip to content

Instantly share code, notes, and snippets.

@vznvzn
Created November 9, 2015 18:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vznvzn/dffe25a601bd8b90e7bd to your computer and use it in GitHub Desktop.
Save vznvzn/dffe25a601bd8b90e7bd to your computer and use it in GitHub Desktop.
#!/usr/bin/ruby1.8
def fs()
lo = [lambda { |n| n * 3 + 1 }, lambda { |n| (n * 3 + 1) / 2 },
lambda { |n| n = (n * 3 + 1) / 2 while (n.odd?); n }]
le = [lambda { |n| n / 2 }, lambda { |n| n /= 2 while (n.even?); n }]
l = []
lo.each \
{
|o|
le.each \
{
|e|
next if (o == lo.last && e == le.last)
l << lambda \
{
|n|
n = o.call(n) if (n.odd?)
n = e.call(n) if (n.even?)
n
}
}
}
return l
end
def dense(n)
s = n.to_s(2)
c = 0
s.length.times \
{
|i|
c += s[i, 1].to_i
}
return c.to_f / s.length
end
def widthdiff(x, y)
x.to_s(2).length - y.to_s(2).length
end
def widthratio(x, y)
x.to_s(2).length.to_f / y.to_s(2).length
end
def f(n, w)
n1 = n
c = 0
l = [n]
cg = nil
while (n != 1)
n = $f.call(n)
l << n
c += 1
cg = c if (cg.nil? && n < n1)
break if (!cg.nil? && w != 'c')
end
cm = (0...l.size).max_by { |x| l[x] }
return {'cm' => cm,
'cg' => cg.nil? ? 0 : cg,
'm' => l[cm].to_s(2).length,
'w' => widthdiff(l[cm], n1),
'r' => widthratio(l[cm], n1),
'c' => l.size,
'd' => (0.5 - dense(n1)).abs}
end
def long(m, w)
return {'n' => rand(2 ** m) | 1 } if (w == 'z')
l = [{'n' => 1, 'p' => 0}.merge(f(1, w))]
t = 0
e = 2000
loop \
{
l = l.sort_by { |x| [x[w], -x['d']] }.reverse
x = l.delete_at(rand([l.size, 20].min))
p2 = x['p'] + 1
n2 = x['n'] + 2 ** p2
x1 = x.dup
x1['p'] = p2
l << x1
x2 = {'n' => n2, 'p' => p2}.merge(f(n2, w))
l << x2
t += 1
w2 = w
if (w == 'r') then
z = l.sort_by { |x| x['n'] }.reverse[0...100].max_by { |x| x['r'] }
w2 = 's'
else
z = l.max_by { |x| x[w] }
end
z.merge!({ 't' => t, 's' => t.to_f / e })
return z if (z[w2] >= m)
return if (t >= e)
}
end
def stat(l)
return 0, 0, 0 if (l.empty?)
t = t2 = 0
l.each \
{
|x|
t += x
t2 += x ** 2
}
c = l.size
a = t.to_f / c
z = t2.to_f / c - a ** 2
sd = Math.sqrt(z < 0 ? 0 : z)
raise if (sd.nan?)
return a, sd, l.max
end
def seed(p, k, m)
r = p[k]
a, b = r
x = a + m * (b - a)
z = long(x, k)
return z
end
def run1(n)
l = []
while (n != 1)
n = $f.call(n)
ns = n.to_s(2)
m0 = stat(ns.split(/1+/).map { |x| x.length })
m1 = stat(ns.split(/0+/).map { |x| x.length })
l << [ns.length, m0, m1, dense(n)].flatten
end
return l
end
def sum(l)
m = l.map { |l2| l2.size - 1 }
mx = m.max
l1 = []
(0..mx).each \
{
|x|
t = [0] * l[0][0].size
l.each \
{
|l2|
i = (x.to_f / mx * (l2.size - 1)).to_i
l2[i].size.times { |j| t[j] += l2[i][j] }
}
puts(t.map { |x| x.to_f / l.size }.join("\t"))
}
end
p = {'p' => [0, 350],
'c' => [0, 1200],
'w' => [0, 75],
'm' => [0, 300],
'cg' => [0, 350],
'cm' => [0, 200],
'r' => [0.0, 1.0],
'z' => [0, 1000],
}
$f = fs()[0]
l = []
1000.times \
{
|i|
z = seed(p, 'w', 0.25)
next if (z.nil?)
$stderr.puts([i, z['s'], z['n'].to_s(2)].inspect)
l << run1(z['n'])
}
sum(l)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment