Skip to content

Commit cee862e

Browse files
committed
Add ListOps exercise
1 parent 1e05b8c commit cee862e

File tree

7 files changed

+540
-0
lines changed

7 files changed

+540
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,14 @@
932932
"practices": [],
933933
"prerequisites": [],
934934
"difficulty": 2
935+
},
936+
{
937+
"slug": "list-ops",
938+
"name": "List Ops",
939+
"uuid": "56f36086-96a8-4941-8c46-b563f02e5b09",
940+
"practices": [],
941+
"prerequisites": [],
942+
"difficulty": 5
935943
}
936944
]
937945
},
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Instructions
2+
3+
Implement basic list operations.
4+
5+
In functional languages list operations like `length`, `map`, and `reduce` are very common.
6+
Implement a series of basic list operations, without using existing functions.
7+
8+
The precise number and names of the operations to be implemented will be track dependent to avoid conflicts with existing names, but the general operations you will implement include:
9+
10+
- `append` (_given two lists, add all items in the second list to the end of the first list_);
11+
- `concatenate` (_given a series of lists, combine all items in all lists into one flattened list_);
12+
- `filter` (_given a predicate and a list, return the list of all items for which `predicate(item)` is True_);
13+
- `length` (_given a list, return the total number of items within it_);
14+
- `map` (_given a function and a list, return the list of the results of applying `function(item)` on all items_);
15+
- `foldl` (_given a function, a list, and initial accumulator, fold (reduce) each item into the accumulator from the left_);
16+
- `foldr` (_given a function, a list, and an initial accumulator, fold (reduce) each item into the accumulator from the right_);
17+
- `reverse` (_given a list, return a list with all the original items, but in reversed order_).
18+
19+
Note, the ordering in which arguments are passed to the fold functions (`foldl`, `foldr`) is significant.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"authors": ["homersimpsons"],
3+
"files": {
4+
"solution": [
5+
"ListOps.php"
6+
],
7+
"test": [
8+
"ListOpsTest.php"
9+
],
10+
"example": [
11+
".meta/example.php"
12+
]
13+
},
14+
"blurb": "Implement basic list operations."
15+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?php
2+
3+
/*
4+
* By adding type hints and enabling strict type checking, code can become
5+
* easier to read, self-documenting and reduce the number of potential bugs.
6+
* By default, type declarations are non-strict, which means they will attempt
7+
* to change the original type to match the type specified by the
8+
* type-declaration.
9+
*
10+
* In other words, if you pass a string to a function requiring a float,
11+
* it will attempt to convert the string value to a float.
12+
*
13+
* To enable strict mode, a single declare directive must be placed at the top
14+
* of the file.
15+
* This means that the strictness of typing is configured on a per-file basis.
16+
* This directive not only affects the type declarations of parameters, but also
17+
* a function's return type.
18+
*
19+
* For more info review the Concept on strict type checking in the PHP track
20+
* <link>.
21+
*
22+
* To disable strict typing, comment out the directive below.
23+
*/
24+
25+
declare(strict_types=1);
26+
27+
class ListOps
28+
{
29+
public static function append(array $list1, array $list2): array
30+
{
31+
foreach ($list2 as $el) {
32+
$list1[] = $el;
33+
}
34+
return $list1;
35+
}
36+
37+
public static function concat(array $list1, array ...$listn): array
38+
{
39+
foreach ($listn as $list) {
40+
$list1 = self::append($list1, $list);
41+
}
42+
return $list1;
43+
}
44+
45+
public static function filter(callable $predicate, array $list): array
46+
{
47+
$result = [];
48+
foreach ($list as $el) {
49+
if ($predicate($el)) {
50+
$result[] = $el;
51+
}
52+
}
53+
return $result;
54+
}
55+
56+
public static function length(array $list): int
57+
{
58+
$count = 0;
59+
foreach ($list as $_el) {
60+
$count++;
61+
}
62+
return $count;
63+
}
64+
65+
public static function map(callable $function, array $list): array
66+
{
67+
$result = [];
68+
foreach ($list as $el) {
69+
$result[] = $function($el);
70+
}
71+
return $result;
72+
}
73+
74+
public static function foldl(callable $function, array $list, $accumulator)
75+
{
76+
foreach ($list as $el) {
77+
$accumulator = $function($accumulator, $el);
78+
}
79+
return $accumulator;
80+
}
81+
82+
public static function foldr(callable $function, array $list, $accumulator)
83+
{
84+
while (self::length($list) > 0) {
85+
$el = array_pop($list);
86+
$accumulator = $function($accumulator, $el);
87+
}
88+
return $accumulator;
89+
}
90+
91+
public static function reverse(array $list): array
92+
{
93+
$result = [];
94+
while (self::length($list) > 0) {
95+
$result[] = array_pop($list);
96+
}
97+
return $result;
98+
}
99+
}
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[485b9452-bf94-40f7-a3db-c3cf4850066a]
13+
description = "append entries to a list and return the new list -> empty lists"
14+
15+
[2c894696-b609-4569-b149-8672134d340a]
16+
description = "append entries to a list and return the new list -> list to empty list"
17+
18+
[e842efed-3bf6-4295-b371-4d67a4fdf19c]
19+
description = "append entries to a list and return the new list -> empty list to list"
20+
21+
[71dcf5eb-73ae-4a0e-b744-a52ee387922f]
22+
description = "append entries to a list and return the new list -> non-empty lists"
23+
24+
[28444355-201b-4af2-a2f6-5550227bde21]
25+
description = "concatenate a list of lists -> empty list"
26+
27+
[331451c1-9573-42a1-9869-2d06e3b389a9]
28+
description = "concatenate a list of lists -> list of lists"
29+
30+
[d6ecd72c-197f-40c3-89a4-aa1f45827e09]
31+
description = "concatenate a list of lists -> list of nested lists"
32+
33+
[0524fba8-3e0f-4531-ad2b-f7a43da86a16]
34+
description = "filter list returning only values that satisfy the filter function -> empty list"
35+
36+
[88494bd5-f520-4edb-8631-88e415b62d24]
37+
description = "filter list returning only values that satisfy the filter function -> non-empty list"
38+
39+
[1cf0b92d-8d96-41d5-9c21-7b3c37cb6aad]
40+
description = "returns the length of a list -> empty list"
41+
42+
[d7b8d2d9-2d16-44c4-9a19-6e5f237cb71e]
43+
description = "returns the length of a list -> non-empty list"
44+
45+
[c0bc8962-30e2-4bec-9ae4-668b8ecd75aa]
46+
description = "return a list of elements whose values equal the list value transformed by the mapping function -> empty list"
47+
48+
[11e71a95-e78b-4909-b8e4-60cdcaec0e91]
49+
description = "return a list of elements whose values equal the list value transformed by the mapping function -> non-empty list"
50+
51+
[613b20b7-1873-4070-a3a6-70ae5f50d7cc]
52+
description = "folds (reduces) the given list from the left with a function -> empty list"
53+
include = false
54+
55+
[e56df3eb-9405-416a-b13a-aabb4c3b5194]
56+
description = "folds (reduces) the given list from the left with a function -> direction independent function applied to non-empty list"
57+
include = false
58+
59+
[d2cf5644-aee1-4dfc-9b88-06896676fe27]
60+
description = "folds (reduces) the given list from the left with a function -> direction dependent function applied to non-empty list"
61+
include = false
62+
63+
[36549237-f765-4a4c-bfd9-5d3a8f7b07d2]
64+
description = "folds (reduces) the given list from the left with a function -> empty list"
65+
reimplements = "613b20b7-1873-4070-a3a6-70ae5f50d7cc"
66+
67+
[7a626a3c-03ec-42bc-9840-53f280e13067]
68+
description = "folds (reduces) the given list from the left with a function -> direction independent function applied to non-empty list"
69+
reimplements = "e56df3eb-9405-416a-b13a-aabb4c3b5194"
70+
71+
[d7fcad99-e88e-40e1-a539-4c519681f390]
72+
description = "folds (reduces) the given list from the left with a function -> direction dependent function applied to non-empty list"
73+
reimplements = "d2cf5644-aee1-4dfc-9b88-06896676fe27"
74+
75+
[aeb576b9-118e-4a57-a451-db49fac20fdc]
76+
description = "folds (reduces) the given list from the right with a function -> empty list"
77+
include = false
78+
79+
[c4b64e58-313e-4c47-9c68-7764964efb8e]
80+
description = "folds (reduces) the given list from the right with a function -> direction independent function applied to non-empty list"
81+
include = false
82+
83+
[be396a53-c074-4db3-8dd6-f7ed003cce7c]
84+
description = "folds (reduces) the given list from the right with a function -> direction dependent function applied to non-empty list"
85+
include = false
86+
87+
[17214edb-20ba-42fc-bda8-000a5ab525b0]
88+
description = "folds (reduces) the given list from the right with a function -> empty list"
89+
reimplements = "aeb576b9-118e-4a57-a451-db49fac20fdc"
90+
91+
[e1c64db7-9253-4a3d-a7c4-5273b9e2a1bd]
92+
description = "folds (reduces) the given list from the right with a function -> direction independent function applied to non-empty list"
93+
reimplements = "c4b64e58-313e-4c47-9c68-7764964efb8e"
94+
95+
[8066003b-f2ff-437e-9103-66e6df474844]
96+
description = "folds (reduces) the given list from the right with a function -> direction dependent function applied to non-empty list"
97+
reimplements = "be396a53-c074-4db3-8dd6-f7ed003cce7c"
98+
99+
[94231515-050e-4841-943d-d4488ab4ee30]
100+
description = "reverse the elements of the list -> empty list"
101+
102+
[fcc03d1e-42e0-4712-b689-d54ad761f360]
103+
description = "reverse the elements of the list -> non-empty list"
104+
105+
[40872990-b5b8-4cb8-9085-d91fc0d05d26]
106+
description = "reverse the elements of the list -> list of lists is not flattened"
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
/*
4+
* By adding type hints and enabling strict type checking, code can become
5+
* easier to read, self-documenting and reduce the number of potential bugs.
6+
* By default, type declarations are non-strict, which means they will attempt
7+
* to change the original type to match the type specified by the
8+
* type-declaration.
9+
*
10+
* In other words, if you pass a string to a function requiring a float,
11+
* it will attempt to convert the string value to a float.
12+
*
13+
* To enable strict mode, a single declare directive must be placed at the top
14+
* of the file.
15+
* This means that the strictness of typing is configured on a per-file basis.
16+
* This directive not only affects the type declarations of parameters, but also
17+
* a function's return type.
18+
*
19+
* For more info review the Concept on strict type checking in the PHP track
20+
* <link>.
21+
*
22+
* To disable strict typing, comment out the directive below.
23+
*/
24+
25+
declare(strict_types=1);
26+
27+
class ListOps
28+
{
29+
public static function append(array $list1, array $list2): array
30+
{
31+
throw new \BadMethodCallException("Implement the append function");
32+
}
33+
34+
public static function concat(array $list1, array ...$listn): array
35+
{
36+
throw new \BadMethodCallException("Implement the concat function");
37+
}
38+
39+
public static function filter(callable $predicate, array $list): array
40+
{
41+
throw new \BadMethodCallException("Implement the filter function");
42+
}
43+
44+
public static function length(array $list): int
45+
{
46+
throw new \BadMethodCallException("Implement the length function");
47+
}
48+
49+
public static function map(callable $function, array $list): array
50+
{
51+
throw new \BadMethodCallException("Implement the map function");
52+
}
53+
54+
public static function foldl(callable $function, array $list, $accumulator)
55+
{
56+
throw new \BadMethodCallException("Implement the foldl function");
57+
}
58+
59+
public static function foldr(callable $function, array $list, $accumulator)
60+
{
61+
throw new \BadMethodCallException("Implement the foldr function");
62+
}
63+
64+
public static function reverse(array $list): array
65+
{
66+
throw new \BadMethodCallException("Implement the reverse function");
67+
}
68+
}

0 commit comments

Comments
 (0)