Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ bin/configlet
.psc-ide-port

.merlin
_opam
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,14 @@
"practices": [],
"prerequisites": [],
"difficulty": 2
},
{
"slug": "collatz-conjecture",
"name": "Collatz Conjecture",
"uuid": "eedc9471-326b-4498-b763-5b1c8eedca88",
"practices": [],
"prerequisites": [],
"difficulty": 3
}
]
},
Expand Down
6 changes: 0 additions & 6 deletions exercises/practice/anagram/test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ let tests = [
"no matches" >::
ae [] (anagrams "diaper" ["hello"; "world"; "zombies"; "pants"]);
"detects two anagrams" >::
ae ["stream"; "maters"] (anagrams "master" ["stream"; "pigeon"; "maters"]);
"detects two anagrams" >::
ae ["lemons"; "melons"] (anagrams "solemn" ["lemons"; "cherry"; "melons"]);
"does not detect anagram subsets" >::
ae [] (anagrams "good" ["dog"; "goody"]);
Expand All @@ -33,17 +31,13 @@ let tests = [
ae [] (anagrams "go" ["go Go GO"]);
"anagrams must use all letters exactly once" >::
ae [] (anagrams "tapper" ["patter"]);
"words are not anagrams of themselves (case-insensitive)" >::
ae [] (anagrams "BANANA" ["BANANA"; "Banana"; "banana"]);
"words are not anagrams of themselves" >::
ae [] (anagrams "BANANA" ["BANANA"]);
"words are not anagrams of themselves even if letter case is partially different" >::
ae [] (anagrams "BANANA" ["Banana"]);
"words are not anagrams of themselves even if letter case is completely different" >::
ae [] (anagrams "BANANA" ["banana"]);
"words other than themselves can be anagrams" >::
ae ["Silent"] (anagrams "LISTEN" ["Listen"; "Silent"; "LISTEN"]);
"words other than themselves can be anagrams" >::
ae ["Silent"] (anagrams "LISTEN" ["LISTEN"; "Silent"]);
]

Expand Down
3 changes: 3 additions & 0 deletions exercises/practice/collatz-conjecture/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Instructions

Given a positive integer, return the number of steps it takes to reach 1 according to the rules of the Collatz Conjecture.
28 changes: 28 additions & 0 deletions exercises/practice/collatz-conjecture/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Introduction

One evening, you stumbled upon an old notebook filled with cryptic scribbles, as though someone had been obsessively chasing an idea.
On one page, a single question stood out: **Can every number find its way to 1?**
It was tied to something called the **Collatz Conjecture**, a puzzle that has baffled thinkers for decades.

The rules were deceptively simple.
Pick any positive integer.

- If it's even, divide it by 2.
- If it's odd, multiply it by 3 and add 1.

Then, repeat these steps with the result, continuing indefinitely.

Curious, you picked number 12 to test and began the journey:

12 ➜ 6 ➜ 3 ➜ 10 ➜ 5 ➜ 16 ➜ 8 ➜ 4 ➜ 2 ➜ 1

Counting from the second number (6), it took 9 steps to reach 1, and each time the rules repeated, the number kept changing.
At first, the sequence seemed unpredictable — jumping up, down, and all over.
Yet, the conjecture claims that no matter the starting number, we'll always end at 1.

It was fascinating, but also puzzling.
Why does this always seem to work?
Could there be a number where the process breaks down, looping forever or escaping into infinity?
The notebook suggested solving this could reveal something profound — and with it, fame, [fortune][collatz-prize], and a place in history awaits whoever could unlock its secrets.

[collatz-prize]: https://mathprize.net/posts/collatz-conjecture/
22 changes: 22 additions & 0 deletions exercises/practice/collatz-conjecture/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"authors": [
"therealowenrees"
],
"files": {
"solution": [
"collatz_conjecture.ml"
],
"test": [
"test.ml"
],
"example": [
".meta/example.ml"
],
"editor": [
"collatz_conjecture.mli"
]
},
"blurb": "Calculate the number of steps to reach 1 using the Collatz conjecture.",
"source": "Wikipedia",
"source_url": "https://en.wikipedia.org/wiki/Collatz_conjecture"
}
13 changes: 13 additions & 0 deletions exercises/practice/collatz-conjecture/.meta/example.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
let collatz_conjecture n =
let rec aux n count =
match n with
| 1 -> Ok count
| _ ->
(match n mod 2 with
| 0 -> aux (n / 2) (count + 1)
| _ -> aux (n * 3 + 1) (count + 1)
)
in
if n < 1 then Error "Only positive integers are allowed"
else aux n 0

38 changes: 38 additions & 0 deletions exercises/practice/collatz-conjecture/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[540a3d51-e7a6-47a5-92a3-4ad1838f0bfd]
description = "zero steps for one"

[3d76a0a6-ea84-444a-821a-f7857c2c1859]
description = "divide if even"

[754dea81-123c-429e-b8bc-db20b05a87b9]
description = "even and odd steps"

[ecfd0210-6f85-44f6-8280-f65534892ff6]
description = "large number of even and odd steps"

[7d4750e6-def9-4b86-aec7-9f7eb44f95a3]
description = "zero is an error"
include = false

[2187673d-77d6-4543-975e-66df6c50e2da]
description = "zero is an error"
reimplements = "7d4750e6-def9-4b86-aec7-9f7eb44f95a3"

[c6c795bf-a288-45e9-86a1-841359ad426d]
description = "negative value is an error"
include = false

[ec11f479-56bc-47fd-a434-bcd7a31a7a2e]
description = "negative value is an error"
reimplements = "c6c795bf-a288-45e9-86a1-841359ad426d"
9 changes: 9 additions & 0 deletions exercises/practice/collatz-conjecture/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
default: clean test

test:
dune runtest

clean:
dune clean

.PHONY: clean
2 changes: 2 additions & 0 deletions exercises/practice/collatz-conjecture/collatz_conjecture.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
let collatz_conjecture _ =
failwith "'collatz_conjecture' is missing"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
val collatz_conjecture : int -> (int, string) result
20 changes: 20 additions & 0 deletions exercises/practice/collatz-conjecture/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
(executable
(name test)
(libraries base ounit2))

(alias
(name runtest)
(deps
(:x test.exe))
(action
(run %{x})))

(alias
(name buildtest)
(deps
(:x test.exe)))

(env
(dev
(flags
(:standard -warn-error -A))))
1 change: 1 addition & 0 deletions exercises/practice/collatz-conjecture/dune-project
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(lang dune 1.1)
26 changes: 26 additions & 0 deletions exercises/practice/collatz-conjecture/test.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
open OUnit2
open Collatz_conjecture

let option_printer = function
| Error m -> Printf.sprintf "Error \"%s\"" m
| Ok n -> Printf.sprintf "Ok %d" n

let ae exp got _test_ctxt = assert_equal ~printer:option_printer exp got

let tests = [
"zero steps for one" >::
ae (Ok 0) (collatz_conjecture (1));
"divide if even" >::
ae (Ok 4) (collatz_conjecture (16));
"even and odd steps" >::
ae (Ok 9) (collatz_conjecture (12));
"large number of even and odd steps" >::
ae (Ok 152) (collatz_conjecture (1000000));
"zero is an error" >::
ae (Error "Only positive integers are allowed") (collatz_conjecture (0));
"negative value is an error" >::
ae (Error "Only positive integers are allowed") (collatz_conjecture (-15));
]

let () =
run_test_tt_main ("collatz-conjecture tests" >::: tests)
2 changes: 1 addition & 1 deletion exercises/practice/etl/dune-project
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
(lang dune 1.1)
(version 1.0.1)
(version 1.0)
42 changes: 0 additions & 42 deletions exercises/practice/pangram/test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ let tests = [
ae false (is_pangram "7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog");
"mixed case and punctuation" >::
ae true (is_pangram "\"Five quacking Zephyrs jolt my wax bed.\"");
"case insensitive" >::
ae false (is_pangram "the quick brown fox jumps over with lazy FX");
"a-m and A-M are 26 different characters but not a pangram" >::
ae false (is_pangram "abcdefghijklm ABCDEFGHIJKLM");
"empty sentence" >::
Expand All @@ -44,8 +42,6 @@ let tests = [
ae false (is_pangram "7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog");
"mixed case and punctuation" >::
ae true (is_pangram "\"Five quacking Zephyrs jolt my wax bed.\"");
"case insensitive" >::
ae false (is_pangram "the quick brown fox jumps over with lazy FX");
"a-m and A-M are 26 different characters but not a pangram" >::
ae false (is_pangram "abcdefghijklm ABCDEFGHIJKLM");
"empty sentence" >::
Expand All @@ -66,8 +62,6 @@ let tests = [
ae false (is_pangram "7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog");
"mixed case and punctuation" >::
ae true (is_pangram "\"Five quacking Zephyrs jolt my wax bed.\"");
"case insensitive" >::
ae false (is_pangram "the quick brown fox jumps over with lazy FX");
"a-m and A-M are 26 different characters but not a pangram" >::
ae false (is_pangram "abcdefghijklm ABCDEFGHIJKLM");
"empty sentence" >::
Expand All @@ -88,8 +82,6 @@ let tests = [
ae false (is_pangram "7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog");
"mixed case and punctuation" >::
ae true (is_pangram "\"Five quacking Zephyrs jolt my wax bed.\"");
"case insensitive" >::
ae false (is_pangram "the quick brown fox jumps over with lazy FX");
"a-m and A-M are 26 different characters but not a pangram" >::
ae false (is_pangram "abcdefghijklm ABCDEFGHIJKLM");
"empty sentence" >::
Expand All @@ -110,8 +102,6 @@ let tests = [
ae false (is_pangram "7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog");
"mixed case and punctuation" >::
ae true (is_pangram "\"Five quacking Zephyrs jolt my wax bed.\"");
"case insensitive" >::
ae false (is_pangram "the quick brown fox jumps over with lazy FX");
"a-m and A-M are 26 different characters but not a pangram" >::
ae false (is_pangram "abcdefghijklm ABCDEFGHIJKLM");
"empty sentence" >::
Expand All @@ -132,8 +122,6 @@ let tests = [
ae false (is_pangram "7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog");
"mixed case and punctuation" >::
ae true (is_pangram "\"Five quacking Zephyrs jolt my wax bed.\"");
"case insensitive" >::
ae false (is_pangram "the quick brown fox jumps over with lazy FX");
"a-m and A-M are 26 different characters but not a pangram" >::
ae false (is_pangram "abcdefghijklm ABCDEFGHIJKLM");
"empty sentence" >::
Expand All @@ -154,8 +142,6 @@ let tests = [
ae false (is_pangram "7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog");
"mixed case and punctuation" >::
ae true (is_pangram "\"Five quacking Zephyrs jolt my wax bed.\"");
"case insensitive" >::
ae false (is_pangram "the quick brown fox jumps over with lazy FX");
"a-m and A-M are 26 different characters but not a pangram" >::
ae false (is_pangram "abcdefghijklm ABCDEFGHIJKLM");
"empty sentence" >::
Expand All @@ -176,8 +162,6 @@ let tests = [
ae false (is_pangram "7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog");
"mixed case and punctuation" >::
ae true (is_pangram "\"Five quacking Zephyrs jolt my wax bed.\"");
"case insensitive" >::
ae false (is_pangram "the quick brown fox jumps over with lazy FX");
"a-m and A-M are 26 different characters but not a pangram" >::
ae false (is_pangram "abcdefghijklm ABCDEFGHIJKLM");
"empty sentence" >::
Expand All @@ -198,8 +182,6 @@ let tests = [
ae false (is_pangram "7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog");
"mixed case and punctuation" >::
ae true (is_pangram "\"Five quacking Zephyrs jolt my wax bed.\"");
"case insensitive" >::
ae false (is_pangram "the quick brown fox jumps over with lazy FX");
"a-m and A-M are 26 different characters but not a pangram" >::
ae false (is_pangram "abcdefghijklm ABCDEFGHIJKLM");
"empty sentence" >::
Expand All @@ -220,30 +202,6 @@ let tests = [
ae false (is_pangram "7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog");
"mixed case and punctuation" >::
ae true (is_pangram "\"Five quacking Zephyrs jolt my wax bed.\"");
"case insensitive" >::
ae false (is_pangram "the quick brown fox jumps over with lazy FX");
"a-m and A-M are 26 different characters but not a pangram" >::
ae false (is_pangram "abcdefghijklm ABCDEFGHIJKLM");
"empty sentence" >::
ae false (is_pangram "");
"perfect lower case" >::
ae true (is_pangram "abcdefghijklmnopqrstuvwxyz");
"only lower case" >::
ae true (is_pangram "the quick brown fox jumps over the lazy dog");
"missing the letter 'x'" >::
ae false (is_pangram "a quick movement of the enemy will jeopardize five gunboats");
"missing the letter 'h'" >::
ae false (is_pangram "five boxing wizards jump quickly at it");
"with underscores" >::
ae true (is_pangram "the_quick_brown_fox_jumps_over_the_lazy_dog");
"with numbers" >::
ae true (is_pangram "the 1 quick brown fox jumps over the 2 lazy dogs");
"missing letters replaced by numbers" >::
ae false (is_pangram "7h3 qu1ck brown fox jumps ov3r 7h3 lazy dog");
"mixed case and punctuation" >::
ae true (is_pangram "\"Five quacking Zephyrs jolt my wax bed.\"");
"case insensitive" >::
ae false (is_pangram "the quick brown fox jumps over with lazy FX");
"a-m and A-M are 26 different characters but not a pangram" >::
ae false (is_pangram "abcdefghijklm ABCDEFGHIJKLM");
]
Expand Down
Loading