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:
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 CGRect
ends 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 CGFloat
s 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.