Compare commits
16 Commits
8c06a5172e
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| ed15159576 | |||
| 0ec0d19e65 | |||
| fa33a7bdf7 | |||
| 2317033e75 | |||
| 45c27ba067 | |||
| 5f57627225 | |||
| ec9d9b2a38 | |||
| 126064340b | |||
| 873ab82b19 | |||
| fda74621cb | |||
| 01b22927cf | |||
| 3052288380 | |||
| 3558a24b47 | |||
| 8edca7f075 | |||
| 7c95a358ad | |||
| 17f44d6fec |
@@ -1,3 +1,5 @@
|
|||||||
|
-- Description
|
||||||
|
--
|
||||||
-- Solution --------------------------------------------------------------------
|
-- Solution --------------------------------------------------------------------
|
||||||
function f()
|
function f()
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
-- Implement a function to return the largest value in a list.
|
||||||
|
--
|
||||||
-- Solution --------------------------------------------------------------------
|
-- Solution --------------------------------------------------------------------
|
||||||
function maximum(list)
|
function maximum(list)
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
-- Implement is_leap_year() below, returning whether the given year is
|
||||||
|
-- a leap year according to the Gregorian calendar.
|
||||||
|
--
|
||||||
-- Solution --------------------------------------------------------------------
|
-- Solution --------------------------------------------------------------------
|
||||||
function is_leap_year(year)
|
function is_leap_year(year)
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
-- The hamming distance is the number of positions in which two
|
||||||
|
-- strings differ, and is used to measure how similar strings are.
|
||||||
|
-- Implement the hamming_distance() function below to calculate this;
|
||||||
|
-- you may assume that the strings are of equal length.
|
||||||
|
--
|
||||||
-- Solution --------------------------------------------------------------------
|
-- Solution --------------------------------------------------------------------
|
||||||
function hamming_distance(str1, str2)
|
function hamming_distance(str1, str2)
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
@@ -1,18 +1,8 @@
|
|||||||
|
-- Write a function to determine the resistance (in ohms) of a given
|
||||||
|
-- three-part resistor colour code. The colour code is passed as a
|
||||||
|
-- list of strings.
|
||||||
|
--
|
||||||
-- Solution --------------------------------------------------------------------
|
-- Solution --------------------------------------------------------------------
|
||||||
-- Give the colours whatever values are convenient
|
|
||||||
black = undefined
|
|
||||||
brown = undefined
|
|
||||||
red = undefined
|
|
||||||
orange = undefined
|
|
||||||
yellow = undefined
|
|
||||||
green = undefined
|
|
||||||
blue = undefined
|
|
||||||
violet = undefined
|
|
||||||
grey = undefined
|
|
||||||
white = undefined
|
|
||||||
gold = undefined
|
|
||||||
silver = undefined
|
|
||||||
|
|
||||||
function decode_resistance(colours)
|
function decode_resistance(colours)
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
end
|
end
|
||||||
@@ -22,27 +12,27 @@ end
|
|||||||
local luaunit = require("luaunit.luaunit")
|
local luaunit = require("luaunit.luaunit")
|
||||||
|
|
||||||
function test_violet_orange_black_is_73_ohms()
|
function test_violet_orange_black_is_73_ohms()
|
||||||
local resistance = decode_resistance({violet, orange, black})
|
local resistance = decode_resistance({"violet", "orange", "black"})
|
||||||
luaunit.assertEquals(resistance, 73)
|
luaunit.assertEquals(resistance, 73)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_brown_green_black_is_15_ohms()
|
function test_brown_green_black_is_15_ohms()
|
||||||
local resistance = decode_resistance({brown, green, black})
|
local resistance = decode_resistance({"brown", "green", "black"})
|
||||||
luaunit.assertEquals(resistance, 15)
|
luaunit.assertEquals(resistance, 15)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_green_blue_orange_is_56_kiloohms()
|
function test_green_blue_orange_is_56_kiloohms()
|
||||||
local resistance = decode_resistance({green, blue, orange})
|
local resistance = decode_resistance({"green", "blue", "orange"})
|
||||||
luaunit.assertEquals(resistance, 56000)
|
luaunit.assertEquals(resistance, 56000)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_white_yellow_yellow_is_940_kiloohms()
|
function test_white_yellow_yellow_is_940_kiloohms()
|
||||||
local resistance = decode_resistance({white, yellow, yellow})
|
local resistance = decode_resistance({"white", "yellow", "yellow"})
|
||||||
luaunit.assertEquals(resistance, 940000)
|
luaunit.assertEquals(resistance, 940000)
|
||||||
end
|
end
|
||||||
|
|
||||||
function test_orange_red_silver_is_320_milliohms()
|
function test_orange_red_silver_is_320_milliohms()
|
||||||
local resistance = decode_resistance({orange, red, silver})
|
local resistance = decode_resistance({"orange", "red", "silver"})
|
||||||
luaunit.assertEquals(resistance, 0.32)
|
luaunit.assertEquals(resistance, 0.32)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
-- The greatest common divisor (GCD) of two numbers is, as the name
|
||||||
|
-- suggests, the largest number which evenly divides both. Implement
|
||||||
|
-- the function below to calculate this. It's recommended that you
|
||||||
|
-- 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)
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
-- Write a function to determine whether a given number is prime.
|
||||||
|
--
|
||||||
-- Solution --------------------------------------------------------------------
|
-- Solution --------------------------------------------------------------------
|
||||||
function is_prime(x)
|
function is_prime(x)
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
-- Implement is_palindrome(), which should return whether the passed
|
||||||
|
-- string is palindromic (i.e the same forwards as it is backwards).
|
||||||
|
-- Ignore non-letters and case.
|
||||||
|
--
|
||||||
-- Solution --------------------------------------------------------------------
|
-- Solution --------------------------------------------------------------------
|
||||||
function is_palindrome(str)
|
function is_palindrome(str)
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
-- Implement the is_anagram() function below, so that it returns true if
|
||||||
|
-- the two passed strings are anagrams of each other. Any non-
|
||||||
|
-- alphabetical characters in the string should be ignored.
|
||||||
|
--
|
||||||
-- Solution --------------------------------------------------------------------
|
-- Solution --------------------------------------------------------------------
|
||||||
function is_anagram(str1, str2)
|
function is_anagram(str1, str2)
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
-- Implement the function is_queen_threat() below. It should return
|
||||||
|
-- true if the queen is threatening the pawn and false otherwise. The
|
||||||
|
-- coordinates are as given as file (A-H), rank (1-8) pairs such as B3
|
||||||
|
-- and D7.
|
||||||
|
--
|
||||||
-- Solution --------------------------------------------------------------------
|
-- Solution --------------------------------------------------------------------
|
||||||
function is_queen_threat(queen_position, pawn_position)
|
function is_queen_threat(queen_position, pawn_position)
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
|
-- Write a function to return the hexadecimal representation (in a
|
||||||
|
-- string) of a number. Use lowercase a to f.
|
||||||
|
--
|
||||||
-- Solution --------------------------------------------------------------------
|
-- Solution --------------------------------------------------------------------
|
||||||
function hexadecimal(x)
|
function hexadecimal(x)
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
-- Write a function to calculate the nth fibonacci number.
|
||||||
|
--
|
||||||
-- Solution --------------------------------------------------------------------
|
-- Solution --------------------------------------------------------------------
|
||||||
function nth_fibonacci_number(n)
|
function nth_fibonacci_number(n)
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
@@ -1,3 +1,7 @@
|
|||||||
|
-- Implement is_balanced(), which should return true or false depending
|
||||||
|
-- on whether the brackets in the input string are balanced,
|
||||||
|
-- i.e. there is a closing bracket for each opening one.
|
||||||
|
--
|
||||||
-- Solution --------------------------------------------------------------------
|
-- Solution --------------------------------------------------------------------
|
||||||
function is_balanced(input)
|
function is_balanced(input)
|
||||||
-- Your implementation here
|
-- Your implementation here
|
||||||
43
13_prime_sieve.lua
Normal file
43
13_prime_sieve.lua
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
-- 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())
|
||||||
64
14_vigenere.lua
Normal file
64
14_vigenere.lua
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
-- 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())
|
||||||
28
15_run_length_encoding.lua
Normal file
28
15_run_length_encoding.lua
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
-- 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())
|
||||||
47
16_postfix.lua
Normal file
47
16_postfix.lua
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
-- 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())
|
||||||
50
17_prime_factors.lua
Normal file
50
17_prime_factors.lua
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
-- 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())
|
||||||
81
18_towers_of_hanoi.lua
Normal file
81
18_towers_of_hanoi.lua
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
-- 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())
|
||||||
105
19_dependencies.lua
Normal file
105
19_dependencies.lua
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
-- 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())
|
||||||
340
20_legal_captures.lua
Normal file
340
20_legal_captures.lua
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
-- 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())
|
||||||
39
README.md
Normal file
39
README.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Lua Exercises
|
||||||
|
|
||||||
|
This repo contains some Lua exercises along with automated tests for
|
||||||
|
solutions. Each file contains a description of the problem and an
|
||||||
|
area for a solution as well as the tests.
|
||||||
|
|
||||||
|
## Set Up
|
||||||
|
|
||||||
|
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
|
||||||
|
run `lua <the-file>`. For example, if you were working on the
|
||||||
|
anagrams exercise, you would run `lua 08_anagrams.lua`. For each
|
||||||
|
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.
|
||||||
Reference in New Issue
Block a user