From c9a000993d7e77fdea4952f54cebc70ecc7dc151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Fri, 20 Sep 2024 15:14:37 -0700 Subject: [PATCH 1/2] Add bob --- config.json | 8 + exercises/practice/bob/.docs/instructions.md | 19 ++ exercises/practice/bob/.docs/introduction.md | 10 + exercises/practice/bob/.meta/config.json | 19 ++ exercises/practice/bob/.meta/example.red | 52 +++++ exercises/practice/bob/.meta/tests.toml | 85 +++++++ exercises/practice/bob/bob-test.red | 224 +++++++++++++++++++ exercises/practice/bob/bob.red | 11 + exercises/practice/bob/testlib.red | 217 ++++++++++++++++++ 9 files changed, 645 insertions(+) create mode 100644 exercises/practice/bob/.docs/instructions.md create mode 100644 exercises/practice/bob/.docs/introduction.md create mode 100644 exercises/practice/bob/.meta/config.json create mode 100644 exercises/practice/bob/.meta/example.red create mode 100644 exercises/practice/bob/.meta/tests.toml create mode 100644 exercises/practice/bob/bob-test.red create mode 100644 exercises/practice/bob/bob.red create mode 100644 exercises/practice/bob/testlib.red diff --git a/config.json b/config.json index 59589d2..a80c229 100644 --- a/config.json +++ b/config.json @@ -66,6 +66,14 @@ "prerequisites": [], "difficulty": 3 }, + { + "slug": "bob", + "name": "Bob", + "uuid": "362467ef-8ed3-4609-ae07-7395e5512f32", + "practices": [], + "prerequisites": [], + "difficulty": 2 + }, { "slug": "collatz-conjecture", "name": "Collatz Conjecture", diff --git a/exercises/practice/bob/.docs/instructions.md b/exercises/practice/bob/.docs/instructions.md new file mode 100644 index 0000000..bb702f7 --- /dev/null +++ b/exercises/practice/bob/.docs/instructions.md @@ -0,0 +1,19 @@ +# Instructions + +Your task is to determine what Bob will reply to someone when they say something to him or ask him a question. + +Bob only ever answers one of five things: + +- **"Sure."** + This is his response if you ask him a question, such as "How are you?" + The convention used for questions is that it ends with a question mark. +- **"Whoa, chill out!"** + This is his answer if you YELL AT HIM. + The convention used for yelling is ALL CAPITAL LETTERS. +- **"Calm down, I know what I'm doing!"** + This is what he says if you yell a question at him. +- **"Fine. Be that way!"** + This is how he responds to silence. + The convention used for silence is nothing, or various combinations of whitespace characters. +- **"Whatever."** + This is what he answers to anything else. diff --git a/exercises/practice/bob/.docs/introduction.md b/exercises/practice/bob/.docs/introduction.md new file mode 100644 index 0000000..ea4a807 --- /dev/null +++ b/exercises/practice/bob/.docs/introduction.md @@ -0,0 +1,10 @@ +# Introduction + +Bob is a [lackadaisical][] teenager. +He likes to think that he's very cool. +And he definitely doesn't get excited about things. +That wouldn't be cool. + +When people talk to him, his responses are pretty limited. + +[lackadaisical]: https://www.collinsdictionary.com/dictionary/english/lackadaisical diff --git a/exercises/practice/bob/.meta/config.json b/exercises/practice/bob/.meta/config.json new file mode 100644 index 0000000..0737644 --- /dev/null +++ b/exercises/practice/bob/.meta/config.json @@ -0,0 +1,19 @@ +{ + "authors": [ + "BNAndras" + ], + "files": { + "solution": [ + "bob.red" + ], + "test": [ + "bob-test.red" + ], + "example": [ + ".meta/example.red" + ] + }, + "blurb": "Bob is a lackadaisical teenager. In conversation, his responses are very limited.", + "source": "Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial.", + "source_url": "https://pine.fm/LearnToProgram/?Chapter=06" +} diff --git a/exercises/practice/bob/.meta/example.red b/exercises/practice/bob/.meta/example.red new file mode 100644 index 0000000..120d8e9 --- /dev/null +++ b/exercises/practice/bob/.meta/example.red @@ -0,0 +1,52 @@ +Red [ + description: {"Bob" exercise solution for exercism platform} + author: "BNAndras" +] + +response: function [ + heyBob +] [ + case [ + silent? heyBob [ "Fine. Be that way!" ] + loud-question? heyBob [ "Calm down, I know what I'm doing!" ] + loud-statement? heyBob [ "Whoa, chill out!" ] + question? heyBob [ "Sure." ] + true [ "Whatever." ] + ] +] + +silent?: function [ + message +] [ + "" == trim message +] + +loud-question?: function [ + message +] [ + and~ loud? message + question? message +] + +loud-statement?: function [ + message +] [ + loud? message +] + +question?: function [ + message +] [ + #"?" == last trim message +] + +loud?: function [ + message +] [ + and~ has-letter? message + message == uppercase copy message +] + +has-letter?: func [phrase][ + not none? find phrase charset [#"a" - #"z" #"A" - #"Z"] +] diff --git a/exercises/practice/bob/.meta/tests.toml b/exercises/practice/bob/.meta/tests.toml new file mode 100644 index 0000000..ea47d6b --- /dev/null +++ b/exercises/practice/bob/.meta/tests.toml @@ -0,0 +1,85 @@ +# 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. + +[e162fead-606f-437a-a166-d051915cea8e] +description = "stating something" + +[73a966dc-8017-47d6-bb32-cf07d1a5fcd9] +description = "shouting" + +[d6c98afd-df35-4806-b55e-2c457c3ab748] +description = "shouting gibberish" + +[8a2e771d-d6f1-4e3f-b6c6-b41495556e37] +description = "asking a question" + +[81080c62-4e4d-4066-b30a-48d8d76920d9] +description = "asking a numeric question" + +[2a02716d-685b-4e2e-a804-2adaf281c01e] +description = "asking gibberish" + +[c02f9179-ab16-4aa7-a8dc-940145c385f7] +description = "talking forcefully" + +[153c0e25-9bb5-4ec5-966e-598463658bcd] +description = "using acronyms in regular speech" + +[a5193c61-4a92-4f68-93e2-f554eb385ec6] +description = "forceful question" + +[a20e0c54-2224-4dde-8b10-bd2cdd4f61bc] +description = "shouting numbers" + +[f7bc4b92-bdff-421e-a238-ae97f230ccac] +description = "no letters" + +[bb0011c5-cd52-4a5b-8bfb-a87b6283b0e2] +description = "question with no letters" + +[496143c8-1c31-4c01-8a08-88427af85c66] +description = "shouting with special characters" + +[e6793c1c-43bd-4b8d-bc11-499aea73925f] +description = "shouting with no exclamation mark" + +[aa8097cc-c548-4951-8856-14a404dd236a] +description = "statement containing question mark" + +[9bfc677d-ea3a-45f2-be44-35bc8fa3753e] +description = "non-letters with question" + +[8608c508-f7de-4b17-985b-811878b3cf45] +description = "prattling on" + +[bc39f7c6-f543-41be-9a43-fd1c2f753fc0] +description = "silence" + +[d6c47565-372b-4b09-b1dd-c40552b8378b] +description = "prolonged silence" + +[4428f28d-4100-4d85-a902-e5a78cb0ecd3] +description = "alternate silence" + +[66953780-165b-4e7e-8ce3-4bcb80b6385a] +description = "multiple line question" + +[5371ef75-d9ea-4103-bcfa-2da973ddec1b] +description = "starting with whitespace" + +[05b304d6-f83b-46e7-81e0-4cd3ca647900] +description = "ending with whitespace" + +[72bd5ad3-9b2f-4931-a988-dce1f5771de2] +description = "other whitespace" + +[12983553-8601-46a8-92fa-fcaa3bc4a2a0] +description = "non-question ending with whitespace" diff --git a/exercises/practice/bob/bob-test.red b/exercises/practice/bob/bob-test.red new file mode 100644 index 0000000..b44cf23 --- /dev/null +++ b/exercises/practice/bob/bob-test.red @@ -0,0 +1,224 @@ +Red [ + description: {Tests for "Bob" Exercism exercise} + author: "loziniak" +] + +#include %testlib.red + +test-init/limit %bob.red 1 +; test-init/limit %.meta/example.red 1 ; test example solution + +canonical-cases: [#[ + description: "stating something" + input: #[ + heyBob: "Tom-ay-to, tom-aaaah-to." + ] + expected: "Whatever." + function: "response" + uuid: "e162fead-606f-437a-a166-d051915cea8e" +] #[ + description: "shouting" + input: #[ + heyBob: "WATCH OUT!" + ] + expected: "Whoa, chill out!" + function: "response" + uuid: "73a966dc-8017-47d6-bb32-cf07d1a5fcd9" +] #[ + description: "shouting gibberish" + input: #[ + heyBob: "FCECDFCAAB" + ] + expected: "Whoa, chill out!" + function: "response" + uuid: "d6c98afd-df35-4806-b55e-2c457c3ab748" +] #[ + description: "asking a question" + input: #[ + heyBob: "Does this cryogenic chamber make me look fat?" + ] + expected: "Sure." + function: "response" + uuid: "8a2e771d-d6f1-4e3f-b6c6-b41495556e37" +] #[ + description: "asking a numeric question" + input: #[ + heyBob: "You are, what, like 15?" + ] + expected: "Sure." + function: "response" + uuid: "81080c62-4e4d-4066-b30a-48d8d76920d9" +] #[ + description: "asking gibberish" + input: #[ + heyBob: "fffbbcbeab?" + ] + expected: "Sure." + function: "response" + uuid: "2a02716d-685b-4e2e-a804-2adaf281c01e" +] #[ + description: "talking forcefully" + input: #[ + heyBob: "Hi there!" + ] + expected: "Whatever." + function: "response" + uuid: "c02f9179-ab16-4aa7-a8dc-940145c385f7" +] #[ + description: "using acronyms in regular speech" + input: #[ + heyBob: "It's OK if you don't want to go work for NASA." + ] + expected: "Whatever." + function: "response" + uuid: "153c0e25-9bb5-4ec5-966e-598463658bcd" +] #[ + description: "forceful question" + input: #[ + heyBob: "WHAT'S GOING ON?" + ] + expected: "Calm down, I know what I'm doing!" + function: "response" + uuid: "a5193c61-4a92-4f68-93e2-f554eb385ec6" +] #[ + description: "shouting numbers" + input: #[ + heyBob: "1, 2, 3 GO!" + ] + expected: "Whoa, chill out!" + function: "response" + uuid: "a20e0c54-2224-4dde-8b10-bd2cdd4f61bc" +] #[ + description: "no letters" + input: #[ + heyBob: "1, 2, 3" + ] + expected: "Whatever." + function: "response" + uuid: "f7bc4b92-bdff-421e-a238-ae97f230ccac" +] #[ + description: "question with no letters" + input: #[ + heyBob: "4?" + ] + expected: "Sure." + function: "response" + uuid: "bb0011c5-cd52-4a5b-8bfb-a87b6283b0e2" +] #[ + description: "shouting with special characters" + input: #[ + heyBob: "ZOMG THE %^^*@#$(*^^ ZOMBIES ARE COMING!!11!!1!" + ] + expected: "Whoa, chill out!" + function: "response" + uuid: "496143c8-1c31-4c01-8a08-88427af85c66" +] #[ + description: "shouting with no exclamation mark" + input: #[ + heyBob: "I HATE THE DENTIST" + ] + expected: "Whoa, chill out!" + function: "response" + uuid: "e6793c1c-43bd-4b8d-bc11-499aea73925f" +] #[ + description: "statement containing question mark" + input: #[ + heyBob: "Ending with ? means a question." + ] + expected: "Whatever." + function: "response" + uuid: "aa8097cc-c548-4951-8856-14a404dd236a" +] #[ + description: "non-letters with question" + input: #[ + heyBob: ":) ?" + ] + expected: "Sure." + function: "response" + uuid: "9bfc677d-ea3a-45f2-be44-35bc8fa3753e" +] #[ + description: "prattling on" + input: #[ + heyBob: "Wait! Hang on. Are you going to be OK?" + ] + expected: "Sure." + function: "response" + uuid: "8608c508-f7de-4b17-985b-811878b3cf45" +] #[ + description: "silence" + input: #[ + heyBob: "" + ] + expected: "Fine. Be that way!" + function: "response" + uuid: "bc39f7c6-f543-41be-9a43-fd1c2f753fc0" +] #[ + description: "prolonged silence" + input: #[ + heyBob: " " + ] + expected: "Fine. Be that way!" + function: "response" + uuid: "d6c47565-372b-4b09-b1dd-c40552b8378b" +] #[ + description: "alternate silence" + input: #[ + heyBob: "^-^-^-^-^-^-^-^-^-^-" + ] + expected: "Fine. Be that way!" + function: "response" + uuid: "4428f28d-4100-4d85-a902-e5a78cb0ecd3" +] #[ + description: "multiple line question" + input: #[ + heyBob: {^/Does this cryogenic chamber make me look fat?^/No.} + ] + expected: "Whatever." + function: "response" + uuid: "66953780-165b-4e7e-8ce3-4bcb80b6385a" +] #[ + description: "starting with whitespace" + input: #[ + heyBob: " hmmmmmmm..." + ] + expected: "Whatever." + function: "response" + uuid: "5371ef75-d9ea-4103-bcfa-2da973ddec1b" +] #[ + description: "ending with whitespace" + input: #[ + heyBob: "Okay if like my spacebar quite a bit? " + ] + expected: "Sure." + function: "response" + uuid: "05b304d6-f83b-46e7-81e0-4cd3ca647900" +] #[ + description: "other whitespace" + input: #[ + heyBob: "^/^M ^-" + ] + expected: "Fine. Be that way!" + function: "response" + uuid: "72bd5ad3-9b2f-4931-a988-dce1f5771de2" +] #[ + description: "non-question ending with whitespace" + input: #[ + heyBob: "This is a statement ending with whitespace " + ] + expected: "Whatever." + function: "response" + uuid: "12983553-8601-46a8-92fa-fcaa3bc4a2a0" +]] + + +foreach c-case canonical-cases [ + case-code: reduce [ + 'expect c-case/expected compose [ + (to word! c-case/function) (values-of c-case/input) + ] + ] + + test c-case/description case-code +] + +test-results/print diff --git a/exercises/practice/bob/bob.red b/exercises/practice/bob/bob.red new file mode 100644 index 0000000..7b1f77e --- /dev/null +++ b/exercises/practice/bob/bob.red @@ -0,0 +1,11 @@ +Red [ + description: {"Bob" exercise solution for exercism platform} + author: "" ; you can write your name here, in quotes +] + +response: function [ + heyBob +] [ + cause-error 'user 'message "You need to implement response function." +] + diff --git a/exercises/practice/bob/testlib.red b/exercises/practice/bob/testlib.red new file mode 100644 index 0000000..9b0b79e --- /dev/null +++ b/exercises/practice/bob/testlib.red @@ -0,0 +1,217 @@ +Red [ + description: {Unit testing library} + author: "loziniak" +] + + +context [ + tested: ignore-after: test-file: results: output: none + + set 'test-init function [ + file [file!] + /limit + ia [integer!] + ] [ + self/tested: 0 + self/ignore-after: either limit [ia] [none] + self/test-file: file + self/results: copy [] + self/output: copy "" + ] + + sandbox!: context [ + + assert: function [ + code [block!] + /local result + ] [ + res: last results + + set/any 'result do code + either :result = true [ + res/status: 'pass + ] [ + res/status: 'fail + throw/name none 'expect-fail + ] + + :result + ] + + expect: function [ + expectation [any-type!] + code [block!] + /local result + ] [ + res: last results + res/expected: :expectation + + set/any 'result do code + res/actual: :result + + either :result = :expectation [ + res/status: 'pass + ] [ + res/status: 'fail + throw/name none 'expect-fail + ] + + :result + ] + + expect-error: function [ + type [word!] + code [block!] + /message + msg [string!] + /local result result-or-error + ] [ + returned-error?: no + set/any 'result-or-error try [ + set/any 'result do code + returned-error?: yes + :result + ] + + res: last results + res/actual: :result-or-error + res/expected: compose [type: (type)] + if message [append res/expected compose [id: 'message arg1: (msg)]] + + either all [ + error? :result-or-error + not returned-error? + result-or-error/type = type + any [ + not message + all [ + result-or-error/id = 'message + result-or-error/arg1 = msg + ] + ] + ] [ + res/status: 'pass + ] [ + res/status: 'fail + throw/name none 'expect-fail + ] + + :result-or-error + ] + ] + + set 'test function [ + summary [string!] + code [block!] + /extern + tested + ] [ + append results result: make map! compose/only [ + summary: (summary) ;@@ [string!] + test-code: (copy code) ;@@ [block!] + status: none ;@@ [word!] : 'pass | 'fail | 'error | 'ignored + ;-- expected (optional field) + ;-- actual (optional field) + ;-- output (optional field) + ] + + either any [ + none? ignore-after + tested < ignore-after + ] [ + clear output + old-functions: override-console + + exercise: make sandbox! load test-file + code: bind code exercise + uncaught?: yes + outcome: catch [ + outcome: try [ + catch/name [ + do code + ] 'expect-fail + none + ] + uncaught?: no + outcome + ] + + case [ + error? outcome [ + result/status: 'error + result/actual: outcome + ] + uncaught? [ + result/status: 'error + result/actual: make error! [type: 'throw id: 'throw arg1: outcome] + ] + ] + + restore-console old-functions + result/output: copy output + ] [ + result/status: 'ignored + ] + + tested: tested + 1 + ] + + set 'test-results function [ + /print + ] [ + either print [ + foreach result self/results [ + system/words/print rejoin [ + pad/with result/summary 40 #"." + "... " + switch result/status [ + pass ["✓"] + fail [rejoin [ + {FAILED.} + either find result 'expected [rejoin [ + { Expected: } result/expected + either find result 'actual [rejoin [ + {, but got } result/actual + ]] [] + ]] [] + newline + result/output + ]] + error [rejoin [ + newline + result/output + form result/actual + ]] + ignored ["(ignored)"] + ] + ] + ] + ] [ + self/results + ] + ] + + + override-console: function [] [ + old-functions: reduce [:prin :print :probe] + + system/words/prin: function [value [any-type!]] [ + append self/output form :value + return () + ] + system/words/print: function [value [any-type!]] [ + append self/output reduce [form :value #"^/"] + return () + ] + system/words/probe: function [value [any-type!]] [ + append self/output reduce [mold :value #"^/"] + return :value + ] + return old-functions + ] + + restore-console: function [old-functions [block!]] [ + set [prin print probe] old-functions + ] + +] From 959e86de93558464d0b8af07387051ed884c1801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20B=20Nagy?= <20251272+BNAndras@users.noreply.github.com> Date: Fri, 29 Nov 2024 13:49:35 -0800 Subject: [PATCH 2/2] EOL Co-authored-by: Victor Goff --- exercises/practice/bob/bob.red | 1 - 1 file changed, 1 deletion(-) diff --git a/exercises/practice/bob/bob.red b/exercises/practice/bob/bob.red index 7b1f77e..919d17d 100644 --- a/exercises/practice/bob/bob.red +++ b/exercises/practice/bob/bob.red @@ -8,4 +8,3 @@ response: function [ ] [ cause-error 'user 'message "You need to implement response function." ] -