Skip to content

Instantly share code, notes, and snippets.

@diath
Last active December 3, 2017 14:16
Show Gist options
  • Save diath/fd5e6568e042fb878857 to your computer and use it in GitHub Desktop.
Save diath/fd5e6568e042fb878857 to your computer and use it in GitHub Desktop.
Advent of Code, 2015, Lua
-- NOTE: Input as a table sequence
local str = {}
local getOutput = function(str)
local out = {}
local curr, next = -1, -1
local counter = 1
for i = 1, #str do
curr = str[i]
next = str[i + 1]
if curr == next then
counter = counter + 1
else
table.insert(out, counter)
table.insert(out, curr)
counter = 1
end
end
return out
end
local out = getOutput(str)
for i = 1, 39 do
out = getOutput(out)
end
io.write(('Length: %d\n'):format(#out))
-- NOTE: Input as a table sequence
local str = {}
local getOutput = function(str)
local out = {}
local curr, next = -1, -1
local counter = 1
for i = 1, #str do
curr = str[i]
next = str[i + 1]
if curr == next then
counter = counter + 1
else
table.insert(out, counter)
table.insert(out, curr)
counter = 1
end
end
return out
end
local out = getOutput(str)
for i = 1, 49 do
out = getOutput(out)
end
io.write(('Length: %d\n'):format(#out))
local str = '__your_input__'
local isValid = function(password)
-- Contains i, o, or l
if password:match('[iol]') then
return false
end
-- Doubles
if not str:match('(.)%1.*(.)%2') then
return false
end
-- No three char increasing sequence
local found = false
for i = 1, #str - 3 do
ch1 = password:sub(i, i):byte()
ch2 = password:sub(i + 1, i + 1):byte()
ch3 = password:sub(i + 2, i + 2):byte()
if ch1 == ch2 - 1 and ch2 == ch3 - 1 then
found = true
break
end
end
return found
end
local replace = function(str, pos, new)
return ('%s%s%s'):format(str:sub(1, pos - 1), new, str:sub(pos + 1))
end
local getNext = function(str)
local i = #str
while i > 1 and str:sub(i, i) == 'z' do
str = replace(str, i, 'a')
i = i - 1
end
str = replace(str, i, string.char(str:sub(i, i):byte() + 1))
return str
end
repeat
str = getNext(str)
until isValid(str)
io.write(('New password: %s\n'):format(str))
-- NOTE: It's exactly the same as D11P1.lua
local str = '__your_input__'
local isValid = function(password)
-- Contains i, o, or l
if password:match('[iol]') then
return false
end
-- Doubles
if not str:match('(.)%1.*(.)%2') then
return false
end
-- No three char increasing sequence
local found = false
for i = 1, #str - 3 do
ch1 = password:sub(i, i):byte()
ch2 = password:sub(i + 1, i + 1):byte()
ch3 = password:sub(i + 2, i + 2):byte()
if ch1 == ch2 - 1 and ch2 == ch3 - 1 then
found = true
break
end
end
return found
end
local replace = function(str, pos, new)
return ('%s%s%s'):format(str:sub(1, pos - 1), new, str:sub(pos + 1))
end
local getNext = function(str)
local i = #str
while i > 1 and str:sub(i, i) == 'z' do
str = replace(str, i, 'a')
i = i - 1
end
str = replace(str, i, string.char(str:sub(i, i):byte() + 1))
return str
end
repeat
str = getNext(str)
until isValid(str)
io.write(('New password: %s\n'):format(str))
local sum = 0
for line in io.lines('D12P1.txt') do
line:gsub('([-]?%d+)', function(value)
sum = sum + tonumber(value)
end)
end
io.write(('Sum of all numbers: %d\n'):format(sum))
local data = {}
local people = {}
local who, value, whom
local contains = function(t, val)
for _, v in pairs(t) do
if v == val then
return true
end
end
return false
end
local getChange = function(who, whom)
for _, v in pairs(data) do
if v.who == who and v.whom == whom then
return v.value
end
end
for _, v in pairs(data) do
if v.who == whom and v.whom == who then
return v.value
end
end
return 0
end
for line in io.lines('D13P1.txt') do
who, value, whom = line:match('(%w+) would gain (%d+) happiness units by sitting next to (%w+)')
if who == nil then
who, value, whom = line:match('(%w+) would lose (%d+) happiness units by sitting next to (%w+)')
if value ~= nil then
value = -value
end
end
table.insert(data, {
who = who,
whom = whom,
value = tonumber(value)
})
if not contains(people, who) then
table.insert(people, who)
end
if not contains(people, whom) then
table.insert(people, whom)
end
end
-- http://rosettacode.org/wiki/Permutations#Lua
local permutation
permutation = function(a, n, cb)
if n == 0 then
cb(a)
else
for i = 1, n do
a[i], a[n] = a[n], a[i]
permutation(a, n - 1, cb)
a[i], a[n] = a[n], a[i]
end
end
end
local highest = 0
local current, total = 0, 0
permutation(people, #people, function(data)
current, total = 0, 0
for i = 1, #data do
current = 0
if i > 1 and i < #data then
current = current + getChange(data[i], data[i + 1])
current = current + getChange(data[i], data[i - 1])
elseif i == 1 then
current = current + getChange(data[i], data[i + 1])
current = current + getChange(data[i], data[#data])
else
current = current + getChange(data[i], data[1])
current = current + getChange(data[i], data[i - 1])
end
total = total + current
end
if total > highest then
highest = total
end
end)
io.write(('The most optimal change in happiness: %d'):format(highest))
-- NOTE: It's exactly the same as D13P1.lua
local data = {}
local people = {}
local who, value, whom
local contains = function(t, val)
for _, v in pairs(t) do
if v == val then
return true
end
end
return false
end
local getChange = function(who, whom)
for _, v in pairs(data) do
if v.who == who and v.whom == whom then
return v.value
end
end
for _, v in pairs(data) do
if v.who == whom and v.whom == who then
return v.value
end
end
return 0
end
for line in io.lines('D13P2.txt') do
who, value, whom = line:match('(%w+) would gain (%d+) happiness units by sitting next to (%w+)')
if who == nil then
who, value, whom = line:match('(%w+) would lose (%d+) happiness units by sitting next to (%w+)')
if value ~= nil then
value = -value
end
end
table.insert(data, {
who = who,
whom = whom,
value = tonumber(value)
})
if not contains(people, who) then
table.insert(people, who)
end
if not contains(people, whom) then
table.insert(people, whom)
end
end
-- http://rosettacode.org/wiki/Permutations#Lua
local permutation
permutation = function(a, n, cb)
if n == 0 then
cb(a)
else
for i = 1, n do
a[i], a[n] = a[n], a[i]
permutation(a, n - 1, cb)
a[i], a[n] = a[n], a[i]
end
end
end
local highest = 0
local current, total = 0, 0
permutation(people, #people, function(data)
current, total = 0, 0
for i = 1, #data do
current = 0
if i > 1 and i < #data then
current = current + getChange(data[i], data[i + 1])
current = current + getChange(data[i], data[i - 1])
elseif i == 1 then
current = current + getChange(data[i], data[i + 1])
current = current + getChange(data[i], data[#data])
else
current = current + getChange(data[i], data[1])
current = current + getChange(data[i], data[i - 1])
end
total = total + current
end
if total > highest then
highest = total
end
end)
io.write(('The most optimal change in happiness: %d'):format(highest))
local grid = {}
local steps = 100
local shift = {
-- E
{ 0, 1},
-- W
{ 0, -1},
-- S
{ 1, 0},
-- N
{-1, 0},
-- NE
{-1, 1},
-- NW
{-1, -1},
-- SE
{ 1, 1},
-- SW
{ 1, -1},
}
local getNeighbourCount = function(g, y, x)
local count = 0
local ny, nx = 0, 0
for i = 1, #shift do
ny = y + shift[i][1]
nx = x + shift[i][2]
if ny > 0 and ny <= #g and nx > 0 and nx <= #g then
if g[ny][nx] then
count = count + 1
end
end
end
return count
end
local index = 0
local ch
for line in io.lines('D18P1.txt') do
index = index + 1
grid[index] = {}
for i = 1, #line do
ch = line:sub(i, i)
if ch == '#' then
grid[index][i] = true
elseif ch == '.' then
grid[index][i] = false
else
io.write(('Unknown character at (%d, %d): %s\n'):format(index, i, ch))
end
end
end
local nc = 0
local ng = {}
for i = 1, steps do
-- Iterate over the grid
-- Temporary grid because we're supposed to check lights simultaneously
for y = 1, #grid do
ng[y] = {}
for x = 1, #grid do
nc = getNeighbourCount(grid, y, x)
if grid[y][x] == true and (nc ~= 2 and nc ~= 3) then
ng[y][x] = false
elseif grid[y][x] == false and nc == 3 then
ng[y][x] = true
else
ng[y][x] = grid[y][x]
end
end
end
-- Copy the grid (this can't be just grid = ng)
for y = 1, #grid do
for x = 1, #grid do
grid[y][x] = ng[y][x]
end
end
end
-- Get the number of lights
local result = 0
for y = 1, #grid do
for x = 1, #grid do
if grid[y][x] then
result = result + 1
end
end
end
io.write(('There are %d lights on after %d steps.\n'):format(result, steps))
local grid = {}
local steps = 100
local shift = {
-- E
{ 0, 1},
-- W
{ 0, -1},
-- S
{ 1, 0},
-- N
{-1, 0},
-- NE
{-1, 1},
-- NW
{-1, -1},
-- SE
{ 1, 1},
-- SW
{ 1, -1},
}
local isCorner = function(g, y, x)
if y == 1 and x == 1 then
return true
end
if y == 1 and x == #g then
return true
end
if y == #g and x == 1 then
return true
end
if y == #g and x == #g then
return true
end
return false
end
local getNeighbourCount = function(g, y, x)
local count = 0
local ny, nx = 0, 0
for i = 1, #shift do
ny = y + shift[i][1]
nx = x + shift[i][2]
if ny > 0 and ny <= #g and nx > 0 and nx <= #g then
if g[ny][nx] or isCorner(g, y, x) then
count = count + 1
end
end
end
return count
end
local index = 0
local ch
for line in io.lines('D18P2.txt') do
index = index + 1
grid[index] = {}
for i = 1, #line do
ch = line:sub(i, i)
if ch == '#' then
grid[index][i] = true
elseif ch == '.' then
grid[index][i] = false
else
io.write(('Unknown character at (%d, %d): %s\n'):format(index, i, ch))
end
end
end
local nc = 0
local ng = {}
for i = 1, steps do
-- Iterate over the grid
-- Temporary grid because we're supposed to check lights simultaneously
for y = 1, #grid do
ng[y] = {}
for x = 1, #grid do
nc = getNeighbourCount(grid, y, x)
if grid[y][x] == true and (nc ~= 2 and nc ~= 3) then
ng[y][x] = false
elseif grid[y][x] == false and nc == 3 then
ng[y][x] = true
else
ng[y][x] = grid[y][x]
end
end
end
-- Copy the grid (this can't be just grid = ng)
for y = 1, #grid do
for x = 1, #grid do
grid[y][x] = ng[y][x]
end
end
end
-- Get the number of lights
local result = 0
for y = 1, #grid do
for x = 1, #grid do
if grid[y][x] then
result = result + 1
end
end
end
io.write(('There are %d lights on after %d steps.\n'):format(result, steps))
local str = '__your_input__'
local floor = 0
local ch
for i = 1, #str do
ch = str:sub(i, i)
if ch == ')' then
floor = floor - 1
elseif ch == '(' then
floor = floor + 1
end
end
io.write(('%d\n'):format(floor))
local str = '__your_input__'
local floor = 0
local ch
for i = 1, #str do
ch = str:sub(i, i)
if ch == ')' then
floor = floor - 1
elseif ch == '(' then
floor = floor + 1
end
if floor == -1 then
io.write(('Basement: %d\n'):format(i))
break
end
end
local program = {}
local pc = 1
local running = true
local registers = {
a = 0,
b = 0,
}
local setRegister = function(reg, value)
registers[reg] = math.max(0, tonumber(value))
end
local getRegister = function(reg)
return registers[reg]
end
local half = function(data)
setRegister(data[1], getRegister(data[1]) / 2)
return true
end
local triple = function(data)
setRegister(data[1], getRegister(data[1]) * 3)
return true
end
local increase = function(data)
setRegister(data[1], getRegister(data[1]) + 1)
return true
end
local jump = function(offset)
if type(offset) == 'table' then
pc = pc + tonumber(offset[1])
else
pc = pc + offset
end
return false
end
local jumpEven = function(data)
if getRegister(data[1]) % 2 == 0 then
return jump(tonumber(data[2]))
end
return true
end
local jumpOne = function(data)
if getRegister(data[1]) == 1 then
return jump(tonumber(data[2]))
end
return true
end
local getData = function(input)
local data = {}
input = input:sub(5):gsub(' ', '')
input:gsub('([^,]+)', function(part)
table.insert(data, part)
end)
return data
end
local lookup = {
['hlf'] = half,
['tpl'] = triple,
['inc'] = increase,
['jmp'] = jump,
['jie'] = jumpEven,
['jio'] = jumpOne,
}
local parse = function(line)
local instruction = line:sub(1, 3)
local data = getData(line)
local func = lookup[instruction]
local ret
if func then
ret = func(data)
else
running = false
end
return ret
end
for line in io.lines('D23P1.txt') do
table.insert(program, line)
end
while running and pc <= #program do
if parse(program[pc]) then
pc = pc + 1
end
end
io.write(('Registers\nA: %d\nB: %d\n'):format(registers.a, registers.b))
local program = {}
local pc = 1
local running = true
local registers = {
a = 1,
b = 0,
}
local setRegister = function(reg, value)
registers[reg] = math.max(0, tonumber(value))
end
local getRegister = function(reg)
return registers[reg]
end
local half = function(data)
setRegister(data[1], getRegister(data[1]) / 2)
return true
end
local triple = function(data)
setRegister(data[1], getRegister(data[1]) * 3)
return true
end
local increase = function(data)
setRegister(data[1], getRegister(data[1]) + 1)
return true
end
local jump = function(offset)
if type(offset) == 'table' then
pc = pc + tonumber(offset[1])
else
pc = pc + offset
end
return false
end
local jumpEven = function(data)
if getRegister(data[1]) % 2 == 0 then
return jump(tonumber(data[2]))
end
return true
end
local jumpOne = function(data)
if getRegister(data[1]) == 1 then
return jump(tonumber(data[2]))
end
return true
end
local getData = function(input)
local data = {}
input = input:sub(5):gsub(' ', '')
input:gsub('([^,]+)', function(part)
table.insert(data, part)
end)
return data
end
local lookup = {
['hlf'] = half,
['tpl'] = triple,
['inc'] = increase,
['jmp'] = jump,
['jie'] = jumpEven,
['jio'] = jumpOne,
}
local parse = function(line)
local instruction = line:sub(1, 3)
local data = getData(line)
local func = lookup[instruction]
local ret
if func then
ret = func(data)
else
running = false
end
return ret
end
for line in io.lines('D23P2.txt') do
table.insert(program, line)
end
while running and pc <= #program do
if parse(program[pc]) then
pc = pc + 1
end
end
io.write(('Registers\nA: %d\nB: %d\n'):format(registers.a, registers.b))
local width, height, length
local a, b, c, min
local total = 0
local getMin = function(a, b, c)
return math.min(math.min(a, b), c)
end
for line in io.lines('D2P1.txt') do
width, height, length = line:match('(%d+)x(%d+)x(%d+)')
a = length * width
b = width * height
c = height * length
min = getMin(a, b, c)
total = total + 2 * a + 2 * b + 2 * c + min
end
io.write(('Total paper needed: %d sqft\n'):format(total))
local width, height, length
local a, b
local total = 0
local getTwoMin = function(...)
local t = {...}
table.sort(t, function(a, b)
return tonumber(a) < tonumber(b)
end)
return t[1], t[2]
end
for line in io.lines('D2P2.txt') do
width, height, length = line:match('(%d+)x(%d+)x(%d+)')
-- Present
a, b = getTwoMin(width, height, length)
total = total + a * 2 + b * 2
-- Bow
total = total + width * height * length
end
io.write(('Total ribbon needed: %d ft\n'):format(total))
local getData = function()
local f = io.open('D3P1.txt', 'r')
local data = f:read('*all'):gsub('%s*$', '')
f:close()
return data
end
local contains = function(t, v)
for _, tmp in pairs(t) do
if v == tmp then
return true
end
end
return false
end
local str = getData()
local visited = {}
local houses = 1
local dir
local hash
local x, y = 0, 0
table.insert(visited, ('%dx%d'):format(x, y))
for i = 1, #str do
dir = str:sub(i, i)
if dir == '^' then
y = y - 1
elseif dir == 'v' then
y = y + 1
elseif dir == '<' then
x = x - 1
else
x = x + 1
end
hash = ('%dx%d'):format(x, y)
if not contains(visited, hash) then
houses = houses + 1
table.insert(visited, hash)
end
end
io.write(('Visited houses: %d\n'):format(houses))
local getData = function()
local f = io.open('D3P1.txt', 'r')
local data = f:read('*all'):gsub('%s*$', '')
f:close()
return data
end
local contains = function(t, v)
for _, tmp in pairs(t) do
if v == tmp then
return true
end
end
return false
end
local str = getData()
local visited = {}
local houses = 1
local dir
local hash
local x, y, n = {0, 0}, {0, 0}, 1
table.insert(visited, ('%dx%d'):format(x[1], y[1]))
for i = 1, #str do
n = ((i - 1) % 2) + 1
dir = str:sub(i, i)
if dir == '^' then
y[n] = y[n] - 1
elseif dir == 'v' then
y[n] = y[n] + 1
elseif dir == '<' then
x[n] = x[n] - 1
else
x[n] = x[n] + 1
end
hash = ('%dx%d'):format(x[n], y[n])
if not contains(visited, hash) then
houses = houses + 1
table.insert(visited, hash)
end
end
io.write(('Visited houses: %d\n'):format(houses))
-- NOTE: Requires luacrypto module
-- luarocks install luacrypto
local crypto = require 'crypto'
local str = '__your_input__'
local input, digest
local i = 0
while true do
input = ('%s%d'):format(str, i)
digest = crypto.digest('md5', input, false)
if digest:sub(1, 5) == '00000' then
io.write(('Solution found.\nInput: %s\nDigest: %s\nNumber: %d\n'):format(input, digest, i))
break
end
i = i + 1
end
-- NOTE: Requires luacrypto module
-- luarocks install luacrypto
local crypto = require 'crypto'
local str = '__your_input__'
local input, digest
local i = 0
while true do
input = ('%s%d'):format(str, i)
digest = crypto.digest('md5', input, false)
if digest:sub(1, 6) == '000000' then
io.write(('Solution found.\nInput: %s\nDigest: %s\nNumber: %d\n'):format(input, digest, i))
break
end
i = i + 1
end
local vowels = 3
local blacklist = {'ab', 'cd', 'pq', 'xy'}
local getVowelCount = function(str)
local _, count = str:gsub('[aeiou]', '')
return count
end
local hasDoubles = function(str)
local ch1, ch2
for i = 1, (#str - 1) do
ch1 = str:sub(i, i)
ch2 = str:sub(i + 1, i + 1)
if ch1 == ch2 then
return true
end
end
return false
end
local hasBlacklistedSeq = function(str)
for _, v in pairs(blacklist) do
if str:find(v) ~= nil then
return true
end
end
return false
end
local nice = 0
for line in io.lines('D5P1.txt') do
if getVowelCount(line) >= vowels and hasDoubles(line) and not hasBlacklistedSeq(line) then
nice = nice + 1
end
end
io.write(('Nice words: %d\n'):format(nice))
-- It contains a pair of any two letters that appears at least twice in
-- the string without overlapping, like xyxy (xy) or aabcdefgaa (aa), but
-- not like aaa (aa, but it overlaps).
local cond1 = function(str)
local ch1, ch2
for i = 1, (#str - 1) do
ch1 = str:sub(i, i)
ch2 = str:sub(i + 1, i + 1)
if str:find(('%s%s'):format(ch1, ch2), i + 2) ~= nil then
return true
end
end
return false
end
-- It contains at least one letter which repeats with exactly one letter
-- between them, like xyx, abcdefeghi (efe), or even aaa.
local cond2 = function(str)
local ch1, ch2
for i = 1, (#str - 2) do
ch1 = str:sub(i, i)
ch2 = str:sub(i + 2, i + 2)
if ch1 == ch2 then
return true
end
end
return false
end
local nice = 0
for line in io.lines('D5P2.txt') do
if cond1(line) and cond2(line) then
nice = nice + 1
end
end
io.write(('Nice words: %d\n'):format(nice))
local lights = {}
for x = 0, 999 do
lights[x] = {}
for y = 0, 999 do
lights[x][y] = false
end
end
local from, to = {}, {}
for line in io.lines('D6P1.txt') do
-- Toggle
from[1], from[2], to[1], to[2] = line:match('toggle (%d+),(%d+) through (%d+),(%d+)')
if from[1] ~= nil then
for x = from[1], to[1] do
for y = from[2], to[2] do
if lights[x][y] then
lights[x][y] = false
else
lights[x][y] = true
end
end
end
end
-- Turn on
from[1], from[2], to[1], to[2] = line:match('turn on (%d+),(%d+) through (%d+),(%d+)')
if from[1] ~= nil then
for x = from[1], to[1] do
for y = from[2], to[2] do
lights[x][y] = true
end
end
end
-- Turn off
from[1], from[2], to[1], to[2] = line:match('turn off (%d+),(%d+) through (%d+),(%d+)')
if from[1] ~= nil then
for x = from[1], to[1] do
for y = from[2], to[2] do
lights[x][y] = false
end
end
end
end
local total = 0
for x = 0, 999 do
for y = 0, 999 do
if lights[x][y] then
total = total + 1
end
end
end
io.write(('Total lights lit: %d\n'):format(total))
local brightness = {}
for x = 0, 999 do
brightness[x] = {}
for y = 0, 999 do
brightness[x][y] = 0
end
end
local from, to = {}, {}
for line in io.lines('D6P2.txt') do
-- Toggle
from[1], from[2], to[1], to[2] = line:match('toggle (%d+),(%d+) through (%d+),(%d+)')
if from[1] ~= nil then
for x = from[1], to[1] do
for y = from[2], to[2] do
brightness[x][y] = brightness[x][y] + 2
end
end
end
-- Turn on
from[1], from[2], to[1], to[2] = line:match('turn on (%d+),(%d+) through (%d+),(%d+)')
if from[1] ~= nil then
for x = from[1], to[1] do
for y = from[2], to[2] do
brightness[x][y] = brightness[x][y] + 1
end
end
end
-- Turn off
from[1], from[2], to[1], to[2] = line:match('turn off (%d+),(%d+) through (%d+),(%d+)')
if from[1] ~= nil then
for x = from[1], to[1] do
for y = from[2], to[2] do
brightness[x][y] = math.max(0, brightness[x][y] - 1)
end
end
end
end
local total = 0
for x = 0, 999 do
for y = 0, 999 do
total = total + brightness[x][y]
end
end
io.write(('Total brightness: %d\n'):format(total))
-- NOTE: Requires Lua 5.3
local wires = {}
local getValue = function(wire)
return wires[wire]
end
local setValue = function(wire, v)
wires[wire] = v & 65535
end
local getResult = function(a, b, op)
local res = 0
if op == 'AND' then
res = a & b
elseif op == 'OR' then
res = a | b
elseif op == 'LSHIFT' then
res = a << b
elseif op == 'RSHIFT' then
res = a >> b
end
return res
end
local wire, lhs, op, rhs
local a, b
local lines = {}
for line in io.lines('D7P1.txt') do
table.insert(lines, line)
end
while getValue('a') == nil do
for _, line in pairs(lines) do
-- Set signal
lhs, wire = line:match('^(%S+) %-%> (%S+)$')
if lhs and wire then
a = tonumber(lhs)
if a == nil then
a = getValue(lhs)
end
if a ~= nil then
setValue(wire, a)
end
end
-- AND, OR, LSHIFT and RSHIFT
lhs, op, rhs, wire = line:match('^(%S+) (%S+) (%S+) %-%> (%S+)$')
if lhs and op and rhs and wire then
a = tonumber(lhs)
if a == nil then
a = getValue(lhs)
end
b = tonumber(rhs)
if b == nil then
b = getValue(rhs)
end
if a ~= nil and b ~= nil then
setValue(wire, getResult(a, b, op))
end
end
-- NOT
lhs, wire = line:match('^NOT (%S+) %-%> (%S+)$')
if lhs and wire then
a = tonumber(lhs)
if a == nil then
a = getValue(lhs)
end
if a ~= nil then
setValue(wire, ~a)
end
end
end
end
io.write(('The signal provided to wire "a" is: %d\n'):format(getValue('a')))
-- NOTE: Requires Lua 5.3
-- It is exactly the same as D7P1.lua
local wires = {}
local getValue = function(wire)
return wires[wire]
end
local setValue = function(wire, v)
wires[wire] = v & 65535
end
local getResult = function(a, b, op)
local res = 0
if op == 'AND' then
res = a & b
elseif op == 'OR' then
res = a | b
elseif op == 'LSHIFT' then
res = a << b
elseif op == 'RSHIFT' then
res = a >> b
end
return res
end
local wire, lhs, op, rhs
local a, b
local lines = {}
for line in io.lines('D7P2.txt') do
table.insert(lines, line)
end
while getValue('a') == nil do
for _, line in pairs(lines) do
-- Set signal
lhs, wire = line:match('^(%S+) %-%> (%S+)$')
if lhs and wire then
a = tonumber(lhs)
if a == nil then
a = getValue(lhs)
end
if a ~= nil then
setValue(wire, a)
end
end
-- AND, OR, LSHIFT and RSHIFT
lhs, op, rhs, wire = line:match('^(%S+) (%S+) (%S+) %-%> (%S+)$')
if lhs and op and rhs and wire then
a = tonumber(lhs)
if a == nil then
a = getValue(lhs)
end
b = tonumber(rhs)
if b == nil then
b = getValue(rhs)
end
if a ~= nil and b ~= nil then
setValue(wire, getResult(a, b, op))
end
end
-- NOT
lhs, wire = line:match('^NOT (%S+) %-%> (%S+)$')
if lhs and wire then
a = tonumber(lhs)
if a == nil then
a = getValue(lhs)
end
if a ~= nil then
setValue(wire, ~a)
end
end
end
end
io.write(('The signal provided to wire "a" is: %d\n'):format(getValue('a')))
local code, value = 0, 0
local tmp
local convert = function(value)
return string.char(tonumber(value, 16))
end
for line in io.lines('D8P1.txt') do
code = code + #line
tmp = line:sub(2, #line - 1)
tmp = tmp:gsub('\\"', '"')
tmp = tmp:gsub('([^\\])\\\\x(%x%x)', '%1\\X%2')
tmp = tmp:gsub('\\\\', '\\')
tmp = tmp:gsub('\\x(%x%x)', convert)
value = value + #tmp
end
io.write(('Original: %d\nDecoded: %d\nResult: %d\n'):format(code, value, code - value))
local code, value = 0, 0
for line in io.lines('D8P2.txt') do
code = code + #line
value = value + #('%q'):format(line)
end
io.write(('Original: %d\nEncoded: %d\nResult: %d'):format(code, value, value - code))
local data = {}
local cities = {}
local from, to, distance
local contains = function(t, val)
for _, v in pairs(t) do
if v == val then
return true
end
end
return false
end
local getDistance = function(from, to)
for _, v in pairs(data) do
if v.from == from and v.to == to then
return v.distance
end
end
for _, v in pairs(data) do
if v.from == to and v.to == from then
return v.distance
end
end
return 0
end
-- http://rosettacode.org/wiki/Permutations#Lua
local permutation
permutation = function(a, n, cb)
if n == 0 then
cb(a)
else
for i = 1, n do
a[i], a[n] = a[n], a[i]
permutation(a, n - 1, cb)
a[i], a[n] = a[n], a[i]
end
end
end
for line in io.lines('D9P1.txt') do
from, to, distance = line:match('(%S+) to (%S+) = (%d+)')
table.insert(data, {
from = from,
to = to,
distance = distance
})
if not contains(cities, from) then
table.insert(cities, from)
end
if not contains(cities, to) then
table.insert(cities, to)
end
end
local shortest = 99999 -- Whatcha gonna do about it, nerd?
permutation(cities, #cities, function(data)
local distance = 0
for i = 1, #data - 1 do
distance = distance + getDistance(data[i], data[i + 1])
end
if distance < shortest then
shortest = distance
end
-- Uncomment to see the list of all routes (will take significantly longer due to I/O and table.concat)
-- io.write(('%s: %d\n'):format(table.concat(data, ' -> '), distance))
end)
io.write(('Shortest distance: %d\n'):format(shortest))
local data = {}
local cities = {}
local from, to, distance
local contains = function(t, val)
for _, v in pairs(t) do
if v == val then
return true
end
end
return false
end
local getDistance = function(from, to)
for _, v in pairs(data) do
if v.from == from and v.to == to then
return v.distance
end
end
for _, v in pairs(data) do
if v.from == to and v.to == from then
return v.distance
end
end
return 0
end
-- http://rosettacode.org/wiki/Permutations#Lua
local permutation
permutation = function(a, n, cb)
if n == 0 then
cb(a)
else
for i = 1, n do
a[i], a[n] = a[n], a[i]
permutation(a, n - 1, cb)
a[i], a[n] = a[n], a[i]
end
end
end
for line in io.lines('D9P2.txt') do
from, to, distance = line:match('(%S+) to (%S+) = (%d+)')
table.insert(data, {
from = from,
to = to,
distance = distance
})
if not contains(cities, from) then
table.insert(cities, from)
end
if not contains(cities, to) then
table.insert(cities, to)
end
end
local longest = 0
permutation(cities, #cities, function(data)
local distance = 0
for i = 1, #data - 1 do
distance = distance + getDistance(data[i], data[i + 1])
end
if distance > longest then
longest = distance
end
-- Uncomment to see the list of all routes (will take significantly longer due to I/O and table.concat)
-- io.write(('%s: %d\n'):format(table.concat(data, ' -> '), distance))
end)
io.write(('Longest distance: %d\n'):format(longest))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment