Loading...
Logo
Processing Forum
With a group of co-authors, I just published a book titled 10 PRINT CHR$(205.5+RND(1)); : GOTO 10. You can download a PDF of the book from the 10PRINT.org website. You can see photos of the book on Flickr. Here's a description:

This book takes a single line of code—the extremely concise BASIC program for the Commodore 64 inscribed in the title—and uses it as a lens through which to consider the phenomenon of creative computing and the way computer programs exist in culture. The authors of this collaboratively written book treat code not as merely functional but as a text—in the case of 10 PRINT, a text that appeared in many different printed sources—that yields a story about its making, its purpose, its assumptions, and more. They consider randomness and regularity in computing and art, the maze in culture, the popular BASIC programming language, and the highly influential Commodore 64 computer.
Here's the challenge—read through the chapter REM VARIATIONS IN PROCESSING and create your own interpretations of this one-line BASIC program. Please post links, code, and thoughts there.

Replies(42)

To flesh out some ideas around 10 PRINT CHR$(205.5+RND(1)); : GOTO 10, check these resources lifted from this Bogost post:

Geeta Dayal's review of the book in Slate

Discussion on Reddit r/Programming, including a hilarious Enterprise Java version.

A discussion at Stack Overflow stemming from a Bash shell version posting.

A discussion on Hacker News, which also features a number of re-implementations.

A post on Boing Boing, which also includes a good comment thread.


I did a quick sketch on this concept today and it turned out fairly interesting.
http://www.openprocessing.org/sketch/81826
I already had a recreation of this lying around that I'd made earlier when I heard of the project.  I cracked it back open, remixed it to make the randomness more interesting, and got it (mostly) working with processing.js so I could post it:

Nice idea Josh. We didn't think to try that.
Gaussian randoms are pretty great. I used to rely on java's Random object; I'd totally recommend adding them to the core Processing math functions (or maybe I should put my money where my mouth is and figure out how to add them myself).
I felt like I should try a more traditional variation. Also I added an option for color to my other one.
http://www.openprocessing.org/sketch/81918
rbrauer, I like the dense patterns in the first program < http://www.openprocessing.org/sketch/81826>. They remind me of some early films made at Bell Labs with Ken Knowlton's software, particularly early Lillian Schwartz films. (She used to have clips up on YouTube, but it looks like they are removed right now.)

I wanted to approach the challenge less in a mimicking way than an equivalent to Processing of what 10 Print does. Original window size, original colours and so on… So here's what could a rather compact static version be :
int c=0;
for(int y=0;y<96;y+=5){
  for(int x=0;x<96;x+=5){
    c=int(random(2))*5;
    line(x+c,y,x+5-c,y+5);
  }
}
As you can notice it sure must had been under 200 char ;) and, yes, 96 is a pretty elegant number…
Soon a dynamic version.
…and here comes the dynamic version :

Copy code
  1. int c, x=0;
  2. int y=-1;
  3. PImage s;
  4. void setup() {
  5.     frameRate(20);
  6. }
  7. void draw() {
  8.     c=int(random(2))*5;
  9.     line(x+c, y, x+5-c, y+5);
  10.     x+=5;
  11.     if (x>95) {
  12.         x=0;
  13.         y+=5;
  14.     }
  15.     if (y>95) {
  16.       y=94;
  17.       s = get();
  18.       background(204);
  19.       image(s, 0, -5);
  20.     }
  21. }

tried to keep it simple and straightforward. Of course one could have used the console for a print("/") print("\\") solution, but I doubt he/she'd succeed in finding a one-liner sketch anyway.
Thank you, Casey, for the book, the idea of the challenge and the inspiration. I'll certainly will use this for beginner and design courses.

Edit: one-liner "/ \" sketch: void draw(){if(random(1)>.5){print("/");}else{print("\\");}} (60 chars)
Here's a nice version in GLSL sent by Mr Doob via Twitter: http://glsl.heroku.com/e#5176.9
It would be fun to move into Processing using the 2.0 Shader functions.
I like the idea of doing the tiny sketch version, Alexis. I tried to get your dynamic version under 200 characters. Someone else might be able to do a better job of this as I'm sure you're probably not supposed to call frameRate(...) every frame.

Also, by the way, found the Vimeo embeds of Lillian Schwartz's work on the following to be playable.
http://lillian.com/?cat=87

void draw() {
  frameRate(20);
  int x = frameCount%20*5;
  int c = int(random(2))*5;
  line(x+c, 95, x+5-c, 100);
  if (x==95) {
    PImage s = get();
    background(204);
    image(s, 0, -5);
  }
}

Very nice and concise version with a single draw(), bravo. I really like your frameCount with modulo technique, and all in less than 200 chars.
Well, now that we are only shifting the last line up, we do not need the get+background+image routine any longer:

void draw() {
  frameRate(20);
  int x = frameCount%20*5;
  int c = int(random(2))*5;
  line(x+c, 89, x+5-c, 94);
  if (x==95) {
    copy(0,0,100,100,0,-5,100,100);
  }
}

…which “tinyfied” can –almost– become a single line sketch:
void draw(){frameRate(20);int x=frameCount%20*5;int c=int(random(2))*5;line(x+c,88,x+5-c,93);if(x==95){copy(0,0,99,99,0,-5,99,99);}} (132 chars)

Good catch with the pixel functions. If you leave out frameRate(...) it can fit in a tweet including formatting and with seven characters to spare.

void draw() {
  int x = frameCount%20*5;
  int c = int(random(2))*5;
  line(x+c,89,x+5-c,94);
  if (x==95) set(0,0,get(0,5,100,x));
}

 
Here are the last two programs (impressively reduced!) in the upcoming color coding:

void draw() {
  int x = frameCount%20*5;
  int c = int(random(2))*5;
  line(x+c, 89, x+5-c, 94);
  if (x==95) set(0, 0, get(0, 5, 100, x));
}

void draw() {   int x = frameCount%20*5;   int c = int(random(2))*5;   line(x+c,89,x+5-c,94);   if (x==95) copy(0,0,100,100,0,-5,100,100); }
The top is shorter, but the bottom is more efficient with copy() moving the pixels  

The original Commodore 64 character grid was 40 x 25. I made a light modification to get 33 characters per row, each line as a 3 x 3 pixel grid instead of the original 8 x 8:

void draw() {
  int x = frameCount%33*3;
  int c = int(random(2))*3;
  line(x+c,94,x+3-c,96);
  if (x==96) copy(0,0,100,100,0,-3,100,100);
}


The first Y constant there should be 93 instead of 94. At least that looks much better to me on this system.

String s="";
void draw() {
  s += "/\\".charAt((int)random(2));
  textFont(createFont("",10,false),10);
  text(s,0,93);
  if (s.length() == 33) {
    copy(0,0,100,100,0,-7,100,100);
    s = "";
  }
}


Rbrauer is correct...

The code should be like this:

Copy code
  1. void draw() {
  2.   int x = frameCount3*3;
  3.   int c = int(random(2))*3;
  4.   line(x+c,93,x+3-c,96);
  5.   if (x==96) copy(0,0,100,100,0,-3,100,100);
  6. }

Or probably even like this:
Copy code
  1. void draw() {
  2.   int x = frameCount3*3;
  3.   int c = int(random(2))*2;
  4.   line(x+c,94,x+2-c,96);
  5.   if (x==96) copy(0,0,100,100,0,-3,100,100);
  6. }

The second version is probably more true to the original, because it can be created from 3x3 blocks.
If you use noSmooth() you can also see the tiny artefacts at the corners where four lines meet.
Those artefacts are characteristic for the block substitution pattern created by the original 10PRINT program.



I love all of these minimal-code variations! Although now my code feels like an Enterprise Java version or something. :)

Yes, the minimal route is wonderful and revealing! I feel like we burrowed in there and are now trapped. It would be fantastic to see more iterations that go beyond, but are related to, the original algorithm and quirks of the Commodore 64. I'll dare to quote Andres, "Let's push it a little."

My explorations ended here, but I know that's just one path:
http://www.flickr.com/photos/_reas/8229214282/in/photostream
http://www.flickr.com/photos/_reas/8100571862/in/set-72157614204930865

Sweet ... now I really want a Java-Enterprise Mode in Processing ;-)

Maybe mouse interaction is also a direction that is worthy of exploration...
I frequently find myself adding mouse interaction to sketches, just because Processing makes it so simple.
So here is a sketch where all randomness comes from the user rather than exploiting the pseudo randomness from the random function:

int w = 200; // canvas size
int n = 25;  // number of grid cells
int d = w/n; // diameter of a grid cell
boolean[][] memory = new boolean[n][n]; // core memory ;-)

void setup() {
  size(w, w);
  noSmooth();
}

void draw() {
 
  // draw the raster
  background(255);
  scale(d);
  strokeWeight(1.0/d);
  for (int x=0; x<n; x++) {
    for (int y=0; y<n; y++) {
      int r = memory[x][y] ? 1 : 0;
      line(x, y+r, x+1, y+1-r);
    }
  }
 
  // rescale and constrain mouse coordinates
  int mX = constrain(mouseX/d, 0, n-1);
  int pmX = constrain(pmouseX/d, 0, n-1);
  int mY = constrain(mouseY/d, 0, n-1);
  int pmY = constrain(pmouseY/d, 0, n-1);
 
  // flip line when the mouse moves to a new square
  if(mX != pmX || mY != pmY) {
    memory[mX][mY] = !memory[mX][mY];
  }
 
}


Here is a 3D Variation:


//////////////////////////////////////////
//                                      //
//    10 PRINT - Stacked 3D Version     //
//                                      //
//////////////////////////////////////////

// Works best in Processing 2.0 JavaMode

int w = 400; // canvas size
int n = 10;  // number of grid cells
int d = w/n; // diameter of a grid cell
float depth = 0.5; // relative cell depth

void setup() {
  size(w, w, P3D);
  rectMode(CENTER);
  background(255);
  strokeWeight(3);
  fill(204);
}

void draw() {

  // get coordinates
  int xy = frameCount % (n*n);

  // shift image in z-direction
  if (xy == 0) {
    PImage img = get();
    background(255); 
    pushMatrix(); 
    translate(0, 0, -d * depth);
    tint(255, 127);
    image(img, 0, 0);
    popMatrix();
  }

  // scale and rotate the square
  scale(d);
  translate(xy%n + .5, xy/n + .5, -depth * .5 );
  rotate(QUARTER_PI - HALF_PI *int(random(2)));
  rotateX(HALF_PI);
  
  // draw the square
  rect(0, 0, sqrt(2), depth);
  
}

Nice! I made a few superficial edits in setup() to have it work better for my eyes:

void setup() {
  size(400, 400, P3D);
  rectMode(CENTER);
  background(255);
  fill(0, 0, 255);
  noStroke();
}

Glad you liked it ...
I cleaned up the code a little bit and posted a slightly modified version
for Processing.js over at Sketchpad.cc :




A bit puzzled by scaling this code.. If someone had a little advice.. I tried comparing to the 3x3 blocks one as well. 

I wanted to make the lines 15px instead of 5px.  

1.Modulo.. the idea with frameCount%20*5 is that it's resetting basically at 100 frames?
2.with int c, made it more widely varying
3.wanted the second x to be further apart in my line() and the ys 15 px apart
4.wanted the get to restart the line further down. 

I think what I'm not getting is something about the frameCount% part. Or the size is more important?  

This is what I had 

Copy code
  1. void draw() {
  2.   int x = frameCount%7*15;
  3.   int c = int(random(2))*15;
  4.   line(x+c, 79, x+15-c, 94);
  5.   if (x==95) set(0, 0, get(0,15, 100, x));
  6. }



A very free variation :P

Copy code
  1. void setup(){size(600,200);}
  2. int l;
  3. void draw(){
  4.   loadPixels();
  5.   for (int i = 0; i < width; i+=3){
  6.     color c  = random(1) >= 0.15? color(0):color(255);
  7.     pixels[min(l+i, pixels.length -1)] = c;
  8.     pixels[min(l+i+1, pixels.length -1)] = c;
  9.     pixels[min(l+i+2, pixels.length -1)] = c;
  10.   }
  11.   updatePixels();
  12.   l=(l+width)%(pixels.length);
  13. }

Here is another pixel level approach:



The 10 Print-Dithering algorithm dithers an image, using the image data as "random generator" for the labyrinth. The lower bits of an image are usually the result of physical noise, so they provide a good source of randomness.

The algorithm is really quite simple:
/* @pjs preload="REAS.png"; */

PImage img;
int d, n = 50;

void setup() {
  size(400, 400);
  d = width/n;
  img = loadImage("REAS.png");
  img.resize(n, n);
}

void draw() {
  int m = constrain(130 * mouseX / width, 1, 129);
  loadPixels();
  for(int x = 0; x < n; x++) for(int y = 0; y < n; y++) {
    float val = 256 - (img.pixels[y*n+x] & 255);
    for(int dx = 0; dx < d; dx++) for(int dy = 0; dy < d; dy++) { 
      int z = val % (2*m) < m ? (dx+dy+1) * 255 / d : (dx+d-dy) * 255 / d;
      pixels[ (y*d + dy) * width + (x*d + dx) ] = val > 2 * abs(z - 255) + 2 ? #000000 : #ffffff; 
    }
  }
  updatePixels();
}

You can see it in action on OpenProcessing.org.
I also did a grayscale variant, that has more of a line-drawing appeal to it:



Also online at OpenProcessing.org

@caseyreas: I hope you don't mind I took your profile pic as as a random source.

I love it bit.craft, particularly the version w/out grays. This is another direction the book authors never considered. Let's get it going with Capture.
Yeah. Let's use 10 PRINT as video filter and 10 PRINT-ify everything :-)
Here's an OpenGL Shader version of my 10 PRINT dithering sketch:

PImage img;
PShader shd;
int w = 50, h = 50;

void setup() {
  size(400, 400, P2D);
  ((PGraphicsOpenGL) g).textureSampling(2); 
  img = loadImage("REAS.png");
  img.resize(w, h);
  shd = loadShader("10PRINT.frag");
  shd.set("imageRes", float(width), float(height));
  shd.set("sampleRes", float(w), float(h));
}

void draw() {
  shd.set("m", float(mouseX) / width);
  shader(shd);
  image(img, 0, 0, width, height);
}

GLSL code for the Fragment Shader:

// 10PRINT.frag - GLSL 10 PRINT filter - bitcraft lab 2012

uniform sampler2D textureSampler;
uniform vec2 imageRes;
uniform vec2 sampleRes;
uniform float m;

void main(void) {
 
	// get texture position
	vec2 pos = gl_FragCoord.xy;
	pos.y = imageRes.y - pos.y;
	
	// get block position
	vec2 d = imageRes / sampleRes;
	vec2 delta = mod(pos, d);
	
	// sample texture brightness
	float val = 1.0 - texture2D(textureSampler, pos / imageRes).r;

	// 10 PRINT dithering
	float z = (delta.x + (mod(val, 2.0 * m) <  m ? delta.y * d.x / d.y : d.x - delta.y * d.x / d.y)) / d.x;
	gl_FragColor = vec4(vec3(val > 2.0 * abs(z - 1.0) ? 0.0 : 1.0), 1.0);

}

I improved the 10PRINT shader a bit and turned it into a camera filter that runs inside the browser using the editor at pixelshaders.com.



The editor provides access to the webcam via the getUserMedia API, so if you have a recent browser and a webcam you can now 10PRINT-ify yourself in realtime using camera colors or  C64 colors.
Here is a rather dry interpretation in Processing, renders to the console only.
int j = 0; int k =0;
//char c[] = new char[]{'\\','/','|','—',' '};
char c[] = new char[]{'\\','/',' '};

void draw() {
  for (int i = 0; i < 40-abs(20-j); ++i) {
     print(c[i>abs(20-j)?(int)(Math.random()*(c.length-1)):c.length-1] + " ");
  }
  j=(j+1)%40;
  println();
}
I've tried to get a slightly different maze using a polar approach:

Copy code
  1. int S=500, N= 200, o=S/2, i= 4, r;
  2. float s= TWO_PI/N;
  3. PVector[] T;

  4. void setup () {
  5.       size (S,S);
  6.       smooth ();
  7.       T = new PVector[N];
  8.       for (int n=0; n<N; n++) T[n] = new PVector (cos (n*s), sin (n*s));
  9. }

  10. void draw () {
  11.       for  (int p=0, j=p+1, r1, r2; p<N; p++, j=(p+1)%N) {
  12.       r1=r2=r;    
  13.       if (random(1)<.5) r1=r+i; else r2=r+i;
  14.       line ( o+T[p].x*r1, o+T[p].y*r1, o+T[j].x*r2, o+T[j].y*r2 );
  15.       }
  16.       r+=i;
  17. }
At OpenProcessing:
http://www.openprocessing.org/sketch/83662

Btw, really nice book, thanks for sharing!

Ale · http://60rpm.tv/i
Very smart and well crafted variations, Good work! :-)

Ale · http://60rpm.tv/i
heeeelp! i'm meltiiiiiing!

Copy code
  1. int s=40;
  2. void setup() {
  3.   size(640,480);
  4.   background(255);
  5.  
  6.   colorMode(HSB);
  7. }
  8. void draw() {
  9.   filter(ERODE);filter(ERODE);
  10.   tint(230);
  11.   image(get(),0,5);
  12.  
  13.   strokeWeight(15);
  14.   strokeCap(PROJECT);
  15.  
  16.   for(int x=0; x < width; x+=s) {
  17.     for(int y=0; y < height; y+=s) {
  18.       stroke(map(y,0,height,90,120),255,200);
  19.       if(noise(x/50f,y/50f,frameCount/100f)>0.5) {
  20.         line(x,y,x+s,y+s);
  21.       } else {
  22.         line(x+s,y,x,y+s);
  23.       }
  24.     }
  25.   }
  26. }
my favorite line in all that mess is the strokeCap. you can do some real magic with that! try taking it out. eww.
and even though the perlin doesn't really show through, it does make lines only sometimes flip, which looks nice.
I like the melting one. Very clever use of noise and video feedback!
Also love your avatar image - reminds me of Vladimir Bonacic's Dynamic Objects.
The effect is pretty nice. :)
I get an out of memory error, though. I am the only one?

Ale · http://60rpm.tv/i
Love all the variations on this so far.

I wanted to try something a little different, and experimented with applying the code more towards the movement of lines in 3D space. I kept the background in setup to get some interesting results over time, but putting it in draw can give you more of a sense on how it could give some organic-looking movement.



Copy code
  1. import processing.opengl.*;

  2. float m = 0.0003;
  3. int x = frameCount/20*5;
  4. int c = int(2*5);
  5. int s = 40;

  6. void setup(){
  7.  size(800,800, OPENGL);
  8.  background(255);  
  9. }

  10. void draw() {
  11.   frameRate(30);
  12.   translate(width/2, height/2);
  13.   scale(0.3);
  14.   for(int x=0; x < width; x+=s) {
  15.     for(int y=0; y < height; y+=s) {
  16.       for(int i=0;i<1;i++){
  17.         stroke(0,20);
  18.         strokeWeight(2);
  19.       if(noise(x/50f,y/50f,frameCount/100f)>0.5) {   
  20.         rotateY(frameCount*m/10);
  21.         line(x*i,y*i,x+s*i,y+s*i);
  22.       } else {
  23.         rotateX(frameCount*m/10);
  24.         rotateZ(frameCount*m/10);
  25.         line(x+s*i,y*i,x*i,y+s*i);
  26.           
  27.         }
  28.       }
  29.     }
  30.   }
  31. }

How about a nice Automondrian?



Copy code
  1. int y = 1;
  2. void draw() {
  3.   int x = frameCount%20*5;
  4.   int c = int(random(2))*5;
  5.  
  6.  if (y==1){
  7.   fill(255,255*int(random(1)),0);
  8.  }
  9.  
  10.  if(y==2){
  11.   fill(255*int(random(1)),0,255);
  12.  }
  13.  if(y==3){
  14.   fill(255,255,255*int(random(1)));
  15.  }
  16.  
  17.  if(int(random(6))>=1){
  18.    fill(255,255,255);
  19.  }
  20.  
  21.   rect(x+c,89,x+5-c,94);
  22.   if (x==95) set(0,0,get(0,5,100,x));
  23.   y = int(random(4));
  24. }

Here's a similar page to this thread, with an expanded set of instructions, through the Manchester Art Gallery:


Awesome idea/topic and amazing effects

Keep it up
I only just saw this thread, but coincidentally worked on something similar for some canvas animations using processing.js on my own website:  http://davidhunterdesign.com/

However there are a few different versions not related to the above (and the page randomly loads them) so I have put the relevant part up on this link to check out:  http://davidhunterdesign.com/processing/tenprint/

It uses an image of the logo, but that could be any image in there, like some of the examples above.

Cool challenge!