Skip to content

Commit d9bbbb6

Browse files
committed
Apply CaesarCipher simplifications from stash
1 parent b4b9b17 commit d9bbbb6

File tree

2 files changed

+109
-59
lines changed

2 files changed

+109
-59
lines changed

app/CaesarCipher.php

Lines changed: 32 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,11 @@ class CaesarCipher
77
const ALPHABET_EN = 'abcdefghijklmnopqrstuvwxyz';
88
const ALPHABET_RU = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя';
99

10-
private string $alphabet;
11-
1210
/**
13-
* @param int $shift
14-
* @param string|null $alphabet
11+
* @param int $shift
12+
* @param string $alphabet
1513
*/
16-
public function __construct(private int $shift, ?string $alphabet = self::ALPHABET_RU)
17-
{
18-
$this->alphabet = $alphabet;
19-
}
14+
public function __construct(private int $shift, private string $alphabet = self::ALPHABET_RU) {}
2015

2116
/**
2217
* @param string|null $alphabet
@@ -32,74 +27,57 @@ public function alphabet(?string $alphabet = self::ALPHABET_RU): static
3227

3328
/**
3429
* @param string $text
30+
* @param int $shift
3531
*
3632
* @return string
3733
*/
38-
public function encrypt(string $text)
34+
private function process(string $text, int $shift): string
3935
{
40-
$encryptedText = '';
36+
$processedText = '';
37+
$alphabetLength = mb_strlen($this->alphabet);
4138

42-
// Проходим по каждому символу входного текста
4339
for ($i = 0; $i < mb_strlen($text); $i++) {
44-
$char = mb_substr($text, $i, 1); // Получаем текущий символ
40+
$char = mb_substr($text, $i, 1);
4541

4642
// Ищем позицию символа в алфавите
4743
$position = mb_strpos($this->alphabet, mb_strtolower($char));
4844

4945
// Если символ не найден в алфавите, оставляем его без изменений
5046
if ($position === false) {
51-
$encryptedText .= $char;
52-
} else {
53-
// Сдвигаем позицию символа на заданное количество шагов
54-
$newPosition = ($position + $this->shift) % mb_strlen($this->alphabet);
55-
$encryptedChar = mb_substr($this->alphabet, $newPosition, 1);
56-
57-
// Учитываем регистр символа
58-
if (mb_strtoupper($char) === $char) {
59-
$encryptedText .= mb_strtoupper($encryptedChar);
60-
} else {
61-
$encryptedText .= $encryptedChar;
62-
}
47+
$processedText .= $char;
48+
continue;
6349
}
50+
51+
// Сдвигаем позицию символа
52+
$newPosition = ($position + $shift + $alphabetLength) % $alphabetLength;
53+
$processedChar = mb_substr($this->alphabet, $newPosition, 1);
54+
55+
// Учитываем регистр символа
56+
$processedText .= mb_strtoupper($char) === $char
57+
? mb_strtoupper($processedChar)
58+
: $processedChar;
6459
}
6560

66-
return $encryptedText;
61+
return $processedText;
6762
}
6863

6964
/**
70-
* @param string $encryptedText
65+
* @param string $text
7166
*
7267
* @return string
7368
*/
74-
public function decrypt(string $encryptedText)
69+
public function encrypt(string $text): string
7570
{
76-
$decryptedText = '';
77-
$shift = mb_strlen($this->alphabet) - $this->shift;
78-
79-
// Проходим по каждому символу зашифрованного текста
80-
for ($i = 0; $i < mb_strlen($encryptedText); $i++) {
81-
$char = mb_substr($encryptedText, $i, 1); // Получаем текущий символ
82-
83-
// Ищем позицию символа в алфавите
84-
$position = mb_strpos($this->alphabet, mb_strtolower($char));
85-
86-
// Если символ не найден в алфавите, оставляем его без изменений
87-
if ($position === false) {
88-
$decryptedText .= $char;
89-
} else {
90-
// Сдвигаем позицию символа на обратное количество шагов
91-
$newPosition = ($position + $shift) % mb_strlen($this->alphabet);
92-
$decryptedChar = mb_substr($this->alphabet, $newPosition, 1);
93-
94-
// Учитываем регистр символа
95-
if (mb_strtoupper($char) === $char) {
96-
$decryptedText .= mb_strtoupper($decryptedChar);
97-
} else {
98-
$decryptedText .= $decryptedChar;
99-
}
100-
}
101-
}
71+
return $this->process($text, $this->shift);
72+
}
10273

103-
return $decryptedText;
74+
/**
75+
* @param string $encryptedText
76+
*
77+
* @return string
78+
*/
79+
public function decrypt(string $encryptedText): string
80+
{
81+
return $this->process($encryptedText, -$this->shift);
10482
}
10583
}

tests/Unit/CaesarCipherTest.php

Lines changed: 77 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@
77

88
class CaesarCipherTest extends TestCase
99
{
10-
/** @test */
11-
public function testEncryptDecrypt()
10+
public function testEncryptDecrypt(): void
1211
{
13-
$cipher = (new CaesarCipher(3))->alphabet(CaesarCipher::ALPHABET_EN);
12+
$cipher = new CaesarCipher(3, CaesarCipher::ALPHABET_EN);
1413

1514
$originalText = 'Hello World!';
1615

@@ -23,8 +22,7 @@ public function testEncryptDecrypt()
2322
$this->assertEquals($originalText, $decryptedText);
2423
}
2524

26-
/** @test */
27-
public function testEncryptDecryptWithRuAlphabet()
25+
public function testEncryptDecryptWithRuAlphabet(): void
2826
{
2927
$cipher = new CaesarCipher(20);
3028

@@ -38,4 +36,78 @@ public function testEncryptDecryptWithRuAlphabet()
3836

3937
$this->assertEquals($originalText, $decryptedText);
4038
}
39+
40+
public function testMixedTextWithNonAlphabetCharacters(): void
41+
{
42+
$cipher = (new CaesarCipher(2))->alphabet(CaesarCipher::ALPHABET_EN);
43+
44+
$originalText = 'Test123, mixed! Text.';
45+
46+
$encryptedText = $cipher->encrypt($originalText);
47+
48+
$this->assertEquals('Vguv123, okzgf! Vgzv.', $encryptedText);
49+
50+
$decryptedText = $cipher->decrypt($encryptedText);
51+
52+
$this->assertEquals($originalText, $decryptedText);
53+
}
54+
55+
public function testEmptyString(): void
56+
{
57+
$cipher = new CaesarCipher(10);
58+
59+
$originalText = '';
60+
$encryptedText = $cipher->encrypt($originalText);
61+
62+
$this->assertEquals('', $encryptedText);
63+
64+
$decryptedText = $cipher->decrypt($encryptedText);
65+
66+
$this->assertEquals('', $decryptedText);
67+
}
68+
69+
public function testShiftExceedingAlphabetLength(): void
70+
{
71+
$cipher = new CaesarCipher(30, CaesarCipher::ALPHABET_EN);
72+
73+
$originalText = 'abc';
74+
$encryptedText = $cipher->encrypt($originalText);
75+
76+
// Сдвиг 30 эквивалентен сдвигу 4 (30 % 26 = 4)
77+
$this->assertEquals('efg', $encryptedText);
78+
79+
$decryptedText = $cipher->decrypt($encryptedText);
80+
81+
$this->assertEquals($originalText, $decryptedText);
82+
}
83+
84+
public function testNegativeShift(): void
85+
{
86+
$cipher = new CaesarCipher(-3, CaesarCipher::ALPHABET_EN);
87+
88+
$originalText = 'xyz';
89+
$encryptedText = $cipher->encrypt($originalText);
90+
91+
// Сдвиг -3 эквивалентен сдвигу 23 (26 - 3)
92+
$this->assertEquals('uvw', $encryptedText);
93+
94+
$decryptedText = $cipher->decrypt($encryptedText);
95+
96+
$this->assertEquals($originalText, $decryptedText);
97+
}
98+
99+
public function testFullAlphabetCycle(): void
100+
{
101+
$cipher = new CaesarCipher(26, CaesarCipher::ALPHABET_EN);
102+
103+
$originalText = 'Complete Cycle';
104+
$encryptedText = $cipher->encrypt($originalText);
105+
106+
// Сдвиг 26 равен полному циклу, текст должен остаться неизменным
107+
$this->assertEquals($originalText, $encryptedText);
108+
109+
$decryptedText = $cipher->decrypt($encryptedText);
110+
111+
$this->assertEquals($originalText, $decryptedText);
112+
}
41113
}

0 commit comments

Comments
 (0)