Skip to content

Instantly share code, notes, and snippets.

@vznvzn
Created October 5, 2018 04:42
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/505806e19d349950028c71b85739548b to your computer and use it in GitHub Desktop.
Save vznvzn/505806e19d349950028c71b85739548b to your computer and use it in GitHub Desktop.
require 'fileutils'
def f1(n)
n = (n * 3 + 1) / 2 while (n.odd?)
n /= 2 while (n.even?)
return n
end
def f2(n)
return n.odd? ? (n * 3 + 1) / 2 : n / 2
end
def d(s)
c = s.split('').select { |x| x == '1' }.size
d = c.to_f / s.length
return d
end
def widthdiff(x, y)
x.to_s(2).length - y.to_s(2).length
end
def widthratio(x, y)
y.to_s(2).length.to_f / x.to_s(2).length
end
def lsb1run(ns)
s = ns.reverse
i = (0...s.length).to_a.index { |x| s[x, 1] == '0' }
i = s.length if (i.nil?)
return i
end
def disordered(l)
l1 = []
j = nil
l.each_with_index \
{
|x, i|
l1 << d(x.to_s(2))
l1.shift if (l1.size == 3)
next if (!(l1.size == 2 && l1[0] * l1[1] < 0))
j = i
break
}
return j.nil? ? l : l[0..j]
end
def mono(l)
i = 0
mn = l[i]
m = {'i' => 0, 'j' => 0, 'mx' => 0}
(1...l.size).each \
{
|j|
i, mn = [j, l[j]] if (l[j] < mn)
mx2 = j - i
m = {'i' => i, 'j' => j, 'mx' => mx2} if (mx2 > m['mx'])
}
return {'l2' => l.size}.merge(m)
end
def sum(l)
t = 0.0
l.each { |x| t += x }
return t
end
def avg(l)
return nil if (l.empty?)
return sum(l) / l.size
end
def len01(ns)
nl = ns.length
l1 = ns.split(/0+/).map { |x| x.length }
l2 = ns.split(/1+/)[1..-1]
l2 = [''] if (l2.nil?)
l0 = l2.map { |x| x.length }
return l0, l1
end
def amx(ns)
l0, l1 = len01(ns)
l = l0 + l1
return {'a' => avg(l), 'mx' => l.max}
end
def avg01(ns)
return avg(l0 + l1)
end
def count(x, l = nil)
n = n1 = x['n']
l = [] if (l.nil?)
l << n
while (n != 1)
n = $f.call(n)
l << n
end
# l = disordered(l)
n1 = l.first
cm1 = (0...l.size).max_by { |x| l[x] }
b = cm1
b += 1 while (l[b] > n1)
# mxl = mono(l[0..cm1])['mx']
# mxr = mono(l[cm1..b])['mx']
d = d(ns = n1.to_s(2))
# mx1l = l[0..cm1].map { |x| lsb1run(x.to_s(2)) }.max
# mx1r = l[cm1..b].map { |x| lsb1run(x.to_s(2)) }.max
ll = l[0..cm1].map { |x| x.to_s(2) }
lr = l[cm1..b].map { |x| x.to_s(2) }
amx01l = ll.map { |x| amx(x) }
amx01r = lr.map { |x| amx(x) }
return {'n' => x['n'],
'ns' => ns,
'd' => d - 0.5,
'da' => (d - 0.5).abs,
# 'mxl' => mxl,
# 'mxr' => mxr,
# 'mx1l' => mx1l,
# 'mx1r' => mx1r,
'mx01l' => amx01l.map { |x| x['mx'] }.max,
'mx01r' => amx01r.map { |x| x['mx'] }.max,
'a01l' => avg(amx01l.map { |x| x['a'] }),
'a01r' => avg(amx01r.map { |x| x['a'] }),
'b' => b,
'c' => l.size,
'cm1' => cm1,
'p' => x['p'],
'nw' => ns.length,
'w' => widthdiff(l[cm1], n1),
'r' => widthratio(l[cm1], n1),
}
end
def out(a, a2 = {}, ti = nil, t = '')
fn = "#{Dir.pwd}/out#{ARGV[0]}.txt"
k = a.keys.sort - a2.select { |k, v| v.nil? }.keys
if ($f1.nil?) then
$f1 = File.open(fn, 'w')
$f1.puts(a.keys.join("\t"))
f2 = File.open('gnuplot.cmd', 'w')
st = ti.nil? ? 'unset title; ' : "set title '#{ti}'; "
f2.puts("set ytics nomirror; set y2tics; set y2range [-1:1]; set colors classic; set key top left; #{st}; plot \\")
a.keys.each \
{
|x|
next if (!k.member?(x))
li = x != 'd' ? 'line' : 'impulse'
f2.puts("'#{fn}' using #{t}(column('#{x}')) with #{li} title '{/:Bold #{x}}' #{a2[x]}, \\")
}
f2.puts
f2.close
end
$f1.puts(a.values.join("\t"))
$f1.flush
end
def next2(z, l, k, ti)
out(z, Hash[[k, ['lw 2'] * k.size].transpose].merge({'n' => nil,
'ns' => nil,
'da' => nil,
't' => nil,
'p' => nil,
'r' => 'axes x1y2',
'd' => 'axes x1y2'}), ti, "(column('t')):") if (z['t'] % 10 == 0)
p = z['p'] + 1
l << [z, count({'n'=>z['n'] + 2 ** p, 'p'=>p}).merge({'t' => z['t']}), z.merge({'p'=>p})]
return
end
def order2(l, k)
l2 = []
k.each_with_index \
{
|k1, n|
s = 1
k1, s = [k1[0..-2], -1] if (k1[-1, 1] == '-')
l2[n] = (0...l.size).sort_by { |x| -l[x][1][k1] * s }
}
l3 = (0...l.size).map { {} }
k.each_with_index \
{
|k1, n|
l2[n].each_with_index { |i, j| l3[i][k1] = j }
}
l3.each { |x| x['z'] = sum(x.values) }
return (0...l3.size).sort_by { |x| l3[x]['z'] }
end
def hard(k, c, n = nil)
srand(n) if (!n.nil?)
$f1 = nil
l = []
ti = "n=#{n} k=#{k.inspect} c=#{c}"
$stderr.puts("\n#{ti}")
next2(count({'n' => 1, 'p' => 0}).merge({'t' => 0}), l, k, ti)
add = nil
seen = {}
f = File.open($fn, 'w')
1e4.to_i.times \
{
|t|
l1 = order2(l, k)
a = {'t1' => t, 'l1' => l.size, 'c' => seen.size}.merge(l[l1[0]][1])
if (!seen.member?(a['n'])) then
seen[a['n']] = nil
f.puts(a)
f.flush
end
$stderr.puts(a.select { |k2, | !['n'].member?(k2)}) if (t != 0 && t % 2000 == 0)
i = l1[rand([l1.size, c].min)]
z = l.delete_at(i)
[z[1], z[2]].each { |x| next2(x.merge({'t' => t}), l, k, ti) }
l.delete_at(l1[-1]) if (l.size > 2000)
}
f.close
end
def rerun()
f = File.open('gnuplot.cmd', 'w')
d1 = 'out'
if (ARGV[0].nil?) then
FileUtils.rm_rf(d1)
Dir.mkdir(d1)
n = 1
else
l = Dir.glob("#{d1}/*").map { |x| x.split('/')[1].to_i }.sort
n = l.empty? ? 1 : l.last + 1
end
d = Dir.pwd + '/' + d1
loop \
{
dn = "#{d}/#{n}"
Dir.mkdir(dn)
Dir.chdir(dn)
f.puts("load '#{dn}/gnuplot.cmd'; pause -1;")
f.flush
$fx.call(n)
n += 1
}
end
def plot(fn, op, ln)
f = File.open('gnuplot2.cmd', op)
ln.each { |x| f.puts(x) }
f.close
end
def vars(m, vs)
vs.map \
{
|v|
"'out#{m}.txt' using (column('t')):(column('#{v}')) title '#{v}' with line axes x1y#{m + 1},\\"
}
end
$f = lambda { |x| f2(x) }
$fn = 'mixdb.txt'
fx = []
fx[0] = lambda { |n| hard(['a01l-', 'a01r-', 'cm1', 'b', 'w'], 50, n) }
fx[1] = lambda { |n| hard(['mx01l-', 'mx01r-', 'cm1', 'b', 'w'], 50, n) }
m = ARGV[0].to_i
$fx = fx[m]
cmd = [["set colors classic; set ytics nomirror; set y2tics; set key bottom right; plot \\",
vars(0, ['a01l', 'a01r'])],
[vars(1, ['mx01l', 'mx01r'])]]
plot('gnuplot2.cmd', ['w', 'a'][m], cmd[m])
$fx.call(1)
#rerun()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment