Skip to content

Commit

Permalink
Add collatz-conjecture exercise
Browse files Browse the repository at this point in the history
  • Loading branch information
glennj committed Nov 11, 2024
1 parent 11fe4a2 commit 53f00cc
Show file tree
Hide file tree
Showing 9 changed files with 211 additions and 0 deletions.
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,14 @@
"prerequisites": [],
"difficulty": 1
},
{
"slug": "collatz-conjecture",
"name": "Collatz Conjecture",
"uuid": "d952ed69-1598-449b-a28e-7dfd19b53f89",
"practices": [],
"prerequisites": [],
"difficulty": 2
},
{
"slug": "crypto-square",
"name": "Crypto Square",
Expand Down
29 changes: 29 additions & 0 deletions exercises/practice/collatz-conjecture/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Instructions

The Collatz Conjecture or 3x+1 problem can be summarized as follows:

Take any positive integer n.
If n is even, divide n by 2 to get n / 2.
If n is odd, multiply n by 3 and add 1 to get 3n + 1.
Repeat the process indefinitely.
The conjecture states that no matter which number you start with, you will always reach 1 eventually.

Given a number n, return the number of steps required to reach 1.

## Examples

Starting with n = 12, the steps would be as follows:

0. 12
1. 6
2. 3
3. 10
4. 5
5. 16
6. 8
7. 4
8. 2
9. 1

Resulting in 9 steps.
So for input n = 12, the return value would be 9.
19 changes: 19 additions & 0 deletions exercises/practice/collatz-conjecture/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"authors": [
"glennj"
],
"files": {
"solution": [
"lib/CollatzConjecture.pm"
],
"test": [
"t/collatz-conjecture.t"
],
"example": [
".meta/solutions/lib/CollatzConjecture.pm"
]
},
"blurb": "Calculate the number of steps to reach 1 using the Collatz conjecture.",
"source": "An unsolved problem in mathematics named after mathematician Lothar Collatz",
"source_url": "https://en.wikipedia.org/wiki/3x_%2B_1_problem"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package CollatzConjecture;

use strict;
use warnings;
use experimental qw<signatures postderef postderef_qq>;

use Exporter qw<import>;
our @EXPORT_OK = qw<steps>;

sub steps ($number) {
die 'Only positive integers are allowed' unless $number > 0;
my $count = 0;
while ( $number > 1 ) {
$number = ( $number % 2 == 0 ) ? ( $number / 2 ) : ( 3 * $number + 1 );
$count++;
}
return $count;
}

1;
39 changes: 39 additions & 0 deletions exercises/practice/collatz-conjecture/.meta/template-data.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
subs: steps
properties:
steps:
test: |-
use Data::Dmp;
if (ref $case->{expected}) {
sprintf(<<'END', $case->{input}{number}, $case->{expected}{error}, dmp($case->{description}));
like(
dies( sub { steps(%s) } ),
qr/%s/,
%s,
);
END
}
else {
sprintf(<<'END', $case->{input}{number}, $case->{expected}, dmp($case->{description}));
is(
steps(%s),
%s,
%s,
);
END
}
stub: |-
sub steps ($number) {
return undef;
}
example: |-
sub steps ($number) {
die 'Only positive integers are allowed' unless $number > 0;
my $count = 0;
while ($number > 1) {
$number = ($number % 2 == 0) ? ($number / 2) : (3 * $number + 1);
$count++;
}
return $count;
}
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"
12 changes: 12 additions & 0 deletions exercises/practice/collatz-conjecture/lib/CollatzConjecture.pm
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package CollatzConjecture;

use v5.40;

use Exporter qw<import>;
our @EXPORT_OK = qw<steps>;

sub steps ($number) {
return undef;
}

1;
45 changes: 45 additions & 0 deletions exercises/practice/collatz-conjecture/t/collatz-conjecture.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env perl
use Test2::V0;

use FindBin qw<$Bin>;
use lib "$Bin/../lib", "$Bin/../local/lib/perl5";

use CollatzConjecture qw<steps>;

is( # begin: 540a3d51-e7a6-47a5-92a3-4ad1838f0bfd
steps(1),
0,
"zero steps for one",
); # end: 540a3d51-e7a6-47a5-92a3-4ad1838f0bfd

is( # begin: 3d76a0a6-ea84-444a-821a-f7857c2c1859
steps(16),
4,
"divide if even",
); # end: 3d76a0a6-ea84-444a-821a-f7857c2c1859

is( # begin: 754dea81-123c-429e-b8bc-db20b05a87b9
steps(12),
9,
"even and odd steps",
); # end: 754dea81-123c-429e-b8bc-db20b05a87b9

is( # begin: ecfd0210-6f85-44f6-8280-f65534892ff6
steps(1000000),
152,
"large number of even and odd steps",
); # end: ecfd0210-6f85-44f6-8280-f65534892ff6

like( # begin: 2187673d-77d6-4543-975e-66df6c50e2da
dies( sub { steps(0) } ),
qr/Only positive integers are allowed/,
"zero is an error",
); # end: 2187673d-77d6-4543-975e-66df6c50e2da

like( # begin: ec11f479-56bc-47fd-a434-bcd7a31a7a2e
dies( sub { steps(-15) } ),
qr/Only positive integers are allowed/,
"negative value is an error",
); # end: ec11f479-56bc-47fd-a434-bcd7a31a7a2e

done_testing;

0 comments on commit 53f00cc

Please sign in to comment.