Skip to content

Commit 2b0ecd7

Browse files
authored
Add Secret Handshake Exercise (#634)
1 parent 7bd7330 commit 2b0ecd7

File tree

8 files changed

+294
-0
lines changed

8 files changed

+294
-0
lines changed

config.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,6 +1180,14 @@
11801180
"prerequisites": [],
11811181
"difficulty": 5
11821182
},
1183+
{
1184+
"slug": "secret-handshake",
1185+
"name": "Secret Handshake",
1186+
"uuid": "c0721b15-5bfb-4a2e-92d3-b2e32c096810",
1187+
"practices": [],
1188+
"prerequisites": [],
1189+
"difficulty": 4
1190+
},
11831191
{
11841192
"slug": "circular-buffer",
11851193
"name": "Circular Buffer",
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Instructions
2+
3+
Your task is to convert a number between 1 and 31 to a sequence of actions in the secret handshake.
4+
5+
The sequence of actions is chosen by looking at the rightmost five digits of the number once it's been converted to binary.
6+
Start at the right-most digit and move left.
7+
8+
The actions for each number place are:
9+
10+
```plaintext
11+
00001 = wink
12+
00010 = double blink
13+
00100 = close your eyes
14+
01000 = jump
15+
10000 = Reverse the order of the operations in the secret handshake.
16+
```
17+
18+
Let's use the number `9` as an example:
19+
20+
- 9 in binary is `1001`.
21+
- The digit that is farthest to the right is 1, so the first action is `wink`.
22+
- Going left, the next digit is 0, so there is no double-blink.
23+
- Going left again, the next digit is 0, so you leave your eyes open.
24+
- Going left again, the next digit is 1, so you jump.
25+
26+
That was the last digit, so the final code is:
27+
28+
```plaintext
29+
wink, jump
30+
```
31+
32+
Given the number 26, which is `11010` in binary, we get the following actions:
33+
34+
- double blink
35+
- jump
36+
- reverse actions
37+
38+
The secret handshake for 26 is therefore:
39+
40+
```plaintext
41+
jump, double blink
42+
```
43+
44+
~~~~exercism/note
45+
If you aren't sure what binary is or how it works, check out [this binary tutorial][intro-to-binary].
46+
47+
[intro-to-binary]: https://medium.com/basecs/bits-bytes-building-with-binary-13cb4289aafa
48+
~~~~
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Introduction
2+
3+
You are starting a secret coding club with some friends and friends-of-friends.
4+
Not everyone knows each other, so you and your friends have decided to create a secret handshake that you can use to recognize that someone is a member.
5+
You don't want anyone who isn't in the know to be able to crack the code.
6+
7+
You've designed the code so that one person says a number between 1 and 31, and the other person turns it into a series of actions.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"authors": [
3+
"tomasnorre"
4+
],
5+
"files": {
6+
"solution": [
7+
"SecretHandshake.php"
8+
],
9+
"test": [
10+
"SecretHandshakeTest.php"
11+
],
12+
"example": [
13+
".meta/example.php"
14+
]
15+
},
16+
"blurb": "Given a decimal number, convert it to the appropriate sequence of events for a secret handshake.",
17+
"source": "Bert, in Mary Poppins",
18+
"source_url": "https://www.imdb.com/title/tt0058331/quotes/?item=qt0437047"
19+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
class SecretHandshake
6+
{
7+
public function commands(int $handshake): array
8+
{
9+
$handshakeCommands = ['wink', 'double blink', 'close your eyes', 'jump'];
10+
$shakeWith = [];
11+
12+
for ($i = 0; $i < 4; $i++) {
13+
if ($handshake & (2 ** $i)) {
14+
$shakeWith[] = $handshakeCommands[$i];
15+
}
16+
}
17+
18+
if ($handshake & (2 ** 4)) {
19+
$shakeWith = array_reverse($shakeWith);
20+
}
21+
22+
return $shakeWith;
23+
}
24+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
11+
12+
[b8496fbd-6778-468c-8054-648d03c4bb23]
13+
description = "wink for 1"
14+
15+
[83ec6c58-81a9-4fd1-bfaf-0160514fc0e3]
16+
description = "double blink for 10"
17+
18+
[0e20e466-3519-4134-8082-5639d85fef71]
19+
description = "close your eyes for 100"
20+
21+
[b339ddbb-88b7-4b7d-9b19-4134030d9ac0]
22+
description = "jump for 1000"
23+
24+
[40499fb4-e60c-43d7-8b98-0de3ca44e0eb]
25+
description = "combine two actions"
26+
27+
[9730cdd5-ef27-494b-afd3-5c91ad6c3d9d]
28+
description = "reverse two actions"
29+
30+
[0b828205-51ca-45cd-90d5-f2506013f25f]
31+
description = "reversing one action gives the same action"
32+
33+
[9949e2ac-6c9c-4330-b685-2089ab28b05f]
34+
description = "reversing no actions still gives no actions"
35+
36+
[23fdca98-676b-4848-970d-cfed7be39f81]
37+
description = "all possible actions"
38+
39+
[ae8fe006-d910-4d6f-be00-54b7c3799e79]
40+
description = "reverse all possible actions"
41+
42+
[3d36da37-b31f-4cdb-a396-d93a2ee1c4a5]
43+
description = "do nothing for zero"
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
/*
4+
* By adding type hints and enabling strict type checking, code can become
5+
* easier to read, self-documenting and reduce the number of potential bugs.
6+
* By default, type declarations are non-strict, which means they will attempt
7+
* to change the original type to match the type specified by the
8+
* type-declaration.
9+
*
10+
* In other words, if you pass a string to a function requiring a float,
11+
* it will attempt to convert the string value to a float.
12+
*
13+
* To enable strict mode, a single declare directive must be placed at the top
14+
* of the file.
15+
* This means that the strictness of typing is configured on a per-file basis.
16+
* This directive not only affects the type declarations of parameters, but also
17+
* a function's return type.
18+
*
19+
* For more info review the Concept on strict type checking in the PHP track
20+
* <link>.
21+
*
22+
* To disable strict typing, comment out the directive below.
23+
*/
24+
25+
declare(strict_types=1);
26+
27+
class SecretHandshake
28+
{
29+
public function commands(int $handshake): array
30+
{
31+
throw new \BadMethodCallException(sprintf('Implement the %s method', __FUNCTION__));
32+
}
33+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
class SecretHandshakeTest extends PHPUnit\Framework\TestCase
6+
{
7+
private SecretHandshake $secretHandshake;
8+
9+
public static function setUpBeforeClass(): void
10+
{
11+
require_once 'SecretHandshake.php';
12+
}
13+
14+
public function setUp(): void
15+
{
16+
$this->secretHandshake = new SecretHandshake();
17+
}
18+
19+
/**
20+
* uuid: b8496fbd-6778-468c-8054-648d03c4bb23
21+
*/
22+
public function testWinkForOne(): void
23+
{
24+
$this->assertEquals(['wink'], $this->secretHandshake->commands(1));
25+
}
26+
27+
/**
28+
* uuid: 83ec6c58-81a9-4fd1-bfaf-0160514fc0e3
29+
*/
30+
public function testDoubleBlinkForTen(): void
31+
{
32+
$this->assertEquals(['double blink'], $this->secretHandshake->commands(0b0_0010));
33+
}
34+
35+
/**
36+
* uuid: 0e20e466-3519-4134-8082-5639d85fef71
37+
*/
38+
public function testCloseYourEyesForHundred(): void
39+
{
40+
$this->assertEquals(['close your eyes'], $this->secretHandshake->commands(0b100));
41+
}
42+
43+
/**
44+
* uuid: b339ddbb-88b7-4b7d-9b19-4134030d9ac0
45+
*/
46+
public function testJumpForThousand(): void
47+
{
48+
$this->assertEquals(['jump'], $this->secretHandshake->commands(8));
49+
}
50+
51+
/**
52+
* uuid: 40499fb4-e60c-43d7-8b98-0de3ca44e0eb
53+
*/
54+
public function testCombineTwoActions(): void
55+
{
56+
$this->assertEquals(['wink', 'double blink'], $this->secretHandshake->commands(3));
57+
}
58+
59+
/**
60+
* uuid: 9730cdd5-ef27-494b-afd3-5c91ad6c3d9d
61+
*/
62+
public function testReverseTwoActions(): void
63+
{
64+
$this->assertEquals(['double blink', 'wink'], $this->secretHandshake->commands(0b10011));
65+
}
66+
67+
/**
68+
* uuid: 0b828205-51ca-45cd-90d5-f2506013f25f
69+
*/
70+
public function testReversingOneActionGivesTheSameAction(): void
71+
{
72+
$this->assertEquals(['jump'], $this->secretHandshake->commands(24));
73+
}
74+
75+
/**
76+
* uuid: 9949e2ac-6c9c-4330-b685-2089ab28b05f
77+
*/
78+
public function testReversingNoActionsStillGivesNoActions(): void
79+
{
80+
$this->assertEquals([], $this->secretHandshake->commands(16));
81+
}
82+
83+
/**
84+
* uuid: 23fdca98-676b-4848-970d-cfed7be39f81
85+
*/
86+
public function testAllPossibleActions(): void
87+
{
88+
$this->assertEquals(
89+
['wink', 'double blink', 'close your eyes', 'jump'],
90+
$this->secretHandshake->commands(15)
91+
);
92+
}
93+
94+
/**
95+
* uuid: ae8fe006-d910-4d6f-be00-54b7c3799e79
96+
*/
97+
public function testReverseAllPossibleActions(): void
98+
{
99+
$this->assertEquals(
100+
['jump', 'close your eyes', 'double blink', 'wink'],
101+
$this->secretHandshake->commands(31)
102+
);
103+
}
104+
105+
/**
106+
* uuid: 3d36da37-b31f-4cdb-a396-d93a2ee1c4a5
107+
*/
108+
public function testDoNothingForZero(): void
109+
{
110+
$this->assertEquals([], $this->secretHandshake->commands(0b0));
111+
}
112+
}

0 commit comments

Comments
 (0)