Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ This is enforced by the "Learning checks" workflow.
bin/add-practice-exercise <exercise-slug>
```

- An exercise should include a `.meta/tests.toml` file if, and only if, the exercise has a `canonical-data.json` in [problem-specifications](https://github.com/exercism/problem-specifications/tree/main/exercises).

#### **Do you want to report a bug?**

- **Ensure the bug was not already reported** by searching the [forum](https://forum.exercism.org/c/programming/factor).
Expand Down
4 changes: 2 additions & 2 deletions bin/extract-known-words
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ x y z w m k i j p q r s u v n
seq seq1 seq2 quot quot1 quot2 quot3 quot: quot:: assoc
key value old elt elt1 elt2 bool string str
old-x new-x 3x 2x n+1 n+10% n+1% length+kerf length+10%
days new-days new-days-or-f symbol direction direction'
new-days new-days-or-f symbol direction direction'
amount rate years seconds planet period arr sortedstr count/f
p' dx dy sx sy points transformed
price prices item items base-speed
Expand All @@ -42,7 +42,7 @@ recipe-step depth >>slot slot>> change-slot
test
n*x n*y n+x n+y newseq newkey newvalue sortedseq headseq tailseq padded
inputs outputs difference label
hour minute hours minutes word words
word words
phrase\'
""".split())

Expand Down
6 changes: 6 additions & 0 deletions concepts/calendar/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"authors": [
"keiravillekode"
],
"blurb": "The calendar vocabulary: <date> and >date< build and split timestamps, day-of-week, leap-year?, and days-in-month query them, and durations like days shift them with time+."
}
60 changes: 60 additions & 0 deletions concepts/calendar/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# About

Factor's [`calendar`][calendar] vocabulary is built around two tuples:

- `timestamp` — a point in time (`year`, `month`, `day`, `hour`,
`minute`, `second`, and a GMT offset).
- `duration` — a span of time (the same fields, used as amounts).

## Timestamps

`<date>` builds a midnight timestamp; `>date<` splits one apart:

```
<date> ( year month day -- timestamp )
>date< ( timestamp -- year month day )
```

```factor
USING: calendar ;

2024 7 14 <date> >date< . ! => 14 (2024 and 7 below it)
```

Common queries:

```factor
USING: calendar calendar.english sequences ;

2024 1 8 <date> day-of-week . ! => 1 (0 = Sunday .. 6 = Saturday)
2024 1 8 <date> day-of-week day-names nth . ! => "Monday"
2024 leap-year? . ! => t
2024 2 1 <date> days-in-month . ! => 29
```

`day-names` (and `month-names`) live in
[`calendar.english`][english].

## Durations and arithmetic

Words like `days`, `weeks`, `hours`, and `minutes` build a `duration`,
and `time+` / `time-` shift a timestamp by one:

```
days ( x -- duration )
time+ ( timestamp duration -- timestamp )
```

```factor
2024 2 28 <date> 1 days time+ >date< . ! => 29 (2024-02-29)
```

Arithmetic carries across month and year boundaries, and two
timestamps naming the same instant compare equal with `=`.

Beyond these, `calendar` offers times of day (`set-time`, `+hour`),
time-zone conversions (`>gmt`, `>local-time`), the current time
(`now`), and — via `calendar.format` — parsing and formatting.

[calendar]: https://docs.factorcode.org/content/vocab-calendar.html
[english]: https://docs.factorcode.org/content/vocab-calendar.english.html
29 changes: 29 additions & 0 deletions concepts/calendar/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Introduction

Factor's [`calendar`][calendar] vocabulary represents a point in time as
a `timestamp` and a span of time as a `duration`.

```factor
USING: calendar ;

2024 7 14 <date> . ! a timestamp at midnight on 2024-07-14
2024 7 14 <date> >date< . ! => 14 (2024 and 7 below it)
```

`day-of-week` returns `0` for Sunday through `6` for Saturday;
`leap-year?` and `days-in-month` answer the usual calendar questions:

```factor
2024 1 8 <date> day-of-week . ! => 1
2024 leap-year? . ! => t
2024 2 1 <date> days-in-month . ! => 29
```

Durations such as `days` and `weeks` shift a timestamp with `time+`:

```factor
2024 2 28 <date> 1 days time+ >date< .
! => 29 (2024-02-29)
```

[calendar]: https://docs.factorcode.org/content/vocab-calendar.html
10 changes: 10 additions & 0 deletions concepts/calendar/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"url": "https://docs.factorcode.org/content/vocab-calendar.html",
"description": "calendar vocabulary reference"
},
{
"url": "https://docs.factorcode.org/content/vocab-calendar.english.html",
"description": "calendar.english — day and month names"
}
]
6 changes: 6 additions & 0 deletions concepts/randomness/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"authors": [
"keiravillekode"
],
"blurb": "The random vocabulary: random picks values and elements, randomize and sample reorder sequences, and with-random plus <mersenne-twister> make results reproducible."
}
58 changes: 58 additions & 0 deletions concepts/randomness/about.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# About

Factor concentrates randomness in the [`random`][random] vocabulary
around a single generic word:

```
random ( obj -- elt )
```

It dispatches on its argument:

- an **integer** `n` yields a random integer in `[0, n)`;
- a **sequence** yields a random element;
- assocs, hash-sets, and `uniform-distribution` tuples are also
supported.

Two sequence helpers build on it:

```factor
USING: random ;

{ 1 2 3 4 5 } randomize . ! shuffle in place (Fisher–Yates)
{ 1 2 3 4 5 } 3 sample . ! 3 distinct elements; error if too many
```

`randomize` mutates and returns the sequence, so `clone` first if you
need to keep the original order.

## Where the randomness comes from

`random` reads the generator held in the `random-generator` dynamic
variable. By default that's a Mersenne Twister seeded from the system
clock, so every process differs. You can install a different generator
for the duration of a quotation:

```
<mersenne-twister> ( seed -- rnd )
with-random ( rnd quot -- )
```

```factor
USING: random random.mersenne-twister ;

42 <mersenne-twister> [ { 1 2 3 } randomize ] with-random .
! => the same ordering on every run
```

Because `with-random` simply binds `random-generator` for the dynamic
extent of the quotation, a word that wraps it should be marked
`inline` so the quotation can leave its result on the stack for the
caller.

Beyond these, `random` offers `random-bits`, `random-unit`,
`uniform-random`, and `normal-random` for other distributions, plus
`system-random-generator` and `secure-random-generator` for
non-reproducible and cryptographic needs.

[random]: https://docs.factorcode.org/content/vocab-random.html
32 changes: 32 additions & 0 deletions concepts/randomness/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Introduction

Factor's [`random`][random] vocabulary provides one generic word,
`random`, that adapts to its argument, plus helpers for shuffling and
sampling sequences.

```factor
USING: random ;

6 random . ! a value from 0..5
{ "rock" "paper" "scissors" } random . ! a random element
{ 1 2 3 4 5 } randomize . ! the same cards, reordered
{ 1 2 3 4 5 } 2 sample . ! two distinct elements
```

`random` of an integer `n` returns a value in `[0, n)`; of a sequence
it returns a random element. `randomize` shuffles in place, and
`sample` draws distinct elements.

By default these draw from a global generator seeded from the system
clock. To make outcomes reproducible, install a seeded generator with
`<mersenne-twister>` (from [`random.mersenne-twister`][mt]) and
`with-random`:

```factor
USING: random random.mersenne-twister ;

42 <mersenne-twister> [ 6 random ] with-random . ! same value every run
```

[random]: https://docs.factorcode.org/content/vocab-random.html
[mt]: https://docs.factorcode.org/content/vocab-random.mersenne-twister.html
10 changes: 10 additions & 0 deletions concepts/randomness/links.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"url": "https://docs.factorcode.org/content/vocab-random.html",
"description": "random vocabulary reference"
},
{
"url": "https://docs.factorcode.org/content/vocab-random.mersenne-twister.html",
"description": "random.mersenne-twister — seeded, reproducible generators"
}
]
90 changes: 90 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,34 @@
],
"status": "beta"
},
{
"slug": "boardwalk-games",
"name": "Boardwalk Games",
"uuid": "2ab5123d-7837-4dad-a7a3-3bca1bfc15f2",
"concepts": [
"randomness"
],
"prerequisites": [
"numbers",
"sequences",
"quotations",
"combinators"
],
"status": "beta"
},
{
"slug": "ferry-schedule",
"name": "Ferry Schedule",
"uuid": "4e03dc97-8707-41d5-8e68-ca269d5f17be",
"concepts": [
"calendar"
],
"prerequisites": [
"numbers",
"sequences"
],
"status": "beta"
},
{
"slug": "bering-bearings",
"name": "Bering Bearings",
Expand Down Expand Up @@ -983,6 +1011,18 @@
],
"difficulty": 3
},
{
"slug": "robot-name",
"name": "Robot Name",
"uuid": "1f3cded8-c357-448d-9640-63e8e6ea8efe",
"practices": [],
"prerequisites": [
"dynamic-variables",
"randomness",
"hash-sets"
],
"difficulty": 3
},
{
"slug": "rotational-cipher",
"name": "Rotational Cipher",
Expand Down Expand Up @@ -1094,6 +1134,19 @@
],
"difficulty": 4
},
{
"slug": "dnd-character",
"name": "D&D Character",
"uuid": "7229dc0f-df0c-4c3d-9aec-810ab2474d6f",
"practices": [],
"prerequisites": [
"randomness",
"tuples",
"locals",
"higher-order-sequences"
],
"difficulty": 4
},
{
"slug": "flatten-array",
"name": "Flatten Array",
Expand Down Expand Up @@ -1158,6 +1211,19 @@
],
"difficulty": 4
},
{
"slug": "meetup",
"name": "Meetup",
"uuid": "faf43296-da2b-4953-ab84-1381e52c600b",
"practices": [],
"prerequisites": [
"calendar",
"case",
"locals",
"arrays"
],
"difficulty": 4
},
{
"slug": "pascals-triangle",
"name": "Pascal's Triangle",
Expand Down Expand Up @@ -1563,6 +1629,20 @@
],
"difficulty": 6
},
{
"slug": "food-chain",
"name": "Food Chain",
"uuid": "7cd07547-7e56-416f-ad19-b2086ff835c1",
"practices": [],
"prerequisites": [
"macros",
"locals",
"higher-order-sequences",
"arrays",
"tabulation"
],
"difficulty": 6
},
{
"slug": "ocr-numbers",
"name": "OCR Numbers",
Expand Down Expand Up @@ -1947,6 +2027,16 @@
"slug": "dynamic-variables",
"name": "Dynamic Variables"
},
{
"uuid": "38b7be75-62ec-4a24-8bd0-d2714c4c8a3c",
"slug": "randomness",
"name": "Randomness"
},
{
"uuid": "cd393574-269e-494e-b515-bb4f0fb677ea",
"slug": "calendar",
"name": "Calendar"
},
{
"uuid": "e9c2a584-0c03-467f-9781-38754f06dd1a",
"slug": "generics",
Expand Down
Loading