Compare commits

..

1 Commits

Author SHA1 Message Date
1acded5363 Add readme describing repo and how to run tests 2023-12-11 15:40:19 +00:00
21 changed files with 8 additions and 794 deletions

View File

@@ -1,43 +0,0 @@
-- Write a function which takes a limit and returns a list of every
-- prime number below that limit. It is recommended that you use the
-- "Sieve of Eratosthenes" algorithm, but you can try a different
-- prime sieve algorithm if you want.
--
-- Solution --------------------------------------------------------------------
function lesser_primes(limit)
-- Your implementation here
end
-- Tests -----------------------------------------------------------------------
local luaunit = require("luaunit.luaunit")
function test_primes_below_2048()
local primes = {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013, 1019,
1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097,
1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181, 1187, 1193, 1201,
1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373, 1381, 1399, 1409,
1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471, 1481, 1483, 1487,
1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579,
1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657, 1663, 1667,
1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747, 1753, 1759, 1777,
1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877,
1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987, 1993,
1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039
}
luaunit.assertEquals(lesser_primes(2048), primes)
end
os.exit(luaunit.LuaUnit.run())

View File

@@ -1,64 +0,0 @@
-- The Vigenère cipher is a way to encrypt text, where a key is
-- repeated for the length of the plaintext and the alphabetical
-- position of the keyword letter determines the amount the letter of
-- the plaintext is shifted by. For example, for plaintext "FOO" and
-- key "BAR", the first letter of the cipher text would be G, the
-- result of shifting the letter F (first letter of the plaintext)
-- over by 1 (the zero-based alphabetical position of B, first letter
-- of the key).
--
-- Implement a function to encode a message with a given keyword. The
-- message should be converted to upper-case and any non-alphabetical
-- characters should be discarded.
--
-- Solution --------------------------------------------------------------------
local a_value = 65
function apply_shift(letter, shift)
local shifted = (letter - a_value + shift) % 26
return a_value + shifted
end
function vigenere_encode(plaintext, keyword)
local key = {}
for i = 1, #keyword do
local shift = string.byte(keyword, i) - a_value
table.insert(key, shift)
end
plaintext = string.gsub(string.upper(plaintext), "%A+", "")
ciphertext = ""
for i = 1, #plaintext do
local letter = string.byte(plaintext, i)
local shift = key[(i - 1) % #key + 1]
local shifted = apply_shift(letter, shift)
ciphertext = ciphertext .. string.char(shifted)
end
return ciphertext
end
-- Tests -----------------------------------------------------------------------
local luaunit = require("luaunit.luaunit")
function test_encoding_of_foo_with_key_BAR()
luaunit.assertEquals(vigenere_encode("FOO", "BAR"), "GOF")
end
function test_encoding_of_the_quick_brown_fox_with_key_JUMPSOVER()
local plaintext = "The quick brown fox"
local key = "JUMPSOVER"
local expected = "CBQFMWXOSAIICXCS"
luaunit.assertEquals(vigenere_encode(plaintext, key), expected)
end
function test_encoding_longer_phrase_with_key_LEAR()
local plaintext =
"They dined on mince and slices of quince, which they ate with a runcible spoon."
local key = "LEAR"
local expected = "ELEPOMNVOSNDTRCVLRDJWMCVDSFHFMNTPAHZNLTYPCAKPAIKSERLYGISWISGZSN"
luaunit.assertEquals(vigenere_encode(plaintext, key), expected)
end
os.exit(luaunit.LuaUnit.run())

View File

@@ -1,28 +0,0 @@
-- Run length encoding is a simple data compression technique where a
-- "run" of the same value is replaced with a count and a single copy.
-- In this exercise we will use the notation "#<count>:<value>" to
-- indicate such a run; however, this should only be put into the
-- output if it is strictly shorter than the string it is replacing.
-- The input will consist only of alphanumeric characters.
--
-- Solution --------------------------------------------------------------------
function run_length_encode(input)
-- Your implementation here
end
-- Tests -----------------------------------------------------------------------
local luaunit = require("luaunit.luaunit")
function test_encoding_of_aaaaaaaa22bbbbbbssssfffffff67eee66666asdfff()
local input = "aaaaaaaa22bbbbbbssssfffffff67eee66666asdfff"
local expected = "#8:a22#6:bssss#7:f67eee#5:6asdfff"
luaunit.assertEquals(run_length_encode(input), expected)
end
function test_encoding_of_wwwwwfffff1223566666666bbbbbbbbbbb78b99asasdfbnfasdafffffff99()
local input = "wwwwwfffff1223566666666bbbbbbbbbbb78b99asasdfbnfasdafffffff99"
local expected = "#5:w#5:f12235#8:6#11:b78b99asasdfbnfasda#7:f99"
luaunit.assertEquals(run_length_encode(input), expected)
end
os.exit(luaunit.LuaUnit.run())

View File

@@ -1,47 +0,0 @@
-- Postfix notation is an alternative to the normal "infix" notation
-- used in mathematical expressions. Instead of writing the operator
-- between the operands, the operator comes after them. For example,
-- "1 + 2" is notated as "1 2 +". This removes the need for operator
-- precedence and parentheses: rather than having to resolve the
-- ambiguity of an expression like "1 + 2 * 3" with convention or
-- parentheses, the evaluation order is explicit -- multiplication-
-- first is "1 2 3 * +" and addition-first is "1 2 + 3 *".
--
-- As well as this notational convenience, postfix can be easily
-- evaluated using a stack. Whenever an operand is encountered, the
-- value is pushed onto the stack, and whenever an operator is
-- encountered, two values are popped from the stack and the result of
-- the operation is pushed on in their place. Finally, the value left
-- on the top of the stack is the result of the operation.
--
-- Write a function that will evaluate a postfix expression and return
-- the result. You can assume that the expression is valid, and not
-- worry about handling error cases. The operators will be "+", "-",
-- "*" and "/".
--
-- Solution --------------------------------------------------------------------
function evaluate_postfix(expression)
-- Your implementation here
end
-- Tests -----------------------------------------------------------------------
local luaunit = require("luaunit.luaunit")
function test_1_2_plus_3_times_is_9()
luaunit.assertEquals(evaluate_postfix("1 2 + 3 *"), 9)
end
function test_1_2_3_times_plus_is_7()
luaunit.assertEquals(evaluate_postfix("1 2 3 * +"), 7)
end
function test_4_6_plus_5_divide_2_1_minus_minus_is_1()
luaunit.assertEquals(evaluate_postfix("4 6 + 5 / 2 1 - -"), 1)
end
function test_12_2_times_6_divide_10_times_2_plus_is_42()
luaunit.assertEquals(evaluate_postfix("12 2 * 6 / 10 * 2 +"), 42)
end
os.exit(luaunit.LuaUnit.run())

View File

@@ -1,50 +0,0 @@
-- Write a function which determines the prime factors of a given
-- number, returning them in a list. You may assume that none of the
-- prime factors are above 10000
--
-- Solution --------------------------------------------------------------------
function prime_factors(n)
-- Your implementation here
end
-- Tests -----------------------------------------------------------------------
local luaunit = require("luaunit.luaunit")
function test_prime_factors_of_42()
luaunit.assertItemsEquals(prime_factors(42), {2, 3, 7})
end
function test_prime_factors_of_70()
luaunit.assertItemsEquals(prime_factors(70), {2, 5, 7})
end
function test_prime_factors_of_253()
luaunit.assertItemsEquals(prime_factors(253), {11, 23})
end
function test_prime_factors_of_245()
luaunit.assertItemsEquals(prime_factors(245), {5, 7, 7})
end
function test_prime_factors_of_36()
luaunit.assertItemsEquals(prime_factors(36), {2, 2, 3, 3})
end
function test_prime_factors_of_1337()
luaunit.assertItemsEquals(prime_factors(1337), {7, 191})
end
function test_prime_factors_of_4321()
luaunit.assertItemsEquals(prime_factors(4321), {29, 149})
end
function test_prime_factors_of_57812834()
luaunit.assertItemsEquals(prime_factors(57812834), {2, 29, 113, 8821})
end
function test_prime_factors_of_8894220()
luaunit.assertItemsEquals(prime_factors(8894220), {2, 2, 3, 5, 271, 547})
end
os.exit(luaunit.LuaUnit.run())

View File

@@ -1,81 +0,0 @@
-- The Towers of Hanoi is a mathematical puzzle consisting of three
-- rods and a number of disks of various diameters which can slide
-- onto any rod. Initially, all the disks are stacked in decreasing
-- size order so that they form a conical shape. The objective to
-- move the entire stack to one of the other two rods, with each move
-- consisting of taking the uppermost disk from one of the rods and
-- placing it on top of the stack on another one. A disk cannot be
-- placed on top of a disk of smaller diameter.
--
-- Write a function which generates an optimal solution to the puzzle.
-- The rods are numbered 1-3, with the stack starting on rod 1. Your
-- function should return a list of {from = <rod>, to = <rod>} tables,
-- and will receive the number of disks in the original stack as its
-- argument.
--
-- Solution --------------------------------------------------------------------
function towers_of_hanoi_solution(disk_count)
-- Your implementation here
end
-- Tests -----------------------------------------------------------------------
local luaunit = require("luaunit.luaunit")
local function disk_stack(count)
local stack = {}
for i = count, 1, -1 do table.insert(stack, i) end
return stack
end
local function assert_valid(state)
for _, rod in ipairs(state) do
local previous = rod[1]
for _, disk in ipairs(rod) do
luaunit.assertTrue(disk <= previous)
previous = disk
end
end
return true
end
local function assert_solved(state, disk_count)
luaunit.assertEquals(state[1], {})
if #state[2] ~= 0 then
luaunit.assertEquals(state[2], disk_stack(disk_count))
luaunit.assertEquals(state[3], {})
else
luaunit.assertEquals(state[2], {})
luaunit.assertEquals(state[3], disk_stack(disk_count))
end
end
local function assert_is_solution(solution, disk_count)
local state = {disk_stack(disk_count), {}, {}}
for i, move in ipairs(solution) do
local disk = table.remove(state[move.from])
table.insert(state[move.to], disk)
assert_valid(state)
end
assert_solved(state, disk_count)
end
local function test_with_count(disk_count)
local solution = towers_of_hanoi_solution(disk_count)
assert_is_solution(solution, disk_count)
luaunit.assertEquals(#solution, 2 ^ disk_count - 1)
end
function test_with_1_disk()
test_with_count(1)
end
function test_with_7_disks()
test_with_count(7)
end
function test_with_12_disks()
test_with_count(12)
end
os.exit(luaunit.LuaUnit.run())

View File

@@ -1,105 +0,0 @@
-- Write a function to generate a valid order for a number of jobs
-- that depend upon each other. Your input is a jobs table; each key
-- is a job number, with its the values being a list jobs it depends
-- on. You may assume that there are no circular dependencies.
--
-- Return a list of job numbers, so that performing the jobs in that
-- order ensures that all jobs are exactly once, and all dependencies
-- of a job are done before prior to it.
--
-- Solution --------------------------------------------------------------------
function schedule(jobs)
-- Your implementation here
end
-- Tests -----------------------------------------------------------------------
local luaunit = require("luaunit.luaunit")
local function keys(t)
local results = {}
for key, _ in pairs(t) do table.insert(results, key) end
return results
end
local function contains(list, target)
for _, item in ipairs(list) do if item == target then return true end end
return false
end
local function deep_copy(original)
local copy = {}
if type(original) == "table" then
for key, value in pairs(original) do
local key_copy = deep_copy(key)
local value_copy = deep_copy(value)
copy[key_copy] = value_copy
end
else
copy = original
end
return copy
end
local function assert_valid(order, jobs)
local done = {}
for _, job in ipairs(order) do
for _, dependency in ipairs(jobs[job]) do
luaunit.assertTrue(contains(done, dependency))
end
table.insert(done, job)
end
end
local function test_case(jobs)
local order = schedule(deep_copy(jobs))
luaunit.assertItemsEquals(order, keys(jobs))
assert_valid(order, jobs)
end
function test_sequential_dependencies()
local jobs = {[1] = {2}, [2] = {3}, [3] = {}}
test_case(jobs)
end
function test_converging_dependencies()
local jobs = {
[1] = {5},
[2] = {5},
[3] = {6},
[4] = {6},
[5] = {7},
[6] = {7},
[7] = {},
}
test_case(jobs)
end
function test_diverging_dependencies()
local jobs = {
[1] = {2, 3},
[2] = {4, 5},
[3] = {6, 7},
[4] = {},
[5] = {},
[6] = {},
[7] = {}
}
test_case(jobs)
end
function test_compound_dependencies()
local jobs = {
[1] = {2, 3, 4},
[2] = {5, 6},
[3] = {7},
[4] = {7},
[5] = {},
[6] = {8},
[7] = {8},
[8] = {}
}
test_case(jobs)
end
os.exit(luaunit.LuaUnit.run())

View File

@@ -1,340 +0,0 @@
-- Write a function which takes a description of a chess position and
-- returns a list of all legal captures from that position.
--
-- The position will be given as a table, containing the keys "turn",
-- indicating which player it is to move, "board", which will contain
-- a rank-major grid of pieces (that is, a list of ranks/rows). Each
-- piece will be indicated by its unicode symbol. The lack of a piece
-- will be indicated by nil. If the previous move was a pawn moving
-- two places, the key "en_passant_target" will be set to a table with
-- "rank" and "file" keys set to the (1-based) rank and file indices
-- of the square passed over by the pawn.
--
-- For example, the starting position would be given as:
--
-- {
-- turn = "white",
-- board = {
-- {"♖", "♘", "♗", "♕", "♔", "♗", "♘", "♖"},
-- {"♙", "♙", "♙", "♙", "♙", "♙", "♙", "♙"},
-- {nil, nil, nil, nil, nil, nil, nil, nil},
-- {nil, nil, nil, nil, nil, nil, nil, nil},
-- {nil, nil, nil, nil, nil, nil, nil, nil},
-- {nil, nil, nil, nil, nil, nil, nil, nil},
-- {"♟︎", "♟︎", "♟︎", "♟︎", "♟︎", "♟︎", "♟︎", "♟︎"},
-- {"♜", "♞", "♝", "♛", "♚", "♝", "♞", "♜"},
-- },
-- }
--
-- Moves should be returned in figurine algebraic notation, without
-- indicators for en passant, check or checkmate (i.e. no "e.p.", "+"
-- or "#"). For example, "♞xc6" for a black night capturing on c6 and
-- "exd7" for an e-file pawn capturing on d7. For the sake of
-- simplicity, there's no requirement to disambiguate between two
-- pieces of the same type when the notation for the capture would
-- otherwise be the same (e.g. if two rooks can capture on the same
-- square). However, there should be duplicate entries in the results
-- list for each.
--
-- Solution --------------------------------------------------------------------
function legal_captures(position)
-- Your implementation here
end
-- Tests -----------------------------------------------------------------------
local luaunit = require("luaunit.luaunit")
function test_starting_position()
local position = {
turn = "white",
board = {
{"", "", "", "", "", "", "", ""},
{"", "", "", "", "", "", "", ""},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{"♟︎", "♟︎", "♟︎", "♟︎", "♟︎", "♟︎", "♟︎", "♟︎"},
{"", "", "", "", "", "", "", ""},
},
}
local expected = {}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_queens_gambit()
local position = {
turn = "black",
board = {
{"", "", "", "", "", "", "", ""},
{"", "", nil, nil, "", "", "", ""},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, "", "", nil, nil, nil, nil},
{nil, nil, nil, "♟︎", nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{"♟︎", "♟︎", "♟︎", nil, "♟︎", "♟︎", "♟︎", "♟︎"},
{"", "", "", "", "", "", "", ""},
},
}
local expected = {"dxc4"}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_scandinavian_defense()
local position = {
turn = "white",
board = {
{"", "", "", "", "", "", "", ""},
{"", "", "", "", nil, "", "", ""},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, "", nil, nil, nil},
{nil, nil, nil, "♟︎", nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{"♟︎", "♟︎", "♟︎", nil, "♟︎", "♟︎", "♟︎", "♟︎"},
{"", "", "", "", "", "", "", ""},
},
}
local expected = {"exd5"}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_knight_captures()
local position = {
turn = "black",
board = {
{"", "", "", "", "", "", "", ""},
{"", "", "", nil, "", "", "", ""},
{"", "", nil, nil, nil, "", "", ""},
{"", nil, nil, "", nil, nil, "", ""},
{"", "", nil, nil, nil, "", "", ""},
{"", "", "", nil, "", "", "", ""},
{"", "", "", "", "", "", "", ""},
{"", "", "", "", "", "", "", ""},
},
}
local expected = {
"♞xb3", "♞xb5", "♞xc2", "♞xc6", "♞xe2", "♞xe6", "♞xf3", "♞xf5",
}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_knight_not_blocked()
local position = {
turn = "white",
board = {
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, "♟︎", "♟︎", "♟︎", nil, nil},
{nil, nil, nil, nil, "♟︎", nil, nil, nil},
{nil, nil, "♟︎", "♟︎", "", nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
},
}
local expected = {"♘xd3", "♘xf3"}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_bishop_captures()
local position = {
turn = "black",
board = {
{nil, nil, nil, nil, nil, nil, nil, nil},
{"", nil, nil, nil, nil, nil, "", nil},
{nil, nil, nil, "", nil, nil, "", nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, "", "", nil, nil, nil, ""},
{nil, nil, nil, nil, "", nil, nil, nil},
{nil, "", nil, nil, nil, nil, nil, nil},
{nil, nil, nil, "", nil, nil, nil, nil},
},
}
local expected = {"♝xa2", "♝xb7", "♝xe6", "♝xg2"}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_bishop_blocked()
local position = {
turn = "black",
board = {
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, "", nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, "", nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, "", nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
},
}
local expected = {}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_rook_captures()
local position = {
turn = "white",
board = {
{nil, nil, nil, nil, nil, nil, nil, nil},
{"♟︎", nil, nil, nil, nil, nil, "♟︎", nil},
{nil, nil, nil, "♟︎", nil, nil, "♟︎", nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, "♟︎", "", nil, nil, nil, "♟︎"},
{nil, nil, nil, nil, "♟︎", nil, nil, nil},
{nil, "♟︎", nil, nil, nil, nil, nil, nil},
{nil, nil, nil, "♟︎", nil, nil, nil, nil},
},
}
local expected = {"♖xc5", "♖xd3", "♖xd8", "♖xh5"}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_rook_blocked()
local position = {
turn = "white",
board = {
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, "", "", nil, nil, nil, "♟︎", nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
},
}
local expected = {}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_queen_captures()
local position = {
turn = "black",
board = {
{nil, "", "", "", "", "", nil, ""},
{"", "", "", nil, "", "", "", ""},
{"", "", nil, nil, nil, "", "", ""},
{"", nil, nil, "", nil, nil, "", nil},
{"", "", nil, nil, nil, "", "", ""},
{"", "", "", nil, "", "", "", ""},
{nil, "", "", "", "", "", nil, ""},
{"", "", "", nil, "", "", "", nil},
},
}
local expected = {
"♛xa4", "♛xb2", "♛xb6", "♛xd1", "♛xd7", "♛xf2", "♛xf6", "♛xg4",
}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_queen_blocked()
local position = {
turn = "white",
board = {
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, "♟︎", nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, "", nil, nil, nil, nil, nil},
{nil, "", "", nil, nil, nil, "♟︎", nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
},
}
local expected = {}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_king_captures()
local position = {
turn = "black",
board = {
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, "", "", "", nil, nil, nil},
{nil, nil, "", "", "", nil, nil, nil},
{nil, nil, "", "", "", nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
},
}
local expected = {"♚xc3","♚xc4","♚xc5","♚xd3","♚xd5","♚xe3","♚xe4","♚xe5",}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_en_passant()
local position = {
turn = "white",
board = {
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, "♟︎", "", nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
},
en_passant_target = {rank = 6, file = 4},
}
local expected = {"exd6"}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_cannot_capture_if_leads_to_check()
local position = {
turn = "white",
board = {
{nil, nil, nil, nil, "", nil, nil, nil},
{nil, nil, nil, nil, "", nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, "♟︎", nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, "", nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
},
en_passant_target = {rank = 6, file = 4},
}
local expected = {}
luaunit.assertItemsEquals(legal_captures(position), expected)
end
function test_position_with_lots_of_captures()
local position = {
turn = "white",
board = {
{"", nil, nil, "", "", nil, nil, ""},
{nil, "", "", "", "", "", "", nil},
{nil, nil, nil, nil, nil, nil, nil, nil},
{"", "", "", "", "", "", "", ""},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, "", "", "", "", "", "", ""},
{nil, nil, nil, nil, nil, nil, nil, nil},
{nil, nil, nil, "", "", "", nil, nil},
},
en_passant_target = {rank = 6, file = 4},
}
local expected = {
"♔xe1", "♔xe2", "♔xc2", "♖xh4", "♖xe1",
"♖xb4", "♖xc2", "♕xf4", "♕xb4", "♕xe1",
"♕xd4", "♕xe2", "♕xc2", "♕xh4", "♕xd4",
"♕xe1", "♕xf4", "♕xe2", "♘xh4", "♘xf4",
"♘xe1", "♗xc6", "♗xc2", "♕xe6", "♕xe2",
"♕xc6", "♕xc2", "♕xd4", "♕xb4", "♕xc6",
"♕xc2", "♕xe6", "♕xe2", "♕xf4", "♕xd4",
"♕xe6", "♕xe2", "♕xh4", "♕xf4", "♕xd8",
"♕xd4", "♕xb4", "♕xc6", "♕xf8", "♕xf4",
"♕xb4", "♕xd8", "♕xd4", "♕xe6", "♕xc6",
"♕xd8", "♕xh4", "♕xd4", "♕xf8", "♕xf4",
"♕xe6", "♘xf8", "♘xh4", "♘xf4", "♗xf8",
"♗xf4", "♕xc6", "♕xe6", "♕xf8", "♕xd8",
}
local captures = legal_captures(position)
luaunit.assertItemsEquals(captures, expected)
end
os.exit(luaunit.LuaUnit.run())

View File

@@ -1,39 +1,13 @@
# Lua Exercises # Lua Exercises
This repo contains some Lua exercises along with automated tests for This repo contains some Lua exercises along with automated tests for
solutions. Each file contains a description of the problem and an their solutions. Each file contains a description of the problem and
area for a solution as well as the tests. an area for your solution as well as the tests. Feel free to define
as many functions and constants as you need in the solution area, but
## Set Up do not modify the tests.
To get started, create a fork of this repo on your own account (with
the "Fork" button in the top-left of the Gitea page"), then clone it,
passing the `--recursive` flag. If you already cloned it without
passing `--recursive`, you can run `git submodule update --init` to
fix it.
```sh
git clone --recursive git@git.wip.sh:<your-username>/lua-exercises.git
```
## Doing the Exercises
It's recommended that you roughly stick to the defined order of the
exercises, but feel free to deviate if you wish. Some of the
exercises are relatively easy, whereas some of them (especially the
last few) are quite challenging; do not be disheartened if solving a
particular exercise takes you a long time, and feel free to ask for
help in the Discord server if you feel you are stuck.
You can define as many functions and constants as you need in the
solution area. You might find it useful to temporarily comment out
some of the tests to work through the cases one by one (especially on
the more complex exercises), but do not modify the test code other
than this, and make sure all the cases are un-commented again before
considering the exercise solved.
To run the tests and check your solution for a given exercise, simply To run the tests and check your solution for a given exercise, simply
run `lua <the-file>`. For example, if you were working on the run `lua <the-file>`. For example, if you were working on the
anagrams exercise, you would run `lua 08_anagrams.lua`. For each anagrams exercise, you would run `lua xxx_anagrams.lua`. For each
exercise, the tests should run in well under a tenth of a second; if exercise, the tests should run in well under a tenth of a second; if
it takes longer than this you should try to speed up your solution. it takes longer than this you should try to speed up your solution.

View File

@@ -1,8 +1,6 @@
-- The greatest common divisor (GCD) of two numbers is, as the name -- The greatest common divisor (GCD) of two numbers X and Y is, as the
-- suggests, the largest number which evenly divides both. Implement -- name suggests, the largest number which evenly divides both X and
-- the function below to calculate this. It's recommended that you -- Y. Implement the function below to calculate this.
-- use Euclid's algorithm but feel free to use another approach if you
-- want.
-- --
-- Solution -------------------------------------------------------------------- -- Solution --------------------------------------------------------------------
function greatest_common_divisor(x, y) function greatest_common_divisor(x, y)