-
-
Save mame/08b38f75b7c7d88a8a7c to your computer and use it in GitHub Desktop.
My program for ICFPc 2013. http://icfpc2013.cloudapp.net/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require "net/http" | |
require "json" | |
Net::HTTP.version_1_2 | |
TOKEN = "***" | |
def post(path, body = {}) | |
sleep 1 | |
body = JSON.dump(body) | |
loop do | |
http = Net::HTTP.new("icfpc2013.cloudapp.net", 80) | |
resp = http.post("/#{ path }?auth=#{ TOKEN }vpsH1H", body) | |
if resp.body == "Too many requests" | |
puts "Too many requests. retry..." | |
sleep 5 | |
else | |
return JSON.parse(resp.body) | |
end | |
end | |
end | |
MASK = 0xffffffffffffffff | |
Inputs = [0] + (0..63).map {|i| 1 << i } | |
32.times do |i| | |
Inputs << (("0" * i + "1") * 64)[-64..-1].to_i(2) | |
Inputs << (("0" * i + "1") * 64)[-64..-1].reverse.to_i(2) | |
end | |
srand(0) | |
Inputs.replace(Inputs.uniq) | |
until Inputs.size == 144 | |
Inputs << rand(MASK + 1) | |
Inputs.replace(Inputs.uniq) | |
end | |
MAX_LIMIT = 1000000 | |
Leaf = Struct.new(:val) | |
class Leaf | |
Order = 0 | |
def eval | |
case val | |
when :x then $input | |
when :y then $arg1 | |
when :z then $arg2 | |
else val | |
end | |
end | |
def inspect | |
val.to_s | |
end | |
def fixed | |
@fixed ||= | |
case val | |
when :x, :z then 0 | |
when :y then 0xffff_ffff_ffff_ff00 | |
else MASK | |
end | |
end | |
def static | |
@static ||= | |
case val | |
when :x, :y, :z then 0 | |
else val | |
end | |
end | |
def <=>(other) | |
if other.is_a?(Leaf) | |
return 0 if val == other.val | |
return 1 if val == :z; return -1 if other.val == :z | |
return 1 if val == :y; return -1 if other.val == :y | |
return 1 if val == :x; return -1 if other.val == :x | |
return -1 if val < other.val | |
return 1 | |
else | |
return -1 | |
end | |
end | |
def fv(h) | |
case val | |
when :x, :y, :z then h[val] += 1 | |
end | |
end | |
include Comparable | |
end | |
Leaf0 = Leaf[0] | |
Leaf1 = Leaf[1] | |
LeafInput = Leaf[:x] | |
LeafArg1 = Leaf[:y] | |
LeafArg2 = Leaf[:z] | |
Op1 = Struct.new(:e) | |
class Op1 | |
def <=>(other) | |
o0 = self.class::Order | |
o1 = other.class::Order | |
return o0 <=> o1 if o0 != o1 | |
return e <=> other.e | |
end | |
include Comparable | |
def fv(h) | |
e.fv(h) | |
end | |
end | |
class Not < Op1 | |
Order = 1 | |
def inspect | |
"(not %p)" % [e] | |
end | |
def eval | |
~e.eval & MASK | |
end | |
def fixed | |
@fixed ||= e.fixed | |
end | |
def static | |
@static ||= ~e.static & MASK | |
end | |
end | |
class Shl1 < Op1 | |
Order = 2 | |
def inspect | |
"(shl1 %p)" % [e] | |
end | |
def eval | |
(e.eval << 1) & MASK | |
end | |
def fixed | |
@fixed ||= (e.fixed << 1) & MASK | 1 | |
end | |
def static | |
@static ||= (e.static << 1) & MASK | |
end | |
end | |
class Shr1 < Op1 | |
Order = 3 | |
def inspect | |
"(shr1 %p)" % [e] | |
end | |
def eval | |
e.eval >> 1 | |
end | |
def fixed | |
@fixed ||= (e.fixed >> 1) & MASK | 0x8000_0000_0000_0000 | |
end | |
def static | |
@static ||= e.static >> 1 | |
end | |
end | |
class Shr4 < Op1 | |
Order = 4 | |
def inspect | |
"(shr4 %p)" % [e] | |
end | |
def eval | |
e.eval >> 4 | |
end | |
def fixed | |
@fixed ||= (e.fixed >> 4) & MASK | 0xf000_0000_0000_0000 | |
end | |
def static | |
@static ||= e.static >> 4 | |
end | |
end | |
class Shr16 < Op1 | |
Order = 5 | |
def inspect | |
"(shr16 %p)" % [e] | |
end | |
def eval | |
e.eval >> 16 | |
end | |
def fixed | |
@fixed ||= (e.fixed >> 16) & MASK | 0xffff_0000_0000_0000 | |
end | |
def static | |
@static ||= e.static >> 16 | |
end | |
end | |
class OpN < Array | |
def <=>(other) | |
o0 = self.class::Order | |
o1 = other.class::Order | |
return o0 <=> o1 if o0 != o1 | |
return size <=> other.size if size != other.size | |
zip(other) do |e0, e1| | |
c = e0 <=> e1 | |
return c if c != 0 | |
end | |
return 0 | |
end | |
include Comparable | |
def fv(h) | |
each {|e| e.fv(h) } | |
end | |
end | |
class And < OpN | |
Order = 6 | |
def inspect | |
s = "" | |
(size - 1).times {|i| s << "(and %p " % [self[i]] } | |
s << last.inspect | |
(size - 1).times { s << ")" } | |
s | |
end | |
def eval | |
inject(MASK) {|z, x| x.eval & z } | |
end | |
def fixed | |
@fixed ||= | |
begin | |
s1 = 0 | |
s2 = MASK | |
each do |e| | |
s1 |= e.fixed & ~e.static | |
s2 &= e.fixed & e.static | |
end | |
s1 | s2 | |
end | |
end | |
def static | |
@static ||= | |
begin | |
s = MASK | |
each {|e| s &= e.static } | |
s | |
end | |
end | |
end | |
class Or < OpN | |
Order = 7 | |
def inspect | |
s = "" | |
(size - 1).times {|i| s << "(or %p " % [self[i]] } | |
s << last.inspect | |
(size - 1).times { s << ")" } | |
s | |
end | |
def eval | |
inject(0) {|z, x| x.eval | z } | |
end | |
def fixed | |
@fixed ||= | |
begin | |
s1 = 0 | |
s2 = MASK | |
each do |e| | |
s1 |= e.fixed & e.static | |
s2 &= e.fixed & ~e.static | |
end | |
s1 | s2 | |
end | |
end | |
def static | |
@static ||= | |
begin | |
s = 0 | |
each {|e| s |= e.static } | |
s | |
end | |
end | |
end | |
class Xor < OpN | |
Order = 8 | |
def inspect | |
s = "" | |
(size - 1).times {|i| s << "(xor %p " % [self[i]] } | |
s << last.inspect | |
(size - 1).times { s << ")" } | |
s | |
end | |
def eval | |
inject(0) {|z, x| x.eval ^ z } | |
end | |
def fixed | |
@fixed ||= | |
begin | |
s = MASK | |
each {|e| s &= e.fixed } | |
s | |
end | |
end | |
def static | |
@static ||= | |
begin | |
s = 0 | |
each {|e| s ^= e.static } | |
s | |
end | |
end | |
end | |
class Plus < OpN | |
Order = 9 | |
def inspect | |
s = "" | |
(size - 1).times {|i| s << "(plus %p " % [self[i]] } | |
s << last.inspect | |
(size - 1).times { s << ")" } | |
s | |
end | |
def eval | |
inject(0) {|z, x| (x.eval + z) & MASK } | |
end | |
def fixed | |
all? {|x| x.fixed == MASK } ? MASK : 0 | |
end | |
def static | |
inject(0) {|z, x| (x.static + z) & MASK } | |
end | |
end | |
If0 = Struct.new(:e_cond, :e_then, :e_else) | |
class If0 | |
Order = 10 | |
def inspect | |
"(if0 %p %p %p)" % [e_cond, e_then, e_else] | |
end | |
def eval | |
(e_cond.eval == 0 ? e_then : e_else).eval | |
end | |
def fixed | |
@fixed ||= | |
if e_cond.fixed == MASK | |
if e_cond.static == 0 | |
e_then.fixed | |
else | |
e_else.fixed | |
end | |
else | |
fixed = e_then.fixed & e_else.fixed | |
s_then = e_then.static | |
s_else = e_else.static | |
64.times do |i| | |
fixed &= ~(1 << i) if s_then[i] != s_else[i] | |
end | |
fixed | |
end | |
end | |
def static | |
@static ||= | |
if e_cond.fixed == MASK | |
if e_cond.static == 0 | |
e_then.static | |
else | |
e_else.static | |
end | |
else | |
e_then.static | |
end | |
end | |
def <=>(other) | |
return -1 if other.is_a?(Fold) | |
return 1 unless other.is_a?(If0) | |
c = e_cond <=> other.e_cond | |
return c if c != 0 | |
c = e_then <=> other.e_then | |
return c if c != 0 | |
c = e_else <=> other.e_else | |
return c | |
end | |
include Comparable | |
def fv(h) | |
e_cond.fv(h) | |
e_then.fv(h) | |
e_else.fv(h) | |
end | |
end | |
Fold = Struct.new(:e_arg1, :e_arg2, :e_body) | |
class Fold | |
Order = 11 | |
def inspect | |
"(fold %p %p (lambda (y z) %p))" % [e_arg1, e_arg2, e_body] | |
end | |
def eval | |
arg1 = e_arg1.eval | |
$arg2 = e_arg2.eval | |
8.times do |i| | |
$arg1 = (arg1 >> (i * 8)) & 0xff | |
$arg2 = e_body.eval | |
end | |
$arg2 | |
end | |
def fixed | |
@fixed ||= e_body.fixed | |
end | |
def static | |
@static ||= e_body.static | |
end | |
def <=>(other) | |
return 1 unless other.is_a?(Fold) | |
c = e_arg1 <=> other.e_arg1 | |
return c if c != 0 | |
c = e_arg2 <=> other.e_arg2 | |
return c if c != 0 | |
c = e_body <=> other.e_body | |
return c | |
end | |
include Comparable | |
def fv(h) | |
raise "assert error" | |
end | |
end | |
Op1s = { :not => Not, :shl1 => Shl1, :shr1 => Shr1, :shr4 => Shr4, :shr16 => Shr16 } | |
Op2s = { :and => And, :or => Or, :xor => Xor, :plus => Plus } | |
# (shl1 (not 0)) == (not 1) | |
def gen_n(op2, len, remain, min, ary, op1s, op2s, no_fold, in_fold, &blk) | |
if len == 1 | |
gen(remain, op1s, op2s, no_fold, in_fold) do |e| | |
next if e == Leaf0 | |
next if e.is_a?(op2) | |
a = ary + [e] | |
if op2 == Or || op2 == And || op2 != Xor | |
next if a.include?(Not[Leaf0]) | |
next if a.any? {|e| ary.include?(Not[e]) } | |
end | |
next if op2 != Plus && ary.last >= e | |
next if op2 == Plus && ary.last > e | |
next if op2 == Plus && op1s.include?(Shl1) && ary.last >= e | |
if op2 != Plus && e.is_a?(Op1) && ary.any? {|ep| ep.is_a?(e.class) } | |
next if !e.is_a?(Not) | |
next if op2 == And && op2s.include?(Or) | |
next if op2 == Or && op2s.include?(And) | |
end | |
if op2 == Plus && ary.first == Leaf1 | |
next if op2s.include?(Or) && (a.drop(1)).all? {|ep| ep.fixed[0] == 1 && ep.static[0] == 0 } | |
end | |
ary << e | |
e = op2.new(ary) | |
unless e.fixed == MASK && (e.static == 0 || e.static == 1) | |
yield e | |
end | |
ary.pop | |
end | |
else | |
min.upto(remain / len) do |size| | |
gen(size, op1s, op2s, no_fold, in_fold) do |e| | |
next if e == Leaf0 | |
if ary.size >= 1 | |
next if op2 != Plus && ary.last >= e | |
next if op2 == Plus && ary.last > e | |
next if op2 == Plus && op1s.include?(Shl1) && ary.last >= e | |
next if op2 != Plus && e.is_a?(Op1) && ary.any? {|ep| ep.is_a?(e.class) } | |
next if op2 == Plus && e.is_a?(Shl1) && ary.any? {|ep| ep.is_a?(Shl1) } | |
end | |
ary << e | |
gen_n(op2, len - 1, remain - size, size, ary, op1s, op2s, no_fold, in_fold, &blk) | |
ary.pop | |
end | |
end | |
end | |
end | |
Cache = {} | |
def gen(size, op1s, op2s, no_fold, in_fold, &blk) | |
if Cache[key = [size, no_fold, in_fold]] | |
return Cache[key].each(&blk) | |
end | |
if size == 1 | |
yield Leaf0 | |
yield Leaf1 | |
yield LeafInput if !$tfold | |
if $tfold || in_fold | |
yield LeafArg1 | |
yield LeafArg2 | |
end | |
return | |
end | |
if size >= 2 && !op1s.empty? | |
op1s.each do |op1| | |
gen(size - 1, op1s, op2s, no_fold, in_fold) do |e| | |
next if op1 == Shr4 && e.is_a?(Shr1) | |
next if op1 == Shr16 && (e.is_a?(Shr1) || e.is_a?(Shr4)) | |
next if op1 == Not && e.is_a?(Not) | |
next if op1 == Not && e.is_a?(If0) && (e.e_then.is_a?(Not) || e.e_else.is_a?(Not)) | |
next if op1 != Not && e == Leaf0 | |
if op1 != Not && op1 != Shl1 | |
mask = (-1 << { Shr1 => 1, Shr4 => 4, Shr16 => 16 }[op1]) & MASK | |
next if e.fixed & mask == mask && (e.static & mask == 0 || e.static & mask == mask) | |
if e.is_a?(Xor) || e.is_a?(Or) | |
next if e.any? {|e| e.fixed & mask == mask && e.static & mask == 0 } | |
end | |
end | |
# (shr1 (not 1)) == (shr1 (not 0)) | |
# (not (shl1 (not ?)) => (or/xor 1 (shl1 ?)) | |
next if op1 == Not && e.is_a?(Shl1) && e.e.is_a?(Not) && (op2s.include?(Or) || op2s.include?(Xor)) | |
next if op1 == Shl1 && e.is_a?(Not) && e.e == Leaf0 # (shl1 (not 0)) == (not 1) | |
next if op1 == Shr1 && e.is_a?(Shl1) && (e.e.is_a?(Shr1) || e.e.is_a?(Shr4) || e.e.is_a?(Shr16)) | |
next if op1 == Shl1 && e.is_a?(Shr1) && e.e.is_a?(Shl1) | |
next if op1 == Shr4 && e.is_a?(Shl1) && e.e.is_a?(Shl1) && e.e.e.is_a?(Shl1) && e.e.e.e.is_a?(Shl1) && (e.e.e.e.e.is_a?(Shr4) || e.e.e.e.e.is_a?(Shr16)) | |
e = op1[e] | |
next if e.fixed == MASK && (e.static == 0 || e.static == 1) | |
yield e | |
end | |
end | |
end | |
if size >= 3 && !op2s.empty? | |
op2s.each do |op2| | |
1.upto((size - 1) / 2) do |count| | |
len = count + 1 | |
remain = size - count | |
gen_n(op2, len, remain, 1, [], op1s, op2s, no_fold, in_fold, &blk) | |
end | |
end | |
end | |
if size >= 4 | |
1.upto(size - 3) do |s_then| | |
gen(s_then, op1s, op2s, no_fold, in_fold) do |e_then| | |
1.upto(size - 2 - s_then) do |s_else| | |
gen(s_else, op1s, op2s, no_fold, in_fold) do |e_else| | |
next if e_then == Leaf0 && e_else == Leaf1 | |
next if e_then == e_else | |
# (if c1 t (if c2 t f)) == (if (if c1 0 c2) t f) | |
# c1 == 0 => t | |
# c1 != 0 && c2 == 0 => t | |
# c1 != 0 && c2 != 0 => f | |
next if e_else.is_a?(If0) && e_then == e_else.e_then | |
# (if c1 (if c2 t f) f) == (if (if c1 c2 1) t f) | |
# c1 == 0 && c2 == 0 => t | |
# c1 == 0 && c2 != 0 => f | |
# c1 != 0 => f | |
next if e_then.is_a?(If0) && e_then.e_else == e_else | |
next if e_then.is_a?(Op1) && e_else.is_a?(e_then.class) | |
gen(size - 1 - s_then - s_else, op1s, op2s, no_fold, in_fold) do |e_cond| | |
next if e_cond.fixed == MASK | |
next if e_cond.fixed & e_cond.static != 0 | |
next if e_cond.is_a?(If0) && e_cond.e_cond == e_cond.e_else && (e_cond.e_then.fixed & e_cond.e_then.static) != 0 | |
next if e_cond == e_then | |
next if e_then == Leaf0 && e_cond == e_else | |
yield If0[e_cond, e_then, e_else] | |
end | |
end | |
end | |
end | |
end | |
end | |
if $fold && size >= 5 && !no_fold | |
1.upto(size - 4) do |s_body| | |
gen(s_body, op1s, op2s, true, true) do |e_body| | |
next if e_body.fixed == MASK | |
next if e_body == LeafArg2 | |
fv = Hash.new(0) | |
e_body.fv(fv) | |
next if fv[:y] == 0 && fv[:z] == 0 | |
1.upto(size - 3 - s_body) do |s_arg1| | |
gen(s_arg1, op1s, op2s, true, false) do |e_arg1| | |
if fv[:y] == 0 | |
next if fv[:z] == 1 | |
next if e_arg1 != Leaf0 | |
end | |
next if fv[:z] == 0 && e_arg1.fixed == MASK && e_arg1.static == 0 | |
gen(size - 2 - s_body - s_arg1, op1s, op2s, true, false) do |e_arg2| | |
if fv[:z] == 0 | |
next if e_arg2 != Leaf0 | |
end | |
yield Fold[e_arg1, e_arg2, e_body] | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
def do_eval(input, e) | |
$input = input | |
e.eval | |
end | |
class Mismatch < RuntimeError; end | |
def update_map(map, es, i, o) | |
map[es].each do |ee| | |
e = ee[0] | |
b = ee[1] * 2 | |
b += 1 if do_eval(i, e) == o | |
ee[1] = b | |
end | |
end | |
def bonus(problem, size) | |
count = 0 | |
count2 = 0 | |
pairs = [] | |
p [:foo, size] | |
5.upto(size) do |s_then| | |
count2 += Cache[[s_then, false, false]].size | |
s_then.upto(size) do |s_else| | |
break if 9 + s_then + s_else > problem["size"] | |
s_cond_max = problem["size"] - 4 - s_then - s_else | |
v_then = Cache[[s_then, false, false]].size | |
v_else = Cache[[s_else, false, false]].size | |
count += v_then * v_else | |
p [:product, s_then, s_else, v_then, v_else, v_then * v_else] | |
pairs << [s_then, s_else] | |
end | |
end | |
pairs2 = [] | |
i = 5 | |
until pairs.empty? | |
pairs2.concat(pairs.select {|a| (a - [*5..i]).empty? }) | |
pairs -= pairs2 | |
i += 1 | |
end | |
i = pairs2.index([7, 7]) || -1 | |
#i = -1 | |
pairs = pairs2[0..i] | |
p pairs | |
p [:confirm, count, count2] | |
#if count > 1500000000 || count2 > 10000000 | |
# p :avoid | |
# puts | |
# $avoid = true | |
# return | |
#end | |
#p [:hit_return] | |
#gets | |
req = {} | |
req[:id] = problem["id"] | |
req[:arguments] = Inputs.map {|x| "0x%x" % x } | |
resp = post("eval", req) | |
outputs = resp["outputs"].map {|x| Integer(x) } | |
time = Time.now | |
puts "Got tests!" | |
tests = {} | |
Inputs.zip(outputs) {|i, o| tests[i] = o } | |
map = {} | |
5.upto(size) do |s| | |
map[s] = Cache[[s, false, false]].map {|e| [e, 0] } | |
end | |
1.upto(4) do |s| | |
map[5].concat(Cache[[s, false, false]].map {|e| [e, 0] }) | |
end | |
$bitmap_all = (1 << tests.size) - 1 | |
updated = {} | |
begin | |
p [:loop, ("%b" % $bitmap_all).size] | |
pairs.each do |s_then, s_else| | |
unless updated[s_then] | |
p [:update, s_then, map[s_then].size] | |
tests.each {|i, o| update_map(map, s_then, i, o) } | |
updated[s_then] = true | |
end | |
unless updated[s_else] | |
p [:update, s_else, map[s_else].size] | |
tests.each {|i, o| update_map(map, s_else, i, o) } | |
updated[s_else] = true | |
end | |
p [:product_main, s_then, s_else] | |
s_cond_max = problem["size"] - 4 - s_then - s_else | |
s_cond_max = 9 if s_cond_max > 9 | |
map[s_then].each do |e_then, b1| | |
next if b1 == 0 | |
map[s_else].each do |e_else, b2| | |
next if b2 == 0 | |
if b1 | b2 == $bitmap_all | |
p :found_pair | |
p [e_then, e_else] | |
5.upto(s_cond_max) do |s_cond| | |
p [s_cond, s_cond_max] | |
map[s_cond].each do |e_cond,| | |
next if e_cond.fixed[0] == 1 | |
2.times do | |
idx = tests.size | |
check = tests.all? do |i, o| | |
idx -= 1 | |
do_eval(i, e_cond) & 1 == 0 ? b1[idx] == 1 : b2[idx] == 1 | |
end | |
if check | |
p :try | |
e = If0[And[e_cond, Leaf1], e_then, e_else] | |
p e | |
req = {} | |
req[:id] = problem["id"] | |
req[:program] = "(lambda (x) #{ e.inspect })" | |
#req[:program] = "(lambda (x) x)" | |
begin | |
resp = post("guess", req) | |
rescue Exception | |
puts "** FAILED **" | |
p $! | |
return | |
end | |
case resp["status"] | |
when "win" | |
p [:win, Time.now - time] | |
puts | |
return | |
when "mismatch" | |
p :mismatch | |
values = resp["values"].map {|x| Integer(x) } | |
p "0x%016x => 0x%016x, but 0x%016x" % [values[0], values[1], values[2]] | |
tests[values[0]] = values[1] | |
$bitmap_all = (1 << tests.size) - 1 | |
updated.each_key do |s| | |
update_map(map, s, values[0], values[1]) | |
end | |
raise Mismatch | |
when "error" | |
raise "error: #{ resp.inspect }" | |
end | |
end | |
e_then, b1, e_else, b2 = e_else, b2, e_then, b1 | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
puts "***********" | |
puts "* BOOOOO! *" | |
puts "***********" | |
puts | |
return | |
rescue Mismatch | |
puts "retry" | |
retry | |
end | |
exit | |
end | |
def brute(problem) | |
ops = problem["operators"].sort.map {|s| s.to_sym } | |
$fold = ops.include?(:fold) | |
$tfold = ops.include?(:tfold) | |
$bonus = ops.include?(:bonus) | |
size = problem["size"] - ($tfold ? 5 : $bonus ? 14 : 1) | |
size = 9 if size > 9 && $bonus | |
op1s = ops.map {|op| Op1s[op] }.compact | |
op2s = ops.map {|op| Op2s[op] }.compact | |
time = Time.now | |
candidates = {} | |
gen_c = 0 | |
Cache.clear | |
1.upto(size) do |i| | |
if $fold && i <= size - 5 | |
cache = [] | |
gen(i, op1s, op2s, true, true) do |e| | |
cache << e | |
gen_c += 1 | |
break if gen_c >= MAX_LIMIT # !!!! | |
print "\r[in_fold, #{ gen_c }] " + e.inspect if gen_c % 10000 == 0 | |
end | |
Cache[[i, true, true]] = cache.freeze | |
cache = [] | |
gen(i, op1s, op2s, true, false) do |e| | |
cache << e | |
gen_c += 1 | |
break if gen_c >= MAX_LIMIT # !!!! | |
print "\r[no_fold, #{ gen_c }] " + e.inspect if gen_c % 10000 == 0 | |
end | |
Cache[[i, true, false]] = cache.freeze | |
end | |
cache = [] | |
gen(i, op1s, op2s, false, false) do |e| | |
cache << e | |
next if $tfold && e.is_a?(And) && e.first == LeafArg2 | |
#p e | |
gen_c += 1 | |
print "\r[#{ gen_c }] " + e.inspect if gen_c % 10000 == 0 | |
break if gen_c >= MAX_LIMIT # !!!! | |
end | |
Cache[[i, false, false]] = cache.freeze | |
break if gen_c >= MAX_LIMIT # !!!! | |
p [:cache, i, Cache[[i, false, false]].size] | |
if i == 8 && false | |
p *Cache[[i, false, false]] | |
p Cache[[i, false, false]].size | |
exit | |
end | |
end | |
p [:gen_c, gen_c] | |
if $bonus | |
return bonus(problem, size) | |
end | |
gen_c = 0 | |
size.downto(1) do |size| | |
next unless Cache[[size, false, false]] | |
puts | |
p [:size, size, gen_c] | |
gen(size, op1s, op2s, false, false) do |e| | |
gen_c += 1 | |
print "\r[#{ gen_c }] " + e.inspect if gen_c % 10000 == 0 | |
e = Fold[LeafInput, Leaf0, e] if $tfold | |
(candidates[[do_eval(0, e), do_eval(1, e), do_eval(MASK, e)]] ||= []) << e | |
end | |
end | |
size = 0 | |
candidates.each_value {|v| size += v.size } | |
p [:candidates, size, Time.now - time, gen_c] | |
#p *candidates | |
raise "what!?" if candidates.empty? | |
# (shl1 (shr1 x)) == (and (not 1) x) | |
req = {} | |
req[:id] = problem["id"] | |
req[:arguments] = Inputs.map {|x| "0x%x" % x } | |
resp = post("eval", req) | |
outputs = resp["outputs"].map {|x| Integer(x) } | |
time = Time.now | |
puts "Got tests!" | |
tests = {} | |
Inputs.zip(outputs) {|i, o| tests[i] = o } | |
p tests[0], tests[1], tests[MASK] | |
candidates = candidates[[tests[0], tests[1], tests[MASK]]] || [] | |
p [:size, candidates.size] | |
candidates.each do |e| | |
next unless tests.all? {|i, o| do_eval(i, e) == o } | |
p :try | |
p e | |
req = {} | |
req[:id] = problem["id"] | |
req[:program] = "(lambda (x) #{ e.inspect })" | |
#req[:program] = "(lambda (x) x)" | |
resp = post("guess", req) | |
case resp["status"] | |
when "win" | |
p [:win, Time.now - time] | |
puts | |
return | |
when "mismatch" | |
p :mismatch | |
values = resp["values"].map {|x| Integer(x) } | |
p "0x%x => 0x%x" % [values[0], values[1]] | |
tests[values[0]] = values[1] | |
when "error" | |
if resp["message"] == "Unable to decide equality" | |
puts "Unable to decide equality" | |
else | |
raise "error: #{ resp.inspect }" | |
end | |
end | |
sleep 3 | |
end | |
puts "***********" | |
puts "* BOOOOO! *" | |
puts "***********" | |
puts | |
end | |
problem = {} | |
#problem["id"] = "YLgTBvDWUf0EQlI04hYjpF0T" | |
#problem["size"] = 15 | |
#problem["operators"] = ["if0", "not", "or", "shr1", "shr16", "tfold"] | |
#problem["challenge"] = "(lambda (x_18249) (fold x_18249 0 (lambda (x_18249 x_18250) (not (if0 (or (shr1 1) (shr16 x_18249)) (not x_18249) x_18249)))))" | |
#brute(problem) | |
[ | |
["id", "1om0twccbswqUmrr3t8zebsb"], | |
["size", 14], | |
["operators", ["fold", "not", "plus", "shl1", "shr4", "xor"]], | |
["challenge", "(lambda (x_32546) (fold (xor (not (shr4 0)) (shl1 x_32546)) 0 (lambda (x_32547 x_32548) (plus (not x_32548) x_32547))))"] | |
].each {|k, v| problem[k] = v } | |
#p *problem | |
#brute(problem) | |
#exit | |
# config | |
target = ["tfold"] | |
size = 30 | |
#req = {} | |
#req[:size] = size | |
#req[:operators] = target | |
#problem = post("train", req) | |
#p *problem | |
#brute(problem) | |
#exit | |
problems = post("myproblems") | |
File.write("myproblems.json", JSON.dump(problems)) | |
problems.sort_by {|p| [p["size"], p["operators"].size, p["id"]] }.each do |problem| | |
next if problem.key?("solved") | |
next if problem["size"] < 27 | |
next if problem["size"] > size | |
if target.empty? | |
next if problem["operators"].include?("fold") | |
next if problem["operators"].include?("tfold") | |
next if problem["operators"].include?("bonus") | |
else | |
next unless problem["operators"].include?(target.first) | |
end | |
sleep 5 unless $avoid | |
$avoid = false | |
p *problem | |
brute(problem) | |
GC.start | |
#break | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment