Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

I have come across an article where students used network traffic to draw their university on the country's IPv6 graph. [image]

Your goal is simple to tell, but hard to implement. Draw the text MAIL (as it is one of the few words that can be read on a 1D graph) on the CPU graph.

It should look something like this:

Result

Elaborating a bit more on what qualifies:

  • The code does not need to be cross-platform (so you won't need unknown APIs to deal with).
  • You may capture it in any general CPU usage utility that you have.
  • The graph looks a bit worse on a different machine: I trust you this time.
  • The base CPU usage % must be continuous, so if you generate a random wave and highlight something that looks like the word MAIL, it's obviously cheating.
  • The contestant may choose the maximum load he's going to use, but it has to be substantial enough to clearly see it.
  • you must follow the linearity of the example. (For M it looks like this: base %, then sudden increase to specified max, fall gradually to a lower %, rise back to max and sudden drop to base % again).
  • If it's unreadable, voters will notice after all.

Standard loopholes apply. Post the images too!

share|improve this question
1  
i changed the goal to code-golf so that it can be more challenging and less artistic :) –  bebe 2 days ago
4  
I don't see a reason for the close vote anymore. I personally find this a fun challenge, albeit a little system specific. –  TheRare 2 days ago
3  
The problem I see with code golf is to judge how legible is legible enough. If you can think of a way to specify that objectively, that would greatly improve the challenge, but it's a really nice idea anyway! –  m.buettner 2 days ago
1  
it's really just the same as your picture, but I guarantee you if you don't put it in words, people will interpret "draw MAIL" very liberally. –  m.buettner 2 days ago
5  
+1, it is so absurd I almost chuckled myself to death... "this is madness..." "madness.. THIS IS CODEGOLF!!!" –  vaxquis yesterday
show 7 more comments

5 Answers

C (Intel Core Duo + OS X/Darwin), 248 bytes

#include <unistd.h>
#include <mach/mach_time.h>
#define M mach_absolute_time()
main(){char*s="JJJIHGFGHIJJJ@BDFHJJJHFDB@JJJJ@JJJJBBBBBBB";uint64_t i,t,y=1;for(;*s;s++){
for(i=40;i;i--){for(t=M+(*s&15)*9090909;t>M;)y*=7;usleep((11-(*s&15))*9091);}}}

This code is about as portable as the Great Pyramid of Cheops. Sorry about that. The values returned from mach_absolute_time() are hardware-dependent, but on my machine the value increments about once per nanosecond.

Here's the result:

The word "MAIL" shown in my CPU history graph

There are two graphs because the processor has two cores. I set the maximum CPU load to about 90% because the process is liable to switch between cores whenever I call usleep(). With a 100% load, the process is chained to one core and the results are illegible (see this, for example)

share|improve this answer
1  
Good job! This looks very interesting. Could you please post a little explanation of the code? :) –  duci9y yesterday
1  
i see braces. why are there braces in the for loops? you can put usleep into the second for loop's last block. i think you can golf down a little more easily. –  bebe yesterday
    
+1 for the great output –  Joshua yesterday
    
Couldn't you put the declaration and initialisation of the uint64_t variables into the header of the following for loop? –  Јοеу yesterday
7  
+1: "This code is about as portable as the Great Pyramid of Cheops" –  Uwe Keim 23 hours ago
show 2 more comments

Python, 143

from time import*
while 1:
 sleep((ord('00012345654321000~~~D:6300036:D~~~000~~~000DDDD~~~~~'[int(time())%52])-48)*0.001);x=10**5
 while x:x-=1

Each character of the string corresponds to one second of activity, from the ASCII character 0 (max load) through to ~ (very light load). The program runs on a time-synchronised loop, so you can run multiple instances for nicer results.

I used Python 2.7.6 on OS X with an Intel Core i7, but it should work on other computers with a bit of tweaking (adjust the 0.001). The screenshot below was taken with significant background activity.

MAIL

Update - I was able to produce a clearer graph with time()/10 and a lower update frequency:

MAIL

And finally, here's a more golfed version (123 bytes) and its result:

from time import*
while 1:
 sleep((ord('002464200~~A5005A~~00~~00DDD~~'[int(time()/2)%30])-48)*0.001);x=10**5
 while x:x-=1
share|improve this answer
add comment

Ruby, 150 characters

a=(0..15).map{|i|[0.9-3*i*=0.02,i]}
[9,*a[0,11],*(z=a.reverse)[5,11],11,*z,*a,2,11,6,*[0.2]*9].map{|x,y|c=Time.now
1until Time.now-c>x/3
sleep y||x%3}

This isn't all that short so far, but in my opinion the output's rather nice, so I figured I'd post this anyway. As with most other solutions, you may have to pin the Ruby process to a certain core by prefixing it with taskset -c $core.

The code is a simple combination of spinning/sleeping for a certain amount of time, which should make it somewhat portable. Smooth gradients are created by varying the ratio of spin/sleep time.

MAIL written CPU monitor

Lowering the CPU sampling frequency makes the edges look a bit better:

Lower sampling frequency

By adding a few more letters to the alphabet (AILMNUVW are somewhat recognizable), we can also write some other words:

MUM, MAW, VILLAIN

These pictures were generated with the following code:

def gradient num_samples, direction, base = 0.3, increment = 0.02, scale = 1
    range = [*0..num_samples]

    samples = case direction
        when :up then range.reverse
        when :down then range
        when :updown then range.reverse + range
        when :downup then range + range.reverse
    end

    samples.map{|i|
        i *= increment
        [base - scale * i, i]
    }
end

# letters are defined as a series of pairs of (spin-time, sleep-time)
# with the time in seconds
THIN_A = gradient(15, :updown, 0.2, 0.2/15)
A = gradient(15, :updown)
I = 2,0
L = 1.5,0, [[0.1,0.2]]*9
M = 2,0, gradient(9, :downup), 2,0
N = 1,0, gradient(9, :down), 2,0
U = 1,0, gradient(9, :downup, 0.1, 0.03, 0.1), 1,0
V = 0.5,0, gradient(12, :downup, 0.25, 0.02), 0.5,0
W = 0.5,0, [gradient(12, :downup, 0.25, 0.02)]*2, 0.5,0

[A,I,L,M,N,U,V,W].map{|i|
    # add 2 second pause after each letter
    i + [0,2]
}.flatten.each_slice(2){|x,y|
    # spin, then sleep
    c = Time.now
    1 until Time.now-c > x
    sleep y
}

Words that can be written with the implemented letters can be found with

grep -E '^[aijlmnuvw]+$' /usr/share/dict/words 
share|improve this answer
    
+1 for the extension into more words! –  Chris Cirefice 14 hours ago
add comment

Python, on Intel Pentium 4 3.0Ghz, 180 166 145 141 138 bytes

Call with taskset -c 0 python cpu_graph_drawer.py.

taskset is needed to restrict the process to use only one CPU/core (hyperthreading in my case.)

from time import*;c=clock
a=[(3,.8),(3,5),(4,5),(1.3,5),(1.3,0)]
a.extend([(.1,.2)]*10)
for x,y in a:
    t=c()
    while c()-t<x:pass
    sleep(y)

Result isn't that great. This one with taskset -c 1

share|improve this answer
3  
I'd love to see this with a CPU monitor that doesn't smoothen the curves... –  Szabolcs yesterday
1  
Me too, but I don't feel like writing up a conky cpu-usage graph and gnome-system-monitor is the only thing I know. Got any alternatives that would run on LMDE Cinnamon? –  user80551 yesterday
    
Enable the "Draw CPU as stacked area chart", and set all colors to black. –  Tejas Kale 23 hours ago
    
@TejasKale The lines would still be curved. –  user80551 23 hours ago
add comment

Java 8, 482 characters

Every character in the String means number of threads, that will be utilized. Image taken on Intel Core i3 (2 cores / 4 threads).

result

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Mail{
public static void main(String[] args) throws InterruptedException{
Thread.sleep(15000);
for(char c:"123432234321000012343210000444000044441111111".toCharArray()){
ExecutorService executorService = Executors.newScheduledThreadPool(4);
for(int i=1;i<c-48;i++)executorService.execute(()->{while(!Thread.interrupted());});
Thread.sleep(1500);
executorService.shutdownNow();
}}}
share|improve this answer
    
What does this syntax mean? i{while(!Thread.interrupted());}? I've never seen that before. –  ValekHalfHeart 9 hours ago
    
There's a less than sign there that got interpreted as HTML and messed up the formatting. –  David Conrad 9 hours ago
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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