Re: Requesting submissions for Exercism track

new topic     » goto parent     » topic index » view thread      » older message » newer message

Oh, you've done yacht, n'er mind, here's a few more that I quickly bashed out smile

function score_yacht(sequence hand, string category) 
    integer score = 0 
    if category[$]='s' then 
        score = find(category,{"ones","twos","threes","fours","fives","sixes"}) 
        score = sum(sq_eq(hand,score))*score 
    else 
        hand = sort(deep_copy(hand)) 
        integer {c1,c2,c3,c4,c5} = hand 
        if category="full house" then 
            if (c1=c3 and c4=c5 and c3!=c4) 
            or (c1=c2 and c3=c5 and c2!=c3) then 
                score = sum(hand) 
            end if 
        elsif category="four of a kind" then 
            if c2=c4 and (c1=c2 or c4=c5) then 
                score = c3*4 
            end if 
        elsif category="little straight" then 
            if hand={1,2,3,4,5} then 
                score = 30 
            end if 
        elsif category="big straight" then 
            if hand={2,3,4,5,6} then 
                score = 30 
            end if 
        elsif category="choice" then 
            score = sum(hand) 
        elsif category="yacht" then 
            if c1=c5 then 
                score = 50 
            end if 
        else 
            ?9/0 
        end if 
    end if 
    return score 
end function 
 
constant tests = {{"Yacht",{5, 5, 5, 5, 5},"yacht",50}, 
                  {"Not Yacht",{1, 3, 3, 2, 5},"yacht",0}, 
                  {"Ones",{1, 1, 1, 3, 5},"ones",3}, 
                  {"Ones, out of order",{3, 1, 1, 5, 1},"ones",3}, 
                  {"No ones",{4, 3, 6, 5, 5},"ones",0}, 
                  {"Twos",{2, 3, 4, 5, 6},"twos",2}, 
                  {"Fours",{1, 4, 1, 4, 1},"fours",8}, 
                  {"Yacht counted as threes",{3, 3, 3, 3, 3},"threes",15}, 
                  {"Yacht of 3s counted as fives",{3, 3, 3, 3, 3},"fives",0}, 
                  {"Fives",{1, 5, 3, 5, 3},"fives",10}, 
                  {"Sixes",{2, 3, 4, 5, 6},"sixes",6}, 
                  {"Full house two small, three big",{2, 2, 4, 4, 4},"full house",16}, 
                  {"Full house three small, two big",{5, 3, 3, 5, 3},"full house",19}, 
                  {"Two pair is not a full house",{2, 2, 4, 4, 5},"full house",0}, 
                  {"Four of a kind is not a full house",{1, 4, 4, 4, 4},"full house",0}, 
                  {"Yacht is not a full house",{2, 2, 2, 2, 2},"full house",0}, 
                  {"Four of a Kind",{6, 6, 4, 6, 6},"four of a kind",24}, 
                  {"Yacht can be scored as Four of a Kind",{3, 3, 3, 3, 3},"four of a kind",12}, 
                  {"Full house is not Four of a Kind",{3, 3, 3, 5, 5},"four of a kind",0}, 
                  {"Little Straight",{3, 5, 4, 1, 2},"little straight",30}, 
                  {"Little Straight as Big Straight",{1, 2, 3, 4, 5},"big straight",0}, 
                  {"Four in order but not a little straight",{1, 1, 2, 3, 4},"little straight",0}, 
                  {"No pairs but not a little straight",{1, 2, 3, 4, 6},"little straight",0}, 
                  {"Minimum is 1, maximum is 5, but not a little straight",{1, 1, 3, 4, 5},"little straight",0}, 
                  {"Big Straight",{4, 6, 2, 5, 3},"big straight",30}, 
                  {"Big Straight as little straight",{6, 5, 4, 3, 2},"little straight",0}, 
                  {"No pairs but not a big straight",{6, 5, 4, 3, 1},"big straight",0}, 
                  {"Choice",{3, 3, 5, 6, 6},"choice",23}, 
                  {"Yacht as choice",{2, 2, 2, 2, 2},"choice",10}} 
for t in tests do 
    {string desc, sequence hand, string category, integer expected} = t 
    assert(score_yacht(hand,category)=expected,desc) 
end for 
 
 
function encode(sequence data) 
    sequence bytes = {} 
    for d in reverse(data) do 
        bytes &= and_bits(d,#7F) 
        d = floor(d/#80) 
        while d do 
            bytes &= and_bits(d,#7F)+#80 
            d = floor(d/#80) 
        end while        
    end for 
    bytes = reverse(bytes) 
    return bytes 
end function 
 
function decode(sequence bytes) 
    sequence data = {} 
    if length(bytes) and and_bits(bytes[$],#80) then 
        return "incomplete sequence" 
    end if 
    atom d = 0 
    for b in bytes do 
        d = d*#80 + and_bits(b,#7F) 
        if not and_bits(b,#80) then 
            data &= d 
            d = 0 
        end if 
    end for 
    return data 
end function 
 
constant e = {{"zero",{#00},{#00}}, 
              {"arbitrary single byte",{#40},{#40}}, 
              {"largest single byte",{#7F},{#7F}}, 
              {"smallest double byte",{#80},{#81, #00}}, 
              {"arbitrary double byte",{#2000},{#C0, #00}}, 
              {"largest double byte",{#3FFF},{#FF, #7F}}, 
              {"smallest triple byte",{#4000},{#81, #80, #00}}, 
              {"arbitrary triple byte",{#100000},{#C0, #80, #00}}, 
              {"largest triple byte",{#1FFFFF},{#FF, #FF, #7F}}, 
              {"smallest quadruple byte",{#200000},{#81, #80, #80, #00}}, 
              {"arbitrary quadruple byte",{#8000000},{#C0, #80, #80, #00}}, 
              {"largest quadruple byte",{#FFFFFFF},{#FF, #FF, #FF, #7F}}, 
              {"smallest quintuple byte",{#10000000},{#81, #80, #80, #80, #00}}, 
              {"arbitrary quintuple byte",{#FF000000},{#8F, #F8, #80, #80, #00}}, 
              {"maximum 32-bit integer input",{#FFFFFFFF},{#8F, #FF, #FF, #FF, #7F}}, 
              {"two single-byte values",{#40, #7F},{#40, #7F}}, 
              {"two multi-byte values",{#4000, #123456},{#81, #80, #00, #C8, #E8, #56}}, 
              {"many multi-byte values",{#2000, #123456, #FFFFFFF, #00, #3FFF, #4000}, 
                                        {#C0, #0, #C8, #E8, #56, #FF, #FF, #FF, #7F, #00, #FF, #7F, #81, #80, #00}}}, 
         d = {{"one byte",{#7F},{#7F}}, 
              {"two bytes",{#C0, #00},{#2000}}, 
              {"three bytes",{#FF, #FF, #7F},{#1FFFFF}}, 
              {"four bytes",{#81, #80, #80, #0},{#200000}}, 
              {"maximum 32-bit integer",{#8F, #FF, #FF, #FF, #7F},{#FFFFFFFF}}, 
              {"incomplete sequence causes error",{#FF},"incomplete sequence"}, 
              {"incomplete sequence causes error, even if value is zero",{#80},"incomplete sequence"}, 
              {"multiple values",{#C0, #00, #C8, #E8, #56, #FF, #FF, #FF, #7F, #00, #FF, #7F, #81, #80, #00}, 
                                 {#2000, #123456, #FFFFFFF, #00, #3FFF, #4000}}} 
 
string desc; sequence data, expected 
for t in e do 
    {desc, data, expected} = t 
    assert(encode(data)=expected,desc) 
end for 
for t in d do 
    {desc, data, expected} = t 
    assert(decode(data)=expected,desc) 
end for 
 
function sum_of_multiples(sequence f, integer lim) 
    integer res = 0 
    for n = 1 to lim-1 do 
        for k in f do  
            if k!=0 and remainder(n,k)=0 then 
                res += n 
                exit 
            end if 
        end for 
    end for 
    return res 
end function 
 
constant tests = {{"no multiples within limit",{3, 5},1,0}, 
                  {"one factor has multiples within limit",{3, 5},4,3}, 
                  {"more than one multiple within limit",{3},7,9}, 
                  {"more than one factor with multiples within limit",{3, 5},10,23}, 
                  {"each multiple is only counted once",{3, 5},100,2318}, 
                  {"a much larger limit",{3, 5},1000,233168}, 
                  {"three factors",{7, 13, 17},20,51}, 
                  {"factors not relatively prime",{4, 6},15,30}, 
                  {"some pairs of factors relatively prime and some not",{5, 6, 8},150,4419}, 
                  {"one factor is a multiple of another",{5, 25},51,275}, 
                  {"much larger factors",{43, 47},10000,2203160}, 
                  {"all numbers are multiples of 1",{1},100,4950}, 
                  {"no factors means an empty sum",{},10000,0}, 
                  {"the only multiple of 0 is 0",{0},1,0}, 
                  {"the factor 0 does not affect the sum of multiples of other factors",{3, 0},4,3}, 
                  {"solutions using include-exclude must extend to cardinality greater than 3",{2, 3, 5, 7, 11},10000,39614537}} 
for t in tests do 
    {string desc, sequence f, integer lim, integer expected} = t 
    assert(sum_of_multiples(f,lim)=expected,desc) 
end for 
 
constant tests = {{"root of 1",1,1}, 
                  {"root of 4",4,2}, 
                  {"root of 25",25,5}, 
                  {"root of 81",81,9}, 
                  {"root of 196",196,14}, 
                  {"root of 65025",65025,255}} 
 
for t in tests do 
    {string desc, integer n, integer expected} = t 
    assert(sqrt(n)=expected,desc) 
end for 
 
function spiral(integer n) 
    integer x = 1, y = 0, counter = 1,  
          len = n, dx = 0, dy = 1 
    sequence m = repeat(repeat(0,n),n) 
    for i=1 to 2*n do                       -- 2n runs.. 
        for j=1 to len do                   -- of a length... 
            x += dx 
            y += dy 
            m[x][y] = counter 
            counter += 1 
        end for 
        len -= odd(i)                       -- ..-1 every other  
        {dx,dy} = {dy,-dx}                  -- in new direction 
    end for 
    return m 
end function 
 
constant tests = {{"empty spiral",0,{}}, 
                  {"trivial spiral",1,{{1}}}, 
                  {"spiral of size 2",2,{{1, 2}, 
                                         {4, 3}}}, 
                  {"spiral of size 3",3,{{1, 2, 3}, 
                                         {8, 9, 4}, 
                                         {7, 6, 5}}}, 
                  {"spiral of size 4",4,{{ 1,  2,  3, 4}, 
                                         {12, 13, 14, 5}, 
                                         {11, 16, 15, 6}, 
                                         {10,  9,  8, 7}}}, 
                  {"spiral of size 5",5,{{ 1,  2,  3,  4, 5}, 
                                         {16, 17, 18, 19, 6}, 
                                         {15, 24, 25, 20, 7}, 
                                         {14, 23, 22, 21, 8}, 
                                         {13, 12, 11, 10, 9}}}} 
for t in tests do 
    {string desc, integer n, sequence expected} = t 
    assert(spiral(n)=expected,desc) 
end for 
 
 
constant ROMAN  = {"M", "CM", "D","CD", "C","XC","L","XL","X","IX","V","IV","I"}, 
         DECML  = {1000, 900, 500, 400, 100, 90, 50,  40,  10,  9,  5,   4,  1 } 
 
function roman(integer val) 
    string res = "" 
    for i=1 to length(ROMAN) do 
        while val>=DECML[i] do 
            res &= ROMAN[i] 
            val -= DECML[i] 
        end while 
    end for 
    return res 
end function 
 
constant tests = {{"1 is I",1,"I"}, 
                  {"2 is II",2,"II"}, 
                  {"3 is III",3,"III"}, 
                  {"4 is IV",4,"IV"}, 
                  {"5 is V",5,"V"}, 
                  {"6 is VI",6,"VI"}, 
                  {"9 is IX",9,"IX"}, 
                  {"16 is XVI",16,"XVI"}, 
                  {"27 is XXVII",27,"XXVII"}, 
                  {"48 is XLVIII",48,"XLVIII"}, 
                  {"49 is XLIX",49,"XLIX"}, 
                  {"59 is LIX",59,"LIX"}, 
                  {"66 is LXVI",66,"LXVI"}, 
                  {"93 is XCIII",93,"XCIII"}, 
                  {"141 is CXLI",141,"CXLI"}, 
                  {"163 is CLXIII",163,"CLXIII"}, 
                  {"166 is CLXVI",166,"CLXVI"}, 
                  {"402 is CDII",402,"CDII"}, 
                  {"575 is DLXXV",575,"DLXXV"}, 
                  {"666 is DCLXVI",666,"DCLXVI"}, 
                  {"911 is CMXI",911,"CMXI"}, 
                  {"1024 is MXXIV",1024,"MXXIV"}, 
                  {"1666 is MDCLXVI",1666,"MDCLXVI"}, 
                  {"3000 is MMM",3000,"MMM"}, 
                  {"3001 is MMMI",3001,"MMMI"}, 
                  {"3999 is MMMCMXCIX",3999,"MMMCMXCIX"}} 
for t in tests do 
    {string desc, integer n, string expected} = t 
    assert(roman(n)=expected,desc) 
end for 
 
 
constant tests = { 
                  {"an empty string","",""}, 
                  {"a word","robot","tobor"}, 
                  {"a capitalized word","Ramen","nemaR"}, 
                  {"a sentence with punctuation","I'm hungry!","!yrgnuh m'I"}, 
                  {"a palindrome","racecar","racecar"}, 
                  {"an even-sized word","drawer","reward"}} 
for t in tests do 
    string {desc, s, expected} = t 
    assert(reverse(s)=expected,desc) 
end for 
 
 
function check(sequence p) 
    integer {r,c} = p 
    if r<0 then return "row not positive" end if 
    if r>7 then return "row not on board" end if 
    if c<0 then return "column not positive" end if 
    if c>7 then return "column not on board" end if 
    return 0 
end function 
 
function can_attack(sequence p) 
    integer {{r1,c1},{r2,c2}} = p 
    return r1=r2 or c1=c2 or r1-c1=r2-c2 or r1+c1=r2+c2 
end function 
 
constant places = {{"queen with a valid position",{2,2},0}, 
                   {"queen must have positive row",{-2,2},"row not positive"}, 
                   {"queen must have row on board",{8,4},"row not on board"}, 
                   {"queen must have positive column",{2,-2},"column not positive"}, 
                   {"queen must have column on board",{4,8},"column not on board"}}, 
        attacks = {{"cannot attack",{{2,4},{6,6}},false}, 
                   {"can attack on same row",{{2,4},{2,6}},true}, 
                   {"can attack on same column",{{4,5},{2,5}},true}, 
                   {"can attack on first diagonal",{{2,2},{0,4}},true}, 
                   {"can attack on second diagonal",{{2,2},{3,1}},true}, 
                   {"can attack on third diagonal",{{2,2},{1,1}},true}, 
                   {"can attack on fourth diagonal",{{1,7},{0,6}},true}, 
                   {"cannot attack if falling diagonals are only the same when reflected across the longest falling diagonal",{{4,1},{2,5}},false}} 
string desc; sequence p; object expected 
for p in places do 
    {desc,p,expected} = p 
    assert(check(p)=expected,desc) 
end for 
for a in attacks do 
    {desc,p,expected} = a 
    assert(can_attack(p)=expected,desc) 
end for 
 
 
function pythagorean_triplets(integer perim) 
    sequence res = {} 
    for a=1 to floor(perim/3) do 
        for b=a+1 to floor((perim-a)/2) do 
            integer c = perim-(a+b) 
            if a*a+b*b=c*c then 
                res = append(res,{a,b,c}) 
            end if 
        end for 
    end for 
    return res 
end function 
 
constant tests = {{"triplets whose sum is 12",12,{{3, 4, 5}}}, 
                  {"triplets whose sum is 108",108,{{27, 36, 45}}}, 
                  {"triplets whose sum is 1000",1000,{{200, 375, 425}}}, 
                  {"no matching triplets for 1001",1001,{}}, 
                  {"returns all matching triplets",90,{{9, 40, 41},{15, 36, 39}}}, 
                  {"several matching triplets",840,{{40, 399, 401},{56, 390, 394},{105, 360, 375},{120, 350, 370},{140, 336, 364},{168, 315, 357},{210, 280, 350},{240, 252, 348}}}, 
                  {"triplets for large number",30000,{{1200, 14375, 14425},{1875, 14000, 14125},{5000, 12000, 13000},{6000, 11250, 12750},{7500, 10000, 12500}}}} 
for t in tests do 
    {string desc, integer n, sequence expected} = t 
    assert(pythagorean_triplets(n)=expected,desc) 
end for 
 
 
function pascal(integer n) 
    sequence res = {}, row = repeat(1,n) 
    for r=1 to n do 
        for n=r-1 to 2 by -1 do 
            row[n] += row[n-1] 
        end for 
        res = append(res,row[1..r]) 
    end for 
    return res 
end function 
 
constant pt = {{1}, 
               {1, 1}, 
               {1, 2, 1}, 
               {1, 3, 3, 1}, 
               {1, 4, 6, 4, 1}, 
               {1, 5, 10, 10, 5, 1}, 
               {1, 6, 15, 20, 15, 6, 1}, 
               {1, 7, 21, 35, 35, 21, 7, 1}, 
               {1, 8, 28, 56, 70, 56, 28, 8, 1}, 
               {1, 9, 36, 84, 126, 126, 84, 36, 9, 1}} 
for n=0 to 10 do 
    assert(pascal(n)=pt[1..n]) 
end for 
 
 
function matrix(string s, rc, integer idx) 
    sequence m = split(s,"\n") 
    for i,r in m do 
        m[i] = apply(split(r,' '),to_integer) 
    end for 
    if rc="row" then return m[idx] end if 
    return vslice(m,idx) 
end function 
 
constant tests = {{"extract row from one number matrix","row","1",1,{1}}, 
                  {"can extract row","row","1 2\n3 4",2,{3,4}}, 
                  {"extract row where numbers have different widths","row","1 2\n10 20",2,{10, 20}}, 
                  {"can extract row from non-square matrix with no corresponding column","row","1 2 3\n4 5 6\n7 8 9\n8 7 6",4,{8, 7, 6}}, 
                  {"extract column from one number matrix","column","1",1,{1}}, 
                  {"can extract column","column","1 2 3\n4 5 6\n7 8 9",3,{3, 6, 9}}, 
                  {"can extract column from non-square matrix with no corresponding row","column","1 2 3 4\n5 6 7 8\n9 8 7 6",4,{4, 8, 6}}, 
                  {"extract column where numbers have different widths","column","89 1903 3\n18 3 1\n9 4 800",2,{1903, 3, 4}}} 
 
for t in tests do 
    string desc, rc, m; integer idx; sequence expected 
    {desc, rc, m, idx, expected} = t 
    printf(1,"%s : %s[%d] = %v (%t)\n",{m,rc,idx,matrix(m,rc,idx),matrix(m,rc,idx)=expected}) 
    assert(matrix(m,rc,idx)=expected,desc) 
end for 
 
function matching_brackets(string s) 
    sequence stack = {} 
    string openers = "[{(", 
           closers = "]})" 
    for ch in s do 
        integer k = find(ch,openers) 
        if k then 
            stack &= closers[k] 
        else 
            k = find(ch,closers) 
            if k then 
                if stack={} or ch!=stack[$] then 
                    return false 
                end if 
                stack = stack[1..$-1] 
            end if 
        end if 
    end for 
    return stack = {} 
end function 
     
constant tests = {{"paired square brackets","[]",true}, 
                  {"empty string","",true}, 
                  {"unpaired brackets","[[",false}, 
                  {"wrong ordered brackets","}{",false}, 
                  {"wrong closing bracket","{]",false}, 
                  {"paired with whitespace","{ }",true}, 
                  {"partially paired brackets","{[])",false}, 
                  {"simple nested brackets","{[]}",true}, 
                  {"several paired brackets","{}[]",true}, 
                  {"paired and nested brackets","([{}({}[])])",true}, 
                  {"unopened closing brackets","{[)][]}",false}, 
                  {"unpaired and nested brackets","([{])",false}, 
                  {"paired and wrong nested brackets","[({]})",false}, 
                  -- Ensures last opened bracket is not the only one being traced 
                  {"paired and wrong nested brackets but innermost are correct","[({}])",false}, 
                  {"paired and incomplete brackets","{}[",false}, 
                  {"too many closing brackets","[]]",false}, 
                  {"early unexpected brackets",")()",false}, 
                  {"early mismatched brackets","{)()",false}, 
                  {"math expression","(((185 + 223.85) * 15) - 543)/2",true}, 
                  {"complex latex expression","\\left(\\begin{array}{cc} \\frac{1}{3} & x\\\\ \\mathrm{e}^{x} &... x^2 \\end{array}\\right)",true}} 
 
for t in tests do 
    {string desc, string b, bool expected} = t 
    printf(1,"%s : %t\n",{b,matching_brackets(b)=expected}) 
    assert(matching_brackets(b)=expected,desc) 
end for 
 
function luhn(string s) 
    s = reverse(filter(s,"out"," ")) 
    if length(s)<=1 then return false end if 
    integer checksum = 0 
    for i,c in s do 
        c -= '0' 
        if c<0 or c>9 then return false end if 
        if even(i) then 
            c *= 2 
            if c>9 then c -= 9 end if 
        end if 
        checksum += c 
    end for 
    return remainder(checksum,10)=0 
end function 
 
constant tests = {{"single digit strings can not be valid","1",false}, 
                  {"a single zero is invalid","0",false}, 
                  {"a simple valid SIN that remains valid if reversed","059",true}, 
                  {"a simple valid SIN that becomes invalid if reversed","59",true}, 
                  {"a valid Canadian SIN","055 444 285",true}, 
                  {"invalid Canadian SIN","055 444 286",false}, 
                  {"invalid credit card","8273 1232 7352 0569",false}, 
                  {"invalid long number with an even remainder","1 2345 6789 1234 5678 9012",false}, 
                  {"invalid long number with a remainder divisible by 5","1 2345 6789 1234 5678 9013",false}, 
                  {"valid number with an even number of digits","095 245 88",true}, 
                  {"valid number with an odd number of spaces","234 567 891 234",true}, 
                  {"valid strings with a non-digit added at the end become invalid","059a",false}, 
                  {"valid strings with punctuation included become invalid","055-444-285",false}, 
                  {"valid strings with symbols included become invalid","055# 444$ 285",false}, 
                  {"single zero with space is invalid"," 0",false}, 
                  {"more than a single zero is valid","0000 0",true}, 
                  {"input digit 9 is correctly converted to output digit 9","091",true}, 
                  -- Designed to prevent converting input to a single number as this approach can risk an overflow 
                  {"very long input is valid","9999999999 9999999999 9999999999 9999999999",true}, 
                  {"valid luhn with an odd number of digits and non zero first digit","109",true}, 
                  -- Convert non-digits to their ascii values and then offset them by 48 sometimes accidentally  
                  -- declare an invalid string to be valid. Next two tests are designed to avoid that solution. 
                  {"using ascii value for non-doubled non-digit isn't allowed","055b 444 285",false}, 
                  {"using ascii value for doubled non-digit isn't allowed",":9",false}, 
                  {"non-numeric, non-space char in the middle with a sum that's divisible by 10 isn't allowed","59%59",false}} 
 
for t in tests do 
    {string desc, string n, bool expected} = t 
    printf(1,"%s : %t\n",{n,luhn(n)=expected}) 
    assert(luhn(n)=expected,desc) 
end for 
new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu