问题描述
简单的例子: 以英语初学者(范围A-Z)为参考。如果给我一个字母-例如'a'-一个数字-例如'2'-我需要找出2号以后的字母。 答案将是'c'('a'-> 1个动作:'b'-> 2个动作:'c')
当然,您可以给它一个大于首字母大小的数字,即26。由于规则是在字母z之后又出现字母a,因此这意味着如果在前面的示例中,传递了数字26我们需要找到的字母是'a'。
该问题的最后一种情况是您可能会收到一个负数。因此,如果字母'a'带有数字'-3',答案将是'x'('a'-> 1个动作:'z'-> 2个动作:'y'-> 3个动作: 'x')。
这是我到目前为止的代码:
function getNewLetter($letter,$number) {
$letters = range('A','Z');
if ($number >= 0) {
return $letters[($number + array_search($letter,$letters) % 26)%26];
} else {
return $letters[($number - (array_search($letter,$letters) % 26))%26];
}
}
echo getNewLetter("H",4); // correctly prints out L
echo getNewLetter("H",26); // correctly prints out H
echo getNewLetter("H",-4); // throws undefined offset -11 error
我的功能有两个主要问题:
- 即使我使用正数进行运算,编译器返回答案也要花费一些时间,因此恐怕这是一个非常耗时的操作,可以更轻松地进行整理。
- 我的函数方法不适用于负数。我非常清楚什么是未定义的偏移量,它无法访问数组的负索引。我只是不知道如何使模运算符向后工作...
任何帮助解决此问题的人都会由衷的感谢。
解决方法
请执行以下操作:
function getNewLetter(string $letter,int $number): string
{
$newOrd = (ord($letter) + $number - 65) % 26;
if ($newOrd < 0) {
$newOrd += 26;
}
return chr(65 + $newOrd);
}
它只是在新字母的序数值上使用模26,相对于字母A(65)。如果
,取26为模是正确的想法。
这是因为1
的偏移量与27
的偏移量相同。 0
的偏移量与偏移量26
,52
等相同,依此类推。
对负数取模26也应用与-27
的旋转相同的逻辑,与-1
的旋转相同。
因此,代码很简单。
- 对数字应用模26。
- 获取当前char的ascii值,并在其中添加“数字”。
- 如果新的ascii值在65到90之间,则返回char值。
- 如果新的ascii值超过90,则使用偏移量直到90,然后返回其chr()+64。如果值低于65,则同样适用,反之亦然。
代码段:
function getNewLetter($letter,$number) {
$number = $number % 26;
$new_ascii_value = ord($letter) + $number;
if($new_ascii_value < 65){
$number = abs($number) - (ord($letter) - 65);
return chr(91 - $number);
}else if($new_ascii_value >= 91){
return chr(64 + ($new_ascii_value - 90));
}
return chr($new_ascii_value);
}
,
Jeto的方法得到了改进,可以使用大写或小写字母返回正确答案:
function getNewLetter(string $letter,int $number): string {
$movement = $letter < 'a' ? 65 : 97; // Depending on case,letter 'a' starts at different numbers of ASCII table
$newOrd = (ord($letter) + $number - $movement) % 26;
if ($newOrd < 0) {
$newOrd += 26;
}
return chr($movement + $newOrd);
}
这里有一些通过测试以尝试使用该方法:
echo getNewLetter("h",4),PHP_EOL;
echo getNewLetter("H",PHP_EOL;
echo getNewLetter("h",-4),26),27),-26),-27),PHP_EOL;
echo PHP_EOL;
echo getNewLetter("a",-2),PHP_EOL;
echo getNewLetter("A",PHP_EOL;
echo getNewLetter("b",-3),PHP_EOL;
echo getNewLetter("B",PHP_EOL;
echo PHP_EOL;
echo getNewLetter("Z",2),PHP_EOL;
echo getNewLetter("Z",PHP_EOL;
echo PHP_EOL;
echo getNewLetter("A",-1),PHP_EOL;