Generate a "GitHub" Avatar

31

5

Background / Description

Note: as @HelkaHomba points out, the actual GitHub identicons are not actually random but based on the hash of a username

The default GitHub avatar is a 5x5-pixel image. A color is picked randomly, and then random pixels are filled in on one side (right or left, 2x5 size) using that color. Then that side is copied & flipped to the other side, across the y-axis. The pixels left over that are not filled in are #F0F0F0, or rgb(240,240,240).

The center column's pixels (1x5 size) are then randomly filled in, using the same color as previously.

Output

Note: for this challenge we will ignore the space that encloses the GitHub avatars

The program should output a 5x5 pixel image file. See http://meta.codegolf.stackexchange.com/a/9095/42499 for specifics

Examples

Note: these were obviously scaled up from 5x5 so you can see them

enter image description here enter image description here

Good luck!

MCMastery

Posted 2016-06-05T03:12:37.657

Reputation: 783

@trichoplax The output is a 5x5 pixel image, thanks. Also note the space around the 5x5 pixels (shown in the example GitHub avatars) should be excluded. – MCMastery – 2016-06-05T03:23:20.260

5

I'd suggest some smaller sample images. These take up way more space than necessary. Also the technical term for these is "identicons" and they are not actually random but based on the hash of a username (but having them random for the challenge is fine).

– Calvin's Hobbies – 2016-06-05T03:29:42.257

@HelkaHomba thank you, I added better examples. – MCMastery – 2016-06-05T03:37:15.600

@trichoplax thank you, I'm editing now – MCMastery – 2016-06-05T03:38:30.793

1I assume "random pixels" means each pixel is colored or blank with 0.5 probability, independently of all other pixels on the same size. And "random color" means each RGB component is independently uniform on [0, 255]. Correct? – Luis Mendo – 2016-06-05T03:48:12.510

Trivia: You can use the identicon API to generate your own identicon, even if you have a real avatar, at https://github.com/identicons/<your_github_username>.png. – mınxomaτ – 2016-06-05T04:17:51.910

@LuisMendo It does not matter for randomness if you pick 3 uniform 256 values or one 256^3 value (if the period of the RNG is over 256^3 of course). – Karl Napf – 2016-06-05T12:12:11.013

GitHub identicons are... based on the hash of a username Hold on a second, how can this be a hash? – user8397947 – 2016-06-05T16:54:08.050

1

I didn't feel it was a valid answer since it doesn't output an actual image, but I made a command line version using ANSI codes: https://gist.github.com/anonymous/3c879c5b01983a07fb7da7a25d778f1b%21

– Dom Hastings – 2016-06-06T07:45:15.880

@dorukayhan the same input always generates the same output, and you can't determine the input from the output. it's a hash – undergroundmonorail – 2016-06-07T03:21:58.707

@DomHastings Displaying output on the screen is acceptable by default. I'd say that output via ANSI color codes to a console is close enough, but that's ultimately the OP's call.

– Mego – 2016-06-07T05:55:42.170

Answers

12

Pyth - 27 bytes

.wC+Kc3O^Cm,240O256 3 15_PK

Obviously doesn't work online, but you can have it print color codes here.

Maltysen

Posted 2016-06-05T03:12:37.657

Reputation: 25 023

10

Perl 5, 77 bytes

This is non-competing as it only has a 256 colour palette, only works on terminals that support ANSI escape codes and doesn't actually output a 5 pixel square image, but I thought I'd post it anyway as it was fun golfing this down.

sub x{"\e[48;5;@{[rand>.5?$-||=rand 254:254]}m  "}say$}=x,$b=x,x,$b,$}for 0..4

Note: the \e is actually ASCII char \x1B.

Usage

perl -E 'sub x{"\e[48;5;@{[rand>.5?$-||=rand 254:254]}m  "}say$}=x,$b=x,x,$b,$}for 0..4'

Explanation

Nothing particularly clever except perhaps:

  • Use $- to automatically round the colour number for use in the escape sequence, used instead of $n=0|rand 254.

Example output

Yeah, you'll be stuck with whatever the last colour was, all over your -boink- terminal.

Dom Hastings

Posted 2016-06-05T03:12:37.657

Reputation: 16 415

9

MATL, 36 29 bytes

5l$rtP+!kllII$r*O16tQ/XE'a'YG

This saves the result in file a.png.

Replacing 'a' by 2 in the code displays the image (scaled up) instead of saving a file:

5l$rtP+!kllII$r*O16tQ/XE2YG

Here's an example output:

enter image description here

Explanation

5l$r     % 5×5 matrix of independent random values with uniform distribution
         % on the interval (0,1)
tP+!     % Duplicate, flip vertically, add, transpose. This gives a horizontally
         % symetric matrix. Center column pixels are uniformly distributed on the 
         % interval (0,2). Rest have a triangular distribution on (0,2)
k        % Round down. In either of the above cases, this gives 0 and 1
         % with the same probability
llII$r   % 1×1×3 array of independent random numbers with uniform distribution
         % on (0,1). This is the foreground color.
*        % Multiply the two arrays with broadcast. Gives a 5×5×3 array. Ones in the
         % 5×5 array become the random foreground color. Zeros remain as zeros.
O        % Push 0
16tQ/    % 16, duplicate, add 1, divide: gives 16/17, or 240/255
XE       % Replace 0 by 16/17: background color
'a'      % Push file name
YG       % Write image to that file

Luis Mendo

Posted 2016-06-05T03:12:37.657

Reputation: 87 464

7

Actually, 53 bytes

3'≡*;╗`┘#8╙r-J┌`MΣ╝5`3"2rJ└"£n3╟;RdX+Σ`nkΣ"P6 5 5 255

Try it online!

Actually is bad at string processing. I think I've mentioned that before. This program outputs a P6 netpbm image using CP437, like the following:

P6 5 5 255
εεεεεεå♠ƒεεεεεεå♠ƒå♠ƒεεεå♠ƒå♠ƒεεεεεεεεεεεεεεεεεεεεεå♠ƒεεεεεεå♠ƒå♠ƒå♠ƒå♠ƒå♠ƒ

This can be converted to a PNG using ImageMagick:

seriously -f prog.srs | convert - out.png

Scaled up PNG version:

sample output

Explanation:

3'≡*;╗`┘#8╙r-J┌`MΣ╝5`3"2rJ└"£n3╟;RdX+Σ`nkΣ"P6 5 5 255
3'≡*                                                   push "≡≡≡" (char 240, 3 times)
    ;╗                                                 save a copy to reg0
      `┘#8╙r-J┌`M                                      map:
       ┘#                                                cp437 char code, as list ([240])
         8╙r-J                                           random value in range(2**8) that is not 240
              ┌                                          char code
                 Σ╝                                    concatenate, push to reg1
                   5`3"2rJ└"£n3╟;RdX+Σ`n               do this 5 times:
                     3"2rJ└"£n                           do this 3 times:
                       2rJ└                                randomly pick 0 or 1, push the value in that register
                              3╟                         push the top 3 items to a list
                                ;RdX+                    duplicate, reverse, discard first value, append (mirror the list)
                                     Σ                   concatenate
                                       kΣ              push stack as list, concatenate
                                         "P6 5 5 255   prepend header

Mego

Posted 2016-06-05T03:12:37.657

Reputation: 32 998

Sorry, but "P6 netpbm" is not in the specified list of allowed image formats, so you should probably add the length of the ImageMagick command line to your answer. :/ – ZeroOne – 2016-06-08T20:59:38.440

@ZeroOne It is an allowed image format - it's a ppm image.

– Mego – 2016-06-08T21:00:34.493

I stand corrected! Sorry about that, and thanks for the clarification. Looks like I need to do some learning on image formats. :) – ZeroOne – 2016-06-08T21:03:06.303

6

Python, 167 164 155 148 bytes

Output as ppm

from random import*
print"P3 5 5 255"
C,P=choice,[[240]*3,[randint(0,255)for _ in"RGB"]]
exec"a,b=C(P),C(P);print' '.join(map(str,a+b+C(P)+b+a));"*5
  • Edit1: range(5) to " "*5
  • Edit2: shoved a byte at the first print
  • Edit3: Replaced list comprehension with map since only str(p) was used
  • Edit4: exec""*5 instead for _ in " "*5:

Some improvement over old, string-based code:

from random import*
print "P3 5 5 255"
j,c,a=' '.join,choice,['']*5
P=["240 "*3,j([str(randint(0,255))for _ in"RGB"])]
for _ in a:a=[c(P)]*5;a[1]=a[3]=c(P);a[2]=c(P);print j(a)

Karl Napf

Posted 2016-06-05T03:12:37.657

Reputation: 4 131

You could save a few by replacing the newlines with a space in the header. The spec just calls for whitespace. http://netpbm.sourceforge.net/doc/ppm.html

– Chuck Morris – 2016-06-07T00:44:50.150

5

Mathematica, 105 102 98 94 bytes

c=1~RandomReal~3;r@l_:={c,4{4,4,4}/17}~RandomChoice~{l,5};Image[Join[#,r@1,Reverse@#]&@r@2]

Mathematica graphics

is the Transpose operator.

Edit 1: Saved 3 bytes by replacing Round + RandomReal with RandomInteger

Edit 2: Saved 4 bytes by replacing RandomInteger with RandomChoice

Edit 3: Saved 4 bytes by replacing RandomColor and GrayLevel with RandomReal

shrx

Posted 2016-06-05T03:12:37.657

Reputation: 462

5

Swift 2.3, 593 585 bytes

var t = 0,g = UIGraphicsGetCurrentContext(),c = UIColor(hue:CGFloat(drand48()),saturation:1,brightness:1,alpha:1).CGColor
srand48(time(&t))
UIGraphicsBeginImageContext(CGSizeMake(5,5))
for x in 0..<3 {for y in 0..<5 {CGContextSetFillColorWithColor(g,drand48()>0.5 ? c : UIColor.whiteColor().CGColor)
var r = [CGRect(x:x,y:y,width:1,height:1)]
if x<2 {let m = x==0 ? 4 : 3;r.append(CGRect(x:m,y:y,width:1,height:1))}
CGContextFillRects(g,&r,r.count)}}
let i = UIGraphicsGetImageFromCurrentImageContext()
UIImagePNGRepresentation(i)!.writeToURL(NSURL(string:"/a/a.png")!,atomically:true)

Update

Swift 3, 551 bytes

var t = 0,g = UIGraphicsGetCurrentContext()!,c = UIColor(hue:CGFloat(drand48()),saturation:1,brightness:1,alpha:1).cgColor
srand48(time(&t))
UIGraphicsBeginImageContext(CGSize(width:5,height:5))
for x in 0..<3 {for y in 0..<5 {g.setFillColor(drand48()>0.5 ? c : UIColor.white().cgColor)
var r = [CGRect(x:x,y:y,width:1,height:1)]
if x<2 {let m = x==0 ? 4 : 3;r.append(CGRect(x:m,y:y,width:1,height:1))}
g.fill(&r,count: r.count)}}
let i = UIGraphicsGetImageFromCurrentImageContext()!
try!UIImagePNGRepresentation(i)!.write(to: URL(string:"/a/a.png")!)

I'm at WWDC and just got the Xcode 8 beta with Swift 3. Apple made some of the CoreGraphics calls more "Swifty," and I am able to reduce the bytecount.

Swift 2 code Ungolfed:

var t = 0
srand48(time(&t))

UIGraphicsBeginImageContext(CGSizeMake(5,5))
let context = UIGraphicsGetCurrentContext()
let color = UIColor(hue: CGFloat(drand48()),saturation:1,brightness:1,alpha:1).CGColor

for x in 0..<3 {
    for y in 0..<5 {
        CGContextSetFillColorWithColor(context, drand48() > 0.5 ? color : UIColor.whiteColor().CGColor)
        var rects = [CGRect(x:x,y:y,width:1,height:1)]

        if x < 2 {
            let mirror = x==0 ? 4 : 3
            rects.append(CGRect(x: mirror, y: y, width: 1, height: 1))
        }

        CGContextFillRects(context, &rects, rects.count)
    }
}


let image = UIGraphicsGetImageFromCurrentImageContext()
UIImagePNGRepresentation(image)!.writeToURL(NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory,inDomains:.UserDomainMask).first!.URLByAppendingPathComponent("a.png"), atomically:true)

This answer assumes UIKit is available and uses the Cocoa Touch framework.

Some example output images:

1 2 3

I know I can't compete with most of the other answers but I wanted to give this a shot as a personal challenge. There is definitely room for improvement with this answer, but I think it will be hard to get this down below a few hundred bytes due to the length of the UIKit and CoreGraphics image writing method names. I opted to write an actual PNG file rather than PPM values as an exercise for myself, but shorter answers would definitely be possible if I used the PPM format.

I already start out as a loss by having to declare a variable to seed srand48 with time. I chose this over arc4random() or arc4random_uniform() because ultimately I would lose more bytes with those. I seed the rng to use drand48 to generate a random color and pick when to write a color to a pixel.

CGSize vs CGSizeMake and CGRect vs CGRectMake:

I switch between the inline C API functions and their Swift extensions to find the shortest constructor for each. CGSizeMake ends up being shorter than CGSize(), and CGRectends up being shorter than CGRectMake():

CGSizeMake(5,5)
CGSize(width:5,height:5)

CGRect(x:x,y:y,width:1,height:1)
CGRectMake(CGFloat(x),CGFloat(y),1,1)

I would have to create CGFloats x and y due to the nature of the for loop. I'm really not thrilled with the 2D loop and if equality checks, but I was really struggling to find a shorter way. There's definitely room to shave off a few bytes here.

Calling CGContextFillRects with an array of CGRect structs is cheaper than calling CGContextFillRect twice with two different values, so I save a few bytes with the array and pointer.

I also save 27 bytes by not calling UIGraphicsEndImageContext(). While this would normally be a "bug" in production code, it's not necessary for this toy program.

Colors:

Colors are also a pain to deal with, since I'm creating UIColor objects but need to write a CGColor opaque type to each pixel. The shortest code I found to create a random color was to use the UIColor constructor and get the CGColor from that UIColor. Same with white. If I were using the Cocoa framework instead of Cocoa Touch, I might be able to save some bytes using CGColorGetConstantColor(), but unfortunately that method is unavailable in the Cocoa Touch SDK.

Writing to to file:

Writing to a file takes almost 100 bytes. I'm not sure how to even go about optimizing this. On some systems depending on your permissions, you may need to use the Documents directory which would be even longer:

UIImagePNGRepresentation(i)!.writeToURL(NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory,inDomains:.UserDomainMask).first!.URLByAppendingPathComponent("a.png"), atomically:true)

Definitely open to further optimizations.

Edit 1: Saved a few bytes by rearranging some variable declarations.

JAL

Posted 2016-06-05T03:12:37.657

Reputation: 304

4

MATLAB, 102 bytes

Hi, this is my matlab solution:

p=@(x)(imwrite(floor(randi(2,5,2)*[eye(2) ones(2,1)./2 fliplr(eye(2))]),[0.9412*[1 1 1];rand(1,3)],x))

The input x of the function is the name of the output file. For example:

p('output.png')

produces a png image called 'output.png'.

Here the results of some executions of this code.

output1.png output2.png output3.png output4.png

PieCot

Posted 2016-06-05T03:12:37.657

Reputation: 1 039

3

Dyalog APL, 43 42 bytes

'P3',5 5 256,∊(3⍴240)(?3⍴256)[⌈(⊢+⌽)?5 5⍴0]

'P3',5 5a,∊(3⍴240)(?3⍴a←256)[⌈(⊢+⌽)?5 5⍴0]

Right to left:

?5 5⍴0 generates a 5×5 matrix of random numbers between 0 and 1 (but never 0 or 1)

(⊢+⌽) is a train that adds the matrix with its reflection

ceiling, returns 1 or 2 for each element

(3⍴240)(?3⍴256) colours - white-ish and a random one

[ ] use each element of the matrix as an index in colours

'P3',5 5 256,∊ flatten and add header

ngn

Posted 2016-06-05T03:12:37.657

Reputation: 11 449

2

PHP, 236 bytes

I know this is an old challenge but I just like to challenge myself.

$o=imagecreate(5,5);$t=imagecolorallocate;$r=rand;for($c=[$t($o,240,240,240),$t($o,$r(0,255),$r(0,255),$r(0,255))];$y++<5;)for($x=-2,$a=[];$x<3;)imagesetpixel($o,$x+2,$y,isset($a[$v=abs($x++)])?$a[$v]:($a[$v]=$c[$r(0,1)]));imagepng($o);

Ungolfed:

// Store these frequently used functions
$t=imagecolorallocate;
$r=rand;

// Create 5x5 image
$o=imagecreate(5, 5);

// Define array of the possible colors
$c=[$t($o,240,240,240),$t($o,$r(0,255),$r(0,255),$r(0,255))];

// Loop over y axis
for($y=0;$y++<5;) {

    // This stores values for colors used in the current row indexed by the absolute value of x starting from -2
    $a = [];

    // Loop over x axis
    for($x=-2;$x<3;) {

        // Set a pixel of a random color for current coordinate. If it exists in the array, use the array value.
        imagesetpixel($o,$x+2,$y, isset($a[$v=abs($x++)]) ? $a[$v] : ($a[$v]=$c[rand(0,1)]) );
    }     

    // Empty the array
    $a = [];
}

// Output as PNG
imagepng($o);

Sample Output:

Github avatar

Github avatar

Kodos Johnson

Posted 2016-06-05T03:12:37.657

Reputation: 776

2

Javascript ES6, 296 bytes

Note: does not produce a file, draws to a canvas.

See it in action in this JS Fiddle.

s=20;W='#fff';M=Math;R=M.random;ctx=document.getElementById('c').getContext('2d');cr=`#${M.floor(R()*16777215).toString(16).slice(0,3)}`;f=Array(5).fill();a=f.map((_,i)=>f.map((_,j)=>R()*2|0));a.map((c,x)=>c.map((v,y)=>{ctx.fillStyle=y>=3?c[y==3?1:0]?cr:W:c[y]?cr:W;ctx.fillRect(y*s,x*s,s,s);}));

Pierlo Upitup

Posted 2016-06-05T03:12:37.657

Reputation: 21

Welcome to the site! :) – James – 2017-10-30T19:25:03.980

After running it a few times it generated this twice - a single black pixel in the top left, and nothing else. Not sure if this is a problem with the code or the fiddle.

– FlipTack – 2017-10-30T19:27:18.473

Right – the code to generate the random hex value was buggy. Updated the link in the answer! – Pierlo Upitup – 2017-10-31T00:25:59.460