This post is automatically translated with LLM. The translation content has NOT been reviewed and may contain errors.
Saw this on Bilibili, av1020723. I might create a PHP version later.
The original program was in Java and wouldn't run on my computer (unknown reason). I translated the source code to Pascal.
Java version:
Program: http://pan.baidu.com/s/1sjtZs1v
Source code: http://pan.baidu.com/s/1ntmFSLV
Pascal version source code:
uses math;
type
relation=record
p:longint;
q:longint;
end;
var
i,boy,girl,total,count:longint;
boylove,girllove:float;
cpresult:relation;
//Union variables
id,sz,lead:array[0..10000]of longint;
//Simulate Java bernoulli function
function possibility(maybe:float):boolean;
var
i:longint;
begin
i:=random(10000);
if(i>maybe*10000)then exit(false) else exit(true);
end;
//Pairing
function cp(i:integer):relation;
var
j:float;
begin
cp.p:=i;
j:=-1;
if(i<boy)then begin
if(possibility(1-boylove))then begin
//This person is single
cp.q:=i;
end else begin
//Randomly pair with a girl
while(j<boy)or(j>boy+girl)do begin
j:=randg(boy+girl/2,girl/2);
end;
cp.q:=trunc(j);
end;
end else begin
if(possibility(1-girllove))then begin
//This person is single
cp.q:=i;
end else begin
//Randomly pair with a boy
while(j<0)or(j>boy)do begin
j:=randg(boy+girl/2,girl/2);
end;
cp.q:=trunc(j);
end;
end;
end;
//Union-Find code
procedure unioninit(n:longint);
var
i:longint;
begin
for i:=0 to n-1 do begin
id[i]:=i;
sz[i]:=1;
lead[i]:=1;
end;
end;
function unionfind(p:longint):longint;
var
t:longint;
begin
t:=p;
//Find relationship root
while(t<>id[t])do t:=id[t];
unionfind:=t;
end;
function unionconnected(p,q:longint):boolean;
begin
unionconnected:=unionfind(p)=unionfind(q);
end;
procedure union(p,q:longint);
var
rootp,rootq:longint;
begin
rootp:=unionfind(p);
rootq:=unionfind(q);
//Relationship chains don't intersect
if(rootp<>rootq)then begin
if(sz[rootp]<sz[rootq])then begin
//Link rootP to rootQ to form relationship
id[rootp]:=rootq;
//Combine chain lengths
sz[rootq]:=sz[rootq]+sz[rootp];
//Remove chain head flag
lead[rootp]:=0;
end else begin
id[rootq]:=rootp;
sz[rootp]:=sz[rootq]+sz[rootp];
lead[rootq]:=0;
end;
count:=count-1;
end;
end;
procedure unionshow;
var
i:longint;
poly:array[0..100]of longint;
begin
for i:=0 to 100 do poly[i]:=0;
for i:=0 to total do begin
if(lead[i]=0)then continue;
poly[sz[i]]:=poly[sz[i]]+1;
end;
for i:=1 to 100 do begin
if(poly[i]<>0)then begin
if(i=1)then writeln('Lonely: ',poly[1])
else if(i=2)then writeln('Couple: ',poly[2])
else writeln(i,' angle love: ',poly[i]);
end;
end;
end;
begin
randomize;
write('Boy number:');
readln(boy);
write('Girl number:');
readln(girl);
total:=boy+girl;
count:=total;
unioninit(total);
write('Boy love rate:');
readln(boylove);
while(boylove>1)do boylove:=boylove/100;
write('Girl love rate:');
readln(girllove);
while(girllove>1)do girllove:=girllove/100;
for i:=0 to total-1 do begin
//Create a pair
cpresult:=cp(i);
//Record the pair
//if(cpresult.p<>cpresult.q)then writeln('Lovers logged: ',cpresult.p,' ',cpresult.q);
union(cpresult.p,cpresult.q);
end;
//Display relationship status
unionshow;
end.
Algorithm explanation:
First initialize three arrays: id
records a person's partner, sz
records relationship chain length, lead
marks whether someone is a chain head.
Initially set all id
to self, sz
to 1, lead
to 1 (true).
Scan all people using random numbers. If someone meets pairing conditions (random number within love rate), randomly assign an opposite-sex partner. The original author used a Gaussian algorithm - Java's version required square roots while Pascal's doesn't. I added square roots during translation and spent 30 minutes debugging an infinite loop.
When establishing relationships:
- Find both individuals' relationship chain roots (e.g., 1→2→3 and 31→32)
- Link roots (3→32) to form complex relationships (pentagonal here)
- Combine chain lengths, set first chain to point to second
- Remove first chain's head flag
Finally, scan the sz
array to output group counts by relationship complexity.