|
|
|
| Ответ 003 на задачу N 22.
С условиями задачи можно ознакомится по ссылке.
<?php
//Unkind
function user_encode($binary, $alphabet)
{
if((string) $binary === "") return "";
if(strlen($alphabet) != 85)
{
echo(
"\x3C\x62\x3E\x4F\x6E\x6C\x79\x20\x38\x35" .
"\x20\x63\x68\x61\x72\x73\x3C\x2F\x62\x3E"
);
return false;
}
for($i = 0; $i < strlen($alphabet); $i++)
{
if(!isset($alphabet_array[ord($alphabet[$i])]))
{
$alphabet_array[ord($alphabet[$i])] = $alphabet[$i];
}
}
//Только уникальные символы
if(count($alphabet_array) <> strlen($alphabet))
{
echo(
"<b>Incorrect alphabet.</b>"
);
return false;
}
sort($alphabet_array, SORT_REGULAR);
$alphabet = implode($alphabet_array);
$binstream = "";
//Перевод в двоичный код
for($i = 0; $i < strlen($binary); $i++)
{
$decvalue = ord($binary[$i]);
$binvalue = "";
//decbin()
while(true)
{
$binvalue .= $decvalue % 2;
if($decvalue < 2) break;
$decvalue /= 2;
}
//strrev()
$buffer = "";
$l = strlen($binvalue);
while(--$l >= 0) $buffer .= $binvalue[$l];
$binvalue = $buffer;
$byte = $binvalue;
while(strlen($byte) < 8) $byte = "0" . $byte; //str_pad()
$binstream .= $byte;
}
$base85_value = "";
//Перевод в base85
for($i = 0; $i < strlen($binstream); $i += 32)
{
$binvalue = substr($binstream, $i, 32);
if(strpos($binvalue, "1") === false)
{
$base85_value .= $alphabet[0] . $alphabet[0] . $alphabet[0] . $alphabet[0] . $alphabet[0];
continue;
}
$decvalue = 0;
//bindec()
for($j = 0; $j < strlen($binvalue); $j++)
{
if(strlen($binvalue) - ($j + 1) == 0) $pow = 1; else $pow = (2 << strlen($binvalue) - ($j + 2));
if($pow < 0) $pow = 0x80000000; //signed int => float
$decvalue += $binvalue[$j] * $pow;
}
$result = "";
while(true)
{
//"Безопасное" деление по модулю, т.е. корректно работает при $decvalue > 0x7FFFFFFF
$modulus = intval($decvalue - strlen($alphabet) * intval($decvalue / strlen($alphabet)));
$result .= $alphabet[$modulus];
if($decvalue < strlen($alphabet)) break;
$decvalue /= strlen($alphabet);
}
//strrev()
$buffer = "";
$l = strlen($result);
while(--$l >= 0) $buffer .= $result[$l];
$result = $buffer;
if($i + 32 < strlen($binstream)) while(strlen($result) < 5) $result = $alphabet[0] . $result;
$base85_value .= $result;
}
return $base85_value;
}
function user_decode($base85_value, $alphabet)
{
if((string) $base85_value === "") return "";
if(strlen($alphabet) != 85)
{
echo(
"\x3C\x62\x3E\x4F\x6E\x6C\x79\x20\x38\x35" .
"\x20\x63\x68\x61\x72\x73\x3C\x2F\x62\x3E"
);
return false;
}
for($i = 0; $i < strlen($alphabet); $i++)
{
if(!isset($alphabet_array[ord($alphabet[$i])]))
{
$alphabet_array[ord($alphabet[$i])] = $alphabet[$i];
}
}
//Только уникальные символы
if(count($alphabet_array) <> strlen($alphabet))
{
echo(
"<b>Incorrect alphabet.</b>"
);
return false;
}
sort($alphabet_array, SORT_REGULAR);
$alphabet = implode($alphabet_array);
$binary = "";
//Считывание по 5 байт для перевода в десятичную, а затем двоичную систему счисления
for($i = 0; $i < strlen($base85_value); $i += 5)
{
$code = substr($base85_value, $i, 5);
if($code === $alphabet[0] . $alphabet[0] . $alphabet[0] . $alphabet[0] . $alphabet[0])
{
$binary .= "\0\0\0\0";
continue;
}
$decvalue = 0;
//strlen($alphabet)'ричная => десятичная
for($j = 0; $j < strlen($code); $j++)
{
$decvalue += strpos($alphabet, $code[$j]) * pow(strlen($alphabet), strlen($code) - ($j + 1));
}
$binvalue = "";
//decbin()
while(true)
{
$binvalue .= $decvalue % 2;
if($decvalue < 2) break;
$decvalue /= 2;
}
//strrev()
$buffer = "";
$l = strlen($binvalue);
while(--$l >= 0) $buffer .= $binvalue[$l];
$binvalue = $buffer;
while(strlen($binvalue) % 8 != 0) $binvalue = "0" . $binvalue; //str_pad()
//Двоичный код => бинарные данные
for($j = 0; $j < strlen($binvalue); $j += 8)
{
$bin = substr($binvalue, $j, 8);
$dec = 0;
//bindec()
for($q = 0; $q < strlen($bin); $q++)
{
$x = strlen($bin) - ($q + 1);
if($x == 0) $pow = 1; else $pow = (2 << $x - 1);
$dec += $bin[$q] * $pow;
}
$binary .= chr($dec);
}
}
return $binary;
}
//Удалите пробелы, поставленные форумом
$abc = "abcdefghijklmnopqrstuvwxyzABCDEFGHI JKLMNOPQRSTUVWXYZ0123456789!@$^*()[],./_+-=~:|?{}`";
$bin = "BinData: ";
for($i = 0; $i <= 255; $i++) $bin .= chr($i);
$start = microtime(true);
$en = user_encode($bin, $abc);
$encode = microtime(true) - $start;
$start = microtime(true);
$de = user_decode($en, $abc);
$decode = microtime(true) - $start;
if($de != $bin)
{
echo("Oops");
}
else
{
echo(
"Длина \x24bin: " . strlen($bin) . "<br />\r\n" .
"Длина \x24en: " . strlen($en) . "<br />\r\n" .
sprintf("Строка увеличилась на %01.2f%%<br />\r\n", (strlen($en) * 100) / strlen($bin) - 100) .
"Время кодирования: " . $encode . "<br />\r\n" .
"Время раскодирования: " . $decode . "<br />\r\n"
);
}
?>
|
http://www.softtime.ru/info/task.php?id_article=111 | |
|
|
|
|
|
|
|
для: SoftTime
(22.06.2007 в 03:28)
| | Увы, 72 балла.
64 - Декодирование выполняется с ошибкой.
8 - несоответствие сравнений данных и кода
Тест вырубается набором данных вида "\0".
Штрафных баллов : 72
Проверка на длинном тестовом наборе: 65792 байт
Тестовый набор данных декодирован с ошибкой:
Размер копии: 69824
В копии не совпадают с оригиналом 65474 байт
|
| |
|
|
|
|
|
|
|
для: Trianon
(22.06.2007 в 14:30)
| | Тест вырубается набором данных вида "\0".
Только если 0x00 будет в начале какой-то четверки байт... | |
|
|
|