Skip to content

Instantly share code, notes, and snippets.

@mame
Created August 11, 2013 22:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mame/08b38f75b7c7d88a8a7c to your computer and use it in GitHub Desktop.
Save mame/08b38f75b7c7d88a8a7c to your computer and use it in GitHub Desktop.
My program for ICFPc 2013. http://icfpc2013.cloudapp.net/
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