Kumite (ko͞omiˌtā) is the practice of taking techniques learned from Kata and applying them through the act of freestyle sparring.
You can create a new kumite by providing some initial code and optionally some test cases. From there other warriors can spar with you, by enhancing, refactoring and translating your code. There is no limit to how many warriors you can spar with.
A great use for kumite is to begin an idea for a kata as one. You can collaborate with other code warriors until you have it right, then you can convert it to a kata.
1 character shorter.
More pedantic approach. nand
function in different module to represent it being the primitive.
mod preloaded; use preloaded::nand; fn not(a: bool) -> bool { nand(a, a) } fn and(a: bool, b: bool) -> bool { nand(nand(a, b), nand(a, b)) } fn or(a: bool, b: bool) -> bool { nand(nand(a, a), nand(b, b)) } fn xor(a: bool, b: bool) -> bool { nand(nand(nand(a, b), nand(nand(a, a), nand(b, b))), nand(nand(a, b), nand(nand(a, a), nand(b, b)))) } fn nor(a: bool, b: bool) -> bool { nand(nand(nand(a, a), nand(b, b)), nand(nand(a, a), nand(b, b))) } fn xnor(a: bool, b: bool) -> bool { nand(nand(a, b), nand(nand(a, a), nand(b, b))) }
fn nand(a: bool, b: bool) -> bool {!(a && b)}- mod preloaded;
- use preloaded::nand;
- fn not(a: bool) -> bool {
- nand(a, a)
- }
- fn and(a: bool, b: bool) -> bool {
not(nand(a, b))- nand(nand(a, b), nand(a, b))
- }
- fn or(a: bool, b: bool) -> bool {
nand(not(a), not(b))- nand(nand(a, a), nand(b, b))
- }
- fn xor(a: bool, b: bool) -> bool {
and(nand(a, b), or(a, b))- nand(nand(nand(a, b), nand(nand(a, a), nand(b, b))), nand(nand(a, b), nand(nand(a, a), nand(b, b))))
- }
- fn nor(a: bool, b: bool) -> bool {
and(not(a), not(b))- nand(nand(nand(a, a), nand(b, b)), nand(nand(a, a), nand(b, b)))
- }
- fn xnor(a: bool, b: bool) -> bool {
- nand(nand(a, b), nand(nand(a, a), nand(b, b)))
- }
#[cfg(test)] mod tests { use super::*; #[test] fn test_not() { assert_eq!(not(false), true); assert_eq!(not(true), false); } #[test] fn test_and() { assert_eq!(and(false, false), false); assert_eq!(and(true, false), false); assert_eq!(and(false, true), false); assert_eq!(and(true, true), true); } #[test] fn test_or() { assert_eq!(or(false, false), false); assert_eq!(or(true, false), true); assert_eq!(or(false, true), true); assert_eq!(or(true, true), true); } #[test] fn test_xor() { assert_eq!(xor(false, false), false); assert_eq!(xor(true, false), true); assert_eq!(xor(false, true), true); assert_eq!(xor(true, true), false); } #[test] fn test_nor() { assert_eq!(nor(false, false), true); assert_eq!(nor(true, false), false); assert_eq!(nor(false, true), false); assert_eq!(nor(true, true), false); } #[test] fn test_xnor() { assert_eq!(xnor(false, false), true); assert_eq!(xnor(true, false), false); assert_eq!(xnor(false, true), false); assert_eq!(xnor(true, true), true); } }
- #[cfg(test)]
- mod tests {
- use super::*;
- #[test]
- fn test_not() {
- assert_eq!(not(false), true);
- assert_eq!(not(true), false);
- }
- #[test]
- fn test_and() {
- assert_eq!(and(false, false), false);
- assert_eq!(and(true, false), false);
- assert_eq!(and(false, true), false);
- assert_eq!(and(true, true), true);
- }
- #[test]
- fn test_or() {
- assert_eq!(or(false, false), false);
- assert_eq!(or(true, false), true);
- assert_eq!(or(false, true), true);
- assert_eq!(or(true, true), true);
- }
- #[test]
- fn test_xor() {
- assert_eq!(xor(false, false), false);
- assert_eq!(xor(true, false), true);
- assert_eq!(xor(false, true), true);
- assert_eq!(xor(true, true), false);
- }
- #[test]
- fn test_nor() {
- assert_eq!(nor(false, false), true);
- assert_eq!(nor(true, false), false);
- assert_eq!(nor(false, true), false);
- assert_eq!(nor(true, true), false);
- }
- #[test]
- fn test_xnor() {
- assert_eq!(xnor(false, false), true);
- assert_eq!(xnor(true, false), false);
- assert_eq!(xnor(false, true), false);
- assert_eq!(xnor(true, true), true);
- }
- }
nevermind, i figured out how to do random tests
import codewars_test as test from solution import str_opt import random import string tru_str_opt = lambda s:s if len(s) == 1 else None if len({s.count(i) for i in {*s}}) <= 1 else sorted([*s], key=lambda x: s.count(x))[0] # test.assert_equals(actual, expected, [optional] message) @test.describe("Example") def test_group(): @test.it("test cases") def test_case(): test.assert_equals(str_opt("abbcc"), "a", "returns the value that repeats the least") test.assert_equals(str_opt("bacc"), "b", "returns the value that repeats the least and goes first") test.assert_equals(str_opt("aabbcc"), None, " returns None if all characters repeat equally") test.assert_equals(str_opt("c"), "c", "returns the value if it is the only one") test.assert_equals(str_opt(""), None, "if it is empty, it returns None") test.assert_equals(str_opt(f"{'a'*10000}{'b'*10000}c"), "c", "shall work with large numbers") test.assert_equals(str_opt(f"{'a'*10000}{'b'*10000}{'c'*10000}"), None, "should handle very long strings with all characters repeating") @test.it("random cases") def _(): for i in range(500): testval = "".join([random.choice([*string.ascii_lowercase]) for _ in range(200)]) test.assert_equals(str_opt(testval), tru_str_opt(testval))
- import codewars_test as test
- from solution import str_opt
- import random
- import string
- tru_str_opt = lambda s:s if len(s) == 1 else None if len({s.count(i) for i in {*s}}) <= 1 else sorted([*s], key=lambda x: s.count(x))[0]
- # test.assert_equals(actual, expected, [optional] message)
- @test.describe("Example")
- def test_group():
- @test.it("test cases")
- def test_case():
- test.assert_equals(str_opt("abbcc"), "a", "returns the value that repeats the least")
- test.assert_equals(str_opt("bacc"), "b", "returns the value that repeats the least and goes first")
- test.assert_equals(str_opt("aabbcc"), None, " returns None if all characters repeat equally")
- test.assert_equals(str_opt("c"), "c", "returns the value if it is the only one")
- test.assert_equals(str_opt(""), None, "if it is empty, it returns None")
- test.assert_equals(str_opt(f"{'a'*10000}{'b'*10000}c"), "c", "shall work with large numbers")
- test.assert_equals(str_opt(f"{'a'*10000}{'b'*10000}{'c'*10000}"), None, "should handle very long strings with all characters repeating")
- @test.it("random cases")
- def _():
- for i in range(500):
- testval = "".join([random.choice([*string.ascii_lowercase]) for _ in range(200)])
- test.assert_equals(str_opt(testval), tru_str_opt(testval))
USING: accessors combinators combinators.smart fry kernel locals math quotations ; USING: vectors prettyprint ; QUALIFIED-WITH: sequences s IN: transducers ! TODO: effects for multiacc, surround, polyvariadic map quot, group to transducer, flatmap ! reducer = finalizer: ( ..yz -- ..zs ) initializer: ( -- ..xs done? ) step: ( ..xs -- ..ys done? ) ! ..xs/..ys are some values, normally accumulators followed by intermediate values being processed, ! the number of intermediate values can change between steps, while accumulators are always there, ! but they are on the stack and can be accessed at any time, thus not much different from other values : reduce ( finalizer: ( ..as -- ..bs ) initializer: ( -- ..as done? ) step: ( ..xs -- ..ys done? ) -- ..bs ) rot [ [ call ] dip [ swap ] [ [ call ] keep ] until drop ] dip call ; inline ! specialized via sequences:any? : reduce-seq ( xs finalizer: ( a -- a' ) initializer: ( -- a done? ) step: ( a x -- a' done? ) -- a' ) rot [ [ call ] dip swap [ drop nip ] [ swapd s:any? drop ] if ] dip call ; inline : iterate ( i-from: ( -- a d? ) r-from: ( a x -- a' d? ) x quot: ( x -- x' ) -- i-to: ( -- a d? ) r-to: ( a -- a' d? ) ) [ [ swap curry '[ [ t ] _ if ] compose ] 2keep ] dip swap [let :> x! '[ x @ [ x! ] keep ] prepose ] ; inline : map ( r-from: ( ..ys -- d? ) quot: ( ..xs -- ..ys ) -- r-to: ( ..xs -- d? ) ) prepose ; : filter ( r-from: ( ..xs -- d? ) quot: ( ..xs+ -- ..xs ? ) -- r-to: ( ..xs -- d? ) ) swap [ [ f ] smart-if* ] 2curry ; : take-while ( r-from: ( ..xs -- d? ) quot: ( ..xs+ -- ..xs ? ) -- r-to: ( ..xs -- d? ) ) swap [ [ t ] smart-if* ] 2curry ; : take-n ( i-from: ( -- d? ) r-from: ( ..xs -- d? ) n -- i-to: ( -- a d? ) r-to: ( ..xs -- d? ) ) [ [ [ drop t ] compose ] dip ] [ [let :> i! [ i 1 - [ drop t ] [ i! ] if-zero ] compose ] ] if-zero ; : drop-while ( r-from: ( ..xs -- d? ) quot: ( ..xs -- ..xs ? ) -- r-to: ( ..xs -- ..xs d? ) ) [let f :> b! [ { { [ b ] [ drop call ] } { [ overd call ] [ 2drop f ] } [ t b! call ] } cond ] 2curry ] ; : drop-n ( r-from: ( ..xs -- d? ) n -- r-to: ( ..xs -- d? ) ) [let :> i! '[ i _ [ 1 - i! drop f ] if-zero ] ] ; ! via sequences:any? : cat-seqs ( r-from: ( ..xs y -- d? ) -- r-to: ( ..xs ys -- d? ) ) '[ _ s:any? ] ; : mapcat ( r-from: ( ..xs y -- d? ) quot: ( r-outer: ( ..xs y -- d? ) z -- f-inner: ( -- ) i-inner: ( -- d? ) r-inner: ( z -- y d? ) ) -- r-to: ( ..xs z -- d? ) ) [let f :> done! '[ _ [ dup done! ] compose swap @ reduce done ] ] ; ! via mapcat : cat-seqs* ( r-from: ( ..xs y -- d? ) -- r-to: ( ..xs ys -- d? ) ) [ [ [ ] [ f ] ] 2dip [ '[ _ s:nth ] map ] [ s:length '[ _ < ] take-while ] bi 0 [ 1 + ] iterate ] mapcat ; ! reduce-seq as map <- take-while <- iterate : reduce-seq* ( xs finalizer: ( a -- a' ) initializer: ( -- a done? ) step: ( a x -- done? ) -- a' ) roll [ '[ _ s:nth ] map ] [ s:length '[ _ < ] take-while ] bi 0 [ 1 + ] iterate reduce ; inline : count-from ( r-from: ( ..xs i -- d? ) n -- r-to: ( ..xs -- d? ) ) [let :> i! [ i [ 1 + i! ] keep ] ] prepose ; ! TODO: generalize ! a temporary variant for testing : group-using-arrays ( f-from: ( a -- a' ) i-from: ( -- a d? ) r-from: ( a x -- a' d? ) n -- f-to: ( a -- a' ) i-to: ( -- a d? ) r-to: ( a x -- a' d? ) ) [let dup V{ } clone :> ( r-from n i! g! ) [ [ i n = [ g r-from call drop ] unless ] prepose ] dip [ g s:push i 1 - [ g r-from call V{ } clone g! n ] [ [ f ] dip ] if-zero i! ] ] ;
- USING: accessors combinators combinators.smart fry kernel locals math quotations ;
- USING: vectors prettyprint ;
- QUALIFIED-WITH: sequences s
- IN: transducers
- ! TODO: effects for multiacc, surround, polyvariadic map quot, group to transducer, flatmap
- ! reducer = finalizer: ( ..yz -- ..zs ) initializer: ( -- ..xs done? ) step: ( ..xs -- ..ys done? )
- ! ..xs/..ys are some values, normally accumulators followed by intermediate values being processed,
- ! the number of intermediate values can change between steps, while accumulators are always there,
- ! but they are on the stack and can be accessed at any time, thus not much different from other values
- : reduce ( finalizer: ( ..as -- ..bs ) initializer: ( -- ..as done? ) step: ( ..xs -- ..ys done? ) -- ..bs )
- rot [ [ call ] dip [ swap ] [ [ call ] keep ] until drop ] dip call ; inline
- ! specialized via sequences:any?
- : reduce-seq ( xs finalizer: ( a -- a' ) initializer: ( -- a done? ) step: ( a x -- a' done? ) -- a' )
- rot [ [ call ] dip swap [ drop nip ] [ swapd s:any? drop ] if ] dip call ; inline
- : iterate ( i-from: ( -- a d? ) r-from: ( a x -- a' d? ) x quot: ( x -- x' ) -- i-to: ( -- a d? ) r-to: ( a -- a' d? ) )
- [ [ swap curry '[ [ t ] _ if ] compose ] 2keep ] dip
- swap [let :> x! '[ x @ [ x! ] keep ] prepose ] ; inline
- : map ( r-from: ( ..ys -- d? ) quot: ( ..xs -- ..ys ) -- r-to: ( ..xs -- d? ) )
- prepose ;
- : filter ( r-from: ( ..xs -- d? ) quot: ( ..xs+ -- ..xs ? ) -- r-to: ( ..xs -- d? ) )
- swap [ [ f ] smart-if* ] 2curry ;
- : take-while ( r-from: ( ..xs -- d? ) quot: ( ..xs+ -- ..xs ? ) -- r-to: ( ..xs -- d? ) )
- swap [ [ t ] smart-if* ] 2curry ;
- : take-n ( i-from: ( -- d? ) r-from: ( ..xs -- d? ) n -- i-to: ( -- a d? ) r-to: ( ..xs -- d? ) )
- [ [ [ drop t ] compose ] dip ] [ [let :> i!
- [ i 1 - [ drop t ] [ i! ] if-zero ] compose
- ] ] if-zero ;
- : drop-while ( r-from: ( ..xs -- d? ) quot: ( ..xs -- ..xs ? ) -- r-to: ( ..xs -- ..xs d? ) )
- [let f :> b! [ {
- { [ b ] [ drop call ] }
- { [ overd call ] [ 2drop f ] }
- [ t b! call ]
- } cond ] 2curry ] ;
- : drop-n ( r-from: ( ..xs -- d? ) n -- r-to: ( ..xs -- d? ) )
- [let :> i! '[ i _ [ 1 - i! drop f ] if-zero ] ] ;
- ! via sequences:any?
- : cat-seqs ( r-from: ( ..xs y -- d? ) -- r-to: ( ..xs ys -- d? ) )
- '[ _ s:any? ] ;
- : mapcat ( r-from: ( ..xs y -- d? ) quot: ( r-outer: ( ..xs y -- d? ) z -- f-inner: ( -- ) i-inner: ( -- d? ) r-inner: ( z -- y d? ) ) -- r-to: ( ..xs z -- d? ) )
- [let f :> done! '[ _ [ dup done! ] compose swap @ reduce done ] ] ;
- ! via mapcat
- : cat-seqs* ( r-from: ( ..xs y -- d? ) -- r-to: ( ..xs ys -- d? ) )
- [ [ [ ] [ f ] ] 2dip [ '[ _ s:nth ] map ] [ s:length '[ _ < ] take-while ] bi 0 [ 1 + ] iterate ] mapcat ;
- ! reduce-seq as map <- take-while <- iterate
- : reduce-seq* ( xs finalizer: ( a -- a' ) initializer: ( -- a done? ) step: ( a x -- done? ) -- a' )
- roll [ '[ _ s:nth ] map ] [ s:length '[ _ < ] take-while ] bi 0 [ 1 + ] iterate reduce ; inline
- : count-from ( r-from: ( ..xs i -- d? ) n -- r-to: ( ..xs -- d? ) )
- [let :> i! [ i [ 1 + i! ] keep ] ] prepose ;
- ! TODO: generalize
- ! a temporary variant for testing
- : group-using-arrays ( f-from: ( a -- a' ) i-from: ( -- a d? ) r-from: ( a x -- a' d? ) n -- f-to: ( a -- a' ) i-to: ( -- a d? ) r-to: ( a x -- a' d? ) )
- [let dup V{ } clone :> ( r-from n i! g! )
- [ [ i n = [ g r-from call drop ] unless ] prepose ] dip
- [ g s:push i 1 - [ g r-from call V{ } clone g! n ] [ [ f ] dip ] if-zero i! ]
- ] ;
USING: arrays kernel math math.order prettyprint tools.testest transducers ; QUALIFIED-WITH: sequences s IN: transducers.tests ERROR: not-lazy-enough ; : into-vector ( -- finalizer initializer step: ( a x -- a' ) ) [ ] [ V{ } clone f ] [ s:suffix! f ] ; : run-tests ( -- ) "reduce-seq" describe#{ "immutable accumulator" it#{ <{ { 1 2 3 4 5 6 } [ ] [ 10 f ] [ + f ] reduce-seq -> 31 }> }# "mutable accumulator" it#{ <{ { 1 2 3 4 5 6 } into-vector reduce-seq -> V{ 1 2 3 4 5 6 } }> }# }# "reduce-seq with transducers" describe#{ "map" it#{ <{ { 1 2 3 4 5 6 } into-vector [ 1 + 2 * ] map reduce-seq -> V{ 4 6 8 10 12 14 } }> }# "map <- map" it#{ <{ { 1 2 3 4 5 6 } into-vector [ 2 * ] map [ 1 + ] map reduce-seq -> V{ 4 6 8 10 12 14 } }> }# "filter" it#{ <{ { 1 2 3 4 5 6 } into-vector [ even? ] filter reduce-seq -> V{ 2 4 6 } }> }# "map <- filter <- map" it#{ <{ { 1 2 3 4 5 6 } into-vector [ 2 * ] map [ even? ] filter [ 1 - ] map reduce-seq -> V{ 0 4 8 } }> }# "take-while" it#{ <{ { 1 2 3 4 5 6 } into-vector [ 4 = not ] take-while reduce-seq -> V{ 1 2 3 } }> }# "take-n" describe#{ "simple" it#{ <{ { 1 2 3 4 5 6 } into-vector 3 take-n reduce-seq -> V{ 1 2 3 } }> }# "0" it#{ <{ { 1 2 3 4 5 6 } into-vector 0 take-n reduce-seq -> V{ } }> }# "take-n <- take-n" it#{ <{ { 1 2 3 4 5 6 } into-vector 3 take-n 3 take-n reduce-seq -> V{ 1 2 3 } }> }# "early termination" it#{ <{ { [ 1 ] [ 2 ] [ not-lazy-enough ] } into-vector 2 take-n [ call ] map reduce-seq -> V{ 1 2 } }> }# "0, early termination" it#{ <{ { [ not-lazy-enough ] } into-vector 0 take-n [ call ] map reduce-seq -> V{ } }> }# }# "drop-while" it#{ <{ { 1 2 3 4 5 6 } into-vector [ 4 = not ] drop-while reduce-seq -> V{ 4 5 6 } }> }# "drop-n" it#{ <{ { 1 2 3 4 5 6 } into-vector 3 drop-n reduce-seq -> V{ 4 5 6 } }> }# "cats" describe#{ "cat-seqs" it#{ <{ { { 1 2 3 } { 4 5 6 } } into-vector cat-seqs reduce-seq -> V{ 1 2 3 4 5 6 } }> }# "take-n <- cat-seqs" it#{ <{ { { 1 2 3 } { 4 5 6 } { 7 8 9 } } into-vector 4 take-n cat-seqs reduce-seq -> V{ 1 2 3 4 } }> }# "mapcat" it#{ <{ { 1 2 3 } into-vector [ [ [ ] [ f ] ] 2dip take-n 0 [ 1 + ] iterate .s ] mapcat reduce-seq -> V{ 0 0 1 0 1 2 } }> }# "cat-seqs*" it#{ <{ { { 1 2 3 } { 4 5 6 } } into-vector cat-seqs* reduce-seq -> V{ 1 2 3 4 5 6 } }> }# "take-n <- cat-seqs*" it#{ <{ { { 1 2 3 } { 4 5 6 } { 7 8 9 } } into-vector 4 take-n cat-seqs* reduce-seq -> V{ 1 2 3 4 } }> }# }# "group-using-arrays" describe#{ "exact" it#{ <{ { 1 2 3 4 5 6 } into-vector 3 group-using-arrays reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } } }> }# "with remainder" it#{ <{ { 1 2 3 4 5 6 7 } into-vector 3 group-using-arrays reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } V{ 7 } } }> }# "exact, cut source" it#{ <{ { 1 2 3 4 5 6 7 8 } into-vector 3 group-using-arrays 6 take-n reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } } }> }# "with remainder, cut source" it#{ <{ { 1 2 3 4 5 6 7 8 } into-vector 3 group-using-arrays 7 take-n reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } V{ 7 } } }> }# "cut destination at end, full" it#{ <{ { 1 2 3 4 5 6 } into-vector 2 take-n 3 group-using-arrays reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } } }> }# "cut destination at end, partial (avoid leaking `reduced`)" it#{ <{ { 1 2 3 4 5 6 7 } into-vector 3 take-n 3 group-using-arrays reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } V{ 7 } } }> }# "cut destination, dropping partial" it#{ <{ { 1 2 3 4 5 6 7 } into-vector 2 take-n 3 group-using-arrays reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } } }> }# "cut destination, dropping full" it#{ <{ { 1 2 3 4 5 6 7 8 9 } into-vector 2 take-n 3 group-using-arrays reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } } }> }# }# }# "reduce-seq* with transducers" describe#{ "map <- filter <- map" it#{ <{ { 1 2 3 4 5 6 } into-vector [ 2 * ] map [ even? ] filter [ 1 - ] map reduce-seq -> V{ 0 4 8 } }> }# }# "iterate (0->1 arity)" describe#{ "low-level" describe#{ "lazy enough (1, cut to 0)" it#{ <{ [ "x" t ] [ not-lazy-enough ] 1 [ not-lazy-enough ] iterate drop call -> "x" t }> }# "lazy enough (1)" it#{ <{ [ "x" f ] [ nip f ] 1 [ not-lazy-enough ] iterate drop call -> 1 f }> }# "lazy enough (2)" it#{ <{ [ "x" f ] [ nip f ] 1 [ 1 = [ 2 ] [ not-lazy-enough ] if ] iterate [ call drop ] dip call -> 2 f }> }# }# "reduce" describe#{ "take-n <- iterate" describe#{ "works" it#{ <{ into-vector 6 take-n 1 [ 1 + ] iterate reduce -> V{ 1 2 3 4 5 6 } }> }# "lazy enough (0)" it#{ <{ into-vector 0 take-n 1 [ not-lazy-enough ] iterate reduce -> V{ } }> }# "lazy enough (1)" it#{ <{ into-vector 1 take-n 1 [ not-lazy-enough ] iterate reduce -> V{ 1 } }> }# "lazy enough (2)" it#{ <{ into-vector 2 take-n 1 [ 1 = [ 2 ] [ not-lazy-enough ] if ] iterate reduce -> V{ 1 2 } }> }# }# "number to digits" it#{ <{ into-vector [ 10 mod ] map [ 0 > ] take-while 123456789 [ 10 /i ] iterate reduce -> V{ 9 8 7 6 5 4 3 2 1 } }> }# }# }# "multiary intermediates" describe#{ "map(2->1) <- map(1->2) with-index-from" it#{ <{ V{ 10 20 30 } into-vector [ 2array ] map 1 count-from reduce-seq -> V{ { 10 1 } { 20 2 } { 30 3 } } }> }# "map(2->1) <- ...(0->0 and 1->1) <- map(1->2) with-index-from" it#{ <{ V{ 10 20 30 40 50 60 } into-vector [ 2array ] map 3 take-n [ [ 3 + ] [ 1 + ] bi* ] map [ 1 + ] map ! any arity [ [ drop ] [ 4 = not ] bi* ] filter ! must be able to drop inputs and keep accumulators [ [ 20 = not ] [ 2 = not ] bi* and ] filter 1 count-from reduce-seq -> V{ { 13 3 } { 33 5 } { 53 7 } } }> }# "multiple accumulators" it#{ <{ { 10 35 20 5 30 } [ ] [ 99 -99 f ] [ [ min ] [ max ] bi-curry bi* f ] reduce-seq* -> 5 35 }> <{ { 10 35 20 5 30 } [ [ { } s:like ] 3dip [ { } s:like ] dip ] [ V{ } clone 99 V{ } clone -99 f ] [ f ] [ [ min [ s:suffix! ] keep ] [ max [ s:suffix! ] keep ] bi-curry 2bi* ] map reduce-seq* -> { 10 10 10 5 5 } 5 { 10 35 35 35 35 } 35 }> }# }# "user-controlled state below reducers" describe#{ "into-vector <- count-from for comparison" it#{ <{ into-vector 3 take-n 1 count-from reduce -> V{ 1 2 3 } }> }# "into-vector <- map" it#{ ! map with 0 inputs, so only accumulator below, finalizer hidden by reduce; ! the state could be in an accumulator as well, but this way doesn't involve initializers/finalizers <{ 1 into-vector 3 take-n [ over [ 1 + ] 2dip ] map reduce -> 4 V{ 1 2 3 } }> }# "reduce-seq should hide finalizers too" it#{ <{ 1 { 7 8 9 } into-vector 3 take-n [ drop over [ 1 + ] 2dip ] map reduce-seq -> 4 V{ 1 2 3 } }> }# }# ; MAIN: run-tests
- USING: arrays kernel math math.order prettyprint tools.testest transducers ;
- QUALIFIED-WITH: sequences s
- IN: transducers.tests
- ERROR: not-lazy-enough ;
- : into-vector ( -- finalizer initializer step: ( a x -- a' ) )
- [ ] [ V{ } clone f ] [ s:suffix! f ] ;
- : run-tests ( -- )
- "reduce-seq" describe#{
- "immutable accumulator" it#{
- <{ { 1 2 3 4 5 6 } [ ] [ 10 f ] [ + f ] reduce-seq -> 31 }>
- }#
- "mutable accumulator" it#{
- <{ { 1 2 3 4 5 6 } into-vector reduce-seq -> V{ 1 2 3 4 5 6 } }>
- }#
- }#
- "reduce-seq with transducers" describe#{
- "map" it#{
- <{ { 1 2 3 4 5 6 } into-vector [ 1 + 2 * ] map reduce-seq -> V{ 4 6 8 10 12 14 } }>
- }#
- "map <- map" it#{
- <{ { 1 2 3 4 5 6 } into-vector [ 2 * ] map [ 1 + ] map reduce-seq -> V{ 4 6 8 10 12 14 } }>
- }#
- "filter" it#{
- <{ { 1 2 3 4 5 6 } into-vector [ even? ] filter reduce-seq -> V{ 2 4 6 } }>
- }#
- "map <- filter <- map" it#{
- <{ { 1 2 3 4 5 6 } into-vector [ 2 * ] map [ even? ] filter [ 1 - ] map reduce-seq -> V{ 0 4 8 } }>
- }#
- "take-while" it#{
- <{ { 1 2 3 4 5 6 } into-vector [ 4 = not ] take-while reduce-seq -> V{ 1 2 3 } }>
- }#
- "take-n" describe#{
- "simple" it#{
- <{ { 1 2 3 4 5 6 } into-vector 3 take-n reduce-seq -> V{ 1 2 3 } }>
- }#
- "0" it#{
- <{ { 1 2 3 4 5 6 } into-vector 0 take-n reduce-seq -> V{ } }>
- }#
- "take-n <- take-n" it#{
- <{ { 1 2 3 4 5 6 } into-vector 3 take-n 3 take-n reduce-seq -> V{ 1 2 3 } }>
- }#
- "early termination" it#{
- <{ { [ 1 ] [ 2 ] [ not-lazy-enough ] } into-vector 2 take-n [ call ] map reduce-seq -> V{ 1 2 } }>
- }#
- "0, early termination" it#{
- <{ { [ not-lazy-enough ] } into-vector 0 take-n [ call ] map reduce-seq -> V{ } }>
- }#
- }#
- "drop-while" it#{
- <{ { 1 2 3 4 5 6 } into-vector [ 4 = not ] drop-while reduce-seq -> V{ 4 5 6 } }>
- }#
- "drop-n" it#{
- <{ { 1 2 3 4 5 6 } into-vector 3 drop-n reduce-seq -> V{ 4 5 6 } }>
- }#
- "cats" describe#{
- "cat-seqs" it#{
- <{ { { 1 2 3 } { 4 5 6 } } into-vector cat-seqs reduce-seq -> V{ 1 2 3 4 5 6 } }>
- }#
- "take-n <- cat-seqs" it#{
- <{ { { 1 2 3 } { 4 5 6 } { 7 8 9 } } into-vector 4 take-n cat-seqs reduce-seq -> V{ 1 2 3 4 } }>
- }#
- "mapcat" it#{
- <{ { 1 2 3 } into-vector [ [ [ ] [ f ] ] 2dip take-n 0 [ 1 + ] iterate .s ] mapcat reduce-seq -> V{ 0 0 1 0 1 2 } }>
- }#
- "cat-seqs*" it#{
- <{ { { 1 2 3 } { 4 5 6 } } into-vector cat-seqs* reduce-seq -> V{ 1 2 3 4 5 6 } }>
- }#
- "take-n <- cat-seqs*" it#{
- <{ { { 1 2 3 } { 4 5 6 } { 7 8 9 } } into-vector 4 take-n cat-seqs* reduce-seq -> V{ 1 2 3 4 } }>
- }#
- }#
- "group-using-arrays" describe#{
- "exact" it#{
- <{ { 1 2 3 4 5 6 } into-vector 3 group-using-arrays reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } } }>
- }#
- "with remainder" it#{
- <{ { 1 2 3 4 5 6 7 } into-vector 3 group-using-arrays reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } V{ 7 } } }>
- }#
- "exact, cut source" it#{
- <{ { 1 2 3 4 5 6 7 8 } into-vector 3 group-using-arrays 6 take-n reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } } }>
- }#
- "with remainder, cut source" it#{
- <{ { 1 2 3 4 5 6 7 8 } into-vector 3 group-using-arrays 7 take-n reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } V{ 7 } } }>
- }#
- "cut destination at end, full" it#{
- <{ { 1 2 3 4 5 6 } into-vector 2 take-n 3 group-using-arrays reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } } }>
- }#
- "cut destination at end, partial (avoid leaking `reduced`)" it#{
- <{ { 1 2 3 4 5 6 7 } into-vector 3 take-n 3 group-using-arrays reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } V{ 7 } } }>
- }#
- "cut destination, dropping partial" it#{
- <{ { 1 2 3 4 5 6 7 } into-vector 2 take-n 3 group-using-arrays reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } } }>
- }#
- "cut destination, dropping full" it#{
- <{ { 1 2 3 4 5 6 7 8 9 } into-vector 2 take-n 3 group-using-arrays reduce-seq -> V{ V{ 1 2 3 } V{ 4 5 6 } } }>
- }#
- }#
- }#
- "reduce-seq* with transducers" describe#{
- "map <- filter <- map" it#{
- <{ { 1 2 3 4 5 6 } into-vector [ 2 * ] map [ even? ] filter [ 1 - ] map reduce-seq -> V{ 0 4 8 } }>
- }#
- }#
- "iterate (0->1 arity)" describe#{
- "low-level" describe#{
- "lazy enough (1, cut to 0)" it#{
- <{ [ "x" t ] [ not-lazy-enough ] 1 [ not-lazy-enough ] iterate drop call -> "x" t }>
- }#
- "lazy enough (1)" it#{
- <{ [ "x" f ] [ nip f ] 1 [ not-lazy-enough ] iterate drop call -> 1 f }>
- }#
- "lazy enough (2)" it#{
- <{ [ "x" f ] [ nip f ] 1 [ 1 = [ 2 ] [ not-lazy-enough ] if ] iterate [ call drop ] dip call -> 2 f }>
- }#
- }#
- "reduce" describe#{
- "take-n <- iterate" describe#{
- "works" it#{
- <{ into-vector 6 take-n 1 [ 1 + ] iterate reduce -> V{ 1 2 3 4 5 6 } }>
- }#
- "lazy enough (0)" it#{
- <{ into-vector 0 take-n 1 [ not-lazy-enough ] iterate reduce -> V{ } }>
- }#
- "lazy enough (1)" it#{
- <{ into-vector 1 take-n 1 [ not-lazy-enough ] iterate reduce -> V{ 1 } }>
- }#
- "lazy enough (2)" it#{
- <{ into-vector 2 take-n 1 [ 1 = [ 2 ] [ not-lazy-enough ] if ] iterate reduce -> V{ 1 2 } }>
- }#
- }#
- "number to digits" it#{
- <{ into-vector [ 10 mod ] map [ 0 > ] take-while 123456789 [ 10 /i ] iterate reduce -> V{ 9 8 7 6 5 4 3 2 1 } }>
- }#
- }#
- }#
- "multiary intermediates" describe#{
- "map(2->1) <- map(1->2) with-index-from" it#{
- <{ V{ 10 20 30 } into-vector [ 2array ] map 1 count-from reduce-seq -> V{ { 10 1 } { 20 2 } { 30 3 } } }>
- }#
- "map(2->1) <- ...(0->0 and 1->1) <- map(1->2) with-index-from" it#{
- <{ V{ 10 20 30 40 50 60 } into-vector
- [ 2array ] map
- 3 take-n
- [ [ 3 + ] [ 1 + ] bi* ] map
- [ 1 + ] map ! any arity
- [ [ drop ] [ 4 = not ] bi* ] filter ! must be able to drop inputs and keep accumulators
- [ [ 20 = not ] [ 2 = not ] bi* and ] filter
- 1 count-from
- reduce-seq
- -> V{ { 13 3 } { 33 5 } { 53 7 } } }>
- }#
- "multiple accumulators" it#{
- <{ { 10 35 20 5 30 } [ ] [ 99 -99 f ] [ [ min ] [ max ] bi-curry bi* f ] reduce-seq* -> 5 35 }>
- <{ { 10 35 20 5 30 } [ [ { } s:like ] 3dip [ { } s:like ] dip ] [ V{ } clone 99 V{ } clone -99 f ] [ f ]
- [ [ min [ s:suffix! ] keep ] [ max [ s:suffix! ] keep ] bi-curry 2bi* ] map
- reduce-seq*
- -> { 10 10 10 5 5 } 5 { 10 35 35 35 35 } 35 }>
- }#
- }#
- "user-controlled state below reducers" describe#{
- "into-vector <- count-from for comparison" it#{
- <{ into-vector 3 take-n 1 count-from reduce -> V{ 1 2 3 } }>
- }#
- "into-vector <- map" it#{
- ! map with 0 inputs, so only accumulator below, finalizer hidden by reduce;
- ! the state could be in an accumulator as well, but this way doesn't involve initializers/finalizers
- <{ 1 into-vector 3 take-n [ over [ 1 + ] 2dip ] map reduce -> 4 V{ 1 2 3 } }>
- }#
- "reduce-seq should hide finalizers too" it#{
- <{ 1 { 7 8 9 } into-vector 3 take-n [ drop over [ 1 + ] 2dip ] map reduce-seq -> 4 V{ 1 2 3 } }>
- }#
- }#
- ;
- MAIN: run-tests
# From Ruby 3.0, RSpec is used under the hood. # See https://rspec.info/ # Defaults to the global `describe` for backwards compatibility, but `RSpec.desribe` works as well. describe "Example" do 100.times do it 'returns the sum of each pair' do expect(twin_sum_solutions([2, 2, 4, 4])).to eq([4, 8]) end it 'only adds the pairs' do expect(twin_sum_solutions([3, 2, 6, 6])).to eq([12]) end it 'returns an empty array when passed no pairs' do expect(twin_sum_solutions([1, 2, 3, 4])).to eq([]) end end end
// Since Node 10, we're using Mocha.// You can use `chai` for assertions.const chai = require("chai");const assert = chai.assert;// Uncomment the following line to disable truncating failure messages for deep equals, do:// chai.config.truncateThreshold = 0;// Since Node 12, we no longer include assertions from our deprecated custom test framework by default.// Uncomment the following to use the old assertions:// const Test = require("@codewars/test-compat");describe("Solution", function() {it("should test for something", function() {// Test.assertEquals(1 + 1, 2);// assert.strictEqual(1 + 1, 2);});});- # From Ruby 3.0, RSpec is used under the hood.
- # See https://rspec.info/
- # Defaults to the global `describe` for backwards compatibility, but `RSpec.desribe` works as well.
- describe "Example" do
- 100.times do
- it 'returns the sum of each pair' do
- expect(twin_sum_solutions([2, 2, 4, 4])).to eq([4, 8])
- end
- it 'only adds the pairs' do
- expect(twin_sum_solutions([3, 2, 6, 6])).to eq([12])
- end
- it 'returns an empty array when passed no pairs' do
- expect(twin_sum_solutions([1, 2, 3, 4])).to eq([])
- end
- end
- end
two obscure chars shorter because Python, ha ha