├── .appends └── .github │ └── labels.yml ├── .github ├── CODEOWNERS ├── dependabot.yml ├── labels.yml └── workflows │ ├── configlet.yml │ ├── no-important-files-changed.yml │ ├── pause-community-contributions.yml │ └── sync-labels.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── bin └── fetch-configlet ├── config.json ├── config └── exercise_readme.go.tmpl ├── docs ├── ABOUT.md ├── INSTALLATION.md ├── LEARNING.md ├── RESOURCES.md ├── SNIPPET.txt ├── TESTS.md └── config.json ├── exercises ├── .keep ├── practice │ ├── accumulate │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── accumulate-example.factor │ │ │ ├── config.json │ │ │ └── tests.toml │ │ ├── accumulate-tests.factor │ │ └── accumulate.factor │ ├── acronym │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── acronym-example.factor │ │ │ ├── config.json │ │ │ └── tests.toml │ │ ├── acronym-tests.factor │ │ └── acronym.factor │ ├── all-your-base │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── all-your-base-example.factor │ │ │ ├── config.json │ │ │ └── tests.toml │ │ ├── all-your-base-tests.factor │ │ └── all-your-base.factor │ ├── armstrong-numbers │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── armstrong-numbers-example.factor │ │ │ ├── config.json │ │ │ └── tests.toml │ │ ├── armstrong-numbers-tests.factor │ │ └── armstrong-numbers.factor │ ├── hello-world │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── hello-world-example.factor │ │ │ └── tests.toml │ │ ├── hello-world-tests.factor │ │ └── hello-world.factor │ ├── isogram │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── isogram-example.factor │ │ │ └── tests.toml │ │ ├── isogram-tests.factor │ │ └── isogram.factor │ ├── leap │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── leap-example.factor │ │ │ └── tests.toml │ │ ├── leap-tests.factor │ │ └── leap.factor │ ├── raindrops │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── raindrops-example.factor │ │ │ └── tests.toml │ │ ├── raindrops-tests.factor │ │ └── raindrops.factor │ ├── resistor-color │ │ ├── .docs │ │ │ └── instructions.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── resistor-color-example.factor │ │ │ └── tests.toml │ │ ├── resistor-color-tests.factor │ │ └── resistor-color.factor │ ├── reverse-string │ │ ├── .docs │ │ │ ├── instructions.md │ │ │ └── introduction.md │ │ ├── .meta │ │ │ ├── config.json │ │ │ ├── reverse-string-example.factor │ │ │ └── tests.toml │ │ ├── reverse-string-tests.factor │ │ └── reverse-string.factor │ └── two-fer │ │ ├── .docs │ │ ├── instructions.md │ │ └── introduction.md │ │ ├── .meta │ │ ├── config.json │ │ ├── tests.toml │ │ └── two-fer-example.factor │ │ ├── two-fer-tests.factor │ │ └── two-fer.factor └── shared │ └── .docs │ ├── help.md │ └── tests.md └── reference └── implementing-a-concept-exercise.md /.appends/.github/labels.yml: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------------------------------------------------- # 2 | # These are the repository-specific labels that augment the Exercise-wide labels defined in # 3 | # https://github.com/exercism/org-wide-files/blob/main/global-files/.github/labels.yml. # 4 | # ----------------------------------------------------------------------------------------- # 5 | 6 | - name: "bug" 7 | description: "" 8 | color: "ee0701" 9 | 10 | - name: "duplicate" 11 | description: "" 12 | color: "cccccc" 13 | 14 | - name: "enhancement" 15 | description: "" 16 | color: "84b6eb" 17 | 18 | - name: "help wanted" 19 | description: "" 20 | color: "128A0C" 21 | 22 | - name: "invalid" 23 | description: "" 24 | color: "e6e6e6" 25 | 26 | - name: "question" 27 | description: "" 28 | color: "cc317c" 29 | 30 | - name: "wontfix" 31 | description: "" 32 | color: "ffffff" 33 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # Code owners 2 | .github/CODEOWNERS @exercism/maintainers-admin 3 | 4 | # Changes to `fetch-configlet` should be made in the `exercism/configlet` repo 5 | bin/fetch-configlet @exercism/maintainers-admin 6 | 7 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | 5 | # Keep dependencies for GitHub Actions up-to-date 6 | - package-ecosystem: 'github-actions' 7 | directory: '/' 8 | schedule: 9 | interval: 'monthly' 10 | -------------------------------------------------------------------------------- /.github/labels.yml: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------- # 2 | # This is an auto-generated file - Do not manually edit this file # 3 | # --------------------------------------------------------------- # 4 | 5 | # This file is automatically generated by concatenating two files: 6 | # 7 | # 1. The Exercism-wide labels: defined in https://github.com/exercism/org-wide-files/blob/main/global-files/.github/labels.yml 8 | # 2. The repository-specific labels: defined in the `.appends/.github/labels.yml` file within this repository. 9 | # 10 | # If any of these two files change, a pull request is automatically created containing a re-generated version of this file. 11 | # Consequently, to change repository-specific labels you should update the `.appends/.github/labels.yml` file and _not_ this file. 12 | # 13 | # When the pull request has been merged, the GitHub labels will be automatically updated by the "Sync labels" workflow. 14 | # This typically takes 5-10 minutes. 15 | 16 | # --------------------------------------------------------------------- # 17 | # These are the Exercism-wide labels which are shared across all repos. # 18 | # --------------------------------------------------------------------- # 19 | 20 | # The following Exercism-wide labels are used to show "tasks" on the website, which will point users to things they can contribute to. 21 | 22 | # The `x:action/` labels describe what sort of work the contributor will be engaged in when working on the issue 23 | - name: "x:action/create" 24 | description: "Work on something from scratch" 25 | color: "ffffff" 26 | 27 | - name: "x:action/fix" 28 | description: "Fix an issue" 29 | color: "ffffff" 30 | 31 | - name: "x:action/improve" 32 | description: "Improve existing functionality/content" 33 | color: "ffffff" 34 | 35 | - name: "x:action/proofread" 36 | description: "Proofread text" 37 | color: "ffffff" 38 | 39 | - name: "x:action/sync" 40 | description: "Sync content with its latest version" 41 | color: "ffffff" 42 | 43 | # The `x:knowledge/` labels describe how much Exercism knowledge is required by the contributor 44 | - name: "x:knowledge/none" 45 | description: "No existing Exercism knowledge required" 46 | color: "ffffff" 47 | 48 | - name: "x:knowledge/elementary" 49 | description: "Little Exercism knowledge required" 50 | color: "ffffff" 51 | 52 | - name: "x:knowledge/intermediate" 53 | description: "Quite a bit of Exercism knowledge required" 54 | color: "ffffff" 55 | 56 | - name: "x:knowledge/advanced" 57 | description: "Comprehensive Exercism knowledge required" 58 | color: "ffffff" 59 | 60 | # The `x:module/` labels indicate what part of Exercism the contributor will be working on 61 | - name: "x:module/analyzer" 62 | description: "Work on Analyzers" 63 | color: "ffffff" 64 | 65 | - name: "x:module/concept" 66 | description: "Work on Concepts" 67 | color: "ffffff" 68 | 69 | - name: "x:module/concept-exercise" 70 | description: "Work on Concept Exercises" 71 | color: "ffffff" 72 | 73 | - name: "x:module/generator" 74 | description: "Work on Exercise generators" 75 | color: "ffffff" 76 | 77 | - name: "x:module/practice-exercise" 78 | description: "Work on Practice Exercises" 79 | color: "ffffff" 80 | 81 | - name: "x:module/representer" 82 | description: "Work on Representers" 83 | color: "ffffff" 84 | 85 | - name: "x:module/test-runner" 86 | description: "Work on Test Runners" 87 | color: "ffffff" 88 | 89 | # The `x:rep/` labels describe the amount of reputation to award 90 | # 91 | # For more information on reputation and how these labels should be used, 92 | # check out https://exercism.org/docs/using/product/reputation 93 | - name: "x:rep/tiny" 94 | description: "Tiny amount of reputation" 95 | color: "ffffff" 96 | 97 | - name: "x:rep/small" 98 | description: "Small amount of reputation" 99 | color: "ffffff" 100 | 101 | - name: "x:rep/medium" 102 | description: "Medium amount of reputation" 103 | color: "ffffff" 104 | 105 | - name: "x:rep/large" 106 | description: "Large amount of reputation" 107 | color: "ffffff" 108 | 109 | - name: "x:rep/massive" 110 | description: "Massive amount of reputation" 111 | color: "ffffff" 112 | 113 | # The `x:size/` labels describe the expected amount of work for a contributor 114 | - name: "x:size/tiny" 115 | description: "Tiny amount of work" 116 | color: "ffffff" 117 | 118 | - name: "x:size/small" 119 | description: "Small amount of work" 120 | color: "ffffff" 121 | 122 | - name: "x:size/medium" 123 | description: "Medium amount of work" 124 | color: "ffffff" 125 | 126 | - name: "x:size/large" 127 | description: "Large amount of work" 128 | color: "ffffff" 129 | 130 | - name: "x:size/massive" 131 | description: "Massive amount of work" 132 | color: "ffffff" 133 | 134 | # The `x:status/` label indicates if there is already someone working on the issue 135 | - name: "x:status/claimed" 136 | description: "Someone is working on this issue" 137 | color: "ffffff" 138 | 139 | # The `x:type/` labels describe what type of work the contributor will be engaged in 140 | - name: "x:type/ci" 141 | description: "Work on Continuous Integration (e.g. GitHub Actions workflows)" 142 | color: "ffffff" 143 | 144 | - name: "x:type/coding" 145 | description: "Write code that is not student-facing content (e.g. test-runners, generators, but not exercises)" 146 | color: "ffffff" 147 | 148 | - name: "x:type/content" 149 | description: "Work on content (e.g. exercises, concepts)" 150 | color: "ffffff" 151 | 152 | - name: "x:type/docker" 153 | description: "Work on Dockerfiles" 154 | color: "ffffff" 155 | 156 | - name: "x:type/docs" 157 | description: "Work on Documentation" 158 | color: "ffffff" 159 | 160 | # This Exercism-wide label is added to all automatically created pull requests that help migrate/prepare a track for Exercism v3 161 | - name: "v3-migration 🤖" 162 | description: "Preparing for Exercism v3" 163 | color: "e99695" 164 | 165 | # This Exercism-wide label can be used to bulk-close issues in preparation for pausing community contributions 166 | - name: "paused" 167 | description: "Work paused until further notice" 168 | color: "e4e669" 169 | 170 | # ----------------------------------------------------------------------------------------- # 171 | # These are the repository-specific labels that augment the Exercise-wide labels defined in # 172 | # https://github.com/exercism/org-wide-files/blob/main/global-files/.github/labels.yml. # 173 | # ----------------------------------------------------------------------------------------- # 174 | 175 | - name: "bug" 176 | description: "" 177 | color: "ee0701" 178 | 179 | - name: "duplicate" 180 | description: "" 181 | color: "cccccc" 182 | 183 | - name: "enhancement" 184 | description: "" 185 | color: "84b6eb" 186 | 187 | - name: "help wanted" 188 | description: "" 189 | color: "128A0C" 190 | 191 | - name: "invalid" 192 | description: "" 193 | color: "e6e6e6" 194 | 195 | - name: "question" 196 | description: "" 197 | color: "cc317c" 198 | 199 | - name: "wontfix" 200 | description: "" 201 | color: "ffffff" 202 | -------------------------------------------------------------------------------- /.github/workflows/configlet.yml: -------------------------------------------------------------------------------- 1 | name: Configlet 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - main 8 | workflow_dispatch: 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | configlet: 15 | uses: exercism/github-actions/.github/workflows/configlet.yml@main 16 | -------------------------------------------------------------------------------- /.github/workflows/no-important-files-changed.yml: -------------------------------------------------------------------------------- 1 | name: No important files changed 2 | 3 | on: 4 | pull_request_target: 5 | types: [opened] 6 | branches: [main] 7 | paths: 8 | - "exercises/concept/**" 9 | - "exercises/practice/**" 10 | - "!exercises/*/*/.approaches/**" 11 | - "!exercises/*/*/.articles/**" 12 | - "!exercises/*/*/.docs/**" 13 | - "!exercises/*/*/.meta/**" 14 | 15 | permissions: 16 | pull-requests: write 17 | 18 | jobs: 19 | check: 20 | uses: exercism/github-actions/.github/workflows/check-no-important-files-changed.yml@main 21 | with: 22 | repository: ${{ github.event.pull_request.head.repo.owner.login }}/${{ github.event.pull_request.head.repo.name }} 23 | ref: ${{ github.head_ref }} 24 | -------------------------------------------------------------------------------- /.github/workflows/pause-community-contributions.yml: -------------------------------------------------------------------------------- 1 | name: Pause Community Contributions 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | pull_request_target: 8 | types: 9 | - opened 10 | paths-ignore: 11 | - 'exercises/*/*/.approaches/**' 12 | - 'exercises/*/*/.articles/**' 13 | 14 | permissions: 15 | issues: write 16 | pull-requests: write 17 | 18 | jobs: 19 | pause: 20 | if: github.repository_owner == 'exercism' # Stops this job from running on forks 21 | uses: exercism/github-actions/.github/workflows/community-contributions.yml@main 22 | with: 23 | forum_category: factor 24 | secrets: 25 | github_membership_token: ${{ secrets.COMMUNITY_CONTRIBUTIONS_WORKFLOW_TOKEN }} 26 | -------------------------------------------------------------------------------- /.github/workflows/sync-labels.yml: -------------------------------------------------------------------------------- 1 | name: Tools 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | paths: 8 | - .github/labels.yml 9 | - .github/workflows/sync-labels.yml 10 | workflow_dispatch: 11 | schedule: 12 | - cron: 0 0 1 * * # First day of each month 13 | 14 | permissions: 15 | issues: write 16 | 17 | jobs: 18 | sync-labels: 19 | uses: exercism/github-actions/.github/workflows/labels.yml@main 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .DS_Store 3 | bin/configlet 4 | bin/configlet.exe 5 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | ## Introduction 4 | 5 | Exercism is a platform centered around empathetic conversation. 6 | We have a low tolerance for communication that makes anyone feel unwelcome, unsupported, insulted or discriminated against. 7 | 8 | ## Seen or experienced something uncomfortable? 9 | 10 | If you see or experience abuse, harassment, discrimination, or feel unsafe or upset, please email [abuse@exercism.org](mailto:abuse@exercism.org?subject=%5BCoC%5D) and include \[CoC\] in the subject line. 11 | We will follow up with you as a priority. 12 | 13 | ## Enforcement 14 | 15 | We actively monitor for Code of Conduct (CoC) violations and take any reports of violations extremely seriously. 16 | We have banned contributors, mentors and users due to violations. 17 | 18 | After we receive a report of a CoC violation, we view that person's conversation history on Exercism and related communication channels and attempt to understand whether someone has deliberately broken the CoC, or accidentally crossed a line. 19 | We generally reach out to the person who has been reported to discuss any concerns we have and warn them that repeated violations will result in a ban. 20 | Sometimes we decide that no violation has occurred and that no action is required and sometimes we will also ban people on a first offense. 21 | We strive to be fair, but will err on the side of protecting the culture of our community. 22 | 23 | Exercism's leadership reserve the right to take whatever action they feel appropriate with regards to CoC violations. 24 | 25 | ## The simple version 26 | 27 | - Be empathetic 28 | - Be welcoming 29 | - Be kind 30 | - Be honest 31 | - Be supportive 32 | - Be polite 33 | 34 | ## The details 35 | 36 | Exercism should be a safe place for everybody regardless of 37 | 38 | - Gender, gender identity or gender expression 39 | - Sexual orientation 40 | - Disability 41 | - Physical appearance (including but not limited to body size) 42 | - Race 43 | - Age 44 | - Religion 45 | - Anything else you can think of 46 | 47 | As someone who is part of this community, you agree that: 48 | 49 | - We are collectively and individually committed to safety and inclusivity 50 | - We have zero tolerance for abuse, harassment, or discrimination 51 | - We respect people’s boundaries and identities 52 | - We refrain from using language that can be considered offensive or oppressive (systemically or otherwise), eg. sexist, racist, homophobic, transphobic, ableist, classist, etc. 53 | - this includes (but is not limited to) various slurs. 54 | - We avoid using offensive topics as a form of humor 55 | 56 | We actively work towards: 57 | 58 | - Being a safe community 59 | - Cultivating a network of support & encouragement for each other 60 | - Encouraging responsible and varied forms of expression 61 | 62 | We condemn: 63 | 64 | - Stalking, doxxing, or publishing private information 65 | - Violence, threats of violence or violent language 66 | - Anything that compromises people’s safety 67 | - Conduct or speech which might be considered sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory or offensive in nature 68 | - The use of unwelcome, suggestive, derogatory or inappropriate nicknames or terms 69 | - Disrespect towards others (jokes, innuendo, dismissive attitudes) and towards differences of opinion 70 | - Intimidation or harassment (online or in-person). 71 | Please read the [Citizen Code of Conduct](https://github.com/stumpsyn/policies/blob/master/citizen_code_of_conduct.md) for how we interpret harassment 72 | - Inappropriate attention or contact 73 | - Not understanding the differences between constructive criticism and disparagement 74 | 75 | These things are NOT OK. 76 | 77 | Be aware of how your actions affect others. 78 | If it makes someone uncomfortable, stop. 79 | 80 | If you say something that is found offensive, and you are called out on it, try to: 81 | 82 | - Listen without interruption 83 | - Believe what the person is saying & do not attempt to disqualify what they have to say 84 | - Ask for tips / help with avoiding making the offense in the future 85 | - Apologize and ask forgiveness 86 | 87 | ## History 88 | 89 | This policy was initially adopted from the Front-end London Slack community and has been modified since. 90 | A version history can be seen on [GitHub](https://github.com/exercism/website-copy/edit/main/pages/code_of_conduct.md). 91 | 92 | _This policy is a "living" document, and subject to refinement and expansion in the future. 93 | This policy applies to the Exercism website, the Exercism GitHub organization, any other Exercism-related communication channels (e.g. Discord, Forum, Twitter, email) and any other Exercism entity or event._ 94 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Exercism 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Exercism Factor Track 2 | 3 | --- 4 | 5 | [![Configlet Status](https://github.com/exercism/factor/workflows/configlet/badge.svg)] 6 | 7 | Exercism problems in Factor. 8 | 9 | We :heart: pull requests, issues and suggestions. 10 | 11 | ## Contributing Guide 12 | 13 | Please see the [contributing guide](https://github.com/exercism/x-api/blob/master/CONTRIBUTING.md#the-exercise-data). 14 | 15 | ## Working on the Exercises 16 | 17 | We welcome both improvements to the existing exercises and new exercises. 18 | A pool of exercise ideas can be found in the [x-common repo](https://github.com/exercism/x-common). 19 | 20 | If you do contribute, please try to follow the guidelines for Factor code in this repo: 21 | 22 | * Factor code should run in both the latest stable Factor as well as the latest nightly Factor. This is not a very hard requirement to meet, since Factor is very stable. If something only works in a certain version, find a different way. 23 | 24 | * Code should strictly follow the [Factor code conventions](http://docs.factorcode.org/content/article-conventions.html). This is also not a very hard task, and makes reading and writing code much easier. 25 | 26 | * Code should compile and pass all of its unit tests, tested using [exercism.testing](https://github.com/catb0t/exercism.testing). 27 | 28 | ## Get set up with using Factor to run and test the exercise code 29 | 30 | Here's what you need to do to start working with the Factor code in the `exercises` directory. 31 | 32 | 1. Download [exercism.testing](https://github.com/catb0t/exercism.factor) and put it somewhere Factor can find it. Your `resource:work` directory is a good choice, so `testing.factor` is `resource:work/exercism/testing/testing.factor`. 33 | 34 | 2. Test an exercise's example code with: 35 | ``` 36 | factor (master) $ factor -run=exericsm.testing hello-world 37 | working directory OK: /home/you/git/factor is a dev-env 38 | config.json and exercises OK 39 | 40 | testing exercise: hello-world 41 | 42 | Unit Test: { { "Hello, World!" } [ say-hello ] } 43 | ``` 44 | 45 | Alternatively, to run all tests in all exercise directories: 46 | 47 | ``` 48 | factor (master) $ factor -run=exericsm.testing run-all 49 | working directory OK: /home/you/git/factor is a dev-env 50 | config.json and exercises OK 51 | 52 | testing exercise: hello-world 53 | 54 | Unit Test: { { "Hello, World!" } [ say-hello ] } 55 | ``` 56 | 57 | `config.json` is verified for logical integrity on each run. To only check `config.json`'s validity: 58 | ``` 59 | factor (master) $ factor -run=exericsm.testing VERIFY 60 | working directory OK: /home/you/git/factor is a dev-env 61 | config.json and exercises OK 62 | ``` 63 | If `config.json` is invalid, then an error will be thrown and tests will not run. 64 | 65 | Check out `exercism-testing`'s documentation for more information. 66 | 67 | 4. Find a bug, or have a question or comment about `exercism.testing`? [Open an issue](https://github.com/catb0t/exericsm.factor/issues) or [pull request](https://github.com/catb0t/exericsm.factor/pulls)! 68 | 69 | ## Working on the Documentation 70 | 71 | If you think you've found a factual or technical error, or you just have a question or suggestion about some part of the Markdown or Factor documentation, we'd :heart: you to open an issue or pull request. 72 | 73 | ### [Factor icon](https://github.com/exercism/factor/tree/master/img/icon.png) 74 | 75 | The Factor "Tyrannosaurus Rex" logo is owned by John Benediktsson. We have adapted it, changing the colour scheme, with his permission. 76 | -------------------------------------------------------------------------------- /bin/fetch-configlet: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This file is a copy of the 4 | # https://github.com/exercism/configlet/blob/main/scripts/fetch-configlet file. 5 | # Please submit bugfixes/improvements to the above file to ensure that all tracks benefit from the changes. 6 | 7 | set -eo pipefail 8 | 9 | curlopts=( 10 | --silent 11 | --show-error 12 | --fail 13 | --location 14 | --retry 3 15 | ) 16 | 17 | if [[ -n "${GITHUB_TOKEN}" ]]; then 18 | curlopts+=(--header "authorization: Bearer ${GITHUB_TOKEN}") 19 | fi 20 | 21 | get_download_url() { 22 | local os="$1" 23 | local ext="$2" 24 | local latest='https://api.github.com/repos/exercism/configlet/releases/latest' 25 | local arch 26 | case "$(uname -m)" in 27 | aarch64|arm64) arch='arm64' ;; 28 | x86_64) arch='x86-64' ;; 29 | *686*) arch='i386' ;; 30 | *386*) arch='i386' ;; 31 | *) arch='x86-64' ;; 32 | esac 33 | local suffix="${os}_${arch}.${ext}" 34 | curl "${curlopts[@]}" --header 'Accept: application/vnd.github.v3+json' "${latest}" | 35 | grep "\"browser_download_url\": \".*/download/.*/configlet.*${suffix}\"$" | 36 | cut -d'"' -f4 37 | } 38 | 39 | main() { 40 | local output_dir 41 | if [[ -d ./bin ]]; then 42 | output_dir="./bin" 43 | elif [[ $PWD == */bin ]]; then 44 | output_dir="$PWD" 45 | else 46 | echo "Error: no ./bin directory found. This script should be ran from a repo root." >&2 47 | return 1 48 | fi 49 | 50 | local os 51 | case "$(uname -s)" in 52 | Darwin*) os='macos' ;; 53 | Linux*) os='linux' ;; 54 | Windows*) os='windows' ;; 55 | MINGW*) os='windows' ;; 56 | MSYS_NT-*) os='windows' ;; 57 | *) os='linux' ;; 58 | esac 59 | 60 | local ext 61 | case "${os}" in 62 | windows) ext='zip' ;; 63 | *) ext='tar.gz' ;; 64 | esac 65 | 66 | echo "Fetching configlet..." >&2 67 | local download_url 68 | download_url="$(get_download_url "${os}" "${ext}")" 69 | local output_path="${output_dir}/latest-configlet.${ext}" 70 | curl "${curlopts[@]}" --output "${output_path}" "${download_url}" 71 | 72 | case "${ext}" in 73 | zip) unzip "${output_path}" -d "${output_dir}" ;; 74 | *) tar xzf "${output_path}" -C "${output_dir}" ;; 75 | esac 76 | 77 | rm -f "${output_path}" 78 | 79 | local executable_ext 80 | case "${os}" in 81 | windows) executable_ext='.exe' ;; 82 | *) executable_ext='' ;; 83 | esac 84 | 85 | local configlet_path="${output_dir}/configlet${executable_ext}" 86 | local configlet_version 87 | configlet_version="$(${configlet_path} --version)" 88 | echo "Downloaded configlet ${configlet_version} to ${configlet_path}" 89 | } 90 | 91 | main 92 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "language": "Factor", 3 | "slug": "factor", 4 | "active": false, 5 | "status": { 6 | "concept_exercises": false, 7 | "test_runner": false, 8 | "representer": false, 9 | "analyzer": false 10 | }, 11 | "blurb": "The Factor programming language is a concatenative, stack-based programming language with high-level features including dynamic types, extensible syntax, macros, and garbage collection. On a practical side, Factor has a full-featured library, supports many different platforms, and has been extensively documented.", 12 | "version": 3, 13 | "online_editor": { 14 | "indent_style": "space", 15 | "indent_size": 4, 16 | "highlightjs_language": "factor" 17 | }, 18 | "files": { 19 | "solution": [ 20 | "%{kebab_slug}.factor" 21 | ], 22 | "test": [ 23 | "%{kebab_slug}-tests.factor" 24 | ], 25 | "example": [ 26 | ".meta/%{kebab_slug}-example.factor" 27 | ], 28 | "exemplar": [ 29 | ".meta/%{kebab_slug}-exemplar.factor" 30 | ] 31 | }, 32 | "exercises": { 33 | "concept": [], 34 | "practice": [ 35 | { 36 | "slug": "hello-world", 37 | "name": "Hello World", 38 | "uuid": "c81c4175-f06b-404d-8c01-c4a6dba661d3", 39 | "practices": [ 40 | "stack-effect", 41 | "word-definition" 42 | ], 43 | "prerequisites": [], 44 | "difficulty": 1 45 | }, 46 | { 47 | "slug": "isogram", 48 | "name": "Isogram", 49 | "uuid": "d3afeeb3-8c4e-4a31-81a2-fb039ab3c5af", 50 | "practices": [ 51 | "stack-effect", 52 | "strings", 53 | "word-definition" 54 | ], 55 | "prerequisites": [ 56 | "word-definition" 57 | ], 58 | "difficulty": 1 59 | }, 60 | { 61 | "slug": "two-fer", 62 | "name": "Two Fer", 63 | "uuid": "22c5c529-07bb-4df2-8d2f-e470d1ed48da", 64 | "practices": [ 65 | "quotations", 66 | "stack-effect", 67 | "strings", 68 | "word-definition" 69 | ], 70 | "prerequisites": [ 71 | "stack-effect", 72 | "word-definition" 73 | ], 74 | "difficulty": 2 75 | }, 76 | { 77 | "slug": "resistor-color", 78 | "name": "Resistor Color", 79 | "uuid": "4bf98489-3318-45cd-a0df-309fd2ff4158", 80 | "practices": [ 81 | "conditionals", 82 | "stack-effect", 83 | "word-definition" 84 | ], 85 | "prerequisites": [ 86 | "stack-effect", 87 | "word-definition" 88 | ], 89 | "difficulty": 2 90 | }, 91 | { 92 | "slug": "reverse-string", 93 | "name": "Reverse String", 94 | "uuid": "5d28be8e-395e-4e2a-aab6-c5777bcb0668", 95 | "practices": [ 96 | "stack-effect", 97 | "strings" 98 | ], 99 | "prerequisites": [ 100 | "stack-effect", 101 | "strings" 102 | ], 103 | "difficulty": 3 104 | }, 105 | { 106 | "slug": "leap", 107 | "name": "Leap", 108 | "uuid": "17fb2814-2164-4933-8f72-adeb9b2b5ccf", 109 | "practices": [ 110 | "conditionals", 111 | "math", 112 | "quotations" 113 | ], 114 | "prerequisites": [ 115 | "stack-effect", 116 | "word-definition" 117 | ], 118 | "difficulty": 3, 119 | "topics": [ 120 | "conditionals", 121 | "logical-operators", 122 | "quotations", 123 | "word-definition" 124 | ] 125 | }, 126 | { 127 | "slug": "raindrops", 128 | "name": "Raindrops", 129 | "uuid": "c4c768de-5852-40e7-ac90-d7a8e9bb4926", 130 | "practices": [ 131 | "conditionals", 132 | "quotations", 133 | "stack-effect", 134 | "strings", 135 | "word-definition" 136 | ], 137 | "prerequisites": [ 138 | "stack-effect", 139 | "word-definition" 140 | ], 141 | "difficulty": 3 142 | }, 143 | { 144 | "slug": "acronym", 145 | "name": "Acronym", 146 | "uuid": "e8733850-cc86-4d29-8e5a-92078576e193", 147 | "practices": [ 148 | "strings", 149 | "quotations", 150 | "collections" 151 | ], 152 | "prerequisites": [ 153 | "stack-effect", 154 | "quotations", 155 | "word-definition" 156 | ], 157 | "difficulty": 3 158 | }, 159 | { 160 | "slug": "armstrong-numbers", 161 | "name": "Armstrong Numbers", 162 | "uuid": "61681eb1-b68b-40b3-9bc1-11904d4940e6", 163 | "practices": [ 164 | "quotations", 165 | "collections", 166 | "combinators", 167 | "math" 168 | ], 169 | "prerequisites": [ 170 | "logical-operators", 171 | "quotations" 172 | ], 173 | "difficulty": 4 174 | }, 175 | { 176 | "slug": "accumulate", 177 | "name": "Accumulate", 178 | "uuid": "8a373305-98c9-4b19-9011-085abe19cfed", 179 | "practices": [ 180 | "quotations", 181 | "collections", 182 | "combinators" 183 | ], 184 | "prerequisites": [ 185 | "stack-effect", 186 | "quotations", 187 | "word-definition" 188 | ], 189 | "difficulty": 5 190 | }, 191 | { 192 | "slug": "all-your-base", 193 | "name": "All Your Base", 194 | "uuid": "c5a7ddcd-74ff-4ecf-8ff7-9f871f56084d", 195 | "practices": [ 196 | "collections", 197 | "combinators", 198 | "math", 199 | "quotations" 200 | ], 201 | "prerequisites": [ 202 | "stack-effect", 203 | "collections", 204 | "combinators", 205 | "quotations", 206 | "word-definition" 207 | ], 208 | "difficulty": 6, 209 | "topics": [ 210 | "math" 211 | ] 212 | } 213 | ] 214 | }, 215 | "concepts": [], 216 | "key_features": [ 217 | { 218 | "icon": "interop", 219 | "title": "Concatenative", 220 | "content": "Factor is a language of the concatenative paradigm, like Forth or Postscript." 221 | }, 222 | { 223 | "icon": "multi-paradigm", 224 | "title": "Multi-paradigm", 225 | "content": "Factor includes features from object-oriented programming and functional programming." 226 | }, 227 | { 228 | "icon": "documentation", 229 | "title": "Embedded documentation", 230 | "content": "Factor has a very powerful documentation system available in its custom IDE and online." 231 | }, 232 | { 233 | "icon": "expressive", 234 | "title": "Concise", 235 | "content": "Factor lets you describe complex programs with simple combinations of very short functions." 236 | }, 237 | { 238 | "icon": "extensible", 239 | "title": "Extremely extensible", 240 | "content": "Most of Factor's syntax is actually defined with user-accessible features." 241 | }, 242 | { 243 | "icon": "concurrency", 244 | "title": "Time-traveling debugger", 245 | "content": "Factor's debugger lets you reverse the course of execution from an error." 246 | } 247 | ], 248 | "tags": [ 249 | "paradigm/functional", 250 | "paradigm/object_oriented", 251 | "paradigm/declarative", 252 | "typing/dynamic", 253 | "typing/strong", 254 | "execution_mode/compiled", 255 | "execution_mode/interpreted", 256 | "platform/windows", 257 | "platform/mac", 258 | "platform/linux", 259 | "runtime/language_specific" 260 | ] 261 | } 262 | -------------------------------------------------------------------------------- /config/exercise_readme.go.tmpl: -------------------------------------------------------------------------------- 1 | # {{ .Spec.Name }} 2 | 3 | {{ .Spec.Description -}} 4 | {{- with .Hints }} 5 | {{ . }} 6 | {{ end }} 7 | ## Testing Exercises 8 | 9 | If you followed the [installation instructions](http://exercism.io/languages/factor/installation), just run the provided test suite against your implementation with `"exercise-name" test`. 10 | 11 | ## Submitting Exercises 12 | 13 | Note that, when trying to submit an exercise, make sure the solution is in the `exercism/factor/exercise-name` directory. 14 | 15 | For example, if you're submitting `bob.factor` for the Bob exercise, the submit command would be something like `exercism submit exercism/factor/bob/bob.factor`. 16 | 17 | For more detailed information about running tests, code style and linting, 18 | please see the [help page](http://exercism.io/languages/factor).{{ with .Spec.Credits }} 19 | ## Source 20 | 21 | {{ . }} 22 | {{ end }} 23 | ## Submitting Incomplete Solutions 24 | It's possible to submit an incomplete solution so you can see how others have completed the exercise. 25 | -------------------------------------------------------------------------------- /docs/ABOUT.md: -------------------------------------------------------------------------------- 1 | # About 2 | 3 | Factor was originally designed by Slava Pestov in 2002, as a scripting language implemented on the JVM for game engines. The platform and ecosystem has come a long way since that time, as has the core of the language itself. Factor's standard library has grown enormous, and its implementation, including its self-hosting native code optimising compiler, is now written almost entirely in Factor. 4 | 5 | Factor can create standalone, and even GUI applications that behave exactly the same on Linux, Windows and Mac OS. 6 | 7 | Factor is a simple, yet powerful and expressive stack-oriented high-level language in the vein of Forth, Joy and Lisp. It proposes a concatenative (point-free and compositional) model of data flow, alongside extreme extensibility and a [CLOS](http://enwp.org/Common_Lisp_Object_System)-derived object system. 8 | 9 | Homoiconicity is a large part of Factor's programming model. All values, including functions and blocks of Factor code, go on the same stack and can be manipulated in the same way. This is a simple, yet powerful paradigm that invites interesting solutions to problems, and indefinite extensibility. 10 | 11 | Factor requires from the reader a mindset apart from C or Python. Because of its compositional programming model, each function's output is used as input to the next one. Functions can use other functions or blocks of literal Factor code as input. In this way, it's rather like a (one-directional) Unix pipeline, but far more advanced while being less complicated. It takes some getting used to, but interactive development and re-**Factor**ing are encouraged, and becomes quite fun and interesting to use. 12 | 13 | The Factor programming language is open source, and you can find it in active development on [GitHub](https://github.com/factor/factor). 14 | 15 | If you're even a little bit new to Factor, it's highly recommended you read the [Factor cookbook](http://docs.factorcode.org/content/article-cookbook.html) and [Your first program](http://docs.factorcode.org/content/article-first-program.html) sections of the Factor documentation before continuing. 16 | 17 | ## Glossary of Factor terms 18 | 19 | * **Word** Essentially a function, which takes its arguments from, and returns values to, the **stack**. All words must have a declared stack effect. All elements of Factor's syntax are **words**, which makes defining new syntax very easy. 20 | * **Vocabulary** A collection of **words** organised in a directory or source-file, like a module or library in other languages. 21 | * **Stack** A last-in-first-out list of references to dynamically-typed values used for all operations; the primary way of passing data between functions. It is an implementation detail; Factor could be mostly implemented using term rewriting. 22 | * **Program** A series of **words** that manipulate the **stack** at runtime. This gives the language a powerful foundation which allows many abstractions and paradigms to be built on top. -------------------------------------------------------------------------------- /docs/INSTALLATION.md: -------------------------------------------------------------------------------- 1 | # Installing Factor, and making Factor and Exercism play nice 2 | 3 | [**Even if you already have Factor 0.98 installed, you still need to read the last section of this document for important information about testing Factor code in the Exercism environment.**](#play-nice) 4 | 5 | --- 6 | 7 | ## Installing Factor 8 | 9 | To install Factor, you need a [nightly](#nightly) or [bleeding-edge](#autobuild-from-source) build. 10 | 11 | ***The last stable release of Factor ([0.97 released 2 Nov 2014](https://re-factor.blogspot.com/2014/11/factor-097-now-available.html)) is too old for use with Exercism.*** 12 | 13 | --- 14 | ### Nightly 15 | 16 | provides nightly binaries under the "Development release" section. These binaries are built from git, but only builds that pass are shown. 17 | 18 | --- 19 | 20 | ### (Auto)build from source 21 | 22 | If you want the bleeding edge and even nightly is too old for you, then you will need a modern C++ compiler (GCC >=4.8 or Clang >=3.5), `make`, and `curl`. 23 | 24 | With those simple requirements fulfilled, you can: 25 | 26 | 1. Download the `build` shell script: [**here** for Unix-likes / POSIX shells](https://raw.githubusercontent.com/factor/factor/master/build.sh) or [**here** for Windows](https://raw.githubusercontent.com/factor/factor/master/build.cmd). Put it in the directory under which Factor should be installed. A directory called `factor` containing the codebase will be created. 27 | 28 | 2. Run it like `./build.sh install`, or `.\build.cmd install` on Windows. This will clone Factor's `git` repository, build it, and download a Factor VM image from . This process may take between 2 and 20 minutes, scaling with your link and clock speeds. 29 | 30 | 3. You can now run the `factor` or `factor.exe` binary generated inside the `factor` subdirectory. Try `factor --help` for help. You can also access documentation from the command line, or by pressing F1 in the GUI Listener, which will open the help browser. 31 | 32 | 4. In the future, use the `build.sh` or (`build.cmd` on Windows) inside the `factor` subdirectory to pull from git and rebuild in-place, and download a new VM image if needed. 33 | 34 | The file structure may now look like this: 35 | 36 | ``` 37 | . 38 | ├── build.sh <- delete if you like 39 | └── factor 40 |    ├── basis 41 |    ├── boot.unix-x86.64.image 42 |    ├── build.cmd <- use these from now on 43 |    ├── build.sh <- 44 |    ├── core 45 |    ├── extra 46 |    ├── factor 47 |    ├── Factor.app 48 |    ├── factor.image 49 |    ├── GNUmakefile 50 |    ├── libfactor.a 51 |    ├── libfactor-ffi-test.so 52 |    ├── LICENSE.txt 53 |    ├── misc 54 |    ├── Nmakefile 55 |    ├── README.md 56 |    ├── unmaintained 57 |    ├── vm 58 |    └── work 59 | ``` 60 | 61 | You no longer need the top level `build` script, as in the future the downloaded one should be used. 62 | 63 | --- 64 | 65 | ### Manually build from source (not recommended) 66 | 67 | Clone the [repository](https://github.com/factor/factor) and use `make` in that folder. 68 | 69 | If `make` fails with an error about a non-present target, try `make factor` or, if you can read a Makefile, find the make target for your platform in `GNUmakefile`. 70 | 71 | If *that* fails, open an issue on [factor/factor](https://github.com/factor/factor) containing the error -- the friendly developers will be happy to help. 72 | 73 | --- 74 | 75 | #### Stable (not recommended) 76 | 77 | **Note that Exercism and [the `exercism` vocabulary for Factor exercises on Exercism][ef] both require at least a [nightly build](#nightly)**. 78 | 79 | Only use a stable release if you plan to skip automated testing or thousands of new features and bugfixes, and you do not plan to contribute to [Factor exercises on Exercism](https://github.com/exercism/factor). 80 | 81 | To develop Factor exercises for Exercism, you need to be able to build and run the [`exercism` vocabulary][ef]. 82 | 83 | Download a Stable release binary for your platform from the "Stable release" section on , and run the installer. 84 | 85 | --- 86 | 87 | ## Making Exercism and Factor work together 88 | 89 | 90 | Due to limitations like name clashes and filename disagreements, it's rather difficult to use Factor's `tools.test` on Exercism exercises out of the box. 91 | 92 | Instead, there is a [wrapper testing vocabulary][et] for the Factor workflow in an Exercism context. Users and Exercism maintainers alike can write and run tests in a familiar way, with much less overhead. 93 | 94 | To test your Factor solutions in your `exercism/factor` folder, follow the directions in [the README](https://github.com/catb0t/exercism.factor#getting-started). 95 | 96 | For information on using the `exercism.testing` vocabulary, refer to the [testing documentation](exercism.io/languages/factor#test), or to `exercism.testing`'s documentation by running `"exercism.testing" help` in Factor, after [installing `exercism.testing`](https://github.com/catb0t/exercism.factor/tree/master/README.md). 97 | 98 | [ef]: https://github.com/catb0t/exercism.factor 99 | [et]: https://github.com/catb0t/exercism.factor/tree/master/exercism/testing -------------------------------------------------------------------------------- /docs/LEARNING.md: -------------------------------------------------------------------------------- 1 | # Ways to learn Factor 2 | 3 | There are many great resources for learning Factor. 4 | 5 | * Documentation is an important part of every good Factor vocabulary. Consequently, Factor's amazing and extensive docs are available offline, searchable right from the GUI Listener, or on the command line. These same docs, equally searchable, can be found online.
6 | 7 | * Factor's GitHub repository hosts a Wiki.
8 | 9 | * Björn Lindqvist, one of Factor's developers, has a repo full of interesting tips and tricks. It's not updated very often and is WIP (and much of its content is being moved to the GitHub Wiki), but it's still very cool stuff.
10 | 11 | * [Learn X in Y Minutes](http://learnxinyminutes.com) is a good resource for many languages, and Factor is no exception. Its tutorial is not *extensive* by any means, but it is a good reference and enough to get you started.
12 | 13 | * [Rosetta Code](http://rosettacode.org/wiki/Rosetta_Code) is a [programming chrestomathy ](https://en.wikipedia.org/wiki/Chrestomathy) site. On it, among the hundreds of other languages, is [Rosetta Code:Factor](https://rosettacode.org/wiki/Category:Factor), where you can find solutions to many problems, and compare with languages you know. It also serves as a good reference and starting point for solutions.
14 | 15 | Lastly and maybe leastly, 16 | 17 | * The [Concatenative Wiki](concatenative.org/wiki/view/Factor). Note that while it has good content and it's not wrong by any means, it's not really updated and [is being phased out](https://github.com/factor/factor/issues/706) in favour of the GitHub Wiki above. 18 | 19 | * [Stack Overflow](http://stackoverflow.com/questions/tagged/factor-lang). There's not a large community (okay, about three users including yours truly) but ask there if you're really, truly stuck and someone will surely help you out. 20 | 21 | * The [Mailing List](http://concatenative.org/wiki/view/Factor/Mailing%20list). Here, you can ask about anything Factor-related and a collaborator will answer helpfully. 22 | 23 | * [Factor is on IRC](http://concatenative.org/wiki/view/Concatenative%20IRC%20channel)! Come join us; we're happy to help. 24 | 25 | * Learn and read about [Joy](http://enwp.org/Joy_%28programming_language%29), [Forth](http://enwp.org/Forth_%28programming_language%29) and concatenative / stack-based programming in general. 26 | 27 | * Learn and read about the [Common Lisp Object System](http://enwp.org/Common_Lisp_Object_System). The CLOS is widely regarded as the most advanced and innovative object model in the world, and Factor's object model is heavily based on and inspired by it. 28 | 29 | * In a lot of ways, Factor is a Lisp. It's a postfix, point-free, functional, inside-out-and-backwards funny-looking one, but many ideologies are the same. Because of this, it may be beneficial to learn a Lisp, preferably a Lisp-1 in which functions and variables share a namespace (because functions are values in functional programming). Yours truly humbly recommends [Scheme](http://schemers.org), or, for something more modern and usable, [Racket](http://racket-lang.org), a descendant of Scheme. 30 | 31 | Finally, Factor is written almost entirely in Factor. So, read the source code, and search the docs for words you don't know. -------------------------------------------------------------------------------- /docs/RESOURCES.md: -------------------------------------------------------------------------------- 1 | # Recommended learning resources 2 | 3 | * The [Official Factor Documentation](http://docs.factorcode.org). 4 | * The [Factor GitHub Repository Wiki](http://github.com/factor/factor/wiki). 5 | * [Björn Lindqvist's Factor Playground](http://github.com/bjourne/playground-factor). 6 | * [Learn X in Y Minutes, where X = Factor](http://learnxinyminutes.com/docs/factor). 7 | * [Factor on RosettaCode](http://rosettacode.org/wiki/Category:Factor). 8 | * The [Concatenative.org Factor Wiki](concatenative.org/wiki/view/Factor). 9 | * The [`factor-lang` tag on Stack Overflow](http://stackoverflow.com/questions/tagged/factor-lang). 10 | * The [Factor Mailing List](http://concatenative.org/wiki/view/Factor/Mailing%20list). 11 | * The [Factor IRC Channel](http://concatenative.org/wiki/view/Concatenative%20IRC%20channel). 12 | * The [Joy](http://enwp.org/Joy_%28programming_language%29) and [Forth](http://enwp.org/Forth_%28programming_language%29) programming languages. 13 | * The [Common Lisp Object System](http://enwp.org/Common_Lisp_Object_System). 14 | * [Factor itself](http://github.com/factor/factor). 15 | -------------------------------------------------------------------------------- /docs/SNIPPET.txt: -------------------------------------------------------------------------------- 1 | USING: formatting kernel sequences ; 2 | IN: hello-world 3 | 4 | : say-hello ( -- string ) 5 | "Hello, World!" ; 6 | -------------------------------------------------------------------------------- /docs/TESTS.md: -------------------------------------------------------------------------------- 1 | # [The `tools.test` framework](http://docs.factorcode.org/content/vocab-tools.test.html) 2 | 3 | Factor's built-in testing framework, rather like Factor itself, marries simplicity with unbridled power. 4 | 5 | ``` 6 | { 1 } [ 1 ] unit-test 7 | { } [ "Hello" print ] unit-test ! print doesn't leave anything on the stack 8 | { 3 } [ 1 2 + ] unit-test 9 | ``` 10 | 11 | Assuming you've learned a little Factor by now, you will see that the `unit-test` word (which is actually a special syntax element) takes an array of how the stack should look after running a given quotation. 12 | 13 | Word definitions should be concise and simplified. They should not be more than 5 or 10 lines long in most cases, and their inputs and outputs should be simple and clearly understandable. Importantly, a given word should do one thing and do it well. 14 | 15 | Words written in this way will implicitly be easily `unit-test`able. 16 | 17 | Unit tests (usually a bunch of assertions like above) go in a file called `vocab-name-tests.factor` beside your implementation `vocab-name.factor`. This file is already created for you by Exercism, but would normally need to be created by hand, or by `"exercise" scaffold-tests`. 18 | 19 | Get the [`tools.test` wrapper library for Exercism](https://github.com/catb0t/exercism.factor), and put its `exercism` subfolder inside Factor's `work` folder, such that `testing.factor` is located at `resource:work/exercism/testing/testing.factor`. 20 | 21 | When the current directory is your `exercism/factor` exercises folder: 22 | 23 | * Run a vocabulary's tests from the listener with `USE: exercism.testing "exercise-name" run-exercism-test`, or from the command-line with `factor -run=exercism.testing exercise-name`. 24 | * Run all tests for all exercises with `USE: exercism.testing run-all-exercism-tests` or from the command-line with `factor -run=exercism.testing run-all`. 25 | 26 | For more information, see the Factor documentation on [Unit testing](http://docs.factorcode.org/content/article-tools.test.html), and [`exercism.testing`](https://github.com/catb0t/exercism.factor/tree/HEAD/exercism/testing)'s documentation with `"exercism.testing" help`. 27 | -------------------------------------------------------------------------------- /docs/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "docs": [ 3 | { 4 | "uuid": "1b43d35f-e184-487a-9be7-1a86b9d1aedd", 5 | "slug": "installation", 6 | "path": "docs/INSTALLATION.md", 7 | "title": "Installing Factor locally", 8 | "blurb": "Learn how to install Factor locally to solve Exercism's exercises on your own machine" 9 | }, 10 | { 11 | "uuid": "c0b59939-255c-4c4a-b4cc-5f08e8b3117f", 12 | "slug": "learning", 13 | "path": "docs/LEARNING.md", 14 | "title": "How to learn Factor", 15 | "blurb": "An overview of how to get started from scratch with Factor" 16 | }, 17 | { 18 | "uuid": "dafa95b9-c1c6-44c2-b864-103e2d3a846f", 19 | "slug": "tests", 20 | "path": "docs/TESTS.md", 21 | "title": "Testing on the Factor track", 22 | "blurb": "Learn how to test your Factor exercises on Exercism" 23 | }, 24 | { 25 | "uuid": "8b04aa8c-b072-4a4d-9ea8-9fd7aac46a63", 26 | "slug": "resources", 27 | "path": "docs/RESOURCES.md", 28 | "title": "Useful Factor resources", 29 | "blurb": "A collection of useful resources to help you master Factor" 30 | } 31 | ] 32 | } 33 | -------------------------------------------------------------------------------- /exercises/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/exercism/factor/cdb0b9f66a233fac2449e2d2d970127be0539d62/exercises/.keep -------------------------------------------------------------------------------- /exercises/practice/accumulate/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | Implement the `accumulate` operation, which, given a collection and an 4 | operation to perform on each element of the collection, returns a new 5 | collection containing the result of applying that operation to each element of 6 | the input collection. 7 | 8 | Given the collection of numbers: 9 | 10 | - 1, 2, 3, 4, 5 11 | 12 | And a quotation that performs: 13 | 14 | - square a number (`[ sq ]`) 15 | 16 | Your code should be able to produce the collection of squares: 17 | 18 | - 1, 4, 9, 16, 25 19 | 20 | ## Restrictions 21 | 22 | Keep your hands off that collect/map/fmap/whatchamacallit functionality 23 | provided by your standard library! 24 | 25 | Solve this one yourself using other basic tools instead. 26 | -------------------------------------------------------------------------------- /exercises/practice/accumulate/.meta/accumulate-example.factor: -------------------------------------------------------------------------------- 1 | USING: arrays kernel locals sequences sequences.extras ; 2 | IN: accumulate 3 | 4 | :: accum ( seq xform: ( a -- b ) -- newseq ) 5 | seq >resizable :> seq 6 | seq length seq new-resizable :> newseq 7 | 8 | [ seq empty? ] [ 9 | seq pop xform call 10 | newseq push 11 | ] until 12 | 13 | newseq reverse >array ; inline 14 | 15 | -------------------------------------------------------------------------------- /exercises/practice/accumulate/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "hiljusti" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "accumulate.factor" 8 | ], 9 | "test": [ 10 | "accumulate-tests.factor" 11 | ], 12 | "example": [ 13 | ".meta/accumulate-example.factor" 14 | ] 15 | }, 16 | "blurb": "Implement the `accumulate` operation, which, given a collection and an operation to perform on each element of the collection, returns a new collection containing the result of applying that operation to each element of the input collection.", 17 | "source": "Conversation with James Edward Gray II", 18 | "source_url": "https://twitter.com/jeg2" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/accumulate/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Regular comments will be removed when this 2 | # file is regenerated. Regenerating will not touch any manually added keys, 3 | # so comments can be added in a "comment" key. 4 | 5 | [64d97c14-36dd-44a8-9621-2cecebd6ed23] 6 | description = "accumulate empty" 7 | 8 | [00008ed2-4651-4929-8c08-8b4dbd70872e] 9 | description = "accumulate squares" 10 | 11 | [551016da-4396-4cae-b0ec-4c3a1a264125] 12 | description = "accumulate upcases" 13 | 14 | [cdf95597-b6ec-4eac-a838-3480d13d0d05] 15 | description = "accumulate reversed strings" 16 | 17 | [bee8e9b6-b16f-4cd2-be3b-ccf7457e50bb] 18 | description = "accumulate recursively" 19 | -------------------------------------------------------------------------------- /exercises/practice/accumulate/accumulate-tests.factor: -------------------------------------------------------------------------------- 1 | USING: accumulate io kernel math sequences tools.test unicode ; 2 | IN: accumulate.tests 3 | 4 | "Accumulate:" print 5 | 6 | "accumulate empty" print 7 | { { } } [ { } [ sq ] accum ] unit-test 8 | 9 | "accumulate squares" print 10 | { { 1 4 9 } } [ { 1 2 3 } [ sq ] accum ] unit-test 11 | 12 | "accumulate upcases" print 13 | { { "HELLO" "WORLD" } } 14 | [ { "Hello" "world" } [ >upper ] accum ] unit-test 15 | 16 | "accumulate reversed strings" print 17 | { { "eht" "kciuq" "nworb" "xof" "cte" } } 18 | [ { "the" "quick" "brown" "fox" "etc" } [ string-reverse ] accum ] unit-test 19 | 20 | "accumulate recursively" print 21 | { { { "a1" "a2" "a3" } { "b1" "b2" "b3" } { "c1" "c2" "c3" } } } 22 | [ { "a" "b" "c" } [ dup dup { "1" "2" "3" } [ append ] accum ] accum ] unit-test 23 | 24 | -------------------------------------------------------------------------------- /exercises/practice/accumulate/accumulate.factor: -------------------------------------------------------------------------------- 1 | USING: kernel ; 2 | IN: accumulate 3 | 4 | : accum ( seq xform: ( a -- b ) -- newseq ) 5 | "unimplemented" throw ; 6 | 7 | -------------------------------------------------------------------------------- /exercises/practice/acronym/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | Convert a phrase to its acronym. 4 | 5 | Techies love their TLA (Three Letter Acronyms)! 6 | 7 | Help generate some jargon by writing a program that converts a long name 8 | like Portable Network Graphics to its acronym (PNG). 9 | -------------------------------------------------------------------------------- /exercises/practice/acronym/.meta/acronym-example.factor: -------------------------------------------------------------------------------- 1 | USING: ascii kernel sequences splitting ; 2 | IN: acronym 3 | 4 | : acronym ( str -- abbr ) 5 | " -_" split 6 | [ empty? ] reject 7 | [ 1 head ] map 8 | "" join 9 | >upper 10 | ; 11 | 12 | -------------------------------------------------------------------------------- /exercises/practice/acronym/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "hiljusti" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "acronym.factor" 8 | ], 9 | "test": [ 10 | "acronym-tests.factor" 11 | ], 12 | "example": [ 13 | ".meta/acronym-example.factor" 14 | ] 15 | }, 16 | "blurb": "Convert a long phrase to its acronym.", 17 | "source": "Julien Vanier", 18 | "source_url": "https://github.com/monkbroc" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/acronym/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Regular comments will be removed when this 2 | # file is regenerated. Regenerating will not touch any manually added keys, 3 | # so comments can be added in a "comment" key. 4 | 5 | [1e22cceb-c5e4-4562-9afe-aef07ad1eaf4] 6 | description = "basic" 7 | 8 | [79ae3889-a5c0-4b01-baf0-232d31180c08] 9 | description = "lowercase words" 10 | 11 | [ec7000a7-3931-4a17-890e-33ca2073a548] 12 | description = "punctuation" 13 | 14 | [32dd261c-0c92-469a-9c5c-b192e94a63b0] 15 | description = "all caps word" 16 | 17 | [ae2ac9fa-a606-4d05-8244-3bcc4659c1d4] 18 | description = "punctuation without whitespace" 19 | 20 | [0e4b1e7c-1a6d-48fb-81a7-bf65eb9e69f9] 21 | description = "very long abbreviation" 22 | 23 | [6a078f49-c68d-4b7b-89af-33a1a98c28cc] 24 | description = "consecutive delimiters" 25 | 26 | [5118b4b1-4572-434c-8d57-5b762e57973e] 27 | description = "apostrophes" 28 | 29 | [adc12eab-ec2d-414f-b48c-66a4fc06cdef] 30 | description = "underscore emphasis" 31 | -------------------------------------------------------------------------------- /exercises/practice/acronym/acronym-tests.factor: -------------------------------------------------------------------------------- 1 | USING: acronym io kernel math sequences tools.test unicode ; 2 | IN: acronym.tests 3 | 4 | "Acronym:" print 5 | 6 | "basic" print 7 | { "PNG" } [ "Portable Network Graphics" acronym ] unit-test 8 | 9 | "lowercase words" print 10 | { "ROR" } [ "Ruby on Rails" acronym ] unit-test 11 | 12 | "punctuation" print 13 | { "FIFO" } [ "First In, First Out" acronym ] unit-test 14 | 15 | "all caps word" print 16 | { "GIMP" } [ "GNU Image Manipulation Program" acronym ] unit-test 17 | 18 | "punctuation without whitespace" print 19 | { "CMOS" } [ "Complementary metal-oxide semiconductor" acronym ] unit-test 20 | 21 | "very long abbreviation" print 22 | { "ROTFLSHTMDCOALM" } [ 23 | "Rolling On The Floor Laughing So Hard That My Dogs Came Over And Licked Me" 24 | acronym 25 | ] unit-test 26 | 27 | "consecutive delimiters" print 28 | { "SIMUFTA" } [ "Something - I made up from thin air" acronym ] unit-test 29 | 30 | "apostrophes" print 31 | { "HC" } [ "Halley's Comet" acronym ] unit-test 32 | 33 | "underscore emphasis" print 34 | { "TRNT" } [ "The Road _Not_ Taken" acronym ] unit-test 35 | 36 | -------------------------------------------------------------------------------- /exercises/practice/acronym/acronym.factor: -------------------------------------------------------------------------------- 1 | USING: kernel ; 2 | IN: acronym 3 | 4 | : acronym ( str -- abbr ) 5 | "unimplemented" throw ; 6 | 7 | -------------------------------------------------------------------------------- /exercises/practice/all-your-base/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Convert a sequence of digits in one base, representing a number, into a sequence of digits in another base, representing the same number. 4 | 5 | ~~~~exercism/note 6 | Try to implement the conversion yourself. 7 | Do not use something else to perform the conversion for you. 8 | ~~~~ 9 | 10 | ## About [Positional Notation][positional-notation] 11 | 12 | In positional notation, a number in base **b** can be understood as a linear combination of powers of **b**. 13 | 14 | The number 42, _in base 10_, means: 15 | 16 | `(4 × 10¹) + (2 × 10⁰)` 17 | 18 | The number 101010, _in base 2_, means: 19 | 20 | `(1 × 2⁵) + (0 × 2⁴) + (1 × 2³) + (0 × 2²) + (1 × 2¹) + (0 × 2⁰)` 21 | 22 | The number 1120, _in base 3_, means: 23 | 24 | `(1 × 3³) + (1 × 3²) + (2 × 3¹) + (0 × 3⁰)` 25 | 26 | _Yes. Those three numbers above are exactly the same. Congratulations!_ 27 | 28 | [positional-notation]: https://en.wikipedia.org/wiki/Positional_notation 29 | -------------------------------------------------------------------------------- /exercises/practice/all-your-base/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | You've just been hired as professor of mathematics. 4 | Your first week went well, but something is off in your second week. 5 | The problem is that every answer given by your students is wrong! 6 | Luckily, your math skills have allowed you to identify the problem: the student answers _are_ correct, but they're all in base 2 (binary)! 7 | Amazingly, it turns out that each week, the students use a different base. 8 | To help you quickly verify the student answers, you'll be building a tool to translate between bases. 9 | -------------------------------------------------------------------------------- /exercises/practice/all-your-base/.meta/all-your-base-example.factor: -------------------------------------------------------------------------------- 1 | USING: combinators kernel locals math math.functions math.ranges sequences ; 2 | IN: all-your-base 3 | 4 | :: powers ( base n -- seq ) 5 | n [0,b) reverse 6 | [ base swap ^ ] map ; 7 | 8 | :: from-digits ( digits base -- x ) 9 | digits length :> n 10 | 11 | base n powers 12 | digits [ * ] 2map sum ; 13 | 14 | :: (to-digits) ( digits x base -- newdigits ) 15 | x 0 <= 16 | [ digits ] 17 | [ digits x base mod suffix 18 | x base /i 19 | base 20 | (to-digits) 21 | ] 22 | if ; 23 | 24 | :: to-digits ( x base -- digits ) 25 | { } x base (to-digits) reverse :> newdigits 26 | 27 | newdigits length 0 = 28 | [ { 0 } ] 29 | [ newdigits ] if ; 30 | 31 | :: invalid-digits? ( digits base -- ? ) 32 | digits 33 | [ [ 0 < ] any? ] 34 | [ [ base >= ] any? ] 35 | bi or ; 36 | 37 | :: rebase ( digits base1 base2 -- newdigits ) 38 | { 39 | { [ base1 2 < ] [ "input base must be >= 2" throw ] } 40 | { [ base2 2 < ] [ "output base must be >= 2" throw ] } 41 | { [ digits base1 invalid-digits? ] 42 | [ "all digits must satisfy 0 <= d < input base" throw ] 43 | } 44 | [ digits base1 from-digits base2 to-digits ] 45 | } cond ; 46 | 47 | -------------------------------------------------------------------------------- /exercises/practice/all-your-base/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "hiljusti" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "all-your-base.factor" 8 | ], 9 | "test": [ 10 | "all-your-base-tests.factor" 11 | ], 12 | "example": [ 13 | ".meta/all-your-base-example.factor" 14 | ] 15 | }, 16 | "blurb": "Convert a number, represented as a sequence of digits in one base, to any other base." 17 | } 18 | -------------------------------------------------------------------------------- /exercises/practice/all-your-base/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Regular comments will be removed when this 2 | # file is regenerated. Regenerating will not touch any manually added keys, 3 | # so comments can be added in a "comment" key. 4 | 5 | [5ce422f9-7a4b-4f44-ad29-49c67cb32d2c] 6 | description = "single bit one to decimal" 7 | 8 | [0cc3fea8-bb79-46ac-a2ab-5a2c93051033] 9 | description = "binary to single decimal" 10 | 11 | [f12db0f9-0d3d-42c2-b3ba-e38cb375a2b8] 12 | description = "single decimal to binary" 13 | 14 | [2c45cf54-6da3-4748-9733-5a3c765d925b] 15 | description = "binary to multiple decimal" 16 | 17 | [65ddb8b4-8899-4fcc-8618-181b2cf0002d] 18 | description = "decimal to binary" 19 | 20 | [8d418419-02a7-4824-8b7a-352d33c6987e] 21 | description = "trinary to hexadecimal" 22 | 23 | [d3901c80-8190-41b9-bd86-38d988efa956] 24 | description = "hexadecimal to trinary" 25 | 26 | [5d42f85e-21ad-41bd-b9be-a3e8e4258bbf] 27 | description = "15-bit integer" 28 | 29 | [d68788f7-66dd-43f8-a543-f15b6d233f83] 30 | description = "empty list" 31 | 32 | [5e27e8da-5862-4c5f-b2a9-26c0382b6be7] 33 | description = "single zero" 34 | 35 | [2e1c2573-77e4-4b9c-8517-6c56c5bcfdf2] 36 | description = "multiple zeros" 37 | 38 | [3530cd9f-8d6d-43f5-bc6e-b30b1db9629b] 39 | description = "leading zeros" 40 | 41 | [a6b476a1-1901-4f2a-92c4-4d91917ae023] 42 | description = "input base is one" 43 | 44 | [e21a693a-7a69-450b-b393-27415c26a016] 45 | description = "input base is zero" 46 | 47 | [54a23be5-d99e-41cc-88e0-a650ffe5fcc2] 48 | description = "input base is negative" 49 | 50 | [9eccf60c-dcc9-407b-95d8-c37b8be56bb6] 51 | description = "negative digit" 52 | 53 | [232fa4a5-e761-4939-ba0c-ed046cd0676a] 54 | description = "invalid positive digit" 55 | 56 | [14238f95-45da-41dc-95ce-18f860b30ad3] 57 | description = "output base is one" 58 | 59 | [73dac367-da5c-4a37-95fe-c87fad0a4047] 60 | description = "output base is zero" 61 | 62 | [13f81f42-ff53-4e24-89d9-37603a48ebd9] 63 | description = "output base is negative" 64 | 65 | [0e6c895d-8a5d-4868-a345-309d094cfe8d] 66 | description = "both bases are negative" 67 | -------------------------------------------------------------------------------- /exercises/practice/all-your-base/all-your-base-tests.factor: -------------------------------------------------------------------------------- 1 | USING: all-your-base io kernel math sequences tools.test unicode ; 2 | IN: all-your-base.tests 3 | 4 | "All Your Base:" print 5 | 6 | "single bit one to decimal" print 7 | { { 1 } } [ { 1 } 2 10 rebase ] unit-test 8 | 9 | "binary to single decimal" print 10 | { { 5 } } [ { 1 0 1 } 2 10 rebase ] unit-test 11 | 12 | "single decimal to binary" print 13 | { { 1 0 1 } } [ { 5 } 10 2 rebase ] unit-test 14 | 15 | "binary to multiple decimal" print 16 | { { 4 2 } } [ { 1 0 1 0 1 0 } 2 10 rebase ] unit-test 17 | 18 | "decimal to binary" print 19 | { { 1 0 1 0 1 0 } } [ { 4 2 } 10 2 rebase ] unit-test 20 | 21 | "trinary to hexadecimal" print 22 | { { 2 10 } } [ { 1 1 2 0 } 3 16 rebase ] unit-test 23 | 24 | "hexadecimal to trinary" print 25 | { { 1 1 2 0 } } [ { 2 10 } 16 3 rebase ] unit-test 26 | 27 | "15-bit integer" print 28 | { { 6 10 45 } } [ { 3 46 60 } 97 73 rebase ] unit-test 29 | 30 | "empty list" print 31 | { { 0 } } [ { } 2 10 rebase ] unit-test 32 | 33 | "single zero" print 34 | { { 0 } } [ { 0 } 10 2 rebase ] unit-test 35 | 36 | "multiple zeros" print 37 | { { 0 } } [ { 0 0 0 } 10 2 rebase ] unit-test 38 | 39 | "leading zeros" print 40 | { { 4 2 } } [ { 0 6 0 } 7 10 rebase ] unit-test 41 | 42 | "input base is one" print 43 | [ { 0 } 1 10 rebase ] [ "input base must be >= 2" = ] must-fail-with 44 | 45 | "input base is zero" print 46 | [ { } 0 10 rebase ] [ "input base must be >= 2" = ] must-fail-with 47 | 48 | "input base is negative" print 49 | [ { 1 } -2 10 rebase ] [ "input base must be >= 2" = ] must-fail-with 50 | 51 | "negative digit" print 52 | [ { 1 -1 1 0 1 0 } 2 10 rebase ] [ 53 | "all digits must satisfy 0 <= d < input base" = 54 | ] must-fail-with 55 | 56 | "invalid positive digit" print 57 | [ { 1 2 1 0 1 0 } 2 10 rebase ] [ 58 | "all digits must satisfy 0 <= d < input base" = 59 | ] must-fail-with 60 | 61 | "output base is one" print 62 | [ { 1 0 1 0 1 0 } 2 1 rebase ] [ "output base must be >= 2" = ] must-fail-with 63 | 64 | "output base is zero" print 65 | [ { 7 } 10 0 rebase ] [ "output base must be >= 2" = ] must-fail-with 66 | 67 | "output base is negative" print 68 | [ { 1 } 2 -7 rebase ] [ "output base must be >= 2" = ] must-fail-with 69 | 70 | "both bases are negative" print 71 | [ { 1 } -2 -7 rebase ] [ "input base must be >= 2" = ] must-fail-with 72 | 73 | -------------------------------------------------------------------------------- /exercises/practice/all-your-base/all-your-base.factor: -------------------------------------------------------------------------------- 1 | USING: kernel ; 2 | IN: all-your-base 3 | 4 | : rebase ( seq n m -- newseq ) 5 | "unimplemented" throw ; 6 | 7 | -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Description 2 | 3 | An [Armstrong number](https://en.wikipedia.org/wiki/Narcissistic_number) is a number that is the sum of its own digits each raised to the power of the number of digits. 4 | 5 | For example: 6 | 7 | - 9 is an Armstrong number, because `9 = 9^1 = 9` 8 | - 10 is *not* an Armstrong number, because `10 != 1^2 + 0^2 = 1` 9 | - 153 is an Armstrong number, because: `153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153` 10 | - 154 is *not* an Armstrong number, because: `154 != 1^3 + 5^3 + 4^3 = 1 + 125 + 64 = 190` 11 | 12 | Write some code to determine whether a number is an Armstrong number. 13 | -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/.meta/armstrong-numbers-example.factor: -------------------------------------------------------------------------------- 1 | USING: assocs kernel locals math math.functions math.order sequences ; 2 | IN: armstrong 3 | 4 | :: digits ( x -- digits ) 5 | x 10 /mod :> x! :> xs! 6 | 1 { } new-resizable :> digits 7 | x digits push 8 | 9 | [ xs 0 = not ] 10 | [ 11 | xs 10 /mod x! xs! 12 | x digits push 13 | ] while 14 | 15 | digits reverse ; 16 | 17 | :: powsum ( x -- powsum ) 18 | x digits :> digs 19 | digs length :> len 20 | 21 | digs [ len ^ ] map sum ; 22 | 23 | : armstrong? ( x -- ? ) 24 | [ ] [ powsum ] bi = ; 25 | 26 | -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "hiljusti" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "armstrong-numbers.factor" 8 | ], 9 | "test": [ 10 | "armstrong-numbers-tests.factor" 11 | ], 12 | "example": [ 13 | ".meta/armstrong-numbers-example.factor" 14 | ] 15 | }, 16 | "blurb": "Determine if a number is an Armstrong number.", 17 | "source": "Wikipedia", 18 | "source_url": "https://en.wikipedia.org/wiki/Narcissistic_number" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Regular comments will be removed when this 2 | # file is regenerated. Regenerating will not touch any manually added keys, 3 | # so comments can be added in a "comment" key. 4 | 5 | [c1ed103c-258d-45b2-be73-d8c6d9580c7b] 6 | description = "Zero is an Armstrong number" 7 | 8 | [579e8f03-9659-4b85-a1a2-d64350f6b17a] 9 | description = "Single digit numbers are Armstrong numbers" 10 | 11 | [2d6db9dc-5bf8-4976-a90b-b2c2b9feba60] 12 | description = "There are no 2 digit Armstrong numbers" 13 | 14 | [509c087f-e327-4113-a7d2-26a4e9d18283] 15 | description = "Three digit number that is an Armstrong number" 16 | 17 | [7154547d-c2ce-468d-b214-4cb953b870cf] 18 | description = "Three digit number that is not an Armstrong number" 19 | 20 | [6bac5b7b-42e9-4ecb-a8b0-4832229aa103] 21 | description = "Four digit number that is an Armstrong number" 22 | 23 | [eed4b331-af80-45b5-a80b-19c9ea444b2e] 24 | description = "Four digit number that is not an Armstrong number" 25 | 26 | [f971ced7-8d68-4758-aea1-d4194900b864] 27 | description = "Seven digit number that is an Armstrong number" 28 | 29 | [7ee45d52-5d35-4fbd-b6f1-5c8cd8a67f18] 30 | description = "Seven digit number that is not an Armstrong number" 31 | -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/armstrong-numbers-tests.factor: -------------------------------------------------------------------------------- 1 | USING: armstrong io kernel math sequences tools.test unicode ; 2 | IN: armstrong.tests 3 | 4 | "Armstrong numbers" print 5 | 6 | "Zero is an Armstrong number" print 7 | { t } [ 0 armstrong? ] unit-test 8 | 9 | "Single digit numbers are Armstrong numbers" print 10 | { t } [ 5 armstrong? ] unit-test 11 | 12 | "There are no 2 digit Armstrong numbers" print 13 | { f } [ 10 armstrong? ] unit-test 14 | 15 | "Three digit number that is an Armstrong number" print 16 | { t } [ 153 armstrong? ] unit-test 17 | 18 | "Three digit number that is not an Armstrong number" print 19 | { f } [ 100 armstrong? ] unit-test 20 | 21 | "Four digit number that is an Armstrong number" print 22 | { t } [ 9474 armstrong? ] unit-test 23 | 24 | "Four digit number that is not an Armstrong number" print 25 | { f } [ 9475 armstrong? ] unit-test 26 | 27 | "Seven digit number that is an Armstrong number" print 28 | { t } [ 9926315 armstrong? ] unit-test 29 | 30 | "Seven digit number that is not an Armstrong number" print 31 | { f } [ 9926314 armstrong? ] unit-test 32 | 33 | -------------------------------------------------------------------------------- /exercises/practice/armstrong-numbers/armstrong-numbers.factor: -------------------------------------------------------------------------------- 1 | USING: kernel ; 2 | IN: armstrong 3 | 4 | : armstrong? ( x -- ? ) 5 | "unimplemented" throw ; 6 | 7 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | The classical introductory exercise. Just say "Hello, World!". 4 | 5 | ["Hello, World!"](http://en.wikipedia.org/wiki/%22Hello,_world!%22_program) is 6 | the traditional first program for beginning programming in a new language 7 | or environment. 8 | 9 | The objectives are simple: 10 | 11 | - Write a function that returns the string "Hello, World!". 12 | - Run the test suite and make sure that it succeeds. 13 | - Submit your solution and check it at the website. 14 | 15 | If everything goes well, you will be ready to fetch your first real exercise. 16 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "kytrinyx" 4 | ], 5 | "contributors": [ 6 | "catb0t", 7 | "sjwarner-bp" 8 | ], 9 | "files": { 10 | "solution": [ 11 | "hello-world.factor" 12 | ], 13 | "test": [ 14 | "hello-world-tests.factor" 15 | ], 16 | "example": [ 17 | ".meta/hello-world-example.factor" 18 | ] 19 | }, 20 | "blurb": "The classical introductory exercise. Just say \"Hello, World!\"", 21 | "source": "This is an exercise to introduce users to using Exercism", 22 | "source_url": "http://en.wikipedia.org/wiki/%22Hello,_world!%22_program" 23 | } 24 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/.meta/hello-world-example.factor: -------------------------------------------------------------------------------- 1 | USING: formatting kernel sequences ; 2 | IN: hello-world 3 | 4 | : say-hello ( -- string ) 5 | "Hello, World!" ; 6 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Regular comments will be removed when this 2 | # file is regenerated. Regenerating will not touch any manually added keys, 3 | # so comments can be added in a "comment" key. 4 | 5 | [af9ffe10-dc13-42d8-a742-e7bdafac449d] 6 | description = "Say Hi!" 7 | -------------------------------------------------------------------------------- /exercises/practice/hello-world/hello-world-tests.factor: -------------------------------------------------------------------------------- 1 | USING: hello-world tools.test ; 2 | IN: hello-world.tests 3 | 4 | { "Hello, World!" } [ say-hello ] unit-test -------------------------------------------------------------------------------- /exercises/practice/hello-world/hello-world.factor: -------------------------------------------------------------------------------- 1 | USING: formatting kernel sequences ; 2 | IN: hello-world 3 | 4 | : say-hello ( -- string ) 5 | "Goodbye, Mars!" ; 6 | -------------------------------------------------------------------------------- /exercises/practice/isogram/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Determine if a word or phrase is an isogram. 4 | 5 | An isogram (also known as a "nonpattern word") is a word or phrase without a repeating letter, however spaces and hyphens are allowed to appear multiple times. 6 | 7 | Examples of isograms: 8 | 9 | - lumberjacks 10 | - background 11 | - downstream 12 | - six-year-old 13 | 14 | The word *isograms*, however, is not an isogram, because the s repeats. 15 | -------------------------------------------------------------------------------- /exercises/practice/isogram/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [], 3 | "contributors": [ 4 | "sjwarner-bp" 5 | ], 6 | "files": { 7 | "solution": [ 8 | "isogram.factor" 9 | ], 10 | "test": [ 11 | "isogram-tests.factor" 12 | ], 13 | "example": [ 14 | ".meta/isogram-example.factor" 15 | ] 16 | }, 17 | "blurb": "Determine if a word or phrase is an isogram.", 18 | "source": "Wikipedia", 19 | "source_url": "https://en.wikipedia.org/wiki/Isogram" 20 | } 21 | -------------------------------------------------------------------------------- /exercises/practice/isogram/.meta/isogram-example.factor: -------------------------------------------------------------------------------- 1 | USING: kernel sets ; 2 | IN: isogram 3 | 4 | : isogram? ( str -- ? ) 5 | dup "" set-like = ; 6 | -------------------------------------------------------------------------------- /exercises/practice/isogram/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Regular comments will be removed when this 2 | # file is regenerated. Regenerating will not touch any manually added keys, 3 | # so comments can be added in a "comment" key. 4 | 5 | [a0e97d2d-669e-47c7-8134-518a1e2c4555] 6 | description = "empty string" 7 | 8 | [9a001b50-f194-4143-bc29-2af5ec1ef652] 9 | description = "isogram with only lower case characters" 10 | 11 | [8ddb0ca3-276e-4f8b-89da-d95d5bae78a4] 12 | description = "word with one duplicated character" 13 | 14 | [6450b333-cbc2-4b24-a723-0b459b34fe18] 15 | description = "word with one duplicated character from the end of the alphabet" 16 | 17 | [a15ff557-dd04-4764-99e7-02cc1a385863] 18 | description = "longest reported english isogram" 19 | 20 | [f1a7f6c7-a42f-4915-91d7-35b2ea11c92e] 21 | description = "word with duplicated character in mixed case" 22 | 23 | [14a4f3c1-3b47-4695-b645-53d328298942] 24 | description = "word with duplicated character in mixed case, lowercase first" 25 | 26 | [423b850c-7090-4a8a-b057-97f1cadd7c42] 27 | description = "hypothetical isogrammic word with hyphen" 28 | 29 | [93dbeaa0-3c5a-45c2-8b25-428b8eacd4f2] 30 | description = "hypothetical word with duplicated character following hyphen" 31 | 32 | [36b30e5c-173f-49c6-a515-93a3e825553f] 33 | description = "isogram with duplicated hyphen" 34 | 35 | [cdabafa0-c9f4-4c1f-b142-689c6ee17d93] 36 | description = "made-up name that is an isogram" 37 | 38 | [5fc61048-d74e-48fd-bc34-abfc21552d4d] 39 | description = "duplicated character in the middle" 40 | 41 | [310ac53d-8932-47bc-bbb4-b2b94f25a83e] 42 | description = "same first and last characters" 43 | 44 | [0d0b8644-0a1e-4a31-a432-2b3ee270d847] 45 | description = "word with duplicated character and with two hyphens" 46 | -------------------------------------------------------------------------------- /exercises/practice/isogram/isogram-tests.factor: -------------------------------------------------------------------------------- 1 | USING: io isogram tools.test ; 2 | IN: isogram.tests 3 | 4 | "Isogram:" print 5 | 6 | "empty string" print 7 | { t } [ "" isogram? ] unit-test 8 | 9 | "isogram with only lower case characters" print 10 | { t } [ "isogram" isogram? ] unit-test 11 | 12 | "word with one duplicated character" print 13 | { f } [ "eleven" isogram? ] unit-test 14 | 15 | "longest reported english isogram" print 16 | { t } [ "subdermatoglyphic" isogram? ] unit-test 17 | 18 | "word with duplicated character in mixed case" print 19 | { f } [ "Alphabet" isogram? ] unit-test 20 | 21 | "hypothetical isogrammic word with hyphen" print 22 | { t } [ "thumbscrew-japingly" isogram? ] unit-test 23 | 24 | "isogram with duplicated non letter character" print 25 | { t } [ "Hjelmqvist-Gryb-Zock-Pfund-Wax" isogram? ] unit-test 26 | 27 | "made-up name that is an isogram" print 28 | { t } [ "Emily Jung Schwartzkopf" isogram? ] unit-test 29 | 30 | "duplicated character in the middle" print 31 | { f } [ "accentor" isogram? ] unit-test 32 | 33 | "word with duplicated character and with two hyphens" print 34 | { f } [ "up-to-date" isogram? ] unit-test 35 | 36 | -------------------------------------------------------------------------------- /exercises/practice/isogram/isogram.factor: -------------------------------------------------------------------------------- 1 | USING: kernel ; 2 | IN: isogram 3 | 4 | : isogram? ( str -- ? ) 5 | "unimplemented" throw ; 6 | 7 | -------------------------------------------------------------------------------- /exercises/practice/leap/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Your task is to determine whether a given year is a leap year. 4 | -------------------------------------------------------------------------------- /exercises/practice/leap/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | A leap year (in the Gregorian calendar) occurs: 4 | 5 | - In every year that is evenly divisible by 4. 6 | - Unless the year is evenly divisible by 100, in which case it's only a leap year if the year is also evenly divisible by 400. 7 | 8 | Some examples: 9 | 10 | - 1997 was not a leap year as it's not divisible by 4. 11 | - 1900 was not a leap year as it's not divisible by 400. 12 | - 2000 was a leap year! 13 | 14 | ~~~~exercism/note 15 | For a delightful, four-minute explanation of the whole phenomenon of leap years, check out [this YouTube video](https://www.youtube.com/watch?v=xX96xng7sAE). 16 | ~~~~ 17 | -------------------------------------------------------------------------------- /exercises/practice/leap/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "catb0t" 4 | ], 5 | "contributors": [ 6 | "sjwarner-bp" 7 | ], 8 | "files": { 9 | "solution": [ 10 | "leap.factor" 11 | ], 12 | "test": [ 13 | "leap-tests.factor" 14 | ], 15 | "example": [ 16 | ".meta/leap-example.factor" 17 | ] 18 | }, 19 | "blurb": "Determine whether a given year is a leap year.", 20 | "source": "CodeRanch Cattle Drive, Assignment 3", 21 | "source_url": "https://coderanch.com/t/718816/Leap" 22 | } 23 | -------------------------------------------------------------------------------- /exercises/practice/leap/.meta/leap-example.factor: -------------------------------------------------------------------------------- 1 | USING: formatting kernel math ; 2 | IN: leap 3 | 4 | : my-leap-year? ( year -- leap-year? ) 5 | dup odd? [ drop f ] [ 6 | [ 4 mod zero? ] [ 100 mod 0 > ] [ 400 mod zero? ] tri or and 7 | ] if ; 8 | -------------------------------------------------------------------------------- /exercises/practice/leap/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Regular comments will be removed when this 2 | # file is regenerated. Regenerating will not touch any manually added keys, 3 | # so comments can be added in a "comment" key. 4 | 5 | [6466b30d-519c-438e-935d-388224ab5223] 6 | description = "year not divisible by 4 in common year" 7 | 8 | [ac227e82-ee82-4a09-9eb6-4f84331ffdb0] 9 | description = "year divisible by 2, not divisible by 4 in common year" 10 | 11 | [4fe9b84c-8e65-489e-970b-856d60b8b78e] 12 | description = "year divisible by 4, not divisible by 100 in leap year" 13 | 14 | [7fc6aed7-e63c-48f5-ae05-5fe182f60a5d] 15 | description = "year divisible by 4 and 5 is still a leap year" 16 | 17 | [78a7848f-9667-4192-ae53-87b30c9a02dd] 18 | description = "year divisible by 100, not divisible by 400 in common year" 19 | 20 | [9d70f938-537c-40a6-ba19-f50739ce8bac] 21 | description = "year divisible by 100 but not by 3 is still not a leap year" 22 | 23 | [42ee56ad-d3e6-48f1-8e3f-c84078d916fc] 24 | description = "year divisible by 400 is leap year" 25 | 26 | [57902c77-6fe9-40de-8302-587b5c27121e] 27 | description = "year divisible by 400 but not by 125 is still a leap year" 28 | 29 | [c30331f6-f9f6-4881-ad38-8ca8c12520c1] 30 | description = "year divisible by 200, not divisible by 400 in common year" 31 | -------------------------------------------------------------------------------- /exercises/practice/leap/leap-tests.factor: -------------------------------------------------------------------------------- 1 | USING: io leap tools.test ; 2 | IN: leap.tests 3 | 4 | "Leap year:" print 5 | 6 | "not very common" print 7 | { f } [ 2015 my-leap-year? ] unit-test 8 | 9 | "introduced every 4 years to adjust about a day" print 10 | { t } [ 2016 my-leap-year? ] unit-test 11 | 12 | "skipped every 100 years to remove an extra day" print 13 | { f } [ 1900 my-leap-year? ] unit-test 14 | 15 | "reintroduced every 400 years to adjust yet another day" print 16 | { t } [ 2000 my-leap-year? ] unit-test 17 | 18 | 19 | 20 | "Additional corner cases of leap years:" print 21 | 22 | "not a leap year" print 23 | { f } [ 1978 my-leap-year? ] unit-test 24 | 25 | "a common leap year" print 26 | { t } [ 1992 my-leap-year? ] unit-test 27 | 28 | "is skipped every 100 years" print 29 | { f } [ 2100 my-leap-year? ] unit-test 30 | 31 | "reintroduced every 400 years" print 32 | { f } [ 2100 my-leap-year? ] unit-test 33 | -------------------------------------------------------------------------------- /exercises/practice/leap/leap.factor: -------------------------------------------------------------------------------- 1 | USING: kernel ; 2 | IN: leap 3 | 4 | : my-leap-year? ( year -- leap-year? ) 5 | "unimplemented" throw ; 6 | 7 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Your task is to convert a number into its corresponding raindrop sounds. 4 | 5 | If a given number: 6 | 7 | - is divisible by 3, add "Pling" to the result. 8 | - is divisible by 5, add "Plang" to the result. 9 | - is divisible by 7, add "Plong" to the result. 10 | - **is not** divisible by 3, 5, or 7, the result should be the number as a string. 11 | 12 | ## Examples 13 | 14 | - 28 is divisible by 7, but not 3 or 5, so the result would be `"Plong"`. 15 | - 30 is divisible by 3 and 5, but not 7, so the result would be `"PlingPlang"`. 16 | - 34 is not divisible by 3, 5, or 7, so the result would be `"34"`. 17 | 18 | ~~~~exercism/note 19 | A common way to test if one number is evenly divisible by another is to compare the [remainder][remainder] or [modulus][modulo] to zero. 20 | Most languages provide operators or functions for one (or both) of these. 21 | 22 | [remainder]: https://exercism.org/docs/programming/operators/remainder 23 | [modulo]: https://en.wikipedia.org/wiki/Modulo_operation 24 | ~~~~ 25 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Raindrops is a slightly more complex version of the FizzBuzz challenge, a classic interview question. 4 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "hiljusti" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "raindrops.factor" 8 | ], 9 | "test": [ 10 | "raindrops-tests.factor" 11 | ], 12 | "example": [ 13 | ".meta/raindrops-example.factor" 14 | ] 15 | }, 16 | "blurb": "Convert a number to a string, the content of which depends on the number's factors.", 17 | "source": "A variation on FizzBuzz, a famous technical interview question that is intended to weed out potential candidates. That question is itself derived from Fizz Buzz, a popular children's game for teaching division.", 18 | "source_url": "https://en.wikipedia.org/wiki/Fizz_buzz" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/.meta/raindrops-example.factor: -------------------------------------------------------------------------------- 1 | USING: combinators kernel math.functions math.parser sequences ; 2 | IN: raindrops 3 | 4 | : raindrops ( n -- str ) 5 | dup 6 | [ 3 divisor? "Pling" and ] 7 | [ 5 divisor? "Plang" and ] 8 | [ 7 divisor? "Plong" and ] tri 9 | { } 3sequence sift 10 | [ number>string ] [ concat swap drop ] if-empty ; 11 | 12 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Regular comments will be removed when this 2 | # file is regenerated. Regenerating will not touch any manually added keys, 3 | # so comments can be added in a "comment" key. 4 | 5 | [1575d549-e502-46d4-a8e1-6b7bec6123d8] 6 | description = "the sound for 1 is 1" 7 | 8 | [1f51a9f9-4895-4539-b182-d7b0a5ab2913] 9 | description = "the sound for 3 is Pling" 10 | 11 | [2d9bfae5-2b21-4bcd-9629-c8c0e388f3e0] 12 | description = "the sound for 5 is Plang" 13 | 14 | [d7e60daa-32ef-4c23-b688-2abff46c4806] 15 | description = "the sound for 7 is Plong" 16 | 17 | [6bb4947b-a724-430c-923f-f0dc3d62e56a] 18 | description = "the sound for 6 is Pling as it has a factor 3" 19 | 20 | [ce51e0e8-d9d4-446d-9949-96eac4458c2d] 21 | description = "2 to the power 3 does not make a raindrop sound as 3 is the exponent not the base" 22 | 23 | [0dd66175-e3e2-47fc-8750-d01739856671] 24 | description = "the sound for 9 is Pling as it has a factor 3" 25 | 26 | [022c44d3-2182-4471-95d7-c575af225c96] 27 | description = "the sound for 10 is Plang as it has a factor 5" 28 | 29 | [37ab74db-fed3-40ff-b7b9-04acdfea8edf] 30 | description = "the sound for 14 is Plong as it has a factor of 7" 31 | 32 | [31f92999-6afb-40ee-9aa4-6d15e3334d0f] 33 | description = "the sound for 15 is PlingPlang as it has factors 3 and 5" 34 | 35 | [ff9bb95d-6361-4602-be2c-653fe5239b54] 36 | description = "the sound for 21 is PlingPlong as it has factors 3 and 7" 37 | 38 | [d2e75317-b72e-40ab-8a64-6734a21dece1] 39 | description = "the sound for 25 is Plang as it has a factor 5" 40 | 41 | [a09c4c58-c662-4e32-97fe-f1501ef7125c] 42 | description = "the sound for 27 is Pling as it has a factor 3" 43 | 44 | [bdf061de-8564-4899-a843-14b48b722789] 45 | description = "the sound for 35 is PlangPlong as it has factors 5 and 7" 46 | 47 | [c4680bee-69ba-439d-99b5-70c5fd1a7a83] 48 | description = "the sound for 49 is Plong as it has a factor 7" 49 | 50 | [17f2bc9a-b65a-4d23-8ccd-266e8c271444] 51 | description = "the sound for 52 is 52" 52 | 53 | [e46677ed-ff1a-419f-a740-5c713d2830e4] 54 | description = "the sound for 105 is PlingPlangPlong as it has factors 3, 5 and 7" 55 | 56 | [13c6837a-0fcd-4b86-a0eb-20572f7deb0b] 57 | description = "the sound for 3125 is Plang as it has a factor 5" 58 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/raindrops-tests.factor: -------------------------------------------------------------------------------- 1 | USING: io kernel raindrops tools.test ; 2 | IN: raindrops.test 3 | 4 | "Raindrops" print 5 | 6 | "the sound for 1 is 1" print 7 | { "1" } [ 1 raindrops ] unit-test 8 | 9 | "the sound for 3 is Pling" print 10 | { "Pling" } [ 3 raindrops ] unit-test 11 | 12 | "the sound for 5 is Plang" print 13 | { "Plang" } [ 5 raindrops ] unit-test 14 | 15 | "the sound for 7 is Plong" print 16 | { "Plong" } [ 7 raindrops ] unit-test 17 | 18 | "the sound for 6 is Pling as it has a factor 3" print 19 | { "Pling" } [ 6 raindrops ] unit-test 20 | 21 | "2 to the power 3 does not make a raindrop sound as 3 is the exponent not the base" print 22 | { "8" } [ 8 raindrops ] unit-test 23 | 24 | "the sound for 9 is Pling as it has a factor 3" print 25 | { "Pling" } [ 9 raindrops ] unit-test 26 | 27 | "the sound for 10 is Plang as it has a factor 5" print 28 | { "Plang" } [ 10 raindrops ] unit-test 29 | 30 | "the sound for 14 is Plong as it has a factor of 7" print 31 | { "Plong" } [ 14 raindrops ] unit-test 32 | 33 | "the sound for 15 is PlingPlang as it has factors 3 and 5" print 34 | { "PlingPlang" } [ 15 raindrops ] unit-test 35 | 36 | "the sound for 21 is PlingPlong as it has factors 3 and 7" print 37 | { "PlingPlong" } [ 21 raindrops ] unit-test 38 | 39 | "the sound for 25 is Plang as it has a factor 5" print 40 | { "Plang" } [ 25 raindrops ] unit-test 41 | 42 | "the sound for 27 is Pling as it has a factor 3" print 43 | { "Pling" } [ 27 raindrops ] unit-test 44 | 45 | "the sound for 35 is PlangPlong as it has factors 5 and 7" print 46 | { "PlangPlong" } [ 35 raindrops ] unit-test 47 | 48 | "the sound for 49 is Plong as it has a factor 7" print 49 | { "Plong" } [ 49 raindrops ] unit-test 50 | 51 | "the sound for 52 is 52" print 52 | { "52" } [ 52 raindrops ] unit-test 53 | 54 | "the sound for 105 is PlingPlangPlong as it has factors 3, 5 and 7" print 55 | { "PlingPlangPlong" } [ 105 raindrops ] unit-test 56 | 57 | "the sound for 3125 is Plang as it has a factor 5" print 58 | { "Plang" } [ 3125 raindrops ] unit-test 59 | 60 | -------------------------------------------------------------------------------- /exercises/practice/raindrops/raindrops.factor: -------------------------------------------------------------------------------- 1 | USING: kernel ; 2 | IN: raindrops 3 | 4 | : raindrops ( n -- str ) 5 | "unimplemented" throw ; 6 | 7 | -------------------------------------------------------------------------------- /exercises/practice/resistor-color/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | If you want to build something using a Raspberry Pi, you'll probably use _resistors_. 4 | For this exercise, you need to know two things about them: 5 | 6 | - Each resistor has a resistance value. 7 | - Resistors are small - so small in fact that if you printed the resistance value on them, it would be hard to read. 8 | 9 | To get around this problem, manufacturers print color-coded bands onto the resistors to denote their resistance values. 10 | Each band has a position and a numeric value. 11 | 12 | The first 2 bands of a resistor have a simple encoding scheme: each color maps to a single number. 13 | 14 | In this exercise you are going to create a helpful program so that you don't have to remember the values of the bands. 15 | 16 | These colors are encoded as follows: 17 | 18 | - black: 0 19 | - brown: 1 20 | - red: 2 21 | - orange: 3 22 | - yellow: 4 23 | - green: 5 24 | - blue: 6 25 | - violet: 7 26 | - grey: 8 27 | - white: 9 28 | 29 | The goal of this exercise is to create a way: 30 | 31 | - to look up the numerical value associated with a particular color band 32 | - to list the different band colors 33 | 34 | Mnemonics map the colors to the numbers, that, when stored as an array, happen to map to their index in the array: 35 | Better Be Right Or Your Great Big Values Go Wrong. 36 | 37 | More information on the color encoding of resistors can be found in the [Electronic color code Wikipedia article][e-color-code]. 38 | 39 | [e-color-code]: https://en.wikipedia.org/wiki/Electronic_color_code 40 | -------------------------------------------------------------------------------- /exercises/practice/resistor-color/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "hiljusti" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "resistor-color.factor" 8 | ], 9 | "test": [ 10 | "resistor-color-tests.factor" 11 | ], 12 | "example": [ 13 | ".meta/resistor-color-example.factor" 14 | ] 15 | }, 16 | "blurb": "Convert a resistor band's color to its numeric representation.", 17 | "source": "Maud de Vries, Erik Schierboom", 18 | "source_url": "https://github.com/exercism/problem-specifications/issues/1458" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/resistor-color/.meta/resistor-color-example.factor: -------------------------------------------------------------------------------- 1 | USING: kernel sequences ; 2 | IN: resistor-color 3 | 4 | CONSTANT: colors { "black" "brown" "red" "orange" "yellow" "green" "blue" "violet" "grey" "white" } 5 | 6 | : color>code ( x -- str ) 7 | colors index ; 8 | 9 | -------------------------------------------------------------------------------- /exercises/practice/resistor-color/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Regular comments will be removed when this 2 | # file is regenerated. Regenerating will not touch any manually added keys, 3 | # so comments can be added in a "comment" key. 4 | 5 | [49eb31c5-10a8-4180-9f7f-fea632ab87ef] 6 | description = "Black" 7 | 8 | [0a4df94b-92da-4579-a907-65040ce0b3fc] 9 | description = "White" 10 | 11 | [5f81608d-f36f-4190-8084-f45116b6f380] 12 | description = "Orange" 13 | 14 | [581d68fa-f968-4be2-9f9d-880f2fb73cf7] 15 | description = "Colors" 16 | -------------------------------------------------------------------------------- /exercises/practice/resistor-color/resistor-color-tests.factor: -------------------------------------------------------------------------------- 1 | USING: io kernel resistor-color tools.test ; 2 | IN: resistor-color.tests 3 | 4 | "Resistor Color:" print 5 | 6 | "Color codes" print 7 | "Black" print 8 | { 0 } [ "black" color>code ] unit-test 9 | 10 | "White" print 11 | { 9 } [ "white" color>code ] unit-test 12 | 13 | "Orange" print 14 | { 3 } [ "orange" color>code ] unit-test 15 | 16 | "Colors" print 17 | { { "black" "brown" "red" "orange" "yellow" "green" "blue" "violet" "grey" "white" } } 18 | [ colors ] unit-test 19 | 20 | -------------------------------------------------------------------------------- /exercises/practice/resistor-color/resistor-color.factor: -------------------------------------------------------------------------------- 1 | USING: kernel ; 2 | IN: resistor-color 3 | 4 | : colors ( -- seq ) 5 | "unimplemented" throw ; 6 | 7 | : color>code ( x -- str ) 8 | "unimplemented" throw ; 9 | 10 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Your task is to reverse a given string. 4 | 5 | Some examples: 6 | 7 | - Turn `"stressed"` into `"desserts"`. 8 | - Turn `"strops"` into `"sports"`. 9 | - Turn `"racecar"` into `"racecar"`. 10 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Reversing strings (reading them from right to left, rather than from left to right) is a surprisingly common task in programming. 4 | 5 | For example, in bioinformatics, reversing the sequence of DNA or RNA strings is often important for various analyses, such as finding complementary strands or identifying palindromic sequences that have biological significance. 6 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "hiljusti" 4 | ], 5 | "files": { 6 | "solution": [ 7 | "reverse-string.factor" 8 | ], 9 | "test": [ 10 | "reverse-string-tests.factor" 11 | ], 12 | "example": [ 13 | ".meta/reverse-string-example.factor" 14 | ] 15 | }, 16 | "blurb": "Reverse a given string.", 17 | "source": "Introductory challenge to reverse an input string", 18 | "source_url": "https://medium.freecodecamp.org/how-to-reverse-a-string-in-javascript-in-3-different-ways-75e4763c68cb" 19 | } 20 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/.meta/reverse-string-example.factor: -------------------------------------------------------------------------------- 1 | USING: kernel sequences ; 2 | IN: reverse-string 3 | 4 | : reverse-string ( str -- newstr ) 5 | dup empty? [ "" [ prefix ] reduce ] unless ; 6 | 7 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Regular comments will be removed when this 2 | # file is regenerated. Regenerating will not touch any manually added keys, 3 | # so comments can be added in a "comment" key. 4 | 5 | [c3b7d806-dced-49ee-8543-933fd1719b1c] 6 | description = "an empty string" 7 | 8 | [01ebf55b-bebb-414e-9dec-06f7bb0bee3c] 9 | description = "a word" 10 | 11 | [0f7c07e4-efd1-4aaa-a07a-90b49ce0b746] 12 | description = "a capitalized word" 13 | 14 | [71854b9c-f200-4469-9f5c-1e8e5eff5614] 15 | description = "a sentence with punctuation" 16 | 17 | [1f8ed2f3-56f3-459b-8f3e-6d8d654a1f6c] 18 | description = "a palindrome" 19 | 20 | [b9e7dec1-c6df-40bd-9fa3-cd7ded010c4c] 21 | description = "an even-sized word" 22 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/reverse-string-tests.factor: -------------------------------------------------------------------------------- 1 | USING: reverse-string io kernel tools.test ; 2 | IN: reverse-string.tests 3 | 4 | "Reverse string:" print 5 | 6 | "an empty string" print 7 | { "" } [ "" reverse-string ] unit-test 8 | 9 | "a word" print 10 | { "tobor" } [ "robot" reverse-string ] unit-test 11 | 12 | "a capitalized word" print 13 | { "nemaR" } [ "Ramen" reverse-string ] unit-test 14 | 15 | "a sentence with punctuation" print 16 | { "!yrgnuh m'I" } [ "I'm hungry!" reverse-string ] unit-test 17 | 18 | "a palindrome" print 19 | { "racecar" } [ "racecar" reverse-string ] unit-test 20 | 21 | "an even-sized word" print 22 | { "reward" } [ "drawer" reverse-string ] unit-test 23 | 24 | -------------------------------------------------------------------------------- /exercises/practice/reverse-string/reverse-string.factor: -------------------------------------------------------------------------------- 1 | USING: kernel ; 2 | IN: reverse-string 3 | 4 | : reverse ( str -- newstr ) 5 | "unimplemented" throw ; 6 | 7 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/.docs/instructions.md: -------------------------------------------------------------------------------- 1 | # Instructions 2 | 3 | Your task is to determine what you will say as you give away the extra cookie. 4 | 5 | If you know the person's name (e.g. if they're named Do-yun), then you will say: 6 | 7 | ```text 8 | One for Do-yun, one for me. 9 | ``` 10 | 11 | If you don't know the person's name, you will say _you_ instead. 12 | 13 | ```text 14 | One for you, one for me. 15 | ``` 16 | 17 | Here are some examples: 18 | 19 | | Name | Dialogue | 20 | | :----- | :-------------------------- | 21 | | Alice | One for Alice, one for me. | 22 | | Bohdan | One for Bohdan, one for me. | 23 | | | One for you, one for me. | 24 | | Zaphod | One for Zaphod, one for me. | 25 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/.docs/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | In some English accents, when you say "two for" quickly, it sounds like "two fer". 4 | Two-for-one is a way of saying that if you buy one, you also get one for free. 5 | So the phrase "two-fer" often implies a two-for-one offer. 6 | 7 | Imagine a bakery that has a holiday offer where you can buy two cookies for the price of one ("two-fer one!"). 8 | You take the offer and (very generously) decide to give the extra cookie to someone else in the queue. 9 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/.meta/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "authors": [ 3 | "catb0t" 4 | ], 5 | "contributors": [ 6 | "sjwarner-bp" 7 | ], 8 | "files": { 9 | "solution": [ 10 | "two-fer.factor" 11 | ], 12 | "test": [ 13 | "two-fer-tests.factor" 14 | ], 15 | "example": [ 16 | ".meta/two-fer-example.factor" 17 | ] 18 | }, 19 | "blurb": "Create a sentence of the form \"One for X, one for me.\".", 20 | "source_url": "https://github.com/exercism/problem-specifications/issues/757" 21 | } 22 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/.meta/tests.toml: -------------------------------------------------------------------------------- 1 | # This is an auto-generated file. Regular comments will be removed when this 2 | # file is regenerated. Regenerating will not touch any manually added keys, 3 | # so comments can be added in a "comment" key. 4 | 5 | [1cf3e15a-a3d7-4a87-aeb3-ba1b43bc8dce] 6 | description = "no name given" 7 | 8 | [b4c6dbb8-b4fb-42c2-bafd-10785abe7709] 9 | description = "a name given" 10 | 11 | [3549048d-1a6e-4653-9a79-b0bda163e8d5] 12 | description = "another name given" 13 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/.meta/two-fer-example.factor: -------------------------------------------------------------------------------- 1 | USING: formatting kernel sequences ; 2 | IN: two-fer 3 | 4 | : 2-for-1 ( name -- string ) 5 | dup empty? [ drop "you" ] when 6 | "One for %s, one for me." sprintf ; 7 | -------------------------------------------------------------------------------- /exercises/practice/two-fer/two-fer-tests.factor: -------------------------------------------------------------------------------- 1 | USING: hello-world tools.test ; 2 | IN: two-fer.tests 3 | 4 | ! There are no variadic functions in Factor, due to the nature of the stack. 5 | ! Usually, if you need var args, use an array. Here, we'll just use an empty string. 6 | { "One for you, one for me." } [ "" 2-for-1 ] unit-test 7 | { "One for Alice, one for me." } [ "Alice" 2-for-1 ] unit-test 8 | { "One for Bob, one for me." } [ "Bob" 2-for-1 ] unit-test -------------------------------------------------------------------------------- /exercises/practice/two-fer/two-fer.factor: -------------------------------------------------------------------------------- 1 | USING: kernel ; 2 | IN: two-fer 3 | 4 | : 2-for-1 ( name -- str ) 5 | "unimplemented" throw ; 6 | 7 | -------------------------------------------------------------------------------- /exercises/shared/.docs/help.md: -------------------------------------------------------------------------------- 1 | # {{ .Spec.Name }} 2 | 3 | {{ .Spec.Description -}} 4 | {{- with .Hints }} 5 | {{ . }} 6 | {{ end }} 7 | ## Testing Exercises 8 | 9 | If you followed the [installation instructions](http://exercism.io/languages/factor/installation), just run the provided test suite against your implementation with `"exercise-name" test`. 10 | 11 | ## Submitting Exercises 12 | 13 | Note that, when trying to submit an exercise, make sure the solution is in the `exercism/factor/exercise-name` directory. 14 | 15 | For example, if you're submitting `bob.factor` for the Bob exercise, the submit command would be something like `exercism submit exercism/factor/bob/bob.factor`. 16 | 17 | For more detailed information about running tests, code style and linting, 18 | please see the [help page](http://exercism.io/languages/factor).{{ with .Spec.Credits }} 19 | ## Source 20 | 21 | {{ . }} 22 | {{ end }} 23 | ## Submitting Incomplete Solutions 24 | It's possible to submit an incomplete solution so you can see how others have completed the exercise. 25 | -------------------------------------------------------------------------------- /exercises/shared/.docs/tests.md: -------------------------------------------------------------------------------- 1 | # {{ .Spec.Name }} 2 | 3 | {{ .Spec.Description -}} 4 | {{- with .Hints }} 5 | {{ . }} 6 | {{ end }} 7 | ## Testing Exercises 8 | 9 | If you followed the [installation instructions](http://exercism.io/languages/factor/installation), just run the provided test suite against your implementation with `"exercise-name" test`. 10 | 11 | ## Submitting Exercises 12 | 13 | Note that, when trying to submit an exercise, make sure the solution is in the `exercism/factor/exercise-name` directory. 14 | 15 | For example, if you're submitting `bob.factor` for the Bob exercise, the submit command would be something like `exercism submit exercism/factor/bob/bob.factor`. 16 | 17 | For more detailed information about running tests, code style and linting, 18 | please see the [help page](http://exercism.io/languages/factor).{{ with .Spec.Credits }} 19 | ## Source 20 | 21 | {{ . }} 22 | {{ end }} 23 | ## Submitting Incomplete Solutions 24 | It's possible to submit an incomplete solution so you can see how others have completed the exercise. 25 | -------------------------------------------------------------------------------- /reference/implementing-a-concept-exercise.md: -------------------------------------------------------------------------------- 1 | # How to implement an Factor concept exercise 2 | 3 | TODO: describe how to implement a concept exercise for the Factor track. For inspiration, check out the [C# version of this file][csharp-implementing]. 4 | 5 | [csharp-implementing]: https://github.com/exercism/v3/blob/main/csharp/reference/implementing-a-concept-exercise.md 6 | --------------------------------------------------------------------------------