Skip to content

Instantly share code, notes, and snippets.

@vznvzn
Created December 30, 2018 19:18
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/a1ae84872d812d63ffc535ad0fc19e03 to your computer and use it in GitHub Desktop.
Save vznvzn/a1ae84872d812d63ffc535ad0fc19e03 to your computer and use it in GitHub Desktop.
def f2(n)
return n.odd? ? (n * 3 + 1) / 2 : n / 2
end
def dense(w, d)
w2 = w - 1
a = (0...w2).to_a
s = '0' * w2
(1..(d * w - 1)).map { a.delete_at(rand(a.size)) }.each { |x| s[x, 1] = '1' }
return ('1' + s)
end
def d(s)
c = s.split('').select { |x| x == '1' }.size
d = c.to_f / s.length
return d
end
def e(ns)
l1 = ns.split(/0+/)
l0 = ns.split(/1+/)
l0 = [''] if (l0.nil?)
return (l0 + l1).size.to_f / ns.length
end
def initr(w, m)
l = []
b = 1
while (w > 0)
t = [w, m].min
r = (t <= 1) ? 1 : rand(t) + 1
l << [b] * r
b ^= 1
w -= r
end
s = l.flatten.join
return s
end
def initd(w, m)
d = m.to_f / w
w2 = w - 1
a = (0...w2).to_a
s = '0' * w2
(1..(d * w - 1)).map { a.delete_at(rand(a.size)) }.each { |x| s[x, 1] = '1' }
return ('1' + s)
end
def initb(w, m)
r = m.to_f / w
return '1' + (1...w).map { rand < r ? '0' : '1' }.join
end
def initr2(w, m, b)
l = []
while (w > 0)
t = [w, m].min
r = (t <= 1) ? 1 : rand(t) + 1
l << [b] * r
b ^= 1
w -= r
end
s = l.flatten.join
return s
end
def initw(w, m)
w -= 2
m = [w, m].min
i = rand([w - m, 1].max)
j = w - i - m
b = rand(2)
ns = initr2(i, rand([i - 1, 1].max) + 1, b ^ 1).reverse + ([b] * m).join + initr2(j, rand([j - 1, 1].max) + 1, b ^ 1)
s = '1' + (ns[0].to_i ^ 1).to_s + ns
return s
end
def mut(ns)
ns = ns.dup
i = rand(ns.length - 1) + 1
ns[i, 1] = (ns[i, 1].to_i ^ 1).to_s
return ns
end
def inner(ns1, ns2)
a, b = [ns1, ns2].sort_by { |x| x.length }
d = b.length - a.length
i = rand(d + 1)
c = b.dup
c[i, a.length] = a
ns1.replace(b)
ns2.replace(c)
end
def mix(ns1, ns2)
ns1 = ns1.dup
ns2 = ns2.dup
inner(ns1, ns2)
return (0...ns1.length).map { |x| [ns1, ns2][rand(2)][x, 1] }.join
end
def cut(ns1, ns2)
ns1 = ns1.dup
ns2 = ns2.dup
inner(ns1, ns2)
i = rand(ns1.length)
return ns1[0...i] + ns2[i..-1]
end
def ext(ns)
return (0..rand(3)).map { rand(2) }.join.to_i.to_s + ns
end
def count(ns, a = {})
l1 = []
n1 = n = ns.to_i(2)
while (n >= n1)
l1 << n
n = f2(n)
end
nl = ns.length
cm = (0...l1.size).max_by { |x| l1[x] }
a['l1'] = l1
na = l1[nl]
na = 0 if (na.nil?)
w1 = na.to_s(2).length
w2 = l1[cm].to_s(2).length
w21 = w2 - w1
w21 = -w21 if (cm < nl)
return {
'd' => d(ns),
'e' => e(ns),
'cm' => cm,
'cg' => l1.size,
'nl' => nl,
'z' => w21 * 10
}
end
def fmt(msg, x)
t = msg.member?(x) ? Time.now.to_i - msg[x] : 0
m = t / 60
s = t % 60
msg[x] = "#{m}m #{s}s"
end
def clock(msg)
msg2 = msg.dup
['t', 't1'].each { |x| fmt(msg2, x) }
return msg2
end
def add(h, ns, seen, msg, f)
return if (seen.member?(ns))
seen[ns] = nil
x = {'ns' => ns}.merge(count(ns))
return if (!x.member?('z'))
j = ns.length
h[j] = [] if (!h.member?(j))
a, b = [h[j][0], h[j][-1]]
h[j] = h.fetch(j, []) + [x]
h[j].sort_by! { |x| -x['z'] }
h[j][50..-1] = [] if (h[j].size > 50)
if (msg['a1'].nil? || x['z'] > msg['a1']['z']) then
msg['a1'] = x
puts("==>\t" + clock(msg).inspect)
msg['t1'] = Time.now.to_i
msg['tz'] = 60
end
msg['t0'] = Time.now.to_s
msg['s'] = seen.size
msg['hc1'] = h.size
msg['hc2'] = h.map { |k, v| v.size }.inject(0){ |t, x| t + x }
if (a.nil? || h[j][0]['z'] != a['z']) then
msg['a'] = h[j][0]['z']
msg['n'] = msg.fetch('n', 0) + 1
f.puts(x)
f.flush
end
if (b.nil? || h[j][-1]['z'] != b['z']) then
msg['b'] = h[j][-1]['z']
end
end
def top(h1)
return h1[rand([h1.size / 4, h1.size].max)]
end
def opt(w1)
h = {}
ops = ['initr0', 'initd0', 'initb0', 'initw0', 'mut1', 'mix2', 'cut2']
ops += ['ext1']
seen = {}
msg = {'t' => Time.now.to_i}
f = File.open('mixdb.txt', 'w')
loop \
{
opc = ops[rand(ops.size)]
c = opc[-1..-1].to_i
op = opc[0..-2]
case (c)
when 0
ns = send(op, w1, rand(w1))
add(h, ns, seen, msg, f)
when 1, 2
redo if (h.empty?)
ks = h.keys.sort_by { |x| -h[x][0]['z'] }
h.delete(ks.pop) if (ks.size > 50)
msg['hmn'], msg['hmx'] = [ks.min, ks.max]
ks = ks[0...[ks.size, ks.size / 4].max]
arg = (0...c).map { ks[rand(ks.size)] }
l = arg.map { |x| top(h[x])['ns'] }
ns = send(op, *l)
ns[0, 1] = '1'
add(h, ns, seen, msg, f)
end
if ((t = Time.now.to_i - msg['t1']) >= msg['tz'])
puts("\t" + clock(msg).inspect)
msg['tz'] += 60
end
# break if (t > 180)
}
f.close
end
def sample(l, c)
return l if (l.size <= c)
r = l.size / c
l2 = *(0...l.size).select { |x| x % r == 0 }
l2[c..-1] = []
return l.values_at(*l2)
end
def review(fn)
l = sample(File.open(fn).readlines.map { |x| Kernel.eval(x) }, 2000)
# l.sort_by! { |x| x['z'] }
f = File.open('gnuplot.cmd', 'w')
f.puts('$dat << eof')
k = l[0].keys
f.puts(k.join("\t"))
l.each \
{
|x|
f.puts(x.values.join("\t"))
}
f.puts('eof')
f.puts('set key top left; plot \\')
(k - ['ns']).each \
{
|x|
y2 = ['e', 'd'].member?(x) ? 'axes x1y2' : ''
y2 = 'lw 2' if (x == 'z')
f.puts("$dat using (column('#{x}')) with line #{y2},\\")
}
f.close
exit
end
fn = 'mixdb.txt'
review(fn) if (File.exist?(fn))
opt(10)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment