Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --local print_on_paper = require "print"
- local function deepcopy(o, seen)
- seen = seen or {}
- if o == nil then return nil end
- if seen[o] then return seen[o] end
- local no
- if type(o) == 'table' then
- no = {}
- seen[o] = no
- for k, v in next, o, nil do
- no[deepcopy(k, seen)] = deepcopy(v, seen)
- end
- setmetatable(no, deepcopy(getmetatable(o), seen))
- else -- number, string, boolean, etc
- no = o
- end
- return no
- end
- local env = deepcopy(_G)
- local function run(code)
- local f = load(code, "@stuff", "t", env)
- if not f then return nil end
- return pcall(f)
- end
- local function fitness(code)
- local start_time = os.clock()
- local ok, result = run(code)
- local end_time = os.clock()
- local fitness = 1
- fitness = fitness + ((end_time - start_time) * 10)
- if result then fitness = fitness + math.max(#result, 8) end
- if ok == nil then fitness = 0 end
- if ok == true then fitness = fitness * 5 end
- if ok == false then fitness = fitness * 0.1 end
- return fitness
- end
- local function random_char()
- return string.char(math.random(32, 126))
- end
- local function pick_random(l)
- return l[math.random(1, #l)]
- end
- local function partition(str, at)
- return str:sub(1, at - 1), str:sub(at, at), str:sub(at + 1)
- end
- local function partition_random(str)
- return partition(str, math.random(1, #str))
- end
- local mutations = {
- function(code) -- add char
- local start, c, end_ = partition_random(code)
- return start .. random_char() .. c .. end_
- end,
- function(code) -- delete char
- local start, c, end_ = partition_random(code)
- return start .. end_
- end,
- function(code) -- change char
- local start, c, end_ = partition_random(code)
- return start .. random_char() .. end_
- end
- }
- local function mutate(code)
- for i = 1, math.random(0, 3) do
- code = pick_random(mutations)(code)
- end
- if code:sub(1, 1) == "#" then -- get around weird Cobalt behavior
- code = code:sub(2)
- end
- return code
- end
- local function weighted_random_by(list, get_weight)
- local total_weight = 0
- _.map(list, function(i)
- total_weight = total_weight + get_weight(i)
- end)
- local rand = math.random() * total_weight
- for k, v in pairs(list) do
- local weight = get_weight(v)
- if rand < weight then
- return v
- else
- rand = rand - weight
- end
- end
- assert(false, "Should not be reached")
- end
- local function combine(cf_pairs)
- local out = ""
- local len = _(cf_pairs):map(function(cf) return #cf.code end):reduce(math.max, -math.huge)
- for i = 1, len do
- local char = weighted_random_by(
- _(cf_pairs):map(function(cf) return { c = string.sub(cf.code, i, i), f = cf.fitness } end),
- function(cf) return cf.f end
- ).c
- out = out .. char
- end
- return out
- end
- local function run_gen(g)
- local code_and_fitnesses = _.map(g, function(code)
- return { code = code, fitness = fitness(code) }
- end)
- sleep(0.1)
- print(textutils.serialise(code_and_fitnesses))
- local num_descendants = math.max(math.min(4, math.random(-2, 2) + #g), 16)
- local descendants = {}
- for i = 1, num_descendants do
- local cf_pairs = {}
- for i = 1, math.random(1, 3) do
- table.insert(cf_pairs, weighted_random_by(code_and_fitnesses, function(cf) return cf.fitness end))
- end
- descendants[i] = mutate(combine(cf_pairs))
- end
- return descendants
- end
- local programs = {"print 'hello, world'"}
- while true do
- programs = run_gen(programs)
- sleep()
- end
Add Comment
Please, Sign In to add comment