[英]Why does my hashing program fail the tests
Task:任务:
To register in the system, each resident must come up with a password.要在系统中注册,每个居民都必须提供一个密码。 The password consists of letters of the Latin alphabet (uppercase and lowercase), as well as numbers from 0 to 9, that is, it is possible to use 62 characters in total.
密码由拉丁字母(大写和小写)以及从0到9的数字组成,即总共可以使用62个字符。 The password length is from 5 to 20 characters.
密码长度为 5 到 20 个字符。 The password is stored in the database in encrypted form, encryption is carried out according to the following algorithm:
密码以加密形式存储在数据库中,按照以下算法进行加密:
To quickly search for users in the database, a hash function is calculated for each encrypted password using the following algorithm:为了在数据库中快速搜索用户,使用以下算法为每个加密密码计算 hash function:
A hash function is considered good if collisions rarely occur, that is, the values of the function match for different passwords.如果很少发生冲突,则认为 hash function 是好的,即 function 的值匹配不同的密码。
John came up with a new password.约翰想出了一个新密码。 At the same time, there are already nn passwords in the database, and I would like to avoid collisions.
同时数据库里已经有nn个密码了,希望避免冲突。 Will John succeed?
约翰会成功吗?
Input data输入数据
The first line contains a string representing John's password.第一行包含一个表示 John 密码的字符串。 The second line contains an integer n – the number of passwords in the database.
第二行包含一个 integer n - 数据库中的密码数量。 The third line contains integers p and q.
第三行包含整数 p 和 q。 The following lines store passwords in unencrypted form.
以下行以未加密的形式存储密码。
Output data Output数据
An integer is the number of passwords whose hash function matches the hash function of John's password. An integer is the number of passwords whose hash function matches the hash function of John's password.
Sample Input:样本输入:
AabB1cd AabB1cd
5 5
13 17 13 17
Nik143pasw尼克143pasw
qeAom1 qeAom1
q1w2e3r4t q1w2e3r4t
aBoba2012 aBoba2012
N33iEj N33iEj
Sample Output:样品 Output:
2 2
Note:笔记:
Passwords that match John's hash function are highlighted.与 John 的 hash function 匹配的密码会突出显示。
Processing of John's password: After cyclic shift: CefD1gh (uppercase letters are shifted by 2, lowercase by 4) The sum of the character codes is 38+14+15+39+1+16+17=140 The hash function is equal to (10,4) John的密码的处理:循环移位后:CefD1gh(大写字母移位2,小写字母移位4)字符代码之和为38+14+15+39+1+16+17=140 hash ZC1C425268E68385D1AB5074C17A9等于(10,4)
My Programm:我的程序:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
string pas;
cin >> pas;
int small = 0, big = 0;
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] >= 'A' && pas[i] <= 'Z')big++;
if (pas[i] >= 'a' && pas[i] <= 'z')small++;
}
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] + big >= 'A' && pas[i] + big <= 'Z') pas[i] = pas[i] + big;
else if (pas[i] >= 'A' && pas[i] <= 'Z') {
int tempVar = big;
while (tempVar > 0) {
if (pas[i] == 'Z') {
pas[i] = 'A';
tempVar = tempVar - 1;
}
tempVar = tempVar - 1;
pas[i] = pas[i] + 1;
}
}
}
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] + small >= 'a' && pas[i] + small <= 'z') pas[i] = pas[i] + small;
else if (pas[i] >= 'a' && pas[i] <= 'z') {
int tempVar = small;
while (tempVar > 0) {
if (pas[i] == 'z') {
pas[i] = 'a';
tempVar = tempVar - 1;
}
pas[i] = pas[i] + 1;
tempVar = tempVar - 1;
}
}
}
int hash = 0;
for (int i = 0; i < pas.length(); i++) {
if ('0' <= pas[i] && '9' >= pas[i]) {
hash = hash + (pas[i] - 48);
}
if ('a' <= pas[i] && 'z' >= pas[i]) {
hash = hash + (pas[i] - 87);
}
if ('A' <= pas[i] && 'Z' >= pas[i]) {
hash = hash + (pas[i] - 29);
}
}
int n, p, q;
cin >> n >> p >> q;
int hashfun1 = hash % p;
int hashfun2 = hash % q;
int counter = 0;
while (n--) {
cin >> pas;
int small = 0, big = 0;
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] >= 'A' && pas[i] <= 'Z')big++;
if (pas[i] >= 'a' && pas[i] <= 'z')small++;
}
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] + big >= 'A' && pas[i] + big <= 'Z') pas[i] = pas[i] + big;
else if (pas[i] >= 'A' && pas[i] <= 'Z') {
int tempVar = big;
while (tempVar > 0) {
if (pas[i] == 'Z') {
pas[i] = 'A';
tempVar = tempVar - 1;
}
tempVar = tempVar - 1;
pas[i] = pas[i] + 1;
}
}
}
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] + small >= 'a' && pas[i] + small <= 'z') pas[i] = pas[i] + small;
else if (pas[i] >= 'a' && pas[i] <= 'z') {
int tempVar = small;
while (tempVar > 0) {
if (pas[i] == 'z') {
pas[i] = 'a';
tempVar = tempVar - 1;
}
pas[i] = pas[i] + 1;
tempVar = tempVar - 1;
}
}
}
int hash = 0;
for (int i = 0; i < pas.length(); i++) {
if ('0' <= pas[i] && '9' >= pas[i]) {
hash = hash + (pas[i] - 48);
}
if ('a' <= pas[i] && 'z' >= pas[i]) {
hash = hash + (pas[i] - 87);
}
if ('A' <= pas[i] && 'Z' >= pas[i]) {
hash = hash + (pas[i] - 29);
}
}
int hashfun3 = hash % p;
int hashfun4 = hash % q;
if (hashfun1 == hashfun3 && hashfun2 == hashfun4) {
counter++;
}
}
std::cout << counter;
return 0;
}
Tests:测试:
Test 1. OK测试 1. 好的
Test 2. Wrong answer测试 2. 错误答案
Test 3. OK测试 3. 好的
Test 4. OK测试 4. 好的
Test 5. Wrong answer测试 5. 错误答案
3 of 5 tests passed. 5 次测试中的 3 次通过。
You have a few logic problems in your code.您的代码中有一些逻辑问题。 When you are rotating your upper and lower-case characters to their "encrypted" forms, you iterate through the password twice, and sometimes incorrectly rotate the characters.
当您将大写和小写字符旋转为其“加密的”forms 时,您会重复密码两次,有时会错误地旋转字符。 Take for example just the line
以这条线为例
if (pas[i] + big >= 'A' && pas[i] + big <= 'Z') pas[i] = pas[i] + big;
Consider the case where pas[i] == '9'
and big == 8
.考虑
pas[i] == '9'
和big == 8
的情况。 You will end up transforming all of your 9
's into A
s.您最终会将所有
9
转换为A
。
Now consider the line in the next loop现在考虑下一个循环中的行
if (pas[i] + small >= 'a' && pas[i] + small <= 'z') pas[i] = pas[i] + small;
Which will similarly transform some upper-case letters into lower-case if small
is large enough.如果足够
small
,它同样会将一些大写字母转换为小写字母。
You can also combine these two problems.您也可以将这两个问题结合起来。 Consider the case where
pas[i]
is originally Y
, big
is 1, little
is 7. You'll transform Y --> Z
, and then in the next step transform Z --> a
.考虑一下
pas[i]
最初是Y
的情况, big
是 1, little
是 7。您将转换Y --> Z
,然后在下一步中转换Z --> a
。
main()
in your head.main()
的全部内容保留在您的脑海中。 Humans have limited short-term memory. Some suggested functions would include一些建议的功能包括
bool is_upper(char c)
bool is_lower(char c)
bool is_numeric(char c)
char rotate_upper(char c, int steps)
char rotate_lower(char c, int steps)
Combining all of the above, the two encryption loops of your main function could turn from:结合以上所有内容,您的主要 function 的两个加密循环可以从:
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] + big >= 'A' && pas[i] + big <= 'Z') pas[i] = pas[i] + big;
else if (pas[i] >= 'A' && pas[i] <= 'Z') {
int tempVar = big;
while (tempVar > 0) {
if (pas[i] == 'Z') {
pas[i] = 'A';
tempVar = tempVar - 1;
}
tempVar = tempVar - 1;
pas[i] = pas[i] + 1;
}
}
}
for (int i = 0; i < pas.length(); i++)
{
if (pas[i] + small >= 'a' && pas[i] + small <= 'z') pas[i] = pas[i] + small;
else if (pas[i] >= 'a' && pas[i] <= 'z') {
int tempVar = small;
while (tempVar > 0) {
if (pas[i] == 'z') {
pas[i] = 'a';
tempVar = tempVar - 1;
}
pas[i] = pas[i] + 1;
tempVar = tempVar - 1;
}
}
}
to至
for (int i = 0; i < pas.length(); i++) {
char c = pas[i];
if (is_upper(c)) {
pas[i] = rotate_upper(c, big);
}
else if (is_lower(c)) {
pas[i] = rotate_lower(c, small);
}
}
You can transform 30 lines of code into just under 10. That's much easier to read for both you, the developer, and for any potential reviewers.您可以将 30 行代码转换为不到 10 行代码。这对于您、开发人员和任何潜在的审阅者来说都更容易阅读。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.