Skip to content

Commit

Permalink
Add strain exercise
Browse files Browse the repository at this point in the history
  • Loading branch information
BNAndras committed Dec 24, 2023
1 parent 077312c commit 407bab1
Show file tree
Hide file tree
Showing 11 changed files with 429 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,14 @@
"prerequisites": [],
"difficulty": 1
},
{
"slug": "strain",
"name": "Strain",
"uuid": "5a1a2fa9-e8d0-4784-ba0c-c53fb8405e26",
"practices": [],
"prerequisites": [],
"difficulty": 2
},
{
"slug": "sum-of-multiples",
"name": "Sum of Multiples",
Expand Down
29 changes: 29 additions & 0 deletions exercises/practice/strain/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Instructions

Implement the `keep` and `discard` operation on collections.
Given a collection and a predicate on the collection's elements, `keep` returns a new collection containing those elements where the predicate is true, while `discard` returns a new collection containing those elements where the predicate is false.

For example, given the collection of numbers:

- 1, 2, 3, 4, 5

And the predicate:

- is the number even?

Then your keep operation should produce:

- 2, 4

While your discard operation should produce:

- 1, 3, 5

Note that the union of keep and discard is all the elements.

The functions may be called `keep` and `discard`, or they may need different names in order to not clash with existing functions or concepts in your language.

## Restrictions

Keep your hands off that filter/reject/whatchamacallit functionality provided by your standard library!
Solve this one yourself using other basic tools instead.
27 changes: 27 additions & 0 deletions exercises/practice/strain/.meta/Example.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Here is an example solution for the Strain exercise
*/
component {

/**
* @returns
*/
function keep(list, predicate) {
var results = [];
for (elem in list) {
if (predicate(elem)) {
arrayAppend(results, elem);
}
}

return results;
}

/**
* @returns
*/
function discard(list, predicate) {
var newPredicate = function( x ) {return not predicate(x); }
return keep(list, newPredicate);
}
}
7 changes: 7 additions & 0 deletions exercises/practice/strain/.meta/ExampleTest.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
component extends="StrainTest" {

function beforeAll(){
SUT = createObject( 'Solution' );
}

}
19 changes: 19 additions & 0 deletions exercises/practice/strain/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"BNAndras"
],
"files": {
"solution": [
"Strain.cfc"
],
"test": [
"StrainTest.cfc"
],
"example": [
".meta/Example.cfc"
]
},
"blurb": "Implement the `keep` and `discard` operation on collections. Given a collection and a predicate on the collection's elements, `keep` returns a new collection containing those elements where the predicate is true, while `discard` returns a new collection containing those elements where the predicate is false.",
"source": "Conversation with James Edward Gray II",
"source_url": "http://graysoftinc.com/"
}
52 changes: 52 additions & 0 deletions exercises/practice/strain/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[26af8c32-ba6a-4eb3-aa0a-ebd8f136e003]
description = "keep on empty list returns empty list"

[f535cb4d-e99b-472a-bd52-9fa0ffccf454]
description = "keeps everything"

[950b8e8e-f628-42a8-85e2-9b30f09cde38]
description = "keeps nothing"

[92694259-6e76-470c-af87-156bdf75018a]
description = "keeps first and last"

[938f7867-bfc7-449e-a21b-7b00cbb56994]
description = "keeps neither first nor last"

[8908e351-4437-4d2b-a0f7-770811e48816]
description = "keeps strings"

[2728036b-102a-4f1e-a3ef-eac6160d876a]
description = "keeps lists"

[ef16beb9-8d84-451a-996a-14e80607fce6]
description = "discard on empty list returns empty list"

[2f42f9bc-8e06-4afe-a222-051b5d8cd12a]
description = "discards everything"

[ca990fdd-08c2-4f95-aa50-e0f5e1d6802b]
description = "discards nothing"

[71595dae-d283-48ca-a52b-45fa96819d2f]
description = "discards first and last"

[ae141f79-f86d-4567-b407-919eaca0f3dd]
description = "discards neither first nor last"

[daf25b36-a59f-4f29-bcfe-302eb4e43609]
description = "discards strings"

[a38d03f9-95ad-4459-80d1-48e937e4acaf]
description = "discards lists"
19 changes: 19 additions & 0 deletions exercises/practice/strain/Strain.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Your implementation of the Strain exercise
*/
component {

/**
* @returns
*/
function keep(list, predicate) {
// Implement me here
}

/**
* @returns
*/
function discard(list, predicate) {
// Implement me here
}
}
120 changes: 120 additions & 0 deletions exercises/practice/strain/StrainTest.cfc
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
component extends="testbox.system.BaseSpec" {

function beforeAll(){
SUT = createObject( 'Strain' );
}

function alwaysTrue( x ) { return true; }

function alwaysFalse( x ) { return false; }

function isOdd( x ) { return x % 2 == 1; }

function isEven( x ) { return x % 2 == 0; }

function containsFive( x ) { return arrayContains(x, 5); }

function startWithZ( x ) { return left(x, 1) == 'z'; }

function run(){

describe( "My Strain class", function(){

it( 'keep on empty list returns empty list', function(){
expect( SUT.keep( list=[], predicate=alwaysTrue ) ).toBe( [] );
});

it( 'keeps everything', function(){
expect( SUT.keep( list=[1, 3, 5], predicate=alwaysTrue ) ).toBe( [1,3,5] );
});

it( 'keeps nothing', function(){
expect( SUT.keep( list=[1, 3, 5], predicate=alwaysFalse) ).toBe( [] );
});

it( 'keeps first and last', function(){
expect( SUT.keep( list=[1, 2, 3], predicate=isOdd ) ).toBe( [1,3] );
});

it( 'keeps neither first nor last', function(){
expect( SUT.keep( list=[1, 2, 3], predicate=isEven ) ).toBe( [2] );
});

it( 'keeps strings', function(){
expect( SUT.keep(
list=["apple",
"zebra",
"banana",
"zombies",
"cherimoya",
"zealot"],
predicate=startWithZ ) ).toBe( ["zebra","zombies","zealot"] );
});

it( 'keeps lists', function(){
expect( SUT.keep(
list=[[1, 2, 3],
[5, 5, 5],
[5, 1, 2],
[2, 1, 2],
[1, 5, 2],
[2, 2, 1],
[1, 2, 5]],
predicate=containsFive ) ).toBe( [[5,5,5],
[5,1,2],
[1,5,2],
[1,2,5]] );
});

it( 'discard on empty list returns empty list', function(){
expect( SUT.discard( list=[], predicate=alwaysTrue ) ).toBe( [] );
});

it( 'discards everything', function(){
expect( SUT.discard( list=[1, 3, 5], predicate=alwaysTrue ) ).toBe( [] );
});

it( 'discards nothing', function(){
expect( SUT.discard( list=[1, 3, 5], predicate=alwaysFalse ) ).toBe( [1,3,5] );
});

it( 'discards first and last', function(){
expect( SUT.discard( list=[1, 2, 3], predicate=isOdd ) ).toBe( [2] );
});

it( 'discards neither first nor last', function(){
expect( SUT.discard( list=[1, 2, 3], predicate=isEven ) ).toBe( [1,3] );
});

it( 'discards strings', function(){
expect( SUT.discard(
list=["apple",
"zebra",
"banana",
"zombies",
"cherimoya",
"zealot"],
predicate=startWithZ ) ).toBe( ["apple",
"banana",
"cherimoya"] );
});

it( 'discards lists', function(){
expect( SUT.discard(
list=[[1, 2, 3],
[5, 5, 5],
[5, 1, 2],
[2, 1, 2],
[1, 5, 2],
[2, 2, 1],
[1, 2, 5]],
predicate=containsFive ) ).toBe( [[1,2,3],
[2,1,2],
[2,2,1]] );
});

});

}

}containsFive
Loading

0 comments on commit 407bab1

Please sign in to comment.