bignum = require "_openssl.bignum" function find(card, deck, times) local revert = false local increment = bignum.new(0) local multiply = bignum.new(1) for line in io.lines(arg[1]) do if line:find("^deal into new stack$") then revert = not revert elseif line:find("^cut %-?%d+$") then local val = tonumber(line:match("^cut (%-?%d+)$")) if not revert then increment = (increment - val) % deck else increment = (increment + val) % deck end elseif line:find("^deal with increment %d+$") then local val = tonumber(line:match("^deal with increment (%d+)$")) multiply = (multiply * val) % deck increment = (increment * val) % deck if revert then increment = (increment + (val - 1)) % deck end end end print(card, multiply, increment, deck) card = (card * multiply * times + increment * times) % deck if revert then card = deck - (card + 1) end return card end function revfind(card, deck, times) local revert = false local increment = bignum.new(0) local multiply = bignum.new(1) for line in io.lines(arg[1]) do if line:find("^deal into new stack$") then revert = not revert elseif line:find("^cut %-?%d+$") then local val = tonumber(line:match("^cut (%-?%d+)$")) if not revert then increment = (increment - val) % deck else increment = (increment + val) % deck end elseif line:find("^deal with increment %d+$") then local val = tonumber(line:match("^deal with increment (%d+)$")) multiply = (multiply * val) % deck increment = (increment * val) % deck if revert then increment = (increment + (val - 1)) % deck end end end print(card, multiply, increment, deck) card = (card * multiply * times + increment * times) % deck if revert then card = deck - (card + 1) end return card end print("Part 1:", find(2019, 10007, 1)) print("Part 2:", find(2020, 119315717514047, 101741582076661)) print("Part 1:", revfind(7744, 10007, 1)) print("Part 2:", revfind(2020, 119315717514047, 101741582076661))