奇怪的AV号-BV号转换程序增加了!
众所周知,哔哩哔哩已经把旧版视频番号AV号隐藏,只显示新版番号BV号,而这两种番号可以通过一个算法相互转换。
我用两种深奥编程语言,即娱乐性大于实用性的编程语言实现了番号转换,话不多说,直接上源码
文言 wenyan-lang
以下代码写于2020年3月
吾嘗觀「位經」之書。方悟「異或」之義。
吾嘗觀「列經」之書。方悟「索一」之義。
吾嘗觀「算經」之書。方悟「取底」之義。
吾有一列。名之曰「字母表」。
充「字母表」以『f』。以『Z』。以『o』。以『d』。
以『R』。以『9』。以『X』。以『Q』。以『D』。以『S』。
以『U』。以『m』。以『2』。以『1』。以『y』。以『C』。
以『k』。以『r』。以『6』。以『z』。以『B』。以『q』。
以『i』。以『v』。以『e』。以『Y』。以『a』。以『h』。
以『8』。以『b』。以『t』。以『4』。以『x』。以『s』。
以『W』。以『p』。以『H』。以『n』。以『J』。以『E』。
以『7』。以『j』。以『L』。以『5』。以『V』。以『G』。
以『3』。以『g』。以『u』。以『M』。以『T』。以『K』。
以『N』。以『P』。以『A』。以『w』。以『c』。以『F』。
吾有一列。名之曰「亂序表」。
充「亂序表」以七。以三。以五。以九。以六。以一十。以四。以八。以二。以一。
吾有一數。曰一億七千七百四十五萬一千八百一十二。名之曰「異或數」。
吾有一列。名之曰「加數」。
充「加數」以六。以五十五。以三。以一十七。以一十七。
以一十三。以一十三。以四十。以三十一。以一十三。
今有一術。名之曰「甲號轉乙號」。欲行是術。必先得一數。曰「甲號」。乃行是術曰。
施「異或」於「甲號」於「異或數」。名之曰「子」。
吾有一列。名之曰「丑」。
吾有一言。名之曰「乙號」。
吾有一數。曰一。名之曰「戌」。
恆為是。若「戌」大於十者乃止也。
夫「加數」之「戌」。加其於「子」。昔之「子」者。今其是矣。
夫「子」。除其以五十八。所餘幾何。充「丑」以其。
夫「子」。除其以五十八。取一以施「取底」。昔之「子」者。今其是矣。
加一於「戌」。昔之「戌」者。今其是矣。云云。
凡「亂序表」中之「戌」者。
夫「丑」之「戌」。加其以一。夫「字母表」之其。加其於「乙號」。昔之「乙號」者。今其是矣。
云云。
乃得「乙號」。
是謂「甲號轉乙號」之術也。
今有一術。名之曰「乙號轉甲號」。欲行是術。必先得一言。曰「乙號」。乃行是術曰。
吾有一列。名之曰「丑」。
吾有二數。曰零。曰一。名之曰「子」。曰「戌」。
恆為是。若「戌」大於十者乃止也。
夫「字母表」。夫「乙號」之「戌」。取二以施「索一」。減其以一。名之曰「甲」。
夫「亂序表」之「戌」。名之曰「乙」。
昔之「丑」之「乙」者。今「甲」是矣。
加一於「戌」。昔之「戌」者。今其是矣。云云。
昔之「戌」者。今十是矣。恆為是。若「戌」小於一者乃止也。
夫「丑」之「戌」。名之曰「丙」。
夫「加數」之「戌」。名之曰「丁」。
乘「子」以五十八。加其以「丙」。減其以「丁」。昔之「子」者。今其是矣。
減一於「戌」。昔之「戌」者。今其是矣。云云。
施「異或」於「子」。於「異或數」。乃得矣。
是謂「乙號轉甲號」之術也。
施「甲號轉乙號」於一十七萬零一。書之。
施「乙號轉甲號」於『17x411w7KC』。書之。
dongbei - 东北方言编程语言
以下代码写于2020年8月
异或(老张,老王)咋整:
滚犊子吧整eval(老张、“^”、老王)。
整完了。
老几(张家庄,老张)咋整:
几从一到(张家庄有几个坑)磨叽:
寻思:老张跟张家庄的老几一样一样的?
要行咧就滚犊子吧几。
磨叽完了。
滚犊子吧零。
整完了。
字母表装「“f”,“Z”,“o”,“d”,“R”,“9”,“X”,“Q”,
“D”,“S”,“U”,“m”,“2”,“1”,“y”,“C”,“k”,“r”,
“6”,“z”,“B”,“q”,“i”,“v”,“e”,“Y”,“a”,“h”,
“8”,“b”,“t”,“4”,“x”,“s”,“W”,“p”,“H”,“n”,
“J”,“E”,“7”,“j”,“L”,“5”,“V”,“G”,“3”,“g”,
“u”,“M”,“T”,“K”,“N”,“P”,“A”,“w”,“c”,“F”」。
乱序表装「7,3,5,9,6,10,4,8,2,1」。
异或数装177451812。
【加数】装「6,55,3,17,17,13,13,40,31,13」。
AV转BV(AV号)咋整:
老王装整异或(AV号,异或数)。
张家庄都是活雷锋。
BV号装“”。
几从一到十磨叽:
老王装(老王加【加数】的老几)。
张家庄来了个(老王刨掉一堆堆58)。
老王装(老王齐整整地除以58)。
磨叽完了。
几在乱序表磨叽:
BV号装BV号、字母表的老(张家庄的老几加一)。
磨叽完了。
滚犊子吧BV号!
整完了。
BV转AV(BV号)咋整:
张家庄都是活雷锋。
老王装零。
几从一到十磨叽:
张家庄来了个零。
磨叽完了。
几从一到十磨叽:
张家庄的老(乱序表的老几)装整老几(字母表,BV号的老几)减一。
磨叽完了。
几从一到十磨叽:
老王装老王乘58加(张家庄的老(11减几))减(【加数】的老(11减几))。
磨叽完了。
滚犊子吧整异或(老王,异或数)!
整完了。
唠唠:整AV转BV(170001)。
唠唠:整BV转AV(“17x411w7KC”)。
(附赠完美PHP版本)
以下代码写于2020年7月
<?php
/**
* AV号、BV号转换
*
* @author DGCK81LNN
*/
$avbv_alphabet = 'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF';
$avbv_table = array();
for ($i = 0; $i < strlen($avbv_alphabet); $i++) {
$avbv_table[] = substr($avbv_alphabet, $i, 1);
}
$avbv_bvreg = "/^[$avbv_alphabet]{10}\$/u";
$avbv_s = [6, 2, 4, 8, 5, 9, 3, 7, 1, 0];
$avbv_xor = 177451812;
$avbv_add = [6, 55, 3, 17, 17, 13, 13, 40, 31, 13];
/**
* AV号转BV号
*
* @param int|string $av
* @return string 带“BV”前缀的BV号
*
* @throws InvalidArgumentException 传入的参数不是整数或字符串
* @throws DomainException 传入的整数不是正整数
* @throws UnexpectedValueException 传入的字符串不是"AV"后接一个十进制正整数的形式
*/
function av2bv($av)
{
global $avbv_table, $avbv_s, $avbv_xor, $avbv_add;
$dump = var_export($av, true);
$num = NAN;
if (is_integer($av))
if ($num <= 0)
throw new DomainException("av2bv($dump): AV号必须大于0");
else
$num = $av;
else if (is_string($av))
if (preg_match("/^AV[1-9][0-9]*$/i", $av))
$num = (int)substr($av, 2);
else
throw new UnexpectedValueException("av2bv($dump): AV号格式有误");
else
throw new InvalidArgumentException("av2bv($dump): 参数必须是整数或字符串");
$num ^= $avbv_xor;
$num58 = array();
$result = 'BV';
for ($i = 0; $i < 10; $i++) {
$num += $avbv_add[$i];
$num58[] = $num % 58;
$num = floor($num / 58);
}
foreach ($avbv_s as $digitIndex)
$result .= $avbv_table[$num58[$digitIndex]];
return $result;
}
/**
* BV号转AV号
* (“BV”后的“1”不能省略)
*
* @param string $bv
* @param bool $returnNumber 是否要返回一个整数。默认返回带“AV”前缀的字符串。
* @return int|string 带“AV”前缀的AV号,或整数形式的AV号
*
* @throws InvalidArgumentException 第一个参数不是字符串
* @throws UnexpectedValueException 传入的BV号不符合10位base58或“BV”后接10位base58的格式
* @throws RangeException 进行按位异或运算后得到负数
*/
function bv2av($bv, $returnNumber = false)
{
global $avbv_table, $avbv_bvreg, $avbv_s, $avbv_xor, $avbv_add;
$dump = var_export($bv, true);
$str = '';
$err = false;
if (!is_string($bv))
throw new InvalidArgumentException("bv2av($dump): 第一个参数必须是字符串");
if (strlen($bv) === 10)
$str = $bv;
else if (strlen($bv) === 12 && stripos($bv, 'BV') === 0)
$str = substr($bv, 2);
else
$err=true;
if($err || !preg_match($avbv_bvreg, $str))
throw new UnexpectedValueException("bv2av($dump): BV号格式有误");
$num58 = array();
$num = 0;
for ($i = 0; $i < 10; $i++) {
$char = $str[$i];
$num58[$avbv_s[$i]] = array_search($char, $avbv_table);
}
for ($i = 9; $i >= 0; $i--) {
$num *= 58;
$num += $num58[$i] - $avbv_add[$i];
}
$num ^= $avbv_xor;
if ($num <= 0)
throw new RangeException("bv2av($dump): AV号溢出 ($num)");
return $returnNumber ? $num : "AV$num";
}
/**
* 将任意格式的视频番号转换为AV号数字
* (“BV”后的“1”不能省略)
*
* @param int|string $input
* @return int 整数形式的AV号
*
* @throws InvalidArgumentException 传入的参数不是整数或字符串
* @throws DomainException 传入的整数不是正整数
* @throws UnexpectedValueException 无法识别传入的字符串番号
* @throws RangeException 进行按位异或运算后得到负数
*/
function getAID($input)
{
global $avbv_bvreg;
$dump = var_export($input, true);
if (is_integer($input))
if ($input <= 0)
throw new DomainException("getAID($dump): AV号必须大于0");
else
return $input;
else if (is_string($input)) {
if (preg_match("/^AV[1-9][0-9]*$/i", $input))
return (int)substr($input, 2);
else if (preg_match($avbv_bvreg, substr($input, 2)))
return bv2av($input);
else if (stripos($input, 'BV') === 0 && preg_match($avbv_bvreg, substr($input, 2)))
return bv2av($input);
else
throw new UnexpectedValueException("getAID($dump): 字符串参数格式有误");
}
else
throw new InvalidArgumentException("getAID($dump): 参数必须是整数或字符串");
}
/**
* 将任意格式的视频番号转换为BV号字符串
* (“BV”后的“1”不能省略)
*
* @param int|string $input
* @return string
*
* @throws InvalidArgumentException 传入的参数不是整数或字符串
* @throws DomainException 传入的整数不是正整数
* @throws UnexpectedValueException 无法识别传入的字符串番号
*/
function getBVID($input)
{
global $avbv_bvreg;
$dump = var_export($input, true);
if (is_integer($input))
if ($input <= 0)
throw new DomainException("getBVID($dump): AV号必须大于0");
else
return av2bv($input);
else if (is_string($input)) {
if (preg_match("/^AV[1-9][0-9]*$/i", $input))
return av2bv($input);
else if (preg_match($avbv_bvreg, substr($input, 2)))
return "BV$input";
else if (stripos($input, 'BV') === 0 && preg_match($avbv_bvreg, substr($input, 2)))
return $input;
else
throw new UnexpectedValueException("getBVID($dump): 字符串参数格式有误");
}
else
throw new InvalidArgumentException("getBVID($dump): 参数必须是整数或字符串");
}
?>
(附赠略简陋JS版本)
以下代码写于2020年3月
const table = [...'fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF'];
const s = [6, 2, 4, 8, 5, 9, 3, 7, 1, 0];
const xor = 177451812;
const add = [6, 55, 3, 17, 17, 13, 13, 40, 31, 13];
const av2bv = (av) => {
let num = NaN;
if (typeof av === 'number') {
num = Math.floor(av);
} else if (typeof av === 'string') {
if (av.toUpperCase().startsWith("AV"))
num = Math.floor(av.substr(2));
} else {
let e = new Error();
e.name = "TypeError";
e.message = '传入的AV号必须是字符串或数字';
throw e;
};
if (isNaN(num)){
let e = new Error();
e.name = "SyntaxError";
e.message = 'AV号必须是数字';
throw e;
}
else if (num <= 0) {
let e = new Error();
e.name = "RangeError";
e.message = 'AV号必须大于0';
throw e;
};
num ^= xor;
let num58 = [], result = "BV";
for (let i=0; i<10; i++) {
num += add[i];
num58.push(num%58);
num = Math.floor(num/58);
}
s.forEach(digitIndex => result += table[num58[digitIndex]]);
return result;
};
const bv2av = bv => {
let str = '';
if (typeof bv !== "string") {
let e = new Error();
e.name = "TypeError";
e.message = '传入的BV号必须是字符串';
throw e;
};
if (bv.length === 10) {
str = bv;
} else if (bv.length === 12 && bv.toUpperCase().startsWith("BV")) {
str = bv.substr(2);
} else {
let e = new Error();
e.name = "SyntaxError";
e.message = 'BV号必须是10位字母数字编码';
throw e;
};
if (!str.match(/[fZodR9XQDSUm21yCkr6zBqiveYah8bt4xsWpHnJE7jL5VG3guMTKNPAwcF]{10}/gu)) {
let e = new Error();
e.name = "SyntaxError";
e.message = 'BV号含有非法字符';
throw e;
};
let num58 = [], num=0;
[...str].forEach((char, i) => {
num58[s[i]] = table.indexOf(char);
});
for (let i=9; i>=0; i--){
num *= 58;
num += num58[i] - add[i];
}
num ^= xor;
return "AV" + num;
};