diff --git a/c-distance/credit.c b/c-distance/credit.c index 2bff7f5..7ae5bbc 100644 --- a/c-distance/credit.c +++ b/c-distance/credit.c @@ -1,9 +1,43 @@ #include #include -// implement it here +int distance(lua_State* L) { + size_t len1, len2; + const char* str1 = luaL_checklstring(L, 1, &len1); + const char* str2 = luaL_checklstring(L, 2, &len2); + luaL_argcheck(L, len1 == len2, 2, + "Expect strings of equal length"); + char* result = lua_newuserdata(L, len1); + int mismatches = 0; + int i; + for (i = 0; i < len1; i++) { + char a = str1[i]; + char b = str2[i]; + luaL_argcheck(L, a == '0' || a == '1', 1, + "Only characters '0' and '1' are allowed"); + luaL_argcheck(L, b == '0' || b == '1', 1, + "Only characters '0' and '1' are allowed"); + if (a == b) { + result[i] = a; + } else { + if (mismatches % 2 == 0) { + result[i] = a; + } else { + result[i] = b; + } + mismatches += 1; + } + } + if (mismatches % 2 == 1) { + // result = impossible + lua_pushnil(L); + return 1; + } + lua_pushlstring(L, result, len1); + return 1; +} int luaopen_distance(lua_State* L) { - // return it here - return 0; + lua_pushcfunction(L, distance); + return 1; } diff --git a/c-distance/spec.lua b/c-distance/spec.lua index 6e396b8..b2c476b 100644 --- a/c-distance/spec.lua +++ b/c-distance/spec.lua @@ -1,21 +1,21 @@ describe("distance (implementation)", function() - pending("loads module", function() + it("loads module", function() local f = require 'distance' end) - pending("returns equally distant string", function() + it("returns equally distant string", function() local f = require 'distance' local middle = f('00', '11') assert(middle == '01' or middle == '10') end) - pending("returns nil if no equally distant string exists", + it("returns nil if no equally distant string exists", function() local f = require 'distance' assert(f('0', '1') == nil) end) - pending("throws error if length if input strings differ", + it("throws error if length if input strings differ", function() local f = require 'distance' assert.has_error(function() @@ -23,7 +23,7 @@ describe("distance (implementation)", function() end) end) - pending("throws error if an argument is not string", + it("throws error if an argument is not string", function() local f = require 'distance' assert.has_error(function() @@ -34,7 +34,7 @@ describe("distance (implementation)", function() end) end) - pending("throws error if input contains non-0-or-1", + it("throws error if input contains non-0-or-1", function() local f = require 'distance' assert.has_error(function() diff --git a/lua-distance/credit.lua b/lua-distance/credit.lua index 068643b..e7f4f64 100644 --- a/lua-distance/credit.lua +++ b/lua-distance/credit.lua @@ -1,5 +1,42 @@ +local function dist(a, b) + local mismatches = 0 + for i = 1, #a do + if a:sub(i, i) ~= b:sub(i, i) then + mismatches = mismatches + 1 + end + end + return mismatches +end + +local function has_error(f) + local status, err = pcall(f) + return not status +end + local function g(f) - -- implement it here + local p = f('00', '11') + assert(p == '01' or p == '10') + -- + local p = f('0', '1') + assert(p == nil) + -- + assert(has_error(function() + f() + end)) + assert(has_error(function() + f('', '0') + end)) + assert(has_error(function() + f('a', '0') + end)) + assert(has_error(function() + f('00', '0') + end)) + -- + local p = f('00101', '10100') + assert(#p == 5) + assert(p:match('^[01]*$')) + assert(dist(p, '00101') == dist(p, '10100')) end return g diff --git a/lua-distance/spec.lua b/lua-distance/spec.lua index e49acc9..3786872 100644 --- a/lua-distance/spec.lua +++ b/lua-distance/spec.lua @@ -1,9 +1,9 @@ describe("distance (unit test)", function() - pending("loads module", function() + it("loads module", function() local f = require 'distance.credit' end) - pending("accepts true solution", function() + it("accepts true solution", function() local f = require 'distance.credit' assert.has_no_error(function() f(function(A, B) @@ -36,7 +36,7 @@ describe("distance (unit test)", function() end) end) - pending("accepts true solution 2", function() + it("accepts true solution 2", function() local f = require 'distance.credit' assert.has_no_error(function() f(function(A, B) @@ -70,7 +70,7 @@ describe("distance (unit test)", function() end) end) - pending("throws on bad solutions", function() + it("throws on bad solutions", function() local f = require 'distance.credit' assert.has_error(function() f(function(A, B)