9
\$\begingroup\$

Create a program to display some approximation of a bell curve. You are free to use whatever method you wish for generating the data, but the data must be displayed vertically, as in oriented like so:

Other restrictions:

  • Your code must create the approximation, that is, don't hardcode or take data from the internet.
  • The shape must actually look like a bell.

This is a , so be creative.

\$\endgroup\$
13
  • \$\begingroup\$ Sorry for not remembering to ask this when it was in the sandbox, but is ASCII-art ok? \$\endgroup\$ Mar 2, 2014 at 2:08
  • \$\begingroup\$ @Victor Of course. (as long as you orient vertically) \$\endgroup\$
    – Justin
    Mar 2, 2014 at 2:08
  • 1
    \$\begingroup\$ What is etc? That rule needs clarification. What about getInternetBellCurve+0? What does "hard-coding" imply? This rule is currently highly opinion based. \$\endgroup\$
    – Doorknob
    Mar 2, 2014 at 2:22
  • 2
    \$\begingroup\$ @Doorknob The "etc" means "any other cheating method to avoid actually generating the curve by getting it already done from somewhere else". \$\endgroup\$ Mar 2, 2014 at 3:06
  • 1
    \$\begingroup\$ Related: codegolf.stackexchange.com/questions/9070/… \$\endgroup\$ Mar 3, 2014 at 3:34

19 Answers 19

12
\$\begingroup\$

Java

The method of generation is based off of the game Sugar, Sugar. In that game, sugar particles fall, traveling randomly left and right. In my program, Dust objects fall until they hit the ground. I collect data based on where they land; this is the bell curve:

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import java.util.Stack;
import javax.imageio.ImageIO;

/**
 *
 * @author Quincunx
 */
public class ApproxBellCurve {

    public static final int NUM_DUST = 10_000_000;
    public static final int NUM_THREADS = Runtime.getRuntime().availableProcessors() - 1;
    public static final int LOOP_LIMIT = NUM_DUST / (NUM_THREADS + 1);

    public static void main(String[] args) {
        BufferedImage output = new BufferedImage(2049, 2049, BufferedImage.TYPE_INT_RGB);

        Stack<Thread> threads = new Stack();

        for (int i = 0; i < NUM_THREADS; i++) {
            threads.push(new Thread(new Duster()));
            threads.peek().start();
        }

        Dust d;
        Random r = new Random();
        for (int i = 0; i < LOOP_LIMIT + NUM_DUST - (LOOP_LIMIT * (NUM_THREADS + 1)); i++) {
            d = new Dust(r);
            while (!d.end) {
                d.step();
            }
            if ((i & 1024) == 0) {
                r = new Random();
            }
        }
        while (threads.size() > 0) {
            try {
                threads.pop().join();
            } catch (InterruptedException ex) {

            }
        }
        int maxy = 0;
        for (int x = 0; x < Dust.data.length; x++) {
            maxy = Dust.data[x] > maxy ? Dust.data[x] : maxy;
        }

        for (int x = 0; x < Dust.data.length; x++) {
            for (int y = 0; y < output.getHeight(); y++) {
                output.setRGB(x, y, (y >= output.getHeight() - (Dust.data[x] * output.getHeight() / maxy)) ? 6591981 : 16777215);
            }
        }
        try {
            ImageIO.write(output, "png", new File("Filepath"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    private static class Duster implements Runnable {

        @Override
        public void run() {
            Dust d;
            Random r = new Random();
            for (int i = 0; i < LOOP_LIMIT; i++) {
                d = new Dust(r);
                while (!d.end) {
                    d.step();
                }
                if ((i & 1024) == 0) {
                    r = new Random();
                }
            }
        }

    }

    private static class Dust {

        public static int[] data = new int[2049];

        static {
            for (int i = 0; i < data.length; i++) {
                data[i] = 0;
            }
        }

        private int[] location;
        private Random r;
        public boolean end;

        public Dust(Random rand) {
            location = new int[]{1024, 0};
            r = rand;
            end = false;
        }

        public void step() {
            if (end) {
                return;
            }
            if (location[1] >= 1024) {
                end = true;
                synchronized (data) {
                    data[location[0]] += 1;
                }
                return;
            }
            location[1] += 1;
            location[0] += r.nextInt(21) - 10;
        }
    }
}

Sample output (took 1 minute to create):

enter image description here

Because of the nature of the random number generation, it is possible to get an ArrayIndexOutOfBoundsException.

I used multithreading to speed up the process. The program determines the number of processors available and creates that many threads to run the simulations.

To obtain a finer image, NUM_DUST can be increased, but that would also lead to an increased risk of an ArrayIndexOutOfBoundsException.

Each thread creates a new Random after every 1024 Dust objects are simulated. When that code was removed, the image was more coarse.

rand.nextInt(21) - 10 is to widen the distribution. A change to rand.nextInt(3) - 1 would remove all chance of an ArrayIndexOutOfBoundsException.

\$\endgroup\$
0
9
\$\begingroup\$

Mathematica

I decided it should not only look like a bell curve, it should look like a bell. So hey, let's spin it around the Z-axis and make it 3D.

And hey, while we're at it, it should sound like a bell as well.

So, each time you evaluate the code, it makes a nice pleasing church-bell BWONNGGG!

Manipulate[
 RevolutionPlot3D[PDF[NormalDistribution[mu, sigma], x], {x, -4, 4}, 
  PlotRange -> {Automatic, Automatic, Automatic}, 
  BoxRatios -> {1, 1, 1}, PlotStyle -> {Orange, Yellow}, 
  ImageSize -> {500, 500}], {{mu, 0, "mean"}, -3, 3, 
  Appearance -> "Labeled"}, {{sigma, 1.47, "standard deviation"}, .5, 
  2, Appearance -> "Labeled"}]
EmitSound[Sound[SoundNote[0, 3, "TubularBells", SoundVolume -> 1]]]

Here's what it looks like: Yo quiero Mathematica Bell!

And here's a brief video of the bell ringing.

\$\endgroup\$
7
\$\begingroup\$

Haskell, 9 LoC

Everyone's code is so ... huge, and their approximations are ... less than deterministic. Just to remind everyone of the simplicity of the actual task, here's a nine-liner in Haskell:

import Data.List; import Data.Ratio
main = do
  putStrLn "please choose the width and the maximum height:"
  [w, mh] <- (map read.words) `fmap` getLine
  let dist = map length $ group $ sort $ map length $ subsequences [2..w]
      scale = ceiling $ maximum dist % mh
      maxD = scale * ceiling (maximum dist % scale) 
  putStrLn $ unlines $ map (row dist) [maxD, maxD - scale .. 0]
      where row dist y = map (\x -> if x >= y then '*' else ' ') dist

OK... that wasn't exactly fast. Here's another go. Does it still count as not hard-coded?

import Data.List; import Data.Ratio

main = do
  putStrLn "please choose the width and the maximum height:"
  [w, mh] <- (map read.words) `fmap` getLine
  let dist = map ((w-1) `choose`) [0..(w-1)]
      scale = ceiling $ maximum dist % mh
      maxD = scale * ceiling (maximum dist % scale) 
  putStrLn $ unlines $ map (row dist) [maxD, maxD - scale .. 0]
      where row dist y = map (\x -> if x >= y then '*' else ' ') dist

factorial x = product [1..x]
n `choose` k = factorial n `div` factorial k `div` factorial (n-k)

bell curve

\$\endgroup\$
3
  • 2
    \$\begingroup\$ You mean, "Them Java users' code is so huge." The other people's codes are rather small. Also, is there anything wrong with long code? I personally enjoy popularity-contests because I am free to make my code as long as I want to. \$\endgroup\$
    – Justin
    Mar 2, 2014 at 8:39
  • \$\begingroup\$ @Quincunx Hmm... true. But I'm still shorter than the non-Java solutions :-) as for whether long code or short code should be preferred in this challenge, that's up to voters. I offer consciseness. \$\endgroup\$ Mar 2, 2014 at 8:45
  • 1
    \$\begingroup\$ Yours is huge compared to mine. :P \$\endgroup\$ Mar 6, 2014 at 22:26
6
\$\begingroup\$

Wolfram Alpha (tongue-in-cheek) 4 bytes:

Here is a practical application of the Central Limit Theorem. I even golfed it!

Type this into the input box on Wolfram Alpha:

3d20

Here is a link to the results. It interprets this input as 3 icosahedral dice, and decides you want a graph of the distribution function of the pip sums. It prints the following graph:

enter image description here

We can make the graph more and more bell shaped by adding more dice. I don't see this as taking my data from the internet since, if I could run the query engine for it on my home computer I would. Unfortunately, Wolfram Research doesn't provide it for download, though.

\$\endgroup\$
4
  • \$\begingroup\$ You can get a better looking curve with more dice and die-faces: wolframalpha.com/input/?i=10d50 \$\endgroup\$
    – Justin
    Mar 6, 2014 at 20:33
  • \$\begingroup\$ @Quincunx I wanted to keep it to 20 sided dice so that it could actually be done with physical dice that are fair. I think 20d20 looks pretty good though: wolframalpha.com/input/?i=20d20 \$\endgroup\$ Mar 6, 2014 at 20:37
  • \$\begingroup\$ @Quincunx Oh, I didn't know you could hotlink images here... I learn something new all the time \$\endgroup\$ Mar 6, 2014 at 20:39
  • \$\begingroup\$ @Quincunx I rolled back your edit, because the link went dead. \$\endgroup\$ Mar 6, 2014 at 22:00
4
\$\begingroup\$

Ruby

Simulates the classic example of bell curves, dropping a ball down a grid full of pole thingies.

a = [0]*30
1000.times do
  x = 15
  49.times do
    x += (rand(3) - 1)
  end
  a[[[x.to_i, 29].min, 0].max] += 1
end
until a.all?{|x| x == 0}
  a.each_with_index{|x,i|
    if x == 0
      print ' '
    else
      print 'x'
      a[i] -= 1
    end
  }
  puts
end

Sample output:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  xxxxxxxxxxxxxxxxxxxxxxxxxx
  xxxxxxxxxxxxxxxxxxxxxxxxxx
  xxxxxxxxxxxxxxxxxxxxxxxxxx
  x xxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxx
    xxxxxxxxxxxxxxxxxxxxxxxx
     xxxxxxxxxxxxxxxxxxxxxxx
     xxxxxxxxxxxxxxxxxxxx
     xxxxxxxxxxxxxxxxxxxx
     xxxxxxxxxxxxxxxxxxxx
     xxxxxxxxxxxxxxxxxxxx
     xxxxxxxxxxxxxxxxxxxx
     xxxxxxxxxxxxxxxxxxxx
     xxxxxxxxxxxxxxxxxxxx
     xxxxxxxxxxxxxxxxxxx
      xxxxxxxxxxxxxxxxxx
      xxxxxxxxxxxxxxxxxx
      xxxxxxxxxxxxxxxxxx
      xxxxxxxxxxxxxxxxxx
       xxxxxxxxxxxxxxxxx
        xxxxxxxxxxxxxxxx
        xxxxxxxxxxxxxxxx
        xxxxxxxxxxxxxxx
        xxxxxxxxxxxxxxx
        xxxxxxxxxxxxxxx
        xxxxxxxxxxxxxxx
        xxxxxxxxxxxxxxx
        xxxxxxxxxxxxxxx
        xxxxxxxxxxxxxxx
        xxxxxxxxxxxxxxx
        xxxxxxxxxxxxxx
        xxxxxxxxxxxxxx
         xxxxxxxxxxxxx
         xxxxxxxxxxxxx
         xxxxxxxxxxxxx
         xxxxxxxxxxxxx
         xxxxxxxxxxxxx
         xxxxxxxxxxxxx
         xxxxxxxxxxxx
          xxxxxxxxxxx
          xxxxxxxxxxx
          xxxxxxxxxxx
          xxxxxxxxxxx
           xxxxxxxxxx
           xxxxxxxxxx
           xxxxxxxxxx
           xxxxxxx xx
           xxxxxxx xx
           xxxxxxx xx
            xxxxxx xx
            xxxxxx xx
            xxxxxx x
            xxxxx  x
            xxxxx  x
              xxx  x
              xxx  x
              xxx  x
              xxx  x
              xxx  x
              xxx
              xxx
              xxx
              xxx
              xxx
              xxx
              xxx
              xxx
              xxx
              x x
              x x
              x x
              x x
              x
              x
              x

Oh, did I forget to mention it's upside down?

\$\endgroup\$
1
  • 2
    \$\begingroup\$ +1 for hiding the most abnormal part of the curve below the fold. Genius! :) \$\endgroup\$ Mar 3, 2014 at 15:39
4
\$\begingroup\$

Python

from pygame import*
t,u=640,400;init();d=display;s=d.set_mode((t,u))
s.fill(0xFFFFFF)
for x in range(t):
  d.flip();event.get()
  draw.line(s,u,(x,int(u-2**(-((x-t*.5)/120)**2)*u)),(x,u))

while time.wait(50):
 for e in event.get():
  if e.type==QUIT:exit()

This is actually a normal distribution, using 2 as the base of the exponent instead of e, and not dividing by ⎷2π, because without axes, it doesn't really matter if the area under the curve isn't exactly 1.

The last 3 lines just keep the window open until the user closes it manually.

\$\endgroup\$
4
\$\begingroup\$

Mathematica

Generating the sums of 5 random integers, each between 0 and 100, 20000 times.

Histogram[Plus @@@ RandomInteger[100, {20000, 5}]]

table


Here's the result for sums of 1,2, 3 numbers. As the number of integers to be summed increases, the curve approaches the bell shape.

When single random integers are generated, but not summed, the distribution should be fairly uniform, not favoring any value. The apparent anomaly for 100 may be the result of how Matheamtica bins data. (see https://mathematica.stackexchange.com/questions/43300/does-randominteger0-n-disfavor-n/43302#43302 )

Table[Histogram[Plus @@@ RandomInteger[100, {20000, k}]], {k, 1, 3}]

enter image description here

\$\endgroup\$
4
\$\begingroup\$

C#, WPF

Rough approximation with a hand-crafted Bézier curve. To make it more interesting: No use of Line, Path or similar, only Ellipse.

Bézier curve

public MainWindow()
{
    InitializeComponent();
    // Requires a Canvas named Canvas in XAML file
    DrawBellCurve(Canvas, 300, 300);
}

public static void DrawBellCurve(Canvas canvas, int width, int height)
{
    Point p1 = new Point(0, height);
    Point p2 = new Point(0.3 * width, 1 * height);
    Point p3 = new Point(0.4 * width, 0.1 * height);
    Point peak = new Point(width / 2, 0);
    Point p3r = new Point(width - p3.X, p3.Y);
    Point p2r = new Point(width - p2.X, p2.Y);
    Point p1r = new Point(width, height);
    List<Point> controlPoints = new List<Point> { p1, p2, p3, peak, p3r, p2r, p1r };

    DrawBezierCurve(canvas, controlPoints, Color.FromRgb(50, 200, 25));
    DrawPoints(canvas, controlPoints, 5, Color.FromRgb(80, 80, 220));
}

public static void DrawPoints(Canvas canvas, List<Point> points, double radius, Color color)
{
    foreach (var p in points)
    {
        Ellipse ellipse = new Ellipse();
        ellipse.Width = radius;
        ellipse.Height = radius;
        ellipse.SetValue(Canvas.LeftProperty, p.X - radius / 2);
        ellipse.SetValue(Canvas.TopProperty, p.Y - radius / 2);
        ellipse.Fill = new SolidColorBrush(color);
        canvas.Children.Add(ellipse);
    }
}

public static void DrawBezierCurve(Canvas canvas, List<Point> controlPoints, Color color)
{
    var curvePoints = new List<Point>();
    double tStep = 0.01;
    for (double t = 0; t <= 1; t += tStep)
    {
        curvePoints.Add(GetBezierPoint(controlPoints, t));
    }

    DrawPoints(canvas, curvePoints, 3, color);
}

public static Point GetBezierPoint(List<Point> controlPoints, double t)
{
    // De Casteljau's algorithm
    if (controlPoints.Count == 1)
    {
        return controlPoints[0];
    }

    var newControlPoints = new List<Point>();
    for (int i = 0; i < controlPoints.Count - 1; i++)
    {
        Point p1 = controlPoints[i];
        Point p2 = controlPoints[i + 1];
        Point p = new Point(
            t * p1.X + (1 - t) * p2.X,
            t * p1.Y + (1 - t) * p2.Y);
        newControlPoints.Add(p);
    }
    return GetBezierPoint(newControlPoints, t);
}
\$\endgroup\$
3
\$\begingroup\$

Java 8

It gets the height and the width from the user, chooses width random booleans and count how many are true, registering the counted frequency. Repeat this until some of the generated frequencies is enough to fill the height:

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class Bell {
    public static int[] bell(int width, int height) {
        // I could have used Random.nextGaussian() method, but this way is more fun.
        Random r = new Random();
        int max = 0;
        int[] freqs = new int[width];
        for (int j = 0; max < height - 1; j++) {
            int count = 0;
            for (int i = 0; i < width; i++) {
                if (r.nextBoolean()) count++;
            }
            freqs[count]++;
            if (freqs[count] > max) max++;
        }
        return freqs;
    }

    public static BufferedImage drawBell(int[] ps, int width, int height) {
        BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < ps[i]; j++) {
                bi.setRGB(i, height - j - 1, 0xFF00FFFF); // Cyan
            }
            for (int m = i - 1; m <= i + 1; m++) {
                if (m < 0 || m >= width) continue;
                for (int n = ps[i] - 1; n <= ps[i] + 1; n++) {
                    if (n < 0 || n >= height) continue;
                    bi.setRGB(m, height - n - 1, 0xFF0000FF); // Blue
                }
            }
            for (int j = ps[i] + 1; j < height; j++) {
                bi.setRGB(i, height - j - 1, 0xFFFFFFFF); // White
            }
        }
        return bi;
    }

    public static void main(String[] args) {
        String a = JOptionPane.showInputDialog("Give the width:");
        String b = JOptionPane.showInputDialog("Give the height:");

        int w, h;
        try {
            w = Integer.parseInt(a);
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(null, "Invalid width.");
            return;
        }

        try {
            h = Integer.parseInt(b);
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(null, "Invalid height.");
            return;
        }

        int[] freqs = bell(w, h);
        BufferedImage image = drawBell(freqs, w, h);

        EventQueue.invokeLater(() -> {
            JFrame j = new JFrame("Bell curve");
            j.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            j.add(new SimpleSprite(image));
            j.setResizable(false);
            j.pack();
            j.setVisible(true);
        });
    }

    public static class SimpleSprite extends JComponent {
        private final BufferedImage image;
        private final Dimension dim;

        public SimpleSprite(BufferedImage image) {
            this.image = image;
            this.dim = new Dimension(image.getWidth(), image.getHeight());
        }

        @Override
        public Dimension getMinimumSize() {
            return dim;
        }

        @Override
        public Dimension getMaximumSize() {
            return dim;
        }

        @Override
        public Dimension getPreferredSize() {
            return dim;
        }

        @Override
        public void paintComponent(Graphics g) {
            g.drawImage(image, 0, 0, null);
        }
    }
}

Screenshot:

Bell

\$\endgroup\$
3
\$\begingroup\$

GeoGebra

I don't know whether it is valid to use an application that is made to draw graphs, but if you enter this in the input, you get a Bell Curve:

f(x) = 3ℯ^(-(x - 1)²)

Or, if you want a customizable bell curve:

a = 0
b = 0
c = 0
d = 0
f(x) = a ℯ^((-(x - b)²) / 2 c²) + d

Then, make sure that you enable the sliders for the variables (if they are disabled, click on the circle next to the variable names). Then, you can set a value for them by sliding.

Image of the curve with the sliders (click to enlarge):

GeoGebra Bell Curve

\$\endgroup\$
4
  • \$\begingroup\$ Although the rules didn't technically require posting them, give us the visuals! We'd love to see the result. And is this program specifically designed to give accessibility options for disabled users? That is great! \$\endgroup\$ Mar 3, 2014 at 15:36
  • \$\begingroup\$ @JonathanVanMatre: Done. \$\endgroup\$
    – ProgramFOX
    Mar 3, 2014 at 15:42
  • \$\begingroup\$ Haha, I see now I made a parsing error when reading your text. Nice graph, though! \$\endgroup\$ Mar 3, 2014 at 16:30
  • \$\begingroup\$ It's a cool program, fun to mess around with. \$\endgroup\$ Mar 6, 2014 at 22:21
3
\$\begingroup\$

Java

Throwing 6 dice in every possible combination approaches a 'normal distribution', which happens to be a bell curve.

public class Temp {
    public static void main(String[] args) throws Exception {
        int[] hist = new int[31];
        for (int d1 = 0; d1 < 6; d1++)
            for (int d2 = 0; d2 < 6; d2++)
                for (int d3 = 0; d3 < 6; d3++)
                    for (int d4 = 0; d4 < 6; d4++)
                        for (int d5 = 0; d5 < 6; d5++)
                            for (int d6 = 0; d6 < 6; d6++)
                                hist[d1 + d2 + d3 + d4 + d5 + d6]++;
        for (int y = 4104; y >= 0; y -= 228)
            for (int x = 0; x < 32; x++)
                System.out.print(x == 31? '\n' : hist[x] <= y? '\u3000' : (char)('\u2580' + Math.min(Math.ceil((hist[x] - y) / 28.5), 8)));
    }
}

Some Unicode tricks make the output smoother:

              ▅█▅              
             ▂███▂             
             █████             
            ▁█████▁            
            ███████            
            ███████            
           ▅███████▅           
           █████████           
           █████████           
          ▇█████████▇          
          ███████████          
         ▃███████████▃         
         █████████████         
        ▁█████████████▁        
        ███████████████        
       ▃███████████████▃       
       █████████████████       
     ▁███████████████████▁     
▁▁▁▂▅█████████████████████▅▂▁▁▁

enter image description here

\$\endgroup\$
2
\$\begingroup\$

Python and tkinter

I liked Doorknob's generation method and Victor's output (his generation is actually equivalent), so I decided to combine the two with tkinter!

from tkinter import *
import random

bins = [0]*201
for i in range(20000):
    x = 0
    for j in range(100):
        if random.randint(0, 1):
            x += 0.5
        else:
            x -= 0.5
    bins[int(x)+100] += 1

master = Tk()

w = Canvas(master, width = 201, height=200)
w.pack()

for i in range(201):
    w.create_line(i, 200, i, 200-bins[i]/10, fill="light blue")
    w.create_line(i-1, 200-bins[i-1]/10, i, 200-bins[i]/10, fill="blue")

enter image description here

\$\endgroup\$
2
\$\begingroup\$

C

Based on random walks

#include <stdio.h>
#include <stdlib.h>

#define X_SIZE 40
#define Y_SIZE 15
#define SMOOTH 100

int main(void)
{
int i,j;
int T[X_SIZE*2];
int w;

for (i=0; i<X_SIZE*2; i++) T[i]=0;

// random walks
do  {
    w=X_SIZE;
    for (i=0;i<X_SIZE;i++)
        w+=rand()%2?1:-1;
    T[w]++;
    }
while (T[w]<Y_SIZE*SMOOTH);

// display
for (j=Y_SIZE; j>=0; j--)
    {
    for (i=0; i<X_SIZE*2; i+=2)
        printf("%c", (T[i]>j*SMOOTH)?'#':' ');
    printf("\n");
    }

}

Output :

               ###
               ###
              #####
              #####
              #####
             #######
             #######
            #########
            #########
            #########
           ###########
           ###########
          #############
         ###############
     #######################
\$\endgroup\$
2
\$\begingroup\$

J

load 'plot'
plot (3+i.58)([:+/=)"0 1]3+([:+/?,?,?)"0]1e6#20

Not very creative, but still fun!

Throws three twenty sided dice 1000000 times, summing the result each time. Then to get it in a plot-ready format, we take the array [3..60] and replace each element by the number of times it occures in the random sums.

plot then creates a PDF:

Look at that curve

\$\endgroup\$
2
\$\begingroup\$

Octave

c=79;
x=ifft(fft([ones(1,10) zeros(1,c-10)]).^8);
y=(1:c)*0+' ';
for l=-24:-1,
  for k=1:c,
    if -real(x(k))<l*2e5,
      y(k)='*';
    end
  end
  printf([char(y) '\n'])
end

Try it online!

Instead of directly simulating coin flips, this just uses the observation that the pdf of a sum of random variables is the convolution of the pdfs of each of the random variables. An efficient way to do circular convolution is to take the inverse fourier transform of the element-wise product of the fourier transforms of the pdfs of each of the random variables. For the purpose of this problem (not true in general) circular convolution can stand in for linear convolution.

As an example, given the following pdf of a uniform random variable.

                           **********
                           **********
                           **********
                           **********
                           **********
                           **********
                           **********
                           **********
                           **********
                           ********** 
                           ********** 
                           **********       

The above random variable summed with itself

                                * 
                               *** 
                               ***  
                              *****  
                             *******   
                            *********    
                           ***********                           
                           *********** 
                          *************  
                         ***************    
                        *****************  
                       *******************

The uniform random variable summed with itself 7 times.

                                *                                          
                             *******                                       
                           ***********                                     
                          *************                                    
                         ***************                                   
                        *****************                                  
                       *******************                                 
                     ***********************                               
                    *************************                              
                   ***************************                             
                 *******************************                           
              *************************************                   
\$\endgroup\$
1
\$\begingroup\$

Python (Box-Muller) - 6 lines

This short code uses the Box-Muller transform for simulating a normally distributed variable:

from math import cos, log, pi
from random import random

f = open("normDist.txt",'w')
for i in xrange(10**6):
    f.write(str(cos(2*pi*random())*(-2*log(random()))**.5)+'\n')
f.close()

You can plug the values on GNUPLOT or use this script

f=open("normDist.txt",'r')

v = [0 for i in xrange(51)]
for i in f:
    v[int(float(i)*10) if float(i)<5 and float(i)>-5 else 0]+=1

m=0
for i in v:
    if i>m:
        m=i
for i in v[3:]:
    for j in xrange(int(70.*i/m)):
        print '*',
    print

to produce something like this:

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * *
* * * * * * * * * * * *
* * * * * * * * * *
* * * * * * * *
* * * * * * *
* * * * * *
* * * * *
* * * *
* * *
* * *
* *
* *
* *
* *
* *
* *
* * *
* * *
* * * *
* * * * *
* * * * * *
* * * * * * *
* * * * * * * *
* * * * * * * * * *
* * * * * * * * * * * *
* * * * * * * * * * * * * *
* * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
\$\endgroup\$
1
  • 4
    \$\begingroup\$ Not properly oriented according to the question. Should be rotated 90 degrees. \$\endgroup\$ Mar 6, 2014 at 22:17
1
\$\begingroup\$

awk

#!/ust/bin/awk -f
BEGIN {
  #
  # do WALKS random walks with OOPS times left or right per walk
  #
  WALKS=100000
  OOPS=39
  #
  # output will be H lines
  # the line width will be 2*OOPS+1
  #
  H=23
  #
  # shake awk's pseudorandom generator
  #
  srand()
  #
  # do the walks
  #
  for(i=0;i<WALKS;i++) {
    x=0
    for(j=0;j<OOPS;j++) rand()<0.5?--x:++x
    X[x]++
  }
  #
  # scan for maximum height
  #
  M=0
  for(x=-OOPS;x<=OOPS;x++) {
    if(X[x]>M) M=X[x]
  }
  #
  # "draw" into S[x]: strings of H*X[x]/M "*"s
  #
  for(x=-OOPS;x<=OOPS;x++) {
    s=sprintf("%*s",H*X[x]/M," ")
    gsub(/./,"*",s)
    S[x]=s
  }
  #
  # print S[x] transposed
  #
  for(y=H;y>0;y--) {
    for(x=-OOPS;x<=OOPS;x++) {
      if(c=substr(S[x],y,1)) printf c
      else printf " "
    }
    print ""
  }
}

Output:

                                        *                                      
                                      * *                                      
                                      * *                                      
                                    * * * *                                    
                                    * * * *                                    
                                    * * * *                                    
                                    * * * *                                    
                                  * * * * * *                                  
                                  * * * * * *                                  
                                  * * * * * *                                  
                                  * * * * * *                                  
                                * * * * * * * *                                
                                * * * * * * * *                                
                                * * * * * * * *                                
                                * * * * * * * *                                
                              * * * * * * * * * *                              
                              * * * * * * * * * *                              
                              * * * * * * * * * *                              
                            * * * * * * * * * * *                              
                            * * * * * * * * * * * *                            
                            * * * * * * * * * * * *                            
                          * * * * * * * * * * * * * *                          
*******************************************************************************
\$\endgroup\$
1
\$\begingroup\$

Stax, 20 bytes

⌐∞¶J♠fr"▐cS╥aÆ~a╚∩┌I

Run and debug it

This isn't code-golf but I still want to give Stax a try. Calculates frequency of sum of dices rolled 6 times. Note there are no support for random numbers in Stax.

ASCII equivalent:

6R6|^{|+m{o:G{AJ/'**mMrm

Output:

               *               
              ***              
              ***              
              ***              
             *****             
             *****             
             *****             
             *****             
             *****             
            *******            
            *******            
            *******            
            *******            
            *******            
            *******            
           *********           
           *********           
           *********           
           *********           
           *********           
           *********           
          ***********          
          ***********          
          ***********          
          ***********          
          ***********          
          ***********          
         *************         
         *************         
         *************         
         *************         
         *************         
        ***************        
        ***************        
        ***************        
        ***************        
       *****************       
       *****************       
       *****************       
      *******************      
      *******************      
     *********************     
    *********************** 
\$\endgroup\$
1
\$\begingroup\$

Charcoal

≔⟦Xφ±⁹⟧θF⁹⁹≔E⊞Oθ⁰⁺κ§θ⊖λθ↑θ

Verbose version:

Assign([Power(1000, Negate(9))], q);
for (99) Assign(Map(PushOperator(q, 0), Plus(k, AtIndex(q, Decremented(l)))), q);
Print(:Up, q);

Try it online! Output:

             ||             
             ||             
            ||||            
            ||||            
            ||||            
            ||||            
           ||||||           
           ||||||           
           ||||||           
           ||||||           
           ||||||           
          ||||||||          
          ||||||||          
          ||||||||          
          ||||||||          
          ||||||||          
          ||||||||          
         ||||||||||         
         ||||||||||         
         ||||||||||         
         ||||||||||         
         ||||||||||         
         ||||||||||         
        ||||||||||||        
        ||||||||||||        
        ||||||||||||        
        ||||||||||||        
        ||||||||||||        
        ||||||||||||        
       ||||||||||||||       
       ||||||||||||||       
       ||||||||||||||       
       ||||||||||||||       
       ||||||||||||||       
      ||||||||||||||||      
      ||||||||||||||||      
      ||||||||||||||||      
      ||||||||||||||||      
      ||||||||||||||||      
     ||||||||||||||||||     
     ||||||||||||||||||     
     ||||||||||||||||||     
    ||||||||||||||||||||    
    ||||||||||||||||||||    
    ||||||||||||||||||||    
   ||||||||||||||||||||||   
   ||||||||||||||||||||||   
  ||||||||||||||||||||||||  
 |||||||||||||||||||||||||| 
||||||||||||||||||||||||||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.