Last active
December 3, 2017 14:16
-
-
Save diath/fd5e6568e042fb878857 to your computer and use it in GitHub Desktop.
Advent of Code, 2015, Lua
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
-- 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)) |
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
-- 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)) |
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
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)) |
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
-- 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)) |
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
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)) |
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
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)) |
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
-- 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)) |
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
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)) |
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
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)) |
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
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)) |
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
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 |
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
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)) |
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
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)) |
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
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)) |
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
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)) |
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
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)) |
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
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)) |
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
-- 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 |
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
-- 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 |
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
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)) |
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
-- 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)) |
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
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)) |
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
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)) |
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
-- 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'))) |
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
-- 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'))) |
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
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)) |
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
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)) |
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
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)) |
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
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