Simulate the Universe!
C++ (2420,2243,2353,1860,1822*.9=1639.8)
Ok, so this is probably the worst ever code golf submission, but it's my first and I had fun. I think it even works. :)
#include <iostream>
#include <list>
#include <string>
#include <time.h>
#define D r=rand();d=((double)r/RAND_MAX)
using namespace std;class P{int n[25];public:int S;P(int N){for(S=0;S<24;S++)n[S]=0;n[24]=N;S=1;}void C(){string s[25]={"down quark","down antiquark","up quark","up antiquark","bottom quark","bottom antiquark","tau lepton","antitau lepton","charm quark","charm antiquark","strange quark","strange antiquark","neutrino","antineutrino","muon","antimuon","gluon","photon","electron","positron","top quark","top antiquark","Z boson","W boson","Higgs boson"};int r,i,j,w,f,F,x,y;double d;S=0;F=0;for(i=0;i<25;i++){w=0;for(j=0;j<n[i];j++){D;x=-1;y=-1;if(i==24){if(d<.000433){D;if(d<.648){x=4;y=5;}else if(d<.789){x=23;y=23;}else if(d<.8772){x=16;y=16;}else if(d<.9476){x=6;y=7;}else if(d<.9803){x=8;y=9;}else if(d<.9962){x=22;y=22;}else if(d<.99843){x=17;y=17;}else if(d<.99954){x=22;y=17;}else if(d<.999784){x=14;y=16;}else{x=21;y=20;}}}else if(i==23){if(d<.5){D;if(d<.33){x=19;y=12;}else if(d<.67){x=16;y=12;}else{x=17;y=12;}}}else if(i==22){if(d<.5){D;if(d<.206){x=12;y=13;}else if(d<.24){x=18;y=19;}else if(d<.274){x=14;y=16;}else if(d<.308){x=16;y=17;}else if(d<.46){x=0;y=1;}else if(d<.612){x=10;y=11;}else if(d<.764){x=4;y=5;}else if(d<.882){x=2;y=3;}else{x=8;y=9;}}}else if(i==21||i==20){if(d<.1295){D;x=23;if(d<.33){y=0;}else if(d<.67){y=10;}else{y=4;}if(i==21)y-=32;}}if(x>=0){++n[x];++n[y];w++;}if(x>19||y>19)S=1;}n[i]-=w;if(n[i]>0){F=i;if(i>19)S=1;}}cout<<"The universe contains";f=0;for(i=0;i<25;i++){if(n[i]>0){cout<<(f>0?(i<F?", ":" and "):" ")<<n[i]<<' '<<s[i]<<(n[i]>1?"s":"");f=1;}}cout<<'.'<<endl;}};int main(int c,char* v[]){int w=1,y=0;if(c>1){w=atoi(v[1]);}srand(time(0));rand();P p=P(w);int Time=time(0);while(p.S){p.C();y++;}cout<<"Simulation ended after "<<(double)y/10<<" yoctoseconds.";}
Fast Version
This one isn't as short (9 extra bytes), but it runs way faster for testing huge numbers. Since it's not short enough to compete, I also added a little code to clock real-world execution time and print it right after simulated time. My original version did n=100k in about 8 minutes. The version above does it in about 2 minutes. This fast version can do it in 9 seconds. n=1 million took 53 seconds.
#include <iostream>
#include <list>
#include <string>
#include <time.h>
#define D r=rand();d=((double)r/RAND_MAX)
using namespace std;class P{int n[25];public:int S;P(int N){for(S=0;S<24;S++)n[S]=0;n[24]=N;S=1;}void C(){string s[25]={"down quark","down antiquark","up quark","up antiquark","bottom quark","bottom antiquark","tau lepton","antitau lepton","charm quark","charm antiquark","strange quark","strange antiquark","neutrino","antineutrino","muon","antimuon","gluon","photon","electron","positron","top quark","top antiquark","Z boson","W boson","Higgs boson"};int r,i,j,w,f,F,x,y;double d;S=0;F=0;for(i=20;i<25;i++){w=0;for(j=0;j<n[i];j++){D;x=-1;y=-1;if(i==24){if(d<.000433){D;if(d<.648){x=4;y=5;}else if(d<.789){x=23;y=23;}else if(d<.8772){x=16;y=16;}else if(d<.9476){x=6;y=7;}else if(d<.9803){x=8;y=9;}else if(d<.9962){x=22;y=22;}else if(d<.99843){x=17;y=17;}else if(d<.99954){x=22;y=17;}else if(d<.999784){x=14;y=16;}else{x=21;y=20;}}}else if(i==23){if(d<.5){D;if(d<.33){x=19;y=12;}else if(d<.67){x=16;y=12;}else{x=17;y=12;}}}else if(i==22){if(d<.5){D;if(d<.206){x=12;y=13;}else if(d<.24){x=18;y=19;}else if(d<.274){x=14;y=16;}else if(d<.308){x=16;y=17;}else if(d<.46){x=0;y=1;}else if(d<.612){x=10;y=11;}else if(d<.764){x=4;y=5;}else if(d<.882){x=2;y=3;}else{x=8;y=9;}}}else if(i==21||i==20){if(d<.1295){D;x=23;if(d<.33){y=0;}else if(d<.67){y=10;}else{y=4;}if(i==21)y-=32;}}if(x>=0){++n[x];++n[y];w++;}if(x>19||y>19)S=1;}n[i]-=w;if(n[i]>0&&i>19)S=1;}for(i=0;i<25;i++){if(n[i]>0)F=i;}cout<<"The universe contains";f=0;for(i=0;i<25;i++){if(n[i]>0){cout<<(f>0?(i<F?", ":" and "):" ")<<n[i]<<' '<<s[i]<<(n[i]>1?"s":"");f=1;}}cout<<'.'<<endl;}};int main(int c,char* v[]){int w=1,y=0;if(c>1){w=atoi(v[1]);}srand(time(0));rand();P p=P(w);int Time=time(0);while(p.S){p.C();y++;}cout<<"Simulation ended after "<<(double)y/10<<" yoctoseconds.";cout<<endl<<"Time Taken: "<<(time(0)-Time)<<" seconds."<<endl;}
Sample output (no args)
The universe contains 1 Higgs boson.
... (many lines later)
The universe contains 1 Higgs boson.
The universe contains 1 bottom quark and 1 bottom antiquark.
Simulation ended after 339.4 yoctoseconds.
Sample output (universe.exe 10):
The universe contains 10 Higgs bosons.
The universe contains 1 bottom quark, 1 bottom antiquark and 9 Higgs bosons.
The universe contains 2 bottom quarks, 2 bottom antiquarks and 8 Higgs bosons.
The universe contains 3 bottom quarks, 3 bottom antiquarks and 7 Higgs bosons.
The universe contains 4 bottom quarks, 4 bottom antiquarks and 6 Higgs bosons.
The universe contains 4 bottom quarks, 4 bottom antiquarks, 1 charm quark, 1 charm antiquark and 5 Higgs bosons.
The universe contains 5 bottom quarks, 5 bottom antiquarks, 1 charm quark, 1 charm antiquark and 4 Higgs bosons.
The universe contains 5 bottom quarks, 5 bottom antiquarks, 1 charm quark, 1 charm antiquark, 2 Z bosons and 3 Higgs bosons.
The universe contains 5 bottom quarks, 5 bottom antiquarks, 1 charm quark, 1 charm antiquark, 1 neutrino, 1 antineutrino, 1 Z boson and 3 Higgs bosons.
The universe contains 5 bottom quarks, 5 bottom antiquarks, 1 charm quark, 1 charm antiquark, 2 neutrinos, 2 antineutrinos and 3 Higgs bosons.
The universe contains 6 bottom quarks, 6 bottom antiquarks, 1 charm quark, 1 charm antiquark, 2 neutrinos, 2 antineutrinos and 2 Higgs bosons.
The universe contains 7 bottom quarks, 7 bottom antiquarks, 1 charm quark, 1 charm antiquark, 2 neutrinos, 2 antineutrinos and 1 Higgs boson.
The universe contains 7 bottom quarks, 7 bottom antiquarks, 1 charm quark, 1 charm antiquark, 2 neutrinos, 2 antineutrinos and 2 W bosons.
The universe contains 7 bottom quarks, 7 bottom antiquarks, 1 charm quark, 1 charm antiquark, 2 neutrinos, 2 antineutrinos and 2 W bosons.
The universe contains 7 bottom quarks, 7 bottom antiquarks, 1 charm quark, 1 charm antiquark, 3 neutrinos, 2 antineutrinos, 1 photon and 1 W boson.
The universe contains 7 bottom quarks, 7 bottom antiquarks, 1 charm quark, 1 charm antiquark, 4 neutrinos, 2 antineutrinos, 1 gluon and 1 photon.
Simulation ended after 1160.5 yoctoseconds.
Sample Output (universe.exe 1000000)
(not quite 10^90, but we're getting there)
(about a minute, 14 MB and 33000 lines of output later)
The universe contains 5006 down quarks, 4945 down antiquarks, 3858 up quarks, 3858 up antiquarks, 653289 bottom quarks, 653190 bottom antiquarks, 70388 tau leptons, 70388 antitau leptons, 36449 charm quarks, 36449 charm antiquarks, 4956 strange quarks, 4873 strange antiquarks, 289364 neutrinos, 6764 antineutrinos, 1401 muons, 275514 gluons, 99433 photons, 1065 electrons and 94219 positrons.
Simulation ended after 3299.9 yoctoseconds.
Larger Outputs
If you're using console output from a command line, I would suggest something like universe.exe 100 > temp.txt
so it will go much faster. With Notepad++, you can then open temp.txt, hit ctrl+H
, enter ^(.*?)$\s+?^(?=.*^\1$)
into the Find What field, enter nothing in the Replace With field, turn Search Mode to Regular Expression
, turn In selection and . matches newline OFF
, then hit Replace All
. Now you just see where the changes occurred instead of 8000 lines of output (I do seem to get bugs doing more than 2000-3000 lines at a time though).
Fixes/Tweaks
v4 - complete overhaul, removed list, one character array, moved almost everything into the class functions. Fixed output error, was using "," instead of "and" for last item. Sped up execution a *lot* as an added bonus. :)
v3 - more fixes
v2 - more shorter
v1 - fixed numerous little issues, bug fixes
v0 - baseline
Python 3, 1,247 * 0.9 = 1,122.3
Well, this is my longest entry by a long shot, but at least I'm shorter than C++.
Now with added bonus! It has to be called with a number as the first argument.
My universe didn't work with decaying particles other than Higgs Boson, but now it does. Also, I didn't have pluralization or punctuation correct, but I actually do now.
I'm getting so close to sub 1k!
import random,sys,numpy as h
H,M,G,N,P,K,L,n,s='photon,muon,gluon,neutrino,positron, quark,tau lepton, boson,The universe '.split(',')
c=random.choice
Z=' anti'+K[1:]
B='bottom'+K
A=B[:6]+Z
U='anti '+M
T=U[:4]+L
Q='charm'+K
C=Q[:5]+Z
S='strange'+K
R=S[:7]+Z
D='down'+K
O=D[:4]+Z
def w(c):v,t=zip(*c);t=h.array(t);return v[h.random.choice(len(v),p=t/t.sum())]
y=M,U
f=lambda p:{z:w([(c([('up'+K,'up'+Z),(Q,C)]),11.8),((N,U[:5]+N),20.6),(c([('electron',P),y,(L,T)]),3.4),(c([(S,R),(B,B),(D,O)]),15.2)]),E:(I,c([D,S,B])),F:(I,c([O,R,A])),I:c([(P,N),(U,N),(T,N)]),J:w([((B,A),64.8),((I,I),14.1),((G,G),8.82),((L,T),7.04),((Q,C),3.27),((z,z),1.59),((H,H),0.223),((z,H),0.111),(y,0.0244),((E,F),0.0246)])}[p]
z='Z'+n,50
E='top'+K,12.95
F='top'+Z,E[1]
I='W'+n,50
J='Higgs'+n,.0433
u=[J]*int(sys.argv[1])
b={z,E,F,I,J}
k=isinstance
d=lambda p:p if k(p,str)else w([(p,100-p[1]),(f(p),p[1])])
a=0
g=lambda x:[x[0],x][k(x,str)]
while b&set(u):
n=[]
for p in u:q=d(p);n+=([q],(q,[q])[q in b])[p in b]
e=list(map(g,n));e=[(x,x+'s')[e.count(x)>1]for x in e];print(s+'contains %s'%', '.join(('%s %s'%(e.count(x),g(x))for x in set(e[:-1])))+('.',' and %s %s.'%(e.count(e[-1]),e[-1]))[len(set(e))>1]);a+=.1;u=n
print(s+'ended after %s yoctoseconds.'%round(a,1))
Perl 6, (707 bytes -10%) Score 636.3
With some unneeded line breaks for a bit more readability:
{
my%p;
%p=<H H2309.469bB64.8WW14.1gg8.82lL7.04cC3.27ZZ1.59pp0.223Zp0.111mM0.0244tT0.0216 W W3pn1Mn1Ln1 Z Z100nN20.6ep3.4mM3.4lL3.4dD15.2sS15.2bB15.2uU11.8cC11.8 t t7.722Wd1Ws1Wb1 T T7.722WD1WS1WB1>;
my&f=*.comb[0];
my%h;
%h{.&f}="$_ boson" for <Higgs W Z>;
{
%h{.&f}="$_ quark";
%h{.&f.uc}="$_ antiquark"
} for <bottom top charm up down strange>;
%h{.&f}=$_~"on" for <glu phot electr positr>;
%h{.&f.uc}="anti"~(%h{.&f}=$_) for <muon neutrino>;
%h<L>="anti"~(%h<l>="tau lepton");
my$t;
("H"x$^a),{
$t+=.1;
S:g/./{%((%p{$/}||$/~1).comb(/(\D+|<:!L>+)/)).Mix.roll}/
}...{
say "The universe contains {
.comb.Bag.map({
"{.value,%h{.key}~'s'x(.value>1)}"
}).join(', ')
}.";
!/<[HWZtT]>/
};
say "Simulation ended after $t yoctoseconds."
}
Try it online!
The universe contains 4 Higgs bosons.
The universe contains 4 Higgs bosons.
The universe contains 4 Higgs bosons.
The universe contains 4 Higgs bosons.
The universe contains 3 Higgs bosons, 2 gluons.
The universe contains 3 Higgs bosons, 2 gluons.
The universe contains 3 Higgs bosons, 2 gluons.
The universe contains 3 Higgs bosons, 2 gluons.
The universe contains 3 Higgs bosons, 2 gluons.
The universe contains 3 Higgs bosons, 2 gluons.
The universe contains 3 Higgs bosons, 2 gluons.
The universe contains 3 Higgs bosons, 2 gluons.
The universe contains 1 tau lepton, 2 Higgs bosons, 2 gluons, 1 antitau lepton.
The universe contains 1 tau lepton, 2 Higgs bosons, 2 gluons, 1 antitau lepton.
The universe contains 1 tau lepton, 2 Higgs bosons, 2 gluons, 1 antitau lepton.
The universe contains 1 tau lepton, 2 Higgs bosons, 2 gluons, 1 antitau lepton.
The universe contains 1 tau lepton, 1 Higgs boson, 4 gluons, 1 antitau lepton.
The universe contains 1 tau lepton, 6 gluons, 1 antitau lepton.
Simulation ended after 1.7 yoctoseconds.
Some explanation: God and Man
There are 2 data structures holding the physics %p
and the naming %h
; god and man as it were. The physics hash gives a set of strings indexed by original unstable particle letter, which can be split, hashed and converted to a Mix:
say %((%p<H>).comb(/(\D+|<:!L>+)/)).Mix;
> Mix(H(2309.469), WW(14.1), ZZ(1.59), Zp(0.111), bB(64.8), cC(3.27), gg(8.82), lL(7.04), mM(0.0244), pp(0.223), tT(0.0216))
Each particle gets a letter, and thus each of these Mixes specifies a collection of particle decays. H decays to WW, with probability weighting 14.1. Particle-antiparticle pairs are coded with lower and uppercase letters, like c
and C
for charm quark and charm antiquark.
And man thought for a bit, and named it antitau lepton
The naming is all set up in %h
, which just maps each letter to a particle name. It's golfed to a degree, but I suspect there's room for improvement given the amount of repetition there.
p => positron
g => gluon
Z => Z boson
B => bottom antiquark
e => electron
s => strange quark
d => down quark
W => W boson
m => muon
U => up antiquark
c => charm quark
H => Higgs boson
L => antitau lepton
N => antineutrino
n => neutrino
S => strange antiquark
D => down antiquark
T => top antiquark
u => up quark
t => top quark
b => bottom quark
M => antimuon
C => charm antiquark
l => tau lepton
Original string
With those two structures in place, the universe is simulated, of course, by string manipulation. So "H"
is a universe with a single Higgs boson in it. The generator structure _,_..._
is used to create a loop, and separates evolving the state of the universe string (held in $_
) from printing it out. The printing is done by Bagging the letters in the universe and mapping the resulting counts (with plurals!).
Sneezing particles into being
Evolving particles involves mapping them to a value picked from the Mix for that particle; so t
, the top quark, evolves as
t=>7.722
Wd=>1
Ws=>1
Wb=>1
Perl6 permits us to randomly choose one of those keys with those given weightings via the flooringly simple .roll
. So we roll for t
and get, say Wb
and substitute it into our universe "HtT"->"HWbT". Each unstable particle has itself as a possible roll, which permits us to simplify the structure vs having to check whether it decayed or not; most of the time you roll for "H", you just get "H" again.
Experimental string theory
You can watch the universe string evolve via this modified version.
HHH
HHH
HHbB
HHbB
HHbB
HHbB
HHbB
HHbB
lLHbB
lLHbB
lLHbB
lLHbB
lLHbB
lLbBbB
Performance
I've taken it as far as 100 H on TIO, inevitably if you wanted to go much further it would be better to make some changes, this is Grand Unified String Theory after all.