Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local NUM_COLORS = 6
- local CODE_LENGTH = 4
- -- kubejs:substrate_{type}
- local alchemy = {
- ["igneous"] = { "andesite", "diorite", "granite", "cobblestone", "basalt", "gabbro"},
- ["herbal"] = { "red", "orange", "yellow", "green", "blue", "magenta"},
- ["volatile"] = { "blaze", "slime", "nether", "obsidian", "gunpowder", "prismarine" },
- ["crystal"] = { "arcane", "apatite", "sulfur", "niter", "certus", "quartz"},
- ["metal"] = { "zinc", "copper", "iron", "nickel", "lead", "gold" },
- ["gem"] = { "cinnabar", "lapis", "sapphire", "emerald", "ruby", "diamond" }
- }
- -- ["chaos"] = { "igneous", "herbal", "volatile", "crystal", "metal", "gem" }
- local deviceNames = {
- chest = "metalbarrels:gold_tile_1",
- slot1 = "moreminecarts:minecart_loader_te_0",
- slot2 = "moreminecarts:minecart_loader_te_1",
- slot3 = "moreminecarts:minecart_loader_te_2",
- slot4 = "moreminecarts:minecart_loader_te_3",
- unloader = "moreminecarts:minecart_unloader_te_0",
- centrifuge = "thermal:machine_centrifuge_0"
- }
- local devices = {}
- local reagentSlots = {}
- local function buildMinecraftName(short)
- return string.format("kubejs:substrate_%s", short)
- end
- local function wrapPeripherals()
- devices["chest"] = peripheral.wrap(deviceNames["chest"])
- devices["slots"] = {}
- devices["slots"][1] = peripheral.wrap(deviceNames["slot1"])
- devices["slots"][2] = peripheral.wrap(deviceNames["slot2"])
- devices["slots"][3] = peripheral.wrap(deviceNames["slot3"])
- devices["slots"][4] = peripheral.wrap(deviceNames["slot4"])
- devices["unloader"] = peripheral.wrap(deviceNames["chest"])
- devices["centrifuge"] = peripheral.wrap(deviceNames["chest"])
- end
- -- For testing
- local code = {}
- -- For testing
- local function getRandomCode()
- local code = {};
- local max = NUM_COLORS;
- local min = 1;
- local i, random;
- for i = 1, CODE_LENGTH do
- random = math.floor(math.random(min, max))
- table.insert(code, random)
- end
- return code
- end
- local function solveCode()
- local combinations = {}
- local candidateSolutions = {}
- local currentGuess = {}
- local nextGuesses = {}
- local numGuesses = 0
- local responsePegs = ""
- local function combinationRecursive(combinationLength, position, currentIn, elements)
- local current = { table.unpack(currentIn) }
- local i, element
- if position > combinationLength then
- table.insert(combinations, current)
- table.insert(candidateSolutions, current)
- return
- end
- for i, element in pairs(elements) do
- current[position] = element;
- combinationRecursive(combinationLength, position + 1, current, elements)
- end
- return
- end
- local function createSet()
- local current = {}
- local elements = {}
- local i
- -- Reset the combination/solution tables
- combinations = {}
- candidateSolutions = {}
- for i = 1, CODE_LENGTH do
- current[i] = 0
- end
- for i = 1, NUM_COLORS do
- table.insert(elements, i)
- end
- combinationRecursive(CODE_LENGTH, 1, current, elements);
- end
- local function doCodesMatch(code1, code2)
- return table.concat(code1) == table.concat(code2)
- end
- local function findCodeIndex(set, currentCode)
- local index = 0
- local i, entry
- for i, entry in pairs(set) do
- if doCodesMatch(entry, currentCode) then
- index = i
- break
- end
- end
- return index
- end
- local function removeCode(set, currentCode)
- local index = findCodeIndex(set, currentCode)
- if index > 0 then
- table.remove(set, index)
- end
- end
- local function checkCode(guessIn, codeIn)
- local guess = { table.unpack(guessIn) }
- local code = { table.unpack(codeIn) }
- local result = ""
- local i, j
- -- Count black pegs
- for i = 1, CODE_LENGTH do
- if guess[i] == code[i] then
- result = result .. "B"
- guess[i] = guess[i] * -1
- code[i] = code[i] * -1
- end
- end
- -- Count white pegs
- for i = 1, CODE_LENGTH do
- if code[i] > 0 then
- for j = 1, CODE_LENGTH do
- if code[i] == guess[j] then
- result = result .. "W"
- guess[j] = guess[j] * -1
- break
- end
- end
- end
- end
- return result;
- end
- local function makeGuess(guess)
- return checkCode(guess, code)
- end
- local function pruneCodes(set, currentCode, currentResponse)
- local index
- local i, entry
- for i, entry in pairs(set) do
- if currentResponse ~= checkCode(currentCode, entry) then
- table.remove(set, i)
- end
- end
- end
- local function getMaxScore(inputMap)
- local max = 0
- local key, val
- for key, val in pairs(inputMap) do
- if val > max then
- max = val
- end
- end
- return max
- end
- local function getMinScore(inputMap)
- local min = 0xffff
- local key, val
- for key, val in pairs(inputMap) do
- if val < min then
- min = val
- end
- end
- return min;
- end
- local function minmax()
- local result = {}
- local scoreCount = {}
- local score = {}
- local max, min, i, j, key, val
- for i = 1, #combinations do
- for j = 1, #candidateSolutions do
- -- ComputerCraft watchdog will break if we don't churn the event queue periodically
- if os.epoch() % 5 == 0 then
- os.queueEvent("randomEvent")
- os.pullEvent()
- end
- local pegScore = checkCode(combinations[i], candidateSolutions[j])
- if scoreCount[pegScore] ~= nil then
- scoreCount[pegScore] = scoreCount[pegScore] + 1
- else
- scoreCount[pegScore] = 1
- end
- end
- max = getMaxScore(scoreCount)
- score[combinations[i]] = max
- scoreCount = {}
- end
- min = getMinScore(score)
- for key, val in pairs(score) do
- if val == min then
- table.insert(result, key)
- end
- end
- return result;
- end
- local function getNextGuess(nextGuesses)
- local i, guess, index
- for i, guess in pairs(nextGuesses) do
- if findCodeIndex(candidateSolutions, guess) > 0 then
- return guess
- end
- end
- for i, guess in pairs(nextGuesses) do
- if findCodeIndex(combinations, guess) > 0 then
- return guess
- end
- end
- return nil
- end
- -- Create the master set of possible codes (1296 for six colors and four digit code)
- createSet()
- -- Start with Knuth's initial guess
- currentGuess = { 1, 1, 2, 2 }
- -- Profile runtime
- local startTime = os.epoch()
- -- Guess until we win
- while (true) do
- -- Count number of guesses
- numGuesses = numGuesses + 1
- -- Remove currentGuess from possible solutions
- removeCode(combinations, currentGuess);
- removeCode(candidateSolutions, currentGuess);
- -- Play the guess to get a response of colored and white pegs
- responsePegs = makeGuess(currentGuess)
- -- Show our guess
- print(string.format("%02d", numGuesses) .. ": " .. table.concat(currentGuess) .. " Result: " .. responsePegs)
- -- Check if we correctly guessed the code
- if responsePegs == string.rep("B", CODE_LENGTH) then
- print(" Correct code guessed in " .. numGuesses .. " guesses!")
- break
- end
- -- Remove any code from candidateSolutions that would not give the same response if it were the code
- pruneCodes(candidateSolutions, currentGuess, responsePegs)
- -- Show current guess and result
- print(" " .. #candidateSolutions .. " candidates remain")
- -- Calculate Minmax scores
- nextGuesses = minmax()
- -- Select next guess
- currentGuess = getNextGuess(nextGuesses)
- if currentGuess == nil then
- error("ERROR: No possible combinations left!")
- end
- end
- -- Calculate runtime
- local endTime = os.epoch()
- print("Runtime: " .. (endTime - startTime) / 100000 .. "s")
- end
- -- Seed the RNG
- -- math.randomseed(os.epoch())
- -- Generate a random code
- -- code = getRandomCode()
- -- print("Code: " .. table.concat(code))
- -- solveCode()
- wrapPeripherals()
Add Comment
Please, Sign In to add comment