最近我们机房喜欢猜球——NBA某两队最终分差 ≥ 还是 ≤ 10。对于每一场的猜输者,累加他的出现次数,再用一个随机序列代码,排出一个序列。序列上的人从前往后打水去。
#include //此代码来自zzy
#include
#include
using namespace std;
int a[7]={0,1,2,3,3,4,5};//数字是人名的代号
int main()
{
srand(time(0));
for(int i=1;i<=30000;i++)
random_shuffle(a+1,a+1+6);
for(int i=1;i<=6;i++) printf("%d ",a[i]);
return 0;
}
然而,机房zzy不满足,打水太累了,于是他将代码改了改 (他自己是3):
#include
#include
#include
using namespace std;
int a[7]={0,1,2,3,3,4,5};
int main()
{
srand(time(0));
while(a[5]!=3 || a[6]!=3)
random_shuffle(a+1,a+1+6);
for(int i=1;i<=6;i++) printf("%d ",a[i]);
return 0;
}
zzy还道:“你们看看这份代码有什么问题?” 但是很快就被机智聪明的我们发现了。但我想,我们是否可以更改STL库,神不知鬼不觉地坑队友。
我们知道上面的__first , __last 就是我们传上去的函数头尾的地址。
那么我们把STL上的代码拷下来,并按照格式先打一份目标代码:
#include
#include
#include
using namespace std;
int a[7]={0,1,2,3,3,4,5},tt=0;
void rs(int first,int last)
{
if(first==last) return;
int y;
if(tt==0) { tt++; std::swap(a[first+1],a[last-1]); }
for(int i=first+1;i!=last-1;++i)
{
y=first+rand()%(i-first+1);
/*显然i最大为last-2 而rand()%(last-2-first+1)=
rand()%(last-first-1)
0 <= rand()%(last-first-1) <= last-first-2
也就是说随机数永远都不会改变a[last-1]的值 */
std::swap(a[i],a[y]);
}
}
int main()
{
srand(time(0));
for(int i=1;i<=30000;i++)
// random_shuffle(a+1,a+1+6);
rs(1,1+6);
for(int i=1;i<=6;i++) printf("%d ",a[i]);
return 0;
}
//因为怕有读者看不懂,在这里解释一下代码:
//swap是交换两个值的函数,rand()是返回一个随机的数
我是2,这样可以保证每一次2都在最后,但这样做过于明显,所以可以自主地加一些优化:比如说奇数次运行代码我在最后,偶数次在倒数第2。这些就留给机智聪明的读者们想了。
在这里,我必须要说一个坑点,STL有两个地方要改:
好,说正事:
眼尖的本作者看到了Random,但是我不需要随机,所以我们大胆改造,全变成int
(由于不知名原因不改Random会报错,所以只好更改了……) :
但改成 int 后悲剧了,按下F11后:
但我眼尖地发现除掉Random之后很大一部分是Iterator,所以我么大胆猜测,将所
有_RandomAccessIterator改成_Iterator,上代码:
int __tt=0;
template<typename _Iterator>
void
random_shuffle(_Iterator __first,_Iterator __last)
{
// concept requirements
if (__first == __last)
return;
if(__tt==0) { __tt++; std::iter_swap(__first+1,__last-1); }
for(_Iterator __i=__first+1;__i!=__last-1;++__i)
std::iter_swap(__i,__first+rand()%(__i-__first+1));
}
最后,我们的面板为:除了上述代码外,其他有关的都屏蔽掉:
最后,我们再打回原代码,继续向机房队友炫耀“你们看看这份代码有什么问题?”
然后,挖出大坑等着队友来跳:
#include
#include
#include
using namespace std;
int a[7]={0,1,2,3,3,4,5};//数字是人名的代号
int main()
{
srand(time(0));
for(int i=1;i<=30000;i++)
random_shuffle(a+1,a+1+6);
for(int i=1;i<=6;i++) printf("%d ",a[i]);
return 0;
}
1.笔者自己并不知道STL内的格式,深表惭愧,但代码还是可以用的,以后若是有机会(有能力),再介绍一下STL的书写格式。
2.篡改STL需小心,不然以后调代码时可能会莫名出错,建议另找一台机试试,或打屏蔽保护原代码,如果已经出现了问题,可以到另一台机拷它的STL库来替换。
3.笔者自己曾手贱自建了一个stl_algo.h的C++文件,还运行了,以致Ctrl+左击回不去原STL,像这种情况,直接回 C:\Program Files\Dev-Cpp\MinGW32\lib\gcc\mingw32\4.8.1\include\c++\bits
将原stl_algo.h运行一遍就好了。