From 081276ccb716713452a977b171afffa21b192334 Mon Sep 17 00:00:00 2001 From: Kah Goh Date: Fri, 1 Mar 2024 21:29:45 +0800 Subject: [PATCH] Add list-ops exercise Co-authored-by: Bobby Towers --- config.json | 649 +++++++++++++----- .../practice/list-ops/.docs/instructions.md | 19 + exercises/practice/list-ops/.meta/config.json | 20 + .../practice/list-ops/.meta/src/example.clj | 33 + exercises/practice/list-ops/.meta/tests.toml | 106 +++ exercises/practice/list-ops/deps.edn | 6 + exercises/practice/list-ops/project.clj | 4 + exercises/practice/list-ops/src/list_ops.clj | 33 + .../practice/list-ops/test/list_ops_test.clj | 65 ++ generator.clj | 140 ---- 10 files changed, 781 insertions(+), 294 deletions(-) create mode 100644 exercises/practice/list-ops/.docs/instructions.md create mode 100644 exercises/practice/list-ops/.meta/config.json create mode 100644 exercises/practice/list-ops/.meta/src/example.clj create mode 100644 exercises/practice/list-ops/.meta/tests.toml create mode 100644 exercises/practice/list-ops/deps.edn create mode 100644 exercises/practice/list-ops/project.clj create mode 100644 exercises/practice/list-ops/src/list_ops.clj create mode 100644 exercises/practice/list-ops/test/list_ops_test.clj delete mode 100644 generator.clj diff --git a/config.json b/config.json index 698bace5..9bbb0099 100644 --- a/config.json +++ b/config.json @@ -26,7 +26,7 @@ "test/%{snake_slug}_test.clj" ], "example": [ - "src/example.clj" + ".meta/src/example.clj" ], "exemplar": [ ".meta/exemplar.clj" @@ -122,7 +122,9 @@ "sequential-destructuring" ], "prerequisites": [ - "lists", "vectors", "strings" + "lists", + "vectors", + "strings" ], "status": "beta" }, @@ -138,8 +140,13 @@ "slug": "squeaky-clean", "name": "Squeaky Clean", "uuid": "3af5b219-d751-4243-89f7-c8f05216f534", - "concepts": ["chars"], - "prerequisites": ["basics", "strings"], + "concepts": [ + "chars" + ], + "prerequisites": [ + "basics", + "strings" + ], "status": "beta" }, { @@ -154,16 +161,27 @@ "slug": "coordinate-transformation", "name": "Coordinate Transformation", "uuid": "5b23eabd-6ebb-4fed-b889-9324ad174a5f", - "concepts": ["closures", "atoms"], - "prerequisites": ["vectors"], + "concepts": [ + "closures", + "atoms" + ], + "prerequisites": [ + "vectors" + ], "status": "beta" }, { "slug": "card-games", "name": "Card Games", "uuid": "01a06d2b-ffb1-4497-9bb3-d93ee2d0931b", - "concepts": ["lists"], - "prerequisites": ["basics", "conditionals", "booleans"], + "concepts": [ + "lists" + ], + "prerequisites": [ + "basics", + "conditionals", + "booleans" + ], "status": "beta" } ], @@ -172,17 +190,24 @@ "slug": "two-fer", "name": "Two Fer", "uuid": "1706ec00-9e51-45d1-ac3e-01b0360ea950", - "practices": ["strings"], - "prerequisites": ["strings"], - "difficulty": 1, - "topics": null + "practices": [ + "strings" + ], + "prerequisites": [ + "strings" + ], + "difficulty": 1 }, { "slug": "armstrong-numbers", "name": "Armstrong Numbers", "uuid": "0e0fec77-651a-45a7-af99-a768ebebef05", - "practices": ["numbers"], - "prerequisites": ["numbers"], + "practices": [ + "numbers" + ], + "prerequisites": [ + "numbers" + ], "difficulty": 1, "topics": [ "math" @@ -204,10 +229,13 @@ "name": "Reverse String", "uuid": "0f7b1858-15d0-467d-9f94-56408249c2f7", "practices": [], - "prerequisites": ["strings"], + "prerequisites": [ + "strings" + ], "difficulty": 1, "topics": [ - "strings", "core_functions" + "strings", + "core_functions" ] }, { @@ -215,7 +243,9 @@ "name": "Accumulate", "uuid": "49f62bbc-0f60-4922-b5a6-f266b80442f4", "practices": [], - "prerequisites": ["numbers"], + "prerequisites": [ + "numbers" + ], "difficulty": 2, "topics": [ "algorithms, core_functions" @@ -225,19 +255,30 @@ "slug": "acronym", "name": "Acronym", "uuid": "b99ed7da-98a8-43f0-8162-05c5408f6ac5", - "practices": ["strings"], - "prerequisites": ["strings", "booleans"], + "practices": [ + "strings" + ], + "prerequisites": [ + "strings", + "booleans" + ], "difficulty": 2, "topics": [ - "strings", "regular_expressions" + "strings", + "regular_expressions" ] }, { "slug": "all-your-base", "name": "All Your Base", "uuid": "7b8c5f7e-3c7d-4e69-ba8c-f29bb492a628", - "practices": ["numbers"], - "prerequisites": ["numbers", "vectors"], + "practices": [ + "numbers" + ], + "prerequisites": [ + "numbers", + "vectors" + ], "difficulty": 2, "topics": [ "math" @@ -247,8 +288,13 @@ "slug": "anagram", "name": "Anagram", "uuid": "11818959-7e42-4a1d-8dfd-288cea744d66", - "practices": ["strings"], - "prerequisites": ["strings", "vectors"], + "practices": [ + "strings" + ], + "prerequisites": [ + "strings", + "vectors" + ], "difficulty": 2, "topics": [ "strings" @@ -258,19 +304,31 @@ "slug": "bob", "name": "Bob", "uuid": "0317cc62-dd75-4841-86c3-01c055630fe7", - "practices": ["conditionals"], - "prerequisites": ["conditionals", "strings"], + "practices": [ + "conditionals" + ], + "prerequisites": [ + "conditionals", + "strings" + ], "difficulty": 2, "topics": [ - "strings", "regular_expressions", "conditionals" + "strings", + "regular_expressions", + "conditionals" ] }, { "slug": "collatz-conjecture", "name": "Collatz Conjecture", "uuid": "9516323c-721e-4bfc-84df-9bc32e467197", - "practices": ["numbers"], - "prerequisites": ["numbers", "conditionals"], + "practices": [ + "numbers" + ], + "prerequisites": [ + "numbers", + "conditionals" + ], "difficulty": 2, "topics": [ "math" @@ -280,8 +338,12 @@ "slug": "complex-numbers", "name": "Complex Numbers", "uuid": "ceaacb97-9c2c-43db-a9ac-28ebe6650f47", - "practices": ["numbers"], - "prerequisites": ["numbers"], + "practices": [ + "numbers" + ], + "prerequisites": [ + "numbers" + ], "difficulty": 2, "topics": [ "math" @@ -292,10 +354,15 @@ "name": "ETL", "uuid": "befca7ee-fc29-4ef0-afd7-2d3f68aa47fb", "practices": [], - "prerequisites": ["lists", "numbers", "strings"], + "prerequisites": [ + "lists", + "numbers", + "strings" + ], "difficulty": 2, "topics": [ - "integers", "maps" + "integers", + "maps" ] }, { @@ -303,18 +370,27 @@ "name": "Hamming", "uuid": "d120ad9a-98e9-4de7-9cb6-6aef3101cd1c", "practices": [], - "prerequisites": ["numbers", "strings", "conditionals"], + "prerequisites": [ + "numbers", + "strings", + "conditionals" + ], "difficulty": 2, "topics": [ - "strings", "conditionals" + "strings", + "conditionals" ] }, { "slug": "nth-prime", "name": "Nth Prime", "uuid": "167113f2-b015-4c04-809d-670193758c25", - "practices": ["numbers"], - "prerequisites": ["numbers"], + "practices": [ + "numbers" + ], + "prerequisites": [ + "numbers" + ], "difficulty": 2, "topics": [ "math" @@ -325,40 +401,61 @@ "name": "Nucleotide Count", "uuid": "223d10d6-539d-441f-89ba-77f7743e6092", "practices": [], - "prerequisites": ["strings", "conditionals"], + "prerequisites": [ + "strings", + "conditionals" + ], "difficulty": 2, "topics": [ - "strings", "conditionals", "exception_handling" + "strings", + "conditionals", + "exception_handling" ] }, { "slug": "pangram", "name": "Pangram", "uuid": "1f96161b-c83a-4f66-bc50-3e32e035da1f", - "practices": ["strings"], - "prerequisites": ["strings", "booleans"], + "practices": [ + "strings" + ], + "prerequisites": [ + "strings", + "booleans" + ], "difficulty": 2, "topics": [ - "strings", "maps" + "strings", + "maps" ] }, { "slug": "pig-latin", "name": "Pig Latin", "uuid": "a9b08dfd-3555-46bc-bc54-d605fd225c34", - "practices": ["strings"], - "prerequisites": ["strings"], + "practices": [ + "strings" + ], + "prerequisites": [ + "strings" + ], "difficulty": 2, "topics": [ - "strings", "regular_expressions" + "strings", + "regular_expressions" ] }, { "slug": "protein-translation", "name": "Protein Translation", "uuid": "591c3cc5-0d14-400d-85a2-4ce0e399813e", - "practices": ["strings"], - "prerequisites": ["strings", "vectors"], + "practices": [ + "strings" + ], + "prerequisites": [ + "strings", + "vectors" + ], "difficulty": 2, "topics": [ "pattern_matching", @@ -369,11 +466,19 @@ "slug": "raindrops", "name": "Raindrops", "uuid": "e670c978-8b71-4880-a543-3f9fb28d88b3", - "practices": ["conditionals"], - "prerequisites": ["numbers", "strings", "conditionals"], + "practices": [ + "conditionals" + ], + "prerequisites": [ + "numbers", + "strings", + "conditionals" + ], "difficulty": 2, "topics": [ - "integers", "strings", "conditionals" + "integers", + "strings", + "conditionals" ] }, { @@ -381,10 +486,13 @@ "name": "RNA Transcription", "uuid": "d8773153-d717-43f1-9324-c7e8cf00455c", "practices": [], - "prerequisites": ["strings"], + "prerequisites": [ + "strings" + ], "difficulty": 2, "topics": [ - "strings", "pattern_matching" + "strings", + "pattern_matching" ] }, { @@ -392,10 +500,16 @@ "name": "Robot Name", "uuid": "ce7df719-d3e2-444f-8ae3-f81c89fd15ce", "practices": [], - "prerequisites": ["numbers", "strings"], + "prerequisites": [ + "numbers", + "strings" + ], "difficulty": 2, "topics": [ - "sets", "conditionals", "regular_expressions", "randomness" + "sets", + "conditionals", + "regular_expressions", + "randomness" ] }, { @@ -403,7 +517,10 @@ "name": "Roman Numerals", "uuid": "cad43fab-50c2-470e-8364-6592e971d4df", "practices": [], - "prerequisites": ["numbers", "strings"], + "prerequisites": [ + "numbers", + "strings" + ], "difficulty": 2, "topics": [ "conditionals" @@ -414,10 +531,14 @@ "name": "Rotational Cipher", "uuid": "a40e8d4b-9793-4991-87d8-7efb92a3e3f2", "practices": [], - "prerequisites": ["numbers", "strings"], + "prerequisites": [ + "numbers", + "strings" + ], "difficulty": 2, "topics": [ - "algorithms", "regular_expressions" + "algorithms", + "regular_expressions" ] }, { @@ -425,10 +546,15 @@ "name": "Run-Length Encoding", "uuid": "fa1be98f-59b2-487e-948d-46e744d50dc4", "practices": [], - "prerequisites": ["numbers", "strings"], + "prerequisites": [ + "numbers", + "strings" + ], "difficulty": 2, "topics": [ - "strings", "regular_expressions", "parsing" + "strings", + "regular_expressions", + "parsing" ] }, { @@ -436,10 +562,14 @@ "name": "Scrabble Score", "uuid": "2804d2d1-0029-4473-8431-0857d4767d91", "practices": [], - "prerequisites": ["numbers", "strings"], + "prerequisites": [ + "numbers", + "strings" + ], "difficulty": 2, "topics": [ - "maps", "strings" + "maps", + "strings" ] }, { @@ -447,10 +577,15 @@ "name": "Secret Handshake", "uuid": "9c270d52-b1fe-4f1a-a639-2f7347c7cb92", "practices": [], - "prerequisites": ["numbers", "vectors", "strings"], + "prerequisites": [ + "numbers", + "vectors", + "strings" + ], "difficulty": 2, "topics": [ - "algorithms", "conditionals" + "algorithms", + "conditionals" ] }, { @@ -458,7 +593,10 @@ "name": "Series", "uuid": "f342d3f2-775f-4fb6-93c2-9aea4a8f5f22", "practices": [], - "prerequisites": ["numbers", "vectors"], + "prerequisites": [ + "numbers", + "vectors" + ], "difficulty": 2, "topics": [ "strings" @@ -468,8 +606,13 @@ "slug": "space-age", "name": "Space Age", "uuid": "c97868e9-36ca-4d00-9483-0fc6b4c37231", - "practices": ["floating-point-numbers"], - "prerequisites": ["numbers", "floating-point-numbers"], + "practices": [ + "floating-point-numbers" + ], + "prerequisites": [ + "numbers", + "floating-point-numbers" + ], "difficulty": 2, "topics": [ "math" @@ -480,18 +623,27 @@ "name": "Strain", "uuid": "8db4904c-a46f-4886-b214-0cf06b0f2ff1", "practices": [], - "prerequisites": ["conditionals", "numbers"], + "prerequisites": [ + "conditionals", + "numbers" + ], "difficulty": 2, "topics": [ - "algorithms", "conditionals", "filtering" + "algorithms", + "conditionals", + "filtering" ] }, { "slug": "sublist", "name": "Sublist", "uuid": "85dc1645-8424-45f2-8653-bc9730887b40", - "practices": ["lists"], - "prerequisites": ["lists"], + "practices": [ + "lists" + ], + "prerequisites": [ + "lists" + ], "difficulty": 2, "topics": [ "sets" @@ -502,7 +654,10 @@ "name": "Sum of Multiples", "uuid": "357de34a-c149-4a2c-b6a8-86ffb5eaa152", "practices": [], - "prerequisites": ["numbers", "conditionals"], + "prerequisites": [ + "numbers", + "conditionals" + ], "difficulty": 2, "topics": [ "math" @@ -512,11 +667,18 @@ "slug": "triangle", "name": "Triangle", "uuid": "a148a999-76ef-40d4-8bf7-96d6ae38876e", - "practices": ["floating-point-numbers", "conditionals"], - "prerequisites": ["floating-point-numbers", "conditionals"], + "practices": [ + "floating-point-numbers", + "conditionals" + ], + "prerequisites": [ + "floating-point-numbers", + "conditionals" + ], "difficulty": 2, "topics": [ - "integers", "conditionals" + "integers", + "conditionals" ] }, { @@ -524,10 +686,15 @@ "name": "Word Count", "uuid": "ea3cf3f6-35de-4da1-a74f-b7a13d89c39a", "practices": [], - "prerequisites": ["numbers", "conditionals", "strings"], + "prerequisites": [ + "numbers", + "conditionals", + "strings" + ], "difficulty": 2, "topics": [ - "regular_expressions", "strings" + "regular_expressions", + "strings" ] }, { @@ -535,10 +702,15 @@ "name": "Atbash Cipher", "uuid": "7d37e817-d2b7-4554-8885-b02d57d1d788", "practices": [], - "prerequisites": ["numbers", "conditionals", "strings"], + "prerequisites": [ + "numbers", + "conditionals", + "strings" + ], "difficulty": 3, "topics": [ - "algorithms", "regular_expressions" + "algorithms", + "regular_expressions" ] }, { @@ -546,10 +718,15 @@ "name": "Beer Song", "uuid": "56a4b06b-c48f-4a0f-883a-a08886472b56", "practices": [], - "prerequisites": ["numbers", "conditionals", "strings"], + "prerequisites": [ + "numbers", + "conditionals", + "strings" + ], "difficulty": 3, "topics": [ - "strings", "conditionals" + "strings", + "conditionals" ] }, { @@ -557,7 +734,9 @@ "name": "Binary", "uuid": "daf3daed-61ef-4964-8d33-e7a739c7a470", "practices": [], - "prerequisites": ["numbers"], + "prerequisites": [ + "numbers" + ], "difficulty": 3, "topics": [ "math" @@ -568,10 +747,14 @@ "name": "Binary Search", "uuid": "f32c6a4b-0f23-4cd2-95b2-f6e70e4b40b1", "practices": [], - "prerequisites": ["vectors"], + "prerequisites": [ + "vectors" + ], "difficulty": 3, "topics": [ - "algorithms", "recursion", "conditionals" + "algorithms", + "recursion", + "conditionals" ] }, { @@ -579,10 +762,13 @@ "name": "Binary Search Tree", "uuid": "53678d3d-de3f-483d-9f02-d2313290786d", "practices": [], - "prerequisites": ["vectors"], + "prerequisites": [ + "vectors" + ], "difficulty": 3, "topics": [ - "algorithms", "recursion" + "algorithms", + "recursion" ] }, { @@ -590,7 +776,10 @@ "name": "Change", "uuid": "7945eb6a-20eb-489d-90bd-020df3d9e2cb", "practices": [], - "prerequisites": ["numbers", "vectors"], + "prerequisites": [ + "numbers", + "vectors" + ], "difficulty": 3, "topics": [ "algorithms" @@ -601,10 +790,13 @@ "name": "Flatten Array", "uuid": "6b81cf43-e071-4daf-89a9-d10e213a5751", "practices": [], - "prerequisites": ["vectors"], + "prerequisites": [ + "vectors" + ], "difficulty": 3, "topics": [ - "core_functions", "seqs" + "core_functions", + "seqs" ] }, { @@ -612,7 +804,9 @@ "name": "Gigasecond", "uuid": "798445d8-acad-4b01-b471-3809f46a8a84", "practices": [], - "prerequisites": ["numbers"], + "prerequisites": [ + "numbers" + ], "difficulty": 3, "topics": [ "time" @@ -623,10 +817,14 @@ "name": "Grade School", "uuid": "a48ff289-baf0-4b13-a5aa-78f6ee91571b", "practices": [], - "prerequisites": ["numbers", "strings"], + "prerequisites": [ + "numbers", + "strings" + ], "difficulty": 3, "topics": [ - "maps", "core_functions" + "maps", + "core_functions" ] }, { @@ -634,10 +832,13 @@ "name": "Grains", "uuid": "2e57c7d4-d887-4dba-8483-60e026bdf5ea", "practices": [], - "prerequisites": ["numbers"], + "prerequisites": [ + "numbers" + ], "difficulty": 3, "topics": [ - "integers", "recursion" + "integers", + "recursion" ] }, { @@ -645,7 +846,9 @@ "name": "Hexadecimal", "uuid": "a4b1b39a-d942-4921-9b67-2bd913ff52a0", "practices": [], - "prerequisites": ["numbers"], + "prerequisites": [ + "numbers" + ], "difficulty": 3, "topics": [ "math" @@ -656,21 +859,31 @@ "name": "ISBN Verifier", "uuid": "0479e73c-acb3-4a36-949c-a2065bfb57e5", "practices": [], - "prerequisites": ["strings", "booleans"], + "prerequisites": [ + "strings", + "booleans" + ], "difficulty": 3, "topics": [ - "regular_expressions", "conditionals" + "regular_expressions", + "conditionals" ] }, { "slug": "isogram", "name": "Isogram", "uuid": "ced9928a-05dc-4afa-9645-a2f2e548fe6e", - "practices": ["strings"], - "prerequisites": ["strings", "booleans"], + "practices": [ + "strings" + ], + "prerequisites": [ + "strings", + "booleans" + ], "difficulty": 3, "topics": [ - "filtering", "strings" + "filtering", + "strings" ] }, { @@ -678,10 +891,13 @@ "name": "Kindergarten Garden", "uuid": "e40c52a7-9509-4a4d-9ad6-8ca7a3bdca1d", "practices": [], - "prerequisites": ["strings"], + "prerequisites": [ + "strings" + ], "difficulty": 3, "topics": [ - "strings", "conditionals" + "strings", + "conditionals" ] }, { @@ -689,10 +905,14 @@ "name": "Leap", "uuid": "336aa5ec-f868-4a8a-9fd2-989b6c2fd0be", "practices": [], - "prerequisites": ["conditionals", "numbers"], + "prerequisites": [ + "conditionals", + "numbers" + ], "difficulty": 3, "topics": [ - "integers", "conditionals" + "integers", + "conditionals" ] }, { @@ -700,7 +920,9 @@ "name": "Pascal's Triangle", "uuid": "29b16274-b413-4231-a1c7-aff8f93c9b7e", "practices": [], - "prerequisites": ["numbers"], + "prerequisites": [ + "numbers" + ], "difficulty": 3, "topics": [ "math" @@ -711,7 +933,9 @@ "name": "Perfect Numbers", "uuid": "e10b7063-75ac-46d6-848c-c50db87bddc7", "practices": [], - "prerequisites": ["numbers"], + "prerequisites": [ + "numbers" + ], "difficulty": 3, "topics": [ "math" @@ -722,7 +946,9 @@ "name": "Phone Number", "uuid": "41b95380-2bba-407b-b400-7d8a627f18fa", "practices": [], - "prerequisites": ["strings"], + "prerequisites": [ + "strings" + ], "difficulty": 3, "topics": [ "parsing" @@ -733,7 +959,9 @@ "name": "Prime Factors", "uuid": "96005f0f-5153-4915-9f28-326b41b63fab", "practices": [], - "prerequisites": ["numbers"], + "prerequisites": [ + "numbers" + ], "difficulty": 3, "topics": [ "math" @@ -744,21 +972,36 @@ "name": "Proverb", "uuid": "540d93a9-707f-4043-b46c-1dc83f2d50d8", "practices": [], - "prerequisites": ["strings", "vectors"], + "prerequisites": [ + "strings", + "vectors" + ], "difficulty": 3, "topics": [ - "vectors", "strings", "conditionals" + "vectors", + "strings", + "conditionals" ] }, { "slug": "say", "name": "Say", "uuid": "0ff7efbe-855e-4a81-9b64-f07d1557813f", - "practices": ["numbers", "strings", "conditionals"], - "prerequisites": ["numbers", "strings", "conditionals"], + "practices": [ + "numbers", + "strings", + "conditionals" + ], + "prerequisites": [ + "numbers", + "strings", + "conditionals" + ], "difficulty": 3, "topics": [ - "strings", "integers", "exception_handling" + "strings", + "integers", + "exception_handling" ] }, { @@ -766,7 +1009,10 @@ "name": "Trinary", "uuid": "f8a7f5eb-e317-4ffa-bdef-6e30a36511eb", "practices": [], - "prerequisites": ["numbers", "strings"], + "prerequisites": [ + "numbers", + "strings" + ], "difficulty": 3, "topics": [ "math" @@ -777,7 +1023,10 @@ "name": "Allergies", "uuid": "a71bc471-8359-4019-8ad1-e456774388b7", "practices": [], - "prerequisites": ["vectors", "booleans"], + "prerequisites": [ + "vectors", + "booleans" + ], "difficulty": 4, "topics": [ "conditionals" @@ -788,18 +1037,26 @@ "name": "Crypto Square", "uuid": "7387b271-d765-497c-9b85-481c947439b6", "practices": [], - "prerequisites": ["strings"], + "prerequisites": [ + "strings" + ], "difficulty": 4, "topics": [ - "algorithms", "sorting", "regular_expressions" + "algorithms", + "sorting", + "regular_expressions" ] }, { "slug": "difference-of-squares", "name": "Difference of Squares", "uuid": "6f69d8fe-9da2-48f9-a635-b9f54b626daf", - "practices": ["numbers"], - "prerequisites": ["numbers"], + "practices": [ + "numbers" + ], + "prerequisites": [ + "numbers" + ], "difficulty": 4, "topics": [ "math" @@ -810,18 +1067,27 @@ "name": "Dominoes", "uuid": "da04dfa4-5a66-49a5-a7ca-6320cfa4158f", "practices": [], - "prerequisites": ["numbers", "booleans"], + "prerequisites": [ + "numbers", + "booleans" + ], "difficulty": 4, "topics": [ - "graph_theory", "games" + "graph_theory", + "games" ] }, { "slug": "largest-series-product", "name": "Largest Series Product", "uuid": "2978747b-86e6-48f0-aef2-2d00714c8c5e", - "practices": ["numbers"], - "prerequisites": ["numbers", "strings"], + "practices": [ + "numbers" + ], + "prerequisites": [ + "numbers", + "strings" + ], "difficulty": 4, "topics": [ "math" @@ -832,18 +1098,25 @@ "name": "Meetup", "uuid": "81e37fc7-13cd-46a9-987c-c9bda4ff1ead", "practices": [], - "prerequisites": ["numbers"], + "prerequisites": [ + "numbers" + ], "difficulty": 4, "topics": [ - "dates", "time" + "dates", + "time" ] }, { "slug": "octal", "name": "Octal", "uuid": "fa596153-0cbe-40e9-a4d6-1a66fe6ef7e5", - "practices": ["numbers"], - "prerequisites": ["numbers"], + "practices": [ + "numbers" + ], + "prerequisites": [ + "numbers" + ], "difficulty": 4, "topics": [ "math" @@ -854,7 +1127,11 @@ "name": "Spiral Matrix", "uuid": "71d92de0-9f54-4e07-9a8f-fcd477f00219", "practices": [], - "prerequisites": ["vectors", "numbers", "conditionals"], + "prerequisites": [ + "vectors", + "numbers", + "conditionals" + ], "difficulty": 4, "topics": [ "recursivity" @@ -865,10 +1142,13 @@ "name": "Clock", "uuid": "83b7ffc2-aadd-4c26-9794-5e7f851eea8b", "practices": [], - "prerequisites": ["numbers"], + "prerequisites": [ + "numbers" + ], "difficulty": 5, "topics": [ - "dates", "time" + "dates", + "time" ] }, { @@ -876,7 +1156,9 @@ "name": "Diamond", "uuid": "cc0d15ad-d562-458c-8d05-4b213693cfb9", "practices": [], - "prerequisites": ["strings"], + "prerequisites": [ + "strings" + ], "difficulty": 5, "topics": [ "transforming" @@ -887,10 +1169,14 @@ "name": "Luhn", "uuid": "e2d0287c-2fe9-4f46-abfb-4db855d7489b", "practices": [], - "prerequisites": ["numbers", "strings"], + "prerequisites": [ + "numbers", + "strings" + ], "difficulty": 5, "topics": [ - "integers", "conditionals" + "integers", + "conditionals" ] }, { @@ -898,7 +1184,10 @@ "name": "Sieve", "uuid": "0e87bb30-3e7e-49dc-9f80-2d291dfb0111", "practices": [], - "prerequisites": ["vectors", "numbers"], + "prerequisites": [ + "vectors", + "numbers" + ], "difficulty": 5, "topics": [ "math" @@ -908,22 +1197,36 @@ "slug": "robot-simulator", "name": "Robot Simulator", "uuid": "e69ecf2e-8629-4d20-a90f-6de7536247ce", - "practices": ["conditionals"], - "prerequisites": ["conditionals"], + "practices": [ + "conditionals" + ], + "prerequisites": [ + "conditionals" + ], "difficulty": 6, "topics": [ - "strings", "conditionals" + "strings", + "conditionals" ] }, { "slug": "wordy", "name": "Wordy", "uuid": "5528f567-2b5b-498a-b166-984b2c90f6a5", - "practices": ["numbers", "strings", "conditionals"], - "prerequisites": ["numbers", "strings", "conditionals"], + "practices": [ + "numbers", + "strings", + "conditionals" + ], + "prerequisites": [ + "numbers", + "strings", + "conditionals" + ], "difficulty": 6, "topics": [ - "regular_expressions", "parsing" + "regular_expressions", + "parsing" ] }, { @@ -931,7 +1234,10 @@ "name": "Bank Account", "uuid": "d67a7a46-050c-4472-84bd-2e216079a452", "practices": [], - "prerequisites": ["conditionals", "numbers"], + "prerequisites": [ + "conditionals", + "numbers" + ], "difficulty": 7, "topics": [ "conditionals" @@ -942,7 +1248,10 @@ "name": "Matching Brackets", "uuid": "86f005c6-1754-4907-becb-a0997fd52d05", "practices": [], - "prerequisites": ["strings", "booleans"], + "prerequisites": [ + "strings", + "booleans" + ], "difficulty": 7, "topics": [ "parsing" @@ -953,10 +1262,15 @@ "name": "Minesweeper", "uuid": "e07e545c-997f-424b-b4ca-34fd7cc06bf7", "practices": [], - "prerequisites": ["vectors", "conditionals", "strings"], + "prerequisites": [ + "vectors", + "conditionals", + "strings" + ], "difficulty": 7, "topics": [ - "algorithms", "games" + "algorithms", + "games" ] }, { @@ -964,7 +1278,10 @@ "name": "Poker", "uuid": "f842d531-e2a1-4573-90c3-b77177df4787", "practices": [], - "prerequisites": ["conditionals", "strings"], + "prerequisites": [ + "conditionals", + "strings" + ], "difficulty": 7, "topics": [ "games" @@ -975,10 +1292,15 @@ "name": "Queen Attack", "uuid": "edd7932d-50a6-4350-b945-2bb8a8c891c7", "practices": [], - "prerequisites": ["booleans", "conditionals", "numbers"], + "prerequisites": [ + "booleans", + "conditionals", + "numbers" + ], "difficulty": 7, "topics": [ - "equality", "conditionals" + "equality", + "conditionals" ] }, { @@ -986,7 +1308,9 @@ "name": "Go Counting", "uuid": "f0210181-7fe5-49f9-9036-be4256612b3e", "practices": [], - "prerequisites": ["strings"], + "prerequisites": [ + "strings" + ], "difficulty": 9, "topics": [ "games" @@ -997,7 +1321,10 @@ "name": "POV", "uuid": "ca557f64-9e2d-4ab0-8788-4133764ef703", "practices": [], - "prerequisites": ["strings", "vectors"], + "prerequisites": [ + "strings", + "vectors" + ], "difficulty": 10, "topics": [ "conditionals" @@ -1008,7 +1335,10 @@ "name": "Yacht", "uuid": "459c8468-efc4-46a6-bbc0-9937167827a7", "practices": [], - "prerequisites": ["strings", "vectors"], + "prerequisites": [ + "strings", + "vectors" + ], "difficulty": 5, "topics": [ "conditionals" @@ -1019,11 +1349,22 @@ "name": "Zipper", "uuid": "331b2960-baae-4331-a462-a434fd6e8767", "practices": [], - "prerequisites": ["strings", "vectors"], + "prerequisites": [ + "strings", + "vectors" + ], "difficulty": 9, "topics": [ "conditionals" ] + }, + { + "slug": "list-ops", + "name": "List Ops", + "uuid": "699fb4ec-210d-454d-a41a-f7014abf8423", + "practices": [], + "prerequisites": [], + "difficulty": 3 } ] }, @@ -1127,14 +1468,14 @@ } ], "tags": [ + "execution_mode/compiled", "paradigm/declarative", "paradigm/functional", - "typing/dynamic", - "execution_mode/compiled", - "platform/windows", - "platform/mac", "platform/linux", + "platform/mac", + "platform/windows", "runtime/jvm", + "typing/dynamic", "used_for/artificial_intelligence", "used_for/backends", "used_for/cross_platform_development", diff --git a/exercises/practice/list-ops/.docs/instructions.md b/exercises/practice/list-ops/.docs/instructions.md new file mode 100644 index 00000000..ebc5dffe --- /dev/null +++ b/exercises/practice/list-ops/.docs/instructions.md @@ -0,0 +1,19 @@ +# Instructions + +Implement basic list operations. + +In functional languages list operations like `length`, `map`, and `reduce` are very common. +Implement a series of basic list operations, without using existing functions. + +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: + +- `append` (_given two lists, add all items in the second list to the end of the first list_); +- `concatenate` (_given a series of lists, combine all items in all lists into one flattened list_); +- `filter` (_given a predicate and a list, return the list of all items for which `predicate(item)` is True_); +- `length` (_given a list, return the total number of items within it_); +- `map` (_given a function and a list, return the list of the results of applying `function(item)` on all items_); +- `foldl` (_given a function, a list, and initial accumulator, fold (reduce) each item into the accumulator from the left_); +- `foldr` (_given a function, a list, and an initial accumulator, fold (reduce) each item into the accumulator from the right_); +- `reverse` (_given a list, return a list with all the original items, but in reversed order_). + +Note, the ordering in which arguments are passed to the fold functions (`foldl`, `foldr`) is significant. diff --git a/exercises/practice/list-ops/.meta/config.json b/exercises/practice/list-ops/.meta/config.json new file mode 100644 index 00000000..6d7f4a26 --- /dev/null +++ b/exercises/practice/list-ops/.meta/config.json @@ -0,0 +1,20 @@ +{ + "authors": [ + "bobbicodes" + ], + "contributors": [ + "kahgoh" + ], + "files": { + "solution": [ + "src/list_ops.clj" + ], + "test": [ + "test/list_ops_test.clj" + ], + "example": [ + "src/example.clj" + ] + }, + "blurb": "Implement basic list operations." +} diff --git a/exercises/practice/list-ops/.meta/src/example.clj b/exercises/practice/list-ops/.meta/src/example.clj new file mode 100644 index 00000000..0232d76d --- /dev/null +++ b/exercises/practice/list-ops/.meta/src/example.clj @@ -0,0 +1,33 @@ +(ns list-ops) + +(defn append [list1 list2] + (list-ops/foldl (fn [acc elem] (conj acc elem)) list2 list1)) + +(defn concat [list] + (cond + (empty? list) [] + :else (list-ops/foldl (fn [acc elem] (list-ops/append acc elem)) (rest list) (first list)))) + +(defn filter [f list] + (loop [acc [] l list] + (cond + (empty? l) acc + (f (first l)) (recur (conj acc (first l)) (rest l)) + :else (recur acc (rest l))))) + +(defn length [list] + (list-ops/foldl (fn [acc elem] (+ acc 1)) list 0)) + +(defn map [f list] + (list-ops/foldl (fn [acc elem] (conj acc (f elem))) list [])) +(defn foldl [f list init] + (loop [acc init l list] + (cond + (empty? l) acc + :else (recur (f acc (first l)) (rest l))))) + +(defn foldr [f list init] + (list-ops/foldl f (list-ops/reverse list) init)) + +(defn reverse [list] + (list-ops/foldl (fn [acc elem] (cons elem acc)) list [])) \ No newline at end of file diff --git a/exercises/practice/list-ops/.meta/tests.toml b/exercises/practice/list-ops/.meta/tests.toml new file mode 100644 index 00000000..08b1edc0 --- /dev/null +++ b/exercises/practice/list-ops/.meta/tests.toml @@ -0,0 +1,106 @@ +# 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. + +[485b9452-bf94-40f7-a3db-c3cf4850066a] +description = "append entries to a list and return the new list -> empty lists" + +[2c894696-b609-4569-b149-8672134d340a] +description = "append entries to a list and return the new list -> list to empty list" + +[e842efed-3bf6-4295-b371-4d67a4fdf19c] +description = "append entries to a list and return the new list -> empty list to list" + +[71dcf5eb-73ae-4a0e-b744-a52ee387922f] +description = "append entries to a list and return the new list -> non-empty lists" + +[28444355-201b-4af2-a2f6-5550227bde21] +description = "concatenate a list of lists -> empty list" + +[331451c1-9573-42a1-9869-2d06e3b389a9] +description = "concatenate a list of lists -> list of lists" + +[d6ecd72c-197f-40c3-89a4-aa1f45827e09] +description = "concatenate a list of lists -> list of nested lists" + +[0524fba8-3e0f-4531-ad2b-f7a43da86a16] +description = "filter list returning only values that satisfy the filter function -> empty list" + +[88494bd5-f520-4edb-8631-88e415b62d24] +description = "filter list returning only values that satisfy the filter function -> non-empty list" + +[1cf0b92d-8d96-41d5-9c21-7b3c37cb6aad] +description = "returns the length of a list -> empty list" + +[d7b8d2d9-2d16-44c4-9a19-6e5f237cb71e] +description = "returns the length of a list -> non-empty list" + +[c0bc8962-30e2-4bec-9ae4-668b8ecd75aa] +description = "return a list of elements whose values equal the list value transformed by the mapping function -> empty list" + +[11e71a95-e78b-4909-b8e4-60cdcaec0e91] +description = "return a list of elements whose values equal the list value transformed by the mapping function -> non-empty list" + +[613b20b7-1873-4070-a3a6-70ae5f50d7cc] +description = "folds (reduces) the given list from the left with a function -> empty list" +include = false + +[e56df3eb-9405-416a-b13a-aabb4c3b5194] +description = "folds (reduces) the given list from the left with a function -> direction independent function applied to non-empty list" +include = false + +[d2cf5644-aee1-4dfc-9b88-06896676fe27] +description = "folds (reduces) the given list from the left with a function -> direction dependent function applied to non-empty list" +include = false + +[36549237-f765-4a4c-bfd9-5d3a8f7b07d2] +description = "folds (reduces) the given list from the left with a function -> empty list" +reimplements = "613b20b7-1873-4070-a3a6-70ae5f50d7cc" + +[7a626a3c-03ec-42bc-9840-53f280e13067] +description = "folds (reduces) the given list from the left with a function -> direction independent function applied to non-empty list" +reimplements = "e56df3eb-9405-416a-b13a-aabb4c3b5194" + +[d7fcad99-e88e-40e1-a539-4c519681f390] +description = "folds (reduces) the given list from the left with a function -> direction dependent function applied to non-empty list" +reimplements = "d2cf5644-aee1-4dfc-9b88-06896676fe27" + +[aeb576b9-118e-4a57-a451-db49fac20fdc] +description = "folds (reduces) the given list from the right with a function -> empty list" +include = false + +[c4b64e58-313e-4c47-9c68-7764964efb8e] +description = "folds (reduces) the given list from the right with a function -> direction independent function applied to non-empty list" +include = false + +[be396a53-c074-4db3-8dd6-f7ed003cce7c] +description = "folds (reduces) the given list from the right with a function -> direction dependent function applied to non-empty list" +include = false + +[17214edb-20ba-42fc-bda8-000a5ab525b0] +description = "folds (reduces) the given list from the right with a function -> empty list" +reimplements = "aeb576b9-118e-4a57-a451-db49fac20fdc" + +[e1c64db7-9253-4a3d-a7c4-5273b9e2a1bd] +description = "folds (reduces) the given list from the right with a function -> direction independent function applied to non-empty list" +reimplements = "c4b64e58-313e-4c47-9c68-7764964efb8e" + +[8066003b-f2ff-437e-9103-66e6df474844] +description = "folds (reduces) the given list from the right with a function -> direction dependent function applied to non-empty list" +reimplements = "be396a53-c074-4db3-8dd6-f7ed003cce7c" + +[94231515-050e-4841-943d-d4488ab4ee30] +description = "reverse the elements of the list -> empty list" + +[fcc03d1e-42e0-4712-b689-d54ad761f360] +description = "reverse the elements of the list -> non-empty list" + +[40872990-b5b8-4cb8-9085-d91fc0d05d26] +description = "reverse the elements of the list -> list of lists is not flattened" diff --git a/exercises/practice/list-ops/deps.edn b/exercises/practice/list-ops/deps.edn new file mode 100644 index 00000000..561c3e2d --- /dev/null +++ b/exercises/practice/list-ops/deps.edn @@ -0,0 +1,6 @@ +{:aliases {:test {:extra-paths ["test"] + :extra-deps {io.github.cognitect-labs/test-runner + {:git/url "https://github.com/cognitect-labs/test-runner.git" + :sha "705ad25bbf0228b1c38d0244a36001c2987d7337"}} + :main-opts ["-m" "cognitect.test-runner"] + :exec-fn cognitect.test-runner.api/test}}} \ No newline at end of file diff --git a/exercises/practice/list-ops/project.clj b/exercises/practice/list-ops/project.clj new file mode 100644 index 00000000..31eb1b1b --- /dev/null +++ b/exercises/practice/list-ops/project.clj @@ -0,0 +1,4 @@ +(defproject list-ops "0.1.0-SNAPSHOT" + :description "list-ops exercise." + :url "https://github.com/exercism/clojure/tree/main/exercises/list-ops" + :dependencies [[org.clojure/clojure "1.10.0"]]) diff --git a/exercises/practice/list-ops/src/list_ops.clj b/exercises/practice/list-ops/src/list_ops.clj new file mode 100644 index 00000000..4c4a4b7e --- /dev/null +++ b/exercises/practice/list-ops/src/list_ops.clj @@ -0,0 +1,33 @@ +(ns list-ops) + +(defn append [list1 list2] ;; <- arglist goes here + ;; your code goes here +) + +(defn concat [list] ;; <- arglist goes here + ;; your code goes here +) + +(defn filter [f list] ;; <- arglist goes here + ;; your code goes here +) + +(defn length [list] ;; <- arglist goes here + ;; your code goes here +) + +(defn map [f list] ;; <- arglist goes here + ;; your code goes here +) + +(defn foldl [f list init] ;; <- arglist goes here + ;; your code goes here +) + +(defn foldr [f list init] ;; <- arglist goes here + ;; your code goes here +) + +(defn reverse [list] ;; <- arglist goes here + ;; your code goes here +) \ No newline at end of file diff --git a/exercises/practice/list-ops/test/list_ops_test.clj b/exercises/practice/list-ops/test/list_ops_test.clj new file mode 100644 index 00000000..c144dcf4 --- /dev/null +++ b/exercises/practice/list-ops/test/list_ops_test.clj @@ -0,0 +1,65 @@ +(ns list-ops-test + (:require [clojure.test :refer [deftest testing is]] + list-ops)) + +(deftest append-test + (testing "empty lists" + (is (= [] (list-ops/append [] [])))) + (testing "list to empty list" + (is (= [1 2 3 4] (list-ops/append [] [1 2 3 4])))) + (testing "empty list to list" + (is (= [1 2 3 4] (list-ops/append [1 2 3 4] [])))) + (testing "non-empty lists" + (is (= [1 2 2 3 4 5] (list-ops/append [1 2] [2 3 4 5]))))) + +(deftest concat-test + (testing "empty list" + (is (= [] (list-ops/concat [])))) + (testing "list of lists" + (is (= [1 2 3 4 5 6] (list-ops/concat [[1 2] [3] [] [4 5 6]])))) + (testing "list of nested lists" + (is (= [[1] [2] [3] [] [4 5 6]] (list-ops/concat [[[1] [2]] [[3]] [[]] [[4 5 6]]]))))) + +(deftest filter-test + (testing "empty list" + (is (= [] (list-ops/filter (fn [x] (= (mod x 2) 1)) []))) + (testing "non-empty list" + (is (= [1 3 5] (list-ops/filter (fn [x] (= (mod x 2) 1)) [1 2 3 5])))))) + +(deftest length-test + (testing "empty list" + (is (= 0 (list-ops/length [])))) + (testing "non-empty list" + (is (= 4 (list-ops/length [1 2 3 4]))))) + +(deftest map-test + (testing "empty list" + (is (= [] (list-ops/map (fn [x] (+ x 1)) [])))) + (testing "non-empty list" + (is (= [2 4 6 8] (list-ops/map (fn [x] (+ x 1)) [1 3 5 7]))))) + +(deftest foldl-test + (testing "empty list" + (is (= 2 (list-ops/foldl (fn [acc el] (* el acc)) [] 2)))) + (testing "direction independent function applied to non-empty list" + (is (= 15 (list-ops/foldl (fn [acc el] (+ el acc)) [1 2 3 4] 5)))) + (testing "direction dependent function applied to non-empty list" + (is (= 64 (list-ops/foldl (fn [acc el] (/ el acc)) [1 2 3 4] 24))))) + +(deftest foldr-test + (testing "empty list" + (is (= 2 (list-ops/foldr (fn [acc el] (* el acc)) [] 2)))) + (testing "direction independent function applied to non-empty list" + (is (= 15 (list-ops/foldr (fn [acc el] (+ el acc)) [1 2 3 4] 5)))) + (testing "direction dependent function applied to non-empty list" + (is (= 9 (list-ops/foldr (fn [acc el] (/ el acc)) [1 2 3 4] 24))))) + +(deftest reverse-test + (testing "empty list" + (is (= [] (list-ops/reverse [])))) + (testing "non-empty list" + (is (= [7 5 3 1] (list-ops/reverse [1 3 5 7])))) + (testing "list of lists is not flattened" + (is (= [[4 5 6] [] [3] [1 2]] (list-ops/reverse [[1 2] [3] [] [4 5 6]]))))) + +;(clojure.test/run-tests) \ No newline at end of file diff --git a/generator.clj b/generator.clj deleted file mode 100644 index 3c97c757..00000000 --- a/generator.clj +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/env bb - -(require '[cheshire.core :as json] - '[babashka.fs :as fs] - '[clojure.string :as str]) - -(comment - (def slug "zipper")) - -(def data - (let [url "https://raw.githubusercontent.com/exercism/problem-specifications/main/exercises/"] - {:canonical-data (json/parse-string (slurp (str url "/" slug "/canonical-data.json")) true) - :description (slurp (str url "/" slug "/description.md")) - :metadata (slurp (str url "/" slug "/metadata.toml"))})) - -(second - (str/split (:metadata data) #"=")) - -(defn get-meta - "Returns a vector containing the exercise title and blurb" - [data] - (mapv last - (map #(map str/trim (str/split % #"=")) - (str/split-lines (:metadata data))))) - -(defn init-deps [data] - (fs/create-dirs (fs/path "exercises" "practice" - (:exercise (:canonical-data data)) "src")) - (spit (str (fs/file "exercises" "practice" - (:exercise (:canonical-data data)) - "deps.edn")) - "{:aliases {:test {:extra-paths [\"test\"] - :extra-deps {io.github.cognitect-labs/test-runner - {:git/url \"https://github.com/cognitect-labs/test-runner.git\" - :sha \"705ad25bbf0228b1c38d0244a36001c2987d7337\"}} - :main-opts [\"-m\" \"cognitect.test-runner\"] - :exec-fn cognitect.test-runner.api/test}}}")) - -(defn init-lein [data] - (let [slug (:exercise (:canonical-data data))] - (spit (str (fs/file "exercises" "practice" - (:exercise (:canonical-data data)) "project.clj")) - (str "(defproject " slug " \"0.1.0-SNAPSHOT\" - :description \"" slug " exercise.\" - :url \"https://github.com/exercism/clojure/tree/master/exercises/" slug "\" - :dependencies [[org.clojure/clojure \"1.10.0\"]]) -")))) - -(defn test-ns-form [data] - (str "(ns " (:exercise data) "-test - (:require [clojure.test :refer [deftest testing is]]\n " - (:exercise data) "))\n\n")) - -(defn src-ns-form [data] - (str "(ns " (:exercise data) ")\n\n")) - -(defn testing-form [slug test-case] - (let [property (symbol (str slug "/" (:property test-case))) - input (:input test-case) - args (map #(get input %) (keys input))] - (str " (testing \"" (:description test-case) "\" - (is (= " (:expected test-case) " " - (reverse (into (list property) args)) ")))"))) - -(defn zipper-generator [slug test-case] - (let [input (:input test-case) - ops (for [op (:operations input)] - (if (contains? op :item) - (str "(zipper/" (:operation op) " " - (if (nil? (:item op)) - "nil" - (str (:item op))) ")") - (str "zipper/" (:operation op))))] - (str " (testing \"" (:description test-case) "\" - (is (= " (if (nil? (:value (:expected test-case))) - "nil" (:value (:expected test-case))) " " - "\n (-> " (:initialTree input) "\n " - (apply str (interpose "\n " ops)) "))))"))) - -(defn testing-forms - "Outputs a sequence of the test cases for a given property name - given its name as a string and the canonical data." - [property data] - (let [test-cases (filter #(= property (:property %)) (:cases data))] - (map #(zipper-generator (:exercise data) %) test-cases))) - -(defn deftest-forms [data] - (for [property (distinct (map :property (:cases (:canonical-data data))))] - (str "(deftest " property "-test\n" - (apply str (interpose "\n" - (testing-forms property (:canonical-data data)))) - ")"))) - -(defn init-tests [data] - #_(fs/create-dir (fs/path "exercises" "practice" - (:exercise (:canonical-data data)) "test")) - (spit (str (fs/file "exercises" "practice" - (:exercise (:canonical-data data)) "test" - (str (str/replace (:exercise (:canonical-data data)) "-" "_") - "_test.clj"))) - (str (test-ns-form (:canonical-data data)) - (apply str (interpose "\n\n" - (deftest-forms data)))))) - -(defn init-src [data] - (spit (str (fs/file "exercises" "practice" (:exercise (:canonical-data data)) "src" - (str (str/replace (:exercise (:canonical-data data)) - "-" "_") ".clj"))) - (str (src-ns-form (:canonical-data data)) - (apply str (interpose "\n\n" - (for [property (distinct (map :property (:cases (:canonical-data data))))] - (str "(defn " property " []\n )"))))))) - -(defn init-description! [data] - (let [path ["exercises" "practice" (:exercise (:canonical-data data)) ".docs"]] - (when-not (fs/directory? (apply fs/path path)) - (fs/create-dir (apply fs/path path)) - (spit (str (apply fs/file (conj path "instructions.md"))) - (:description data))))) - -(defn config [data author blurb] - (let [slug (:exercise (:canonical-data data))] - {:authors [author], - :contributors [], - :files {:solution [(str "src/" (str/replace slug "-" "_") ".clj")], - :test [(str "test/" (str/replace slug "-" "_") "_test.clj")], - :example [".meta/src/example.clj"]}, - :blurb blurb})) - -(defn init-config! [data] - (let [path ["exercises" "practice" (:exercise (:canonical-data data)) ".meta"]] - (when-not (fs/directory? (apply fs/path path)) - (fs/create-dirs (apply fs/path (conj path "src"))) - (spit (str (apply fs/file (conj path "config.json"))) - (json/generate-string (config data "porkostomus" (last (get-meta data))) - {:pretty true}))))) - -(comment - (init-config! data) - ) \ No newline at end of file