rkoans 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (460) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/CURRICULUM.md +86 -0
  4. data/README.md +77 -0
  5. data/THIRD_PARTY_NOTICES.md +30 -0
  6. data/exercises/about-array-assignment/about_array_assignment.rb +45 -0
  7. data/exercises/about-array-assignment/brief.md +11 -0
  8. data/exercises/about-array-assignment/hint.md +11 -0
  9. data/exercises/about-arrays/about_arrays.rb +77 -0
  10. data/exercises/about-arrays/brief.md +16 -0
  11. data/exercises/about-arrays/hint.md +13 -0
  12. data/exercises/about-asserts/about_asserts.rb +22 -0
  13. data/exercises/about-asserts/brief.md +22 -0
  14. data/exercises/about-asserts/hint.md +10 -0
  15. data/exercises/about-blocks/about_blocks.rb +76 -0
  16. data/exercises/about-blocks/brief.md +44 -0
  17. data/exercises/about-blocks/hint.md +7 -0
  18. data/exercises/about-class-methods/about_class_methods.rb +105 -0
  19. data/exercises/about-class-methods/brief.md +73 -0
  20. data/exercises/about-class-methods/hint.md +8 -0
  21. data/exercises/about-classes/about_classes.rb +131 -0
  22. data/exercises/about-classes/brief.md +73 -0
  23. data/exercises/about-classes/hint.md +7 -0
  24. data/exercises/about-constants/about_constants.rb +49 -0
  25. data/exercises/about-constants/brief.md +51 -0
  26. data/exercises/about-constants/hint.md +7 -0
  27. data/exercises/about-control-statements/about_control_statements.rb +152 -0
  28. data/exercises/about-control-statements/brief.md +9 -0
  29. data/exercises/about-control-statements/hint.md +7 -0
  30. data/exercises/about-dice-project/about_dice_project.rb +27 -0
  31. data/exercises/about-dice-project/brief.md +12 -0
  32. data/exercises/about-dice-project/hint.md +5 -0
  33. data/exercises/about-exceptions/about_exceptions.rb +84 -0
  34. data/exercises/about-exceptions/brief.md +19 -0
  35. data/exercises/about-exceptions/hint.md +8 -0
  36. data/exercises/about-extra-credit/about_extra_credit.rb +117 -0
  37. data/exercises/about-extra-credit/brief.md +28 -0
  38. data/exercises/about-extra-credit/hint.md +5 -0
  39. data/exercises/about-hashes/about_hashes.rb +160 -0
  40. data/exercises/about-hashes/brief.md +9 -0
  41. data/exercises/about-hashes/hint.md +8 -0
  42. data/exercises/about-inheritance/about_inheritance.rb +63 -0
  43. data/exercises/about-inheritance/brief.md +50 -0
  44. data/exercises/about-inheritance/hint.md +8 -0
  45. data/exercises/about-iteration/about_iteration.rb +96 -0
  46. data/exercises/about-iteration/brief.md +26 -0
  47. data/exercises/about-iteration/hint.md +6 -0
  48. data/exercises/about-keyword-arguments/about_keyword_arguments.rb +56 -0
  49. data/exercises/about-keyword-arguments/brief.md +28 -0
  50. data/exercises/about-keyword-arguments/hint.md +7 -0
  51. data/exercises/about-message-passing/about_message_passing.rb +112 -0
  52. data/exercises/about-message-passing/brief.md +59 -0
  53. data/exercises/about-message-passing/hint.md +8 -0
  54. data/exercises/about-methods/about_methods.rb +104 -0
  55. data/exercises/about-methods/brief.md +55 -0
  56. data/exercises/about-methods/hint.md +8 -0
  57. data/exercises/about-modules/about_modules.rb +43 -0
  58. data/exercises/about-modules/brief.md +44 -0
  59. data/exercises/about-modules/hint.md +8 -0
  60. data/exercises/about-nil/about_nil.rb +29 -0
  61. data/exercises/about-nil/brief.md +12 -0
  62. data/exercises/about-nil/hint.md +11 -0
  63. data/exercises/about-objects/about_objects.rb +51 -0
  64. data/exercises/about-objects/brief.md +14 -0
  65. data/exercises/about-objects/hint.md +12 -0
  66. data/exercises/about-open-classes/about_open_classes.rb +38 -0
  67. data/exercises/about-open-classes/brief.md +34 -0
  68. data/exercises/about-open-classes/hint.md +7 -0
  69. data/exercises/about-pattern-matching/about_pattern_matching.rb +106 -0
  70. data/exercises/about-pattern-matching/brief.md +124 -0
  71. data/exercises/about-pattern-matching/hint.md +8 -0
  72. data/exercises/about-proxy-object-project/about_proxy_object_project.rb +43 -0
  73. data/exercises/about-proxy-object-project/brief.md +10 -0
  74. data/exercises/about-proxy-object-project/hint.md +5 -0
  75. data/exercises/about-regular-expressions/about_regular_expressions.rb +174 -0
  76. data/exercises/about-regular-expressions/brief.md +9 -0
  77. data/exercises/about-regular-expressions/hint.md +8 -0
  78. data/exercises/about-sandwich-code/about_sandwich_code.rb +58 -0
  79. data/exercises/about-sandwich-code/brief.md +14 -0
  80. data/exercises/about-sandwich-code/hint.md +5 -0
  81. data/exercises/about-scope/about_scope.rb +76 -0
  82. data/exercises/about-scope/brief.md +35 -0
  83. data/exercises/about-scope/hint.md +8 -0
  84. data/exercises/about-scoring-project/about_scoring_project.rb +16 -0
  85. data/exercises/about-scoring-project/brief.md +10 -0
  86. data/exercises/about-scoring-project/hint.md +5 -0
  87. data/exercises/about-strings/about_strings.rb +142 -0
  88. data/exercises/about-strings/brief.md +22 -0
  89. data/exercises/about-strings/hint.md +11 -0
  90. data/exercises/about-symbols/about_symbols.rb +53 -0
  91. data/exercises/about-symbols/brief.md +21 -0
  92. data/exercises/about-symbols/hint.md +12 -0
  93. data/exercises/about-to-str/about_to_str.rb +49 -0
  94. data/exercises/about-to-str/brief.md +37 -0
  95. data/exercises/about-to-str/hint.md +7 -0
  96. data/exercises/about-triangle-project/about_triangle_project.rb +15 -0
  97. data/exercises/about-triangle-project/brief.md +11 -0
  98. data/exercises/about-triangle-project/hint.md +5 -0
  99. data/exercises/about-triangle-project-two/about_triangle_project_two.rb +22 -0
  100. data/exercises/about-triangle-project-two/brief.md +10 -0
  101. data/exercises/about-triangle-project-two/hint.md +5 -0
  102. data/exercises/about-true-and-false/about_true_and_false.rb +26 -0
  103. data/exercises/about-true-and-false/brief.md +22 -0
  104. data/exercises/about-true-and-false/hint.md +7 -0
  105. data/exercises/blocks-and-methods/blocks_and_methods.rb +14 -0
  106. data/exercises/blocks-and-methods/brief.md +8 -0
  107. data/exercises/blocks-and-methods/hint.md +6 -0
  108. data/exercises/catalog.json +61 -0
  109. data/exercises/class-state/brief.md +8 -0
  110. data/exercises/class-state/class_state.rb +39 -0
  111. data/exercises/class-state/hint.md +5 -0
  112. data/exercises/closure-capture/brief.md +8 -0
  113. data/exercises/closure-capture/closure_capture.rb +21 -0
  114. data/exercises/closure-capture/hint.md +5 -0
  115. data/exercises/collection-basics/brief.md +8 -0
  116. data/exercises/collection-basics/collection_basics.rb +16 -0
  117. data/exercises/collection-basics/hint.md +6 -0
  118. data/exercises/constant-scope/brief.md +8 -0
  119. data/exercises/constant-scope/constant_scope.rb +18 -0
  120. data/exercises/constant-scope/hint.md +5 -0
  121. data/exercises/core-protocols/brief.md +8 -0
  122. data/exercises/core-protocols/core_protocols.rb +43 -0
  123. data/exercises/core-protocols/hint.md +5 -0
  124. data/exercises/delegation/brief.md +8 -0
  125. data/exercises/delegation/delegation.rb +20 -0
  126. data/exercises/delegation/hint.md +5 -0
  127. data/exercises/dynamic-methods/brief.md +8 -0
  128. data/exercises/dynamic-methods/dynamic_methods.rb +33 -0
  129. data/exercises/dynamic-methods/hint.md +5 -0
  130. data/exercises/exception-flow/brief.md +8 -0
  131. data/exercises/exception-flow/exception_flow.rb +27 -0
  132. data/exercises/exception-flow/hint.md +5 -0
  133. data/exercises/heredoc-layout/brief.md +14 -0
  134. data/exercises/heredoc-layout/heredoc_layout.rb +25 -0
  135. data/exercises/heredoc-layout/hint.md +9 -0
  136. data/exercises/keyword-forwarding/brief.md +8 -0
  137. data/exercises/keyword-forwarding/hint.md +5 -0
  138. data/exercises/keyword-forwarding/keyword_forwarding.rb +27 -0
  139. data/exercises/lazy-enumeration/brief.md +8 -0
  140. data/exercises/lazy-enumeration/hint.md +5 -0
  141. data/exercises/lazy-enumeration/lazy_enumeration.rb +16 -0
  142. data/exercises/literals-and-operators/brief.md +20 -0
  143. data/exercises/literals-and-operators/hint.md +5 -0
  144. data/exercises/literals-and-operators/literals_and_operators.rb +15 -0
  145. data/exercises/method-contracts/brief.md +8 -0
  146. data/exercises/method-contracts/hint.md +5 -0
  147. data/exercises/method-contracts/method_contracts.rb +22 -0
  148. data/exercises/method-lookup/brief.md +8 -0
  149. data/exercises/method-lookup/hint.md +5 -0
  150. data/exercises/method-lookup/method_lookup.rb +26 -0
  151. data/exercises/nonlocal-exit/brief.md +8 -0
  152. data/exercises/nonlocal-exit/hint.md +5 -0
  153. data/exercises/nonlocal-exit/nonlocal_exit.rb +29 -0
  154. data/exercises/numbered-parameters/brief.md +18 -0
  155. data/exercises/numbered-parameters/hint.md +5 -0
  156. data/exercises/numbered-parameters/numbered_parameters.rb +18 -0
  157. data/exercises/numeric-precision/brief.md +8 -0
  158. data/exercises/numeric-precision/hint.md +5 -0
  159. data/exercises/numeric-precision/numeric_precision.rb +17 -0
  160. data/exercises/pattern-matching/brief.md +8 -0
  161. data/exercises/pattern-matching/hint.md +5 -0
  162. data/exercises/pattern-matching/pattern_matching.rb +22 -0
  163. data/exercises/refinement-scope/brief.md +8 -0
  164. data/exercises/refinement-scope/hint.md +5 -0
  165. data/exercises/refinement-scope/refinement_scope.rb +33 -0
  166. data/exercises/regexp-captures/brief.md +8 -0
  167. data/exercises/regexp-captures/hint.md +5 -0
  168. data/exercises/regexp-captures/regexp_captures.rb +25 -0
  169. data/exercises/runtime-context/brief.md +20 -0
  170. data/exercises/runtime-context/hint.md +8 -0
  171. data/exercises/runtime-context/runtime_context.rb +11 -0
  172. data/exercises/shared-rows/brief.md +8 -0
  173. data/exercises/shared-rows/hint.md +7 -0
  174. data/exercises/shared-rows/shared_rows.rb +13 -0
  175. data/exercises/singleton-pattern/brief.md +8 -0
  176. data/exercises/singleton-pattern/hint.md +5 -0
  177. data/exercises/singleton-pattern/singleton_pattern.rb +20 -0
  178. data/exercises/time-and-date/brief.md +8 -0
  179. data/exercises/time-and-date/hint.md +5 -0
  180. data/exercises/time-and-date/time_and_date.rb +21 -0
  181. data/exercises/visibility/brief.md +8 -0
  182. data/exercises/visibility/hint.md +5 -0
  183. data/exercises/visibility/visibility.rb +32 -0
  184. data/lib/rkoans/catalog.rb +31 -0
  185. data/lib/rkoans/checker.rb +62 -0
  186. data/lib/rkoans/cli.rb +79 -0
  187. data/lib/rkoans/error.rb +6 -0
  188. data/lib/rkoans/exercise.rb +50 -0
  189. data/lib/rkoans/keyboard.rb +51 -0
  190. data/lib/rkoans/progress.rb +39 -0
  191. data/lib/rkoans/selection.rb +31 -0
  192. data/lib/rkoans/session.rb +127 -0
  193. data/lib/rkoans/terminal_view.rb +99 -0
  194. data/lib/rkoans/version.rb +1 -1
  195. data/lib/rkoans/watcher.rb +58 -0
  196. data/lib/rkoans.rb +13 -3
  197. data/sig/about_array_assignment_acceptance_test.rbs +3 -0
  198. data/sig/about_arrays_acceptance_test.rbs +3 -0
  199. data/sig/about_asserts_command_test.rbs +4 -0
  200. data/sig/about_blocks_acceptance_test.rbs +3 -0
  201. data/sig/about_class_methods_acceptance_test.rbs +3 -0
  202. data/sig/about_classes_acceptance_test.rbs +3 -0
  203. data/sig/about_constants_acceptance_test.rbs +3 -0
  204. data/sig/about_control_statements_acceptance_test.rbs +3 -0
  205. data/sig/about_dice_project_acceptance_test.rbs +3 -0
  206. data/sig/about_exceptions_acceptance_test.rbs +3 -0
  207. data/sig/about_extra_credit_acceptance_test.rbs +5 -0
  208. data/sig/about_hashes_acceptance_test.rbs +3 -0
  209. data/sig/about_inheritance_acceptance_test.rbs +3 -0
  210. data/sig/about_iteration_acceptance_test.rbs +3 -0
  211. data/sig/about_keyword_arguments_acceptance_test.rbs +3 -0
  212. data/sig/about_message_passing_acceptance_test.rbs +3 -0
  213. data/sig/about_methods_acceptance_test.rbs +3 -0
  214. data/sig/about_modules_acceptance_test.rbs +3 -0
  215. data/sig/about_nil_acceptance_test.rbs +3 -0
  216. data/sig/about_objects_acceptance_test.rbs +3 -0
  217. data/sig/about_open_classes_acceptance_test.rbs +3 -0
  218. data/sig/about_pattern_matching_acceptance_test.rbs +3 -0
  219. data/sig/about_proxy_object_project_acceptance_test.rbs +3 -0
  220. data/sig/about_regular_expressions_acceptance_test.rbs +3 -0
  221. data/sig/about_sandwich_code_acceptance_test.rbs +3 -0
  222. data/sig/about_scope_acceptance_test.rbs +3 -0
  223. data/sig/about_scoring_project_acceptance_test.rbs +3 -0
  224. data/sig/about_strings_acceptance_test.rbs +3 -0
  225. data/sig/about_symbols_acceptance_test.rbs +3 -0
  226. data/sig/about_to_str_acceptance_test.rbs +3 -0
  227. data/sig/about_triangle_project_acceptance_test.rbs +3 -0
  228. data/sig/about_triangle_project_two_acceptance_test.rbs +3 -0
  229. data/sig/about_true_and_false_command_test.rbs +4 -0
  230. data/sig/catalog_error_command_test.rbs +4 -0
  231. data/sig/checker_test.rbs +9 -0
  232. data/sig/class_state_acceptance_test.rbs +3 -0
  233. data/sig/closure_capture_acceptance_test.rbs +3 -0
  234. data/sig/command_support.rbs +18 -0
  235. data/sig/command_test.rbs +5 -0
  236. data/sig/constant_scope_acceptance_test.rbs +3 -0
  237. data/sig/core_protocols_acceptance_test.rbs +3 -0
  238. data/sig/curriculum_cop_test.rbs +9 -0
  239. data/sig/delegation_acceptance_test.rbs +3 -0
  240. data/sig/dynamic_methods_acceptance_test.rbs +3 -0
  241. data/sig/exception_flow_acceptance_test.rbs +3 -0
  242. data/sig/exercise_test.rbs +3 -0
  243. data/sig/exercises/about_array_assignment.rbs +36 -0
  244. data/sig/exercises/about_arrays.rbs +51 -0
  245. data/sig/exercises/about_asserts.rbs +23 -0
  246. data/sig/exercises/about_blocks.rbs +40 -0
  247. data/sig/exercises/about_class_methods.rbs +62 -0
  248. data/sig/exercises/about_classes.rbs +88 -0
  249. data/sig/exercises/about_constants.rbs +53 -0
  250. data/sig/exercises/about_control_statements.rbs +46 -0
  251. data/sig/exercises/about_dice_project.rbs +16 -0
  252. data/sig/exercises/about_exceptions.rbs +36 -0
  253. data/sig/exercises/about_extra_credit.rbs +36 -0
  254. data/sig/exercises/about_hashes.rbs +62 -0
  255. data/sig/exercises/about_inheritance.rbs +50 -0
  256. data/sig/exercises/about_iteration.rbs +37 -0
  257. data/sig/exercises/about_keyword_arguments.rbs +33 -0
  258. data/sig/exercises/about_message_passing.rbs +68 -0
  259. data/sig/exercises/about_methods.rbs +68 -0
  260. data/sig/exercises/about_modules.rbs +38 -0
  261. data/sig/exercises/about_nil.rbs +23 -0
  262. data/sig/exercises/about_objects.rbs +38 -0
  263. data/sig/exercises/about_open_classes.rbs +31 -0
  264. data/sig/exercises/about_pattern_matching.rbs +65 -0
  265. data/sig/exercises/about_proxy_object_project.rbs +31 -0
  266. data/sig/exercises/about_regular_expressions.rbs +83 -0
  267. data/sig/exercises/about_sandwich_code.rbs +17 -0
  268. data/sig/exercises/about_scope.rbs +59 -0
  269. data/sig/exercises/about_scoring_project.rbs +16 -0
  270. data/sig/exercises/about_strings.rbs +85 -0
  271. data/sig/exercises/about_symbols.rbs +46 -0
  272. data/sig/exercises/about_to_str.rbs +36 -0
  273. data/sig/exercises/about_triangle_project.rbs +11 -0
  274. data/sig/exercises/about_triangle_project_two.rbs +12 -0
  275. data/sig/exercises/about_true_and_false.rbs +27 -0
  276. data/sig/exercises/blocks_and_methods.rbs +11 -0
  277. data/sig/exercises/class_state.rbs +19 -0
  278. data/sig/exercises/closure_capture.rbs +10 -0
  279. data/sig/exercises/collection_basics.rbs +6 -0
  280. data/sig/exercises/collection_basics_test.rbs +4 -0
  281. data/sig/exercises/constant_scope.rbs +11 -0
  282. data/sig/exercises/core_protocols.rbs +20 -0
  283. data/sig/exercises/delegation.rbs +14 -0
  284. data/sig/exercises/dynamic_methods.rbs +13 -0
  285. data/sig/exercises/exception_flow.rbs +11 -0
  286. data/sig/exercises/heredoc_layout.rbs +11 -0
  287. data/sig/exercises/keyword_forwarding.rbs +12 -0
  288. data/sig/exercises/lazy_enumeration.rbs +10 -0
  289. data/sig/exercises/literals_and_operators.rbs +12 -0
  290. data/sig/exercises/method_contracts.rbs +11 -0
  291. data/sig/exercises/method_lookup.rbs +16 -0
  292. data/sig/exercises/nonlocal_exit.rbs +14 -0
  293. data/sig/exercises/numbered_parameters.rbs +11 -0
  294. data/sig/exercises/numeric_precision.rbs +11 -0
  295. data/sig/exercises/pattern_matching.rbs +10 -0
  296. data/sig/exercises/refinement_scope.rbs +18 -0
  297. data/sig/exercises/regexp_captures.rbs +11 -0
  298. data/sig/exercises/runtime_context.rbs +23 -0
  299. data/sig/exercises/shared_rows.rbs +11 -0
  300. data/sig/exercises/singleton_pattern.rbs +14 -0
  301. data/sig/exercises/time_and_date.rbs +11 -0
  302. data/sig/exercises/visibility.rbs +18 -0
  303. data/sig/fixture_support.rbs +11 -0
  304. data/sig/help_hint_command_test.rbs +8 -0
  305. data/sig/heredoc_layout_acceptance_test.rbs +3 -0
  306. data/sig/keyboard_session_test.rbs +9 -0
  307. data/sig/keyword_forwarding_acceptance_test.rbs +3 -0
  308. data/sig/lazy_enumeration_acceptance_test.rbs +3 -0
  309. data/sig/literals_and_operators_acceptance_test.rbs +3 -0
  310. data/sig/method_contracts_acceptance_test.rbs +3 -0
  311. data/sig/method_lookup_acceptance_test.rbs +3 -0
  312. data/sig/nonlocal_exit_acceptance_test.rbs +3 -0
  313. data/sig/numbered_parameters_acceptance_test.rbs +3 -0
  314. data/sig/numeric_precision_acceptance_test.rbs +4 -0
  315. data/sig/packaging_test.rbs +3 -0
  316. data/sig/pattern_matching_acceptance_test.rbs +3 -0
  317. data/sig/reference_solutions_test.rbs +3 -0
  318. data/sig/refinement_scope_acceptance_test.rbs +3 -0
  319. data/sig/regexp_captures_acceptance_test.rbs +4 -0
  320. data/sig/rkoans/catalog.rbs +11 -0
  321. data/sig/rkoans/checker.rbs +22 -0
  322. data/sig/rkoans/cli.rbs +21 -0
  323. data/sig/rkoans/exercise.rbs +18 -0
  324. data/sig/rkoans/keyboard.rbs +13 -0
  325. data/sig/rkoans/progress.rbs +9 -0
  326. data/sig/rkoans/selection.rbs +9 -0
  327. data/sig/rkoans/session.rbs +30 -0
  328. data/sig/rkoans/terminal_view.rbs +24 -0
  329. data/sig/rkoans/watcher.rbs +18 -0
  330. data/sig/rkoans.rbs +2 -0
  331. data/sig/runtime_context_command_test.rbs +4 -0
  332. data/sig/selection_command_test.rbs +5 -0
  333. data/sig/session_command_test.rbs +12 -0
  334. data/sig/session_edge_cases_test.rbs +4 -0
  335. data/sig/shared_rows_acceptance_test.rbs +3 -0
  336. data/sig/singleton_pattern_acceptance_test.rbs +3 -0
  337. data/sig/time_and_date_acceptance_test.rbs +4 -0
  338. data/sig/visibility_acceptance_test.rbs +4 -0
  339. data/sig/watcher_test.rbs +3 -0
  340. data/solutions/about-array-assignment/about_array_assignment.rb +36 -0
  341. data/solutions/about-arrays/about_arrays.rb +53 -0
  342. data/solutions/about-asserts/about_asserts.rb +22 -0
  343. data/solutions/about-blocks/about_blocks.rb +30 -0
  344. data/solutions/about-class-methods/about_class_methods.rb +36 -0
  345. data/solutions/about-classes/about_classes.rb +40 -0
  346. data/solutions/about-constants/about_constants.rb +26 -0
  347. data/solutions/about-control-statements/about_control_statements.rb +35 -0
  348. data/solutions/about-dice-project/about_dice_project.rb +27 -0
  349. data/solutions/about-exceptions/about_exceptions.rb +30 -0
  350. data/solutions/about-extra-credit/about_extra_credit.rb +114 -0
  351. data/solutions/about-hashes/about_hashes.rb +52 -0
  352. data/solutions/about-inheritance/about_inheritance.rb +27 -0
  353. data/solutions/about-iteration/about_iteration.rb +31 -0
  354. data/solutions/about-keyword-arguments/about_keyword_arguments.rb +28 -0
  355. data/solutions/about-message-passing/about_message_passing.rb +38 -0
  356. data/solutions/about-methods/about_methods.rb +39 -0
  357. data/solutions/about-modules/about_modules.rb +23 -0
  358. data/solutions/about-nil/about_nil.rb +23 -0
  359. data/solutions/about-objects/about_objects.rb +34 -0
  360. data/solutions/about-open-classes/about_open_classes.rb +23 -0
  361. data/solutions/about-pattern-matching/about_pattern_matching.rb +39 -0
  362. data/solutions/about-proxy-object-project/about_proxy_object_project.rb +44 -0
  363. data/solutions/about-regular-expressions/about_regular_expressions.rb +60 -0
  364. data/solutions/about-sandwich-code/about_sandwich_code.rb +60 -0
  365. data/solutions/about-scope/about_scope.rb +33 -0
  366. data/solutions/about-scoring-project/about_scoring_project.rb +19 -0
  367. data/solutions/about-strings/about_strings.rb +56 -0
  368. data/solutions/about-symbols/about_symbols.rb +35 -0
  369. data/solutions/about-to-str/about_to_str.rb +24 -0
  370. data/solutions/about-triangle-project/about_triangle_project.rb +19 -0
  371. data/solutions/about-triangle-project-two/about_triangle_project_two.rb +25 -0
  372. data/solutions/about-true-and-false/about_true_and_false.rb +25 -0
  373. data/solutions/blocks-and-methods/blocks_and_methods.rb +14 -0
  374. data/solutions/class-state/class_state.rb +33 -0
  375. data/solutions/closure-capture/closure_capture.rb +12 -0
  376. data/solutions/collection-basics/collection_basics.rb +14 -0
  377. data/solutions/constant-scope/constant_scope.rb +18 -0
  378. data/solutions/core-protocols/core_protocols.rb +44 -0
  379. data/solutions/delegation/delegation.rb +17 -0
  380. data/solutions/dynamic-methods/dynamic_methods.rb +32 -0
  381. data/solutions/exception-flow/exception_flow.rb +34 -0
  382. data/solutions/heredoc-layout/heredoc_layout.rb +24 -0
  383. data/solutions/keyword-forwarding/keyword_forwarding.rb +26 -0
  384. data/solutions/lazy-enumeration/lazy_enumeration.rb +11 -0
  385. data/solutions/literals-and-operators/literals_and_operators.rb +22 -0
  386. data/solutions/method-contracts/method_contracts.rb +18 -0
  387. data/solutions/method-lookup/method_lookup.rb +26 -0
  388. data/solutions/nonlocal-exit/nonlocal_exit.rb +46 -0
  389. data/solutions/numbered-parameters/numbered_parameters.rb +18 -0
  390. data/solutions/numeric-precision/numeric_precision.rb +17 -0
  391. data/solutions/pattern-matching/pattern_matching.rb +17 -0
  392. data/solutions/refinement-scope/refinement_scope.rb +34 -0
  393. data/solutions/regexp-captures/regexp_captures.rb +24 -0
  394. data/solutions/runtime-context/runtime_context.rb +19 -0
  395. data/solutions/shared-rows/shared_rows.rb +13 -0
  396. data/solutions/singleton-pattern/singleton_pattern.rb +19 -0
  397. data/solutions/time-and-date/time_and_date.rb +16 -0
  398. data/solutions/visibility/visibility.rb +34 -0
  399. data/test/exercises/about_array_assignment_test.rb +87 -0
  400. data/test/exercises/about_arrays_test.rb +119 -0
  401. data/test/exercises/about_asserts_test.rb +41 -0
  402. data/test/exercises/about_blocks_test.rb +140 -0
  403. data/test/exercises/about_class_methods_test.rb +232 -0
  404. data/test/exercises/about_classes_test.rb +261 -0
  405. data/test/exercises/about_constants_test.rb +111 -0
  406. data/test/exercises/about_control_statements_test.rb +188 -0
  407. data/test/exercises/about_dice_project_test.rb +40 -0
  408. data/test/exercises/about_exceptions_test.rb +98 -0
  409. data/test/exercises/about_extra_credit_test.rb +74 -0
  410. data/test/exercises/about_hashes_test.rb +163 -0
  411. data/test/exercises/about_inheritance_test.rb +121 -0
  412. data/test/exercises/about_iteration_test.rb +148 -0
  413. data/test/exercises/about_keyword_arguments_test.rb +80 -0
  414. data/test/exercises/about_message_passing_test.rb +230 -0
  415. data/test/exercises/about_methods_test.rb +208 -0
  416. data/test/exercises/about_modules_test.rb +98 -0
  417. data/test/exercises/about_nil_test.rb +35 -0
  418. data/test/exercises/about_objects_test.rb +74 -0
  419. data/test/exercises/about_open_classes_test.rb +60 -0
  420. data/test/exercises/about_pattern_matching_test.rb +257 -0
  421. data/test/exercises/about_proxy_object_project_test.rb +75 -0
  422. data/test/exercises/about_regular_expressions_test.rb +243 -0
  423. data/test/exercises/about_sandwich_code_test.rb +82 -0
  424. data/test/exercises/about_scope_test.rb +123 -0
  425. data/test/exercises/about_scoring_project_test.rb +62 -0
  426. data/test/exercises/about_strings_test.rb +255 -0
  427. data/test/exercises/about_symbols_test.rb +120 -0
  428. data/test/exercises/about_to_str_test.rb +89 -0
  429. data/test/exercises/about_triangle_project_test.rb +29 -0
  430. data/test/exercises/about_triangle_project_two_test.rb +28 -0
  431. data/test/exercises/about_true_and_false_test.rb +43 -0
  432. data/test/exercises/blocks_and_methods_test.rb +22 -0
  433. data/test/exercises/class_state_test.rb +29 -0
  434. data/test/exercises/closure_capture_test.rb +29 -0
  435. data/test/exercises/collection_basics_test.rb +18 -0
  436. data/test/exercises/constant_scope_test.rb +18 -0
  437. data/test/exercises/core_protocols_test.rb +28 -0
  438. data/test/exercises/delegation_test.rb +23 -0
  439. data/test/exercises/dynamic_methods_test.rb +28 -0
  440. data/test/exercises/exception_flow_test.rb +17 -0
  441. data/test/exercises/heredoc_layout_test.rb +18 -0
  442. data/test/exercises/keyword_forwarding_test.rb +22 -0
  443. data/test/exercises/lazy_enumeration_test.rb +15 -0
  444. data/test/exercises/literals_and_operators_test.rb +25 -0
  445. data/test/exercises/method_contracts_test.rb +28 -0
  446. data/test/exercises/method_lookup_test.rb +14 -0
  447. data/test/exercises/nonlocal_exit_test.rb +22 -0
  448. data/test/exercises/numbered_parameters_test.rb +15 -0
  449. data/test/exercises/numeric_precision_test.rb +24 -0
  450. data/test/exercises/pattern_matching_test.rb +18 -0
  451. data/test/exercises/refinement_scope_test.rb +14 -0
  452. data/test/exercises/regexp_captures_test.rb +20 -0
  453. data/test/exercises/runtime_context_test.rb +59 -0
  454. data/test/exercises/shared_rows_test.rb +34 -0
  455. data/test/exercises/singleton_pattern_test.rb +16 -0
  456. data/test/exercises/time_and_date_test.rb +22 -0
  457. data/test/exercises/visibility_test.rb +22 -0
  458. metadata +471 -4
  459. data/Rakefile +0 -12
  460. data/sig/test_rkoans.rbs +0 -3
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The example deliberately contrasts received arguments with values actually used.
4
+ # The example deliberately uses for rather than a block iterator.
5
+ # rubocop:disable Lint/UnusedMethodArgument, Style/For
6
+
7
+ module Exercises
8
+ # Implement readers(names) to return a new class with one instance reader per name, using
9
+ # define_method and instance_variable_get.
10
+ class DynamicMethods
11
+ # Builds a class whose readers capture their own instance-variable names.
12
+ # @return [Class]
13
+ def self.readers(names)
14
+ Class.new do
15
+ for name in names
16
+ define_method(name) { instance_variable_get("@#{name}") }
17
+ end
18
+ end
19
+ end
20
+
21
+ # Evaluates a fixed literal expression with access to the local binding.
22
+ # @return [Integer]
23
+ def self.evaluate(factor) = factor * 3
24
+ # Reads the named instance variable from the supplied object.
25
+ # @return [Object]
26
+ def self.instance_value(object, name) = nil
27
+ # Returns the class object seen as self inside class_eval.
28
+ # @return [Class]
29
+ def self.class_value(klass) = nil
30
+ end
31
+ end
32
+
33
+ # rubocop:enable Lint/UnusedMethodArgument, Style/For
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ A for loop shares the captured name; each-created block scopes avoid that trap.
4
+
5
+ eval can use an explicit binding; class_eval changes the evaluation context for class-related operations.
@@ -0,0 +1,8 @@
1
+ # Ensure the trail survives
2
+
3
+ Implement `trace(fail:)`: append "work"; if fail, raise and rescue a StandardError and append "rescue"; otherwise append "else". In both cases append "ensure" in an ensure clause. Return the ordered trail. Implement `reraises` so a rescued ArgumentError is re-raised with its original message.
4
+
5
+ Use `rkoans check` to investigate one failing check at a time. Hints are optional.
6
+
7
+ Edit `exception_flow.rb` in this exercise's folder. Checks call
8
+ `Exercises::ExceptionFlow` and its example classes.
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exercises
4
+ # Implement trace(fail:): append "work"; if fail, raise and rescue a StandardError and append
5
+ # "rescue"; otherwise append "else".
6
+ class ExceptionFlow
7
+ # Implements trace.
8
+ def self.trace(fail:)
9
+ trail = ['work']
10
+ begin
11
+ raise StandardError, 'failure' if fail
12
+ rescue StandardError
13
+ trail << 'rescue'
14
+ else
15
+ trail << 'else'
16
+ end
17
+ trail
18
+ end
19
+
20
+ # Implements reraises.
21
+ def self.reraises
22
+ raise ArgumentError, 'original'
23
+ rescue ArgumentError
24
+ nil
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ else executes only after a successful begin body; ensure executes regardless of a rescued error.
4
+
5
+ Cleanup belongs in ensure; avoid returning from ensure because that can replace the intended result or error.
@@ -0,0 +1,14 @@
1
+ # Whitespace is data
2
+
3
+ A heredoc makes a multiline string between a starting delimiter and its closing
4
+ line. Fix `render(name)` to return exactly `"Hello Ada\n Ruby\n"` for `"Ada"`.
5
+ Other names must interpolate too. Remove common source indentation while keeping
6
+ the two spaces before `Ruby` and the final newline.
7
+
8
+ Then fix `literal` to return the literal characters `Hello #{name}` followed by
9
+ a newline. It must preserve the marker instead of inserting a variable's value.
10
+ Keep both heredoc examples so you can compare indentation and quoting.
11
+
12
+ Compare `<<-TEXT` with `<<~TEXT`, and an unquoted delimiter with a single-quoted
13
+ one. An indented closing delimiter and stripped content indentation are different
14
+ features. Save to rerun the checks automatically.
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exercises
4
+ # Produces multiline strings while preserving deliberate relative indentation.
5
+ class HeredocLayout
6
+ # Fix the delimiter so common indentation disappears but Ruby stays indented.
7
+ # @param name [String] name interpolated into the greeting
8
+ # @return [String]
9
+ def self.render(name)
10
+ <<-TEXT
11
+ Hello #{name}
12
+ Ruby
13
+ TEXT
14
+ end
15
+
16
+ # Quote the delimiter so the interpolation marker remains literal text.
17
+ # @return [String]
18
+ def self.literal
19
+ name = 'Ada'
20
+ <<~TEXT
21
+ Hello #{name}
22
+ TEXT
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,9 @@
1
+ # Hint: indentation and interpolation are separate
2
+
3
+ `<<~` strips the common leading indentation from the content while preserving
4
+ indentation relative to other lines. `<<-` allows an indented closing delimiter
5
+ but keeps the content indentation.
6
+
7
+ Single-quote the starting delimiter to keep `#{name}` as literal text. The
8
+ closing delimiter still uses its plain name. Once quoting is fixed, the local
9
+ `name` assignment in `literal` is no longer needed.
@@ -0,0 +1,8 @@
1
+ # The lost keyword
2
+
3
+ Fix `forward` to preserve positional arguments, keyword arguments, and the block when calling `target`. target takes a payload, suffix: defaulting to "?", and returns the yielded payload string plus the suffix. A positional hash is still a positional payload.
4
+
5
+ Use `rkoans check` to investigate one failing check at a time. Hints are optional.
6
+
7
+ Edit `keyword_forwarding.rb` in this exercise's folder. Checks call
8
+ `Exercises::KeywordForwarding` and its example classes.
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ Ruby 3 separates keyword arguments from a positional final hash.
4
+
5
+ Forward each argument category separately, or use the argument-forwarding shorthand.
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The example deliberately contrasts received arguments with values actually used.
4
+ # The block name is observable through parameter metadata or the explicit forwarding example.
5
+ # The exercise makes positional, keyword, and block forwarding visible.
6
+ # rubocop:disable Lint/UnusedMethodArgument, Naming/BlockForwarding, Style/ArgumentsForwarding
7
+
8
+ module Exercises
9
+ # Fix forward to preserve positional arguments, keyword arguments, and the block when calling
10
+ # target.
11
+ class KeywordForwarding
12
+ # Renders one positional payload with an optional block and suffix.
13
+ # @return [String]
14
+ def self.target(payload, suffix: '?')
15
+ rendered = block_given? ? yield(payload) : payload.to_s
16
+ rendered + suffix
17
+ end
18
+
19
+ # Forwards positional arguments, keywords, and the block to target.
20
+ # @return [String]
21
+ def self.forward(*args, **keywords, &block)
22
+ target(*args, &block)
23
+ end
24
+ end
25
+ end
26
+
27
+ # rubocop:enable Lint/UnusedMethodArgument, Naming/BlockForwarding, Style/ArgumentsForwarding
@@ -0,0 +1,8 @@
1
+ # An endless queue
2
+
3
+ Implement `first_multiples(limit)` to return the first limit positive multiples of seven, starting at seven, using the endless range `(1..)`. Do not materialize the endless sequence. Zero returns [].
4
+
5
+ Use `rkoans check` to investigate one failing check at a time. Hints are optional.
6
+
7
+ Edit `lazy_enumeration.rb` in this exercise's folder. Checks call
8
+ `Exercises::LazyEnumeration` and its example classes.
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ An endless sequence requires a finite consumer.
4
+
5
+ lazy defers selecting until elements are requested.
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The example deliberately contrasts received arguments with values actually used.
4
+ # rubocop:disable Lint/UnusedMethodArgument
5
+
6
+ module Exercises
7
+ # Implement first_multiples(limit) to return the first limit positive multiples of seven, starting
8
+ # at seven, using the endless range (1..).
9
+ class LazyEnumeration
10
+ # Takes the requested number of multiples from a lazy infinite sequence.
11
+ # @return [Array<Integer>]
12
+ def self.first_multiples(limit) = (1..).lazy.select { |n| (n % 7).zero? }.first(3)
13
+ end
14
+ end
15
+
16
+ # rubocop:enable Lint/UnusedMethodArgument
@@ -0,0 +1,20 @@
1
+ # Truthy zero, tricky operators
2
+
3
+ Fill `predictions` for these expressions: `!!0`, `5 / 2`, `5 / 2.0`, `1 + 2 * 3`, `!nil`, `%w[ruby rails]`, and `(1..3).to_a`. The keys are zero_truthy, integer_division, float_division, precedence, not_nil, words, range. Implement `default_for_nil(value)` to substitute "missing" only for nil, preserving false and zero.
4
+
5
+ Use `rkoans check` to investigate one failing check at a time. Hints are optional.
6
+
7
+ Edit `literals_and_operators.rb` in this exercise's folder. Checks call
8
+ `Exercises::LiteralsAndOperators` and its example classes.
9
+
10
+ Use these expressions for the prediction fields, in order:
11
+
12
+ ```ruby
13
+ 0 ? true : false
14
+ 5 / 2
15
+ 5.0 / 2
16
+ 1 + 2 * 3
17
+ !nil
18
+ %w[ruby rails]
19
+ (1..3).to_a
20
+ ```
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ Only nil and false are falsey in Ruby.
4
+
5
+ Integer division and floating-point division have different results; multiplication binds before addition.
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exercises
4
+ # Fill predictions for these expressions: !!0, 5 / 2, 5 / 2.0, 1 + 2 * 3, !nil, %w[ruby rails], and (1..3).to_a.
5
+ class LiteralsAndOperators
6
+ # Implements predictions.
7
+ def self.predictions
8
+ { zero_truthy: false, integer_division: 2.5, float_division: 2, precedence: 9, not_nil: false, words: [],
9
+ range: [] }
10
+ end
11
+
12
+ # Implements default for nil.
13
+ def self.default_for_nil(value) = value || 'missing'
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ # The method’s contract
2
+
3
+ Fix `format_order(name, quantity=1, *extras, unit:, **options, &block)` to return "name:quantity:unit:extra_count:priority" where priority defaults to "normal". If a block is supplied, pass the formatted string to it. Implement `parameters` by exposing the actual method parameter metadata. Keep the declared signature intact.
4
+
5
+ Use `rkoans check` to investigate one failing check at a time. Hints are optional.
6
+
7
+ Edit `method_contracts.rb` in this exercise's folder. Checks call
8
+ `Exercises::MethodContracts` and its example classes.
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ Defaults, splats, keywords, and a block are separate parts of a Ruby method contract.
4
+
5
+ The options hash contains extra keywords; Method#parameters exposes signature details.
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The example deliberately contrasts received arguments with values actually used.
4
+ # rubocop:disable Lint/UnusedMethodArgument
5
+
6
+ module Exercises
7
+ # Fix format_order(name, quantity=1, *extras, unit:, **options, &block) to return
8
+ # "name:quantity:unit:extra_count:priority" where priority defaults to "normal".
9
+ class MethodContracts
10
+ # Formats positional, rest, and keyword options, then applies an optional block.
11
+ # @return [String]
12
+ def self.format_order(name, quantity = 1, *extras, unit:, **options, &block)
13
+ "#{name}:#{quantity}:#{unit}:#{extras.size}:normal"
14
+ end
15
+
16
+ # Reports the parameter kinds and names of format_order.
17
+ # @return [Array<Array<Symbol>>]
18
+ def self.parameters = []
19
+ end
20
+ end
21
+
22
+ # rubocop:enable Lint/UnusedMethodArgument
@@ -0,0 +1,8 @@
1
+ # A wrapper before the class
2
+
3
+ Presenter.new.call returns "base". Wrapper#call adds square brackets around super. Fix composition so the wrapper runs before Presenter without replacing the base method. `lookup` should return the names of the first two ancestors: Exercises::MethodLookup::Wrapper, Exercises::MethodLookup::Presenter.
4
+
5
+ Use `rkoans check` to investigate one failing check at a time. Hints are optional.
6
+
7
+ Edit `method_lookup.rb` in this exercise's folder. Checks call
8
+ `Exercises::MethodLookup` and its example classes.
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ include and prepend place a module on different sides of the class in method lookup.
4
+
5
+ If the class defines the method, an included module’s method will be shadowed.
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exercises
4
+ # Presenter#call returns "base".
5
+ class MethodLookup
6
+ # Example Wrapper for method lookup.
7
+ module Wrapper
8
+ # Returns the value from this scope's example receiver.
9
+ # @return [String]
10
+ def call = "[#{super}]"
11
+ end
12
+
13
+ # Example Presenter for method lookup.
14
+ class Presenter
15
+ include Wrapper
16
+
17
+ # Returns the value from this scope's example receiver.
18
+ # @return [String]
19
+ def call = 'base'
20
+ end
21
+
22
+ # Lists the first two ancestor names in method lookup order.
23
+ # @return [Array<String>]
24
+ def self.lookup = Presenter.ancestors.first(2).map(&:name)
25
+ end
26
+ end
@@ -0,0 +1,8 @@
1
+ # Who does return leave?
2
+
3
+ Implement `lambda_trace` so return inside the lambda ends only that lambda, and the method still appends "after". Implement `escaped_proc` returning an ordinary proc with a nonlocal return: calling it after the defining method has returned must raise LocalJumpError. Implement `find_even` using catch/throw to stop nested traversal, returning the first even number or nil. `skip_odds` uses next to collect only even values.
4
+
5
+ Use `rkoans check` to investigate one failing check at a time. Hints are optional.
6
+
7
+ Edit `nonlocal_exit.rb` in this exercise's folder. Checks call
8
+ `Exercises::NonlocalExit` and its example classes.
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ return in an ordinary proc tries to leave its defining method; lambda return is local.
4
+
5
+ catch/throw is a non-exception mechanism to leave a matching dynamic scope.
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Explicit return is the subject of this example.
4
+ # rubocop:disable Style/RedundantReturn
5
+
6
+ module Exercises
7
+ # Implement lambda_trace so return inside the lambda ends only that lambda, and the method still
8
+ # appends "after".
9
+ class NonlocalExit
10
+ # Collects the lambda result and continues the surrounding method.
11
+ # @return [Array<String>]
12
+ def self.lambda_trace
13
+ action = -> { return 'inside' }
14
+ [action.call]
15
+ end
16
+
17
+ # Returns a proc whose later return targets this already completed method.
18
+ # @return [Proc]
19
+ def self.escaped_proc = -> { return :gone }
20
+ # Uses catch and throw to find the first even number across nested groups.
21
+ # @return [Integer, nil]
22
+ def self.find_even(groups) = groups.flatten.last
23
+ # Skips odd values while collecting the even numbers.
24
+ # @return [Array<Integer>]
25
+ def self.skip_odds(values) = values
26
+ end
27
+ end
28
+
29
+ # rubocop:enable Style/RedundantReturn
@@ -0,0 +1,18 @@
1
+ # No names, still parameters
2
+
3
+ Implement `pair_sums` using the block’s input pairs; for [[2,3],[4,5]], return [5,9]. Explore `_1` and `_2` as alternatives to named block parameters. Fill `predictions` for whether these parse: `[1].map { |n| _1 }` and `[[1,2]].map { _1 + _2 }`. Return explicit_and_numbered and numbered_pair booleans.
4
+
5
+ Use `rkoans check` to investigate one failing check at a time. Hints are optional.
6
+
7
+ Edit `numbered_parameters.rb` in this exercise's folder. Checks call
8
+ `Exercises::NumberedParameters` and its example classes.
9
+
10
+ For the syntax predictions, compare these blocks:
11
+
12
+ ```ruby
13
+ # explicit_and_numbered: can explicit names and numbered parameters be mixed?
14
+ # [[2, 3]].map { |left, right| _1 + _2 }
15
+
16
+ # numbered_pair: does this block receive both components of each pair?
17
+ [[2, 3]].map { _1 + _2 }
18
+ ```
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ Numbered parameters are inferred when a block has no explicit parameter list.
4
+
5
+ Using _2 also introduces _1; pairs can be destructured into the inferred parameters.
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ # These example blocks expose arguments even when the example does not consume them.
4
+ # rubocop:disable Lint/UnusedBlockArgument
5
+
6
+ module Exercises
7
+ # Implement pair_sums using the block’s input pairs; for [[2,3],[4,5]], return [5,9].
8
+ class NumberedParameters
9
+ # Adds both components of each pair using numbered parameters.
10
+ # @return [Array<Integer>]
11
+ def self.pair_sums(pairs) = pairs.map { |left, right| left }
12
+ # Returns predictions for the expressions described in the brief.
13
+ # @return [Hash<Symbol, Object>]
14
+ def self.predictions = { explicit_and_numbered: true, numbered_pair: false }
15
+ end
16
+ end
17
+
18
+ # rubocop:enable Lint/UnusedBlockArgument
@@ -0,0 +1,8 @@
1
+ # One third is not zero
2
+
3
+ Implement `ratios(a,b)` returning integer division, floating division, and exact Rational division under keys integer, floating, rational. Implement `imaginary_product(a,b)` for (a*i)*(b*i), returning Complex. Preserve exact Rational arithmetic when adding one.
4
+
5
+ Use `rkoans check` to investigate one failing check at a time. Hints are optional.
6
+
7
+ Edit `numeric_precision.rb` in this exercise's folder. Checks call
8
+ `Exercises::NumericPrecision` and its example classes.
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ Integer division truncates for integer operands; Float approximates; Rational can remain exact.
4
+
5
+ Changing the operand type changes the division operation.
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The original descriptive check identifiers and example strings remain intact.
4
+ # Short parameter names match the small arithmetic or assignment examples.
5
+ # rubocop:disable Layout/LineLength, Naming/MethodParameterName
6
+
7
+ module Exercises
8
+ # Implement ratios(a,b) returning integer division, floating division, and exact Rational division under keys integer, floating, rational.
9
+ class NumericPrecision
10
+ # Implements ratios.
11
+ def self.ratios(a, b) = { integer: a / b, floating: a / b, rational: a / b }
12
+ # Implements imaginary product.
13
+ def self.imaginary_product(a, b) = Complex(a * b, 0)
14
+ end
15
+ end
16
+
17
+ # rubocop:enable Layout/LineLength, Naming/MethodParameterName
@@ -0,0 +1,8 @@
1
+ # A payload with a pin
2
+
3
+ Implement `amount(payload, kind)` to return a positive Integer amount only when a hash has type equal to the supplied kind and amount is an Integer greater than zero. Extra keys are allowed. Otherwise return nil. Practice a pinned variable and a guard in a pattern.
4
+
5
+ Use `rkoans check` to investigate one failing check at a time. Hints are optional.
6
+
7
+ Edit `pattern_matching.rb` in this exercise's folder. Checks call
8
+ `Exercises::PatternMatching` and its example classes.
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ An underscore matches a value without checking it against your variable.
4
+
5
+ Pin the existing kind value with ^kind, and add a guard for positivity.
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The example deliberately contrasts received arguments with values actually used.
4
+ # rubocop:disable Lint/UnusedMethodArgument
5
+
6
+ module Exercises
7
+ # Implement amount(payload, kind) to return a positive Integer amount only when a hash has type
8
+ # equal to the supplied kind and amount is an Integer greater than zero.
9
+ class PatternMatching
10
+ # Implements amount.
11
+ def self.amount(payload, kind)
12
+ case payload
13
+ in { type: _, amount: Integer => number }
14
+ number
15
+ else
16
+ nil
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ # rubocop:enable Lint/UnusedMethodArgument
@@ -0,0 +1,8 @@
1
+ # A local voice
2
+
3
+ Speaker#say normally returns "plain". A refinement should change it to "local" only in Exercises::RefinementScope::Local.call, which activates the refinement lexically. Exercises::RefinementScope.outside must still return "plain". Fix activation without globally reopening Speaker.
4
+
5
+ Use `rkoans check` to investigate one failing check at a time. Hints are optional.
6
+
7
+ Edit `refinement_scope.rb` in this exercise's folder. Checks call
8
+ `Exercises::RefinementScope` and its example classes.
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ Defining a refinement does not activate it everywhere.
4
+
5
+ using activates a refinement in its lexical scope; it is not an ordinary runtime toggle inside a method.
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Exercises
4
+ # Speaker#say normally returns "plain".
5
+ class RefinementScope
6
+ # Example Speaker for refinement scope.
7
+ class Speaker
8
+ # Returns the voice selected by the lexical refinement scope.
9
+ # @return [String]
10
+ def say = 'plain'
11
+ end
12
+
13
+ # Example Voice for refinement scope.
14
+ module Voice
15
+ refine Speaker do
16
+ # Returns the voice selected by the lexical refinement scope.
17
+ # @return [String]
18
+ def say = 'local'
19
+ end
20
+ end
21
+
22
+ # Example Local for refinement scope.
23
+ module Local
24
+ # Returns the value from this scope's example receiver.
25
+ # @return [String]
26
+ def self.call = Speaker.new.say
27
+ end
28
+
29
+ # Returns the unrefined voice outside the local scope.
30
+ # @return [String]
31
+ def self.outside = Speaker.new.say
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ # The newline loophole
2
+
3
+ Implement `parse(text)` for an entire string of lowercase name, colon, and decimal digits. Return {name: String,id: Integer}, or nil for any other input. Reject trailing newlines and multiple lines. Implement `probe(text)` so /ruby/ matching returns a boolean while preserving a previously established match for "old" in its own scope.
4
+
5
+ Use `rkoans check` to investigate one failing check at a time. Hints are optional.
6
+
7
+ Edit `regexp_captures.rb` in this exercise's folder. Checks call
8
+ `Exercises::RegexpCaptures` and its example classes.
@@ -0,0 +1,5 @@
1
+ # Hint
2
+
3
+ ^ and $ anchor lines; \A and \z anchor the whole string.
4
+
5
+ Named captures are strings even when they contain digits.
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The starter compares boolean coercion of match with match? while observing capture changes.
4
+ # The example explicitly observes the regexp capture variable.
5
+ # rubocop:disable Style/DoubleNegation, Style/SpecialGlobalVars
6
+
7
+ module Exercises
8
+ # Implement parse(text) for an entire string of lowercase name, colon, and decimal digits.
9
+ class RegexpCaptures
10
+ # Implements parse.
11
+ def self.parse(text)
12
+ match = /^(?<name>[a-z]+):(?<id>\d+)$/.match(text)
13
+ match && { name: match[:name], id: match[:id] }
14
+ end
15
+
16
+ # Implements probe.
17
+ def self.probe(text)
18
+ /old/.match('old')
19
+ matched = !!/ruby/.match(text)
20
+ [$~&.to_s, matched]
21
+ end
22
+ end
23
+ end
24
+
25
+ # rubocop:enable Style/DoubleNegation, Style/SpecialGlobalVars
@@ -0,0 +1,20 @@
1
+ # Where am I running?
2
+
3
+ Implement `Exercises::RuntimeContext.context` using the process's actual `ARGV`,
4
+ `ENV['RKOANS_GREETING']`, `$PROGRAM_NAME`, `__FILE__`, `__ENCODING__`, and `RUBY_VERSION`.
5
+
6
+ Return a hash with these keys:
7
+
8
+ - `arguments`: a copy of the current arguments, without consuming or changing `ARGV`.
9
+ - `greeting`: the environment value, or `nil` when that key is absent.
10
+ - `program`: the basename of the entry-point file.
11
+ - `file`: the basename of the file containing `context`.
12
+ - `encoding`: the source encoding's name.
13
+ - `ruby`: the running Ruby version.
14
+
15
+ The checks run this file through a separate entry point, so `program` and `file`
16
+ describe different files. Each check controls its own arguments and environment;
17
+ you do not need to configure your shell. Changing the returned `arguments` array
18
+ must leave `ARGV` unchanged.
19
+
20
+ Save your file to rerun the checks automatically.
@@ -0,0 +1,8 @@
1
+ # Hint: process inputs and source context
2
+
3
+ `ARGV` contains command-line arguments; `ENV` exposes environment entries.
4
+ Reading a missing environment key returns `nil`.
5
+
6
+ `__FILE__` identifies the source file containing the expression, while
7
+ `$PROGRAM_NAME` identifies the entry point. Use `File.basename` to keep only
8
+ their filenames. Think about how to return an array without sharing its mutations.