I have a challenge for you:

  • Print "Hello World" using any language.
  • Each character must be printed from its own, unique thread

That's it. Obviously, as there's no guarantee that the threads will operate in the order you start them, you have to make your program thread safe to ensure the output is printed in the right order.

And, because this is code golf, the shortest program wins.


The winner is Marinus' APL entry, at 34 characters. It also wins the prize for the least readable entry.

  • 10
    \$\begingroup\$ A better name for this would have been HelolW rdlo \$\endgroup\$ – Cristian Lupascu May 19 '12 at 16:36
  • \$\begingroup\$ Ha, I like that. Changing it right away :D \$\endgroup\$ – Tharwen May 19 '12 at 17:02
  • \$\begingroup\$ Aww... it's too short \$\endgroup\$ – Tharwen May 19 '12 at 17:02
  • 1
    \$\begingroup\$ It is funny to see how many people ignore the "obviously, as there's no guarantee that the threads will operate in the order you start them" hint and think they got it right. \$\endgroup\$ – Joa Ebert May 20 '12 at 8:47
  • \$\begingroup\$ Albeit it's true that "there's no guarantee that the threads will operate in the order you start them" in practice they will almost always do for such a trivial program. To avoid this confusion I'd add to the problem that each thread must 1) wait a (small) random number of milliseconds 2) output its char 3) wait for another random (maybe long) amount of time This way people could tell if the code works by just running it a couple of times. And the join() solutions would perform much worse. Without random waiting one could be mislead by a successful run to think that his program is correct. \$\endgroup\$ – silviot May 21 '12 at 11:52

25 Answers 25


APL (Dyalog) (44 43 39 34)

{⍞←⍺⊣⎕DL⍵}&⌿2 11⍴'Hello World',⍳11


  • 2 11⍴'Hello World',⍳11 creates a matrix: (H,1), (e,2), ...
  • &⌿ means: for each column of the matrix, do on a separate thread:
  • In a thread, is now the character and is now the time
  • ⎕DL⊃⍵ waits for seconds.
  • Then, ⍞←⍺ outputs the character.
  • 11
    \$\begingroup\$ You know what? I'll take your word for it... :) \$\endgroup\$ – Bolster May 20 '12 at 9:02
  • \$\begingroup\$ OK, this is the shortest. Congratulations! \$\endgroup\$ – Tharwen May 25 '12 at 8:11

C, 61 62 chars

i;main(){write(1,"Hello World\n"+i++,1);i>13||fork()||main();}

The pthread library functions all have loooooong names, so instead I fired up an entire separate process for each character. fork() is so much shorter.

It was necessary to use write() instead of putchar() because the stdio buffering functions are not thread-safe.

Edited: Back up to 62 chars. In my zeal, dropping down to 61 chars also dropped the thread-safety.

  • \$\begingroup\$ It should be possible to changed the write statement to write(1,"Hello World\n",!!++i) for 2 bytes. Nice solution otherwise. \$\endgroup\$ – primo May 19 '12 at 17:30
  • \$\begingroup\$ You should try that and see what it produces. \$\endgroup\$ – breadbox May 19 '12 at 17:32
  • \$\begingroup\$ My mistake, I meant !!++i \$\endgroup\$ – primo May 19 '12 at 17:34
  • \$\begingroup\$ That appears to be what you wrote the first time, so I don't see what mistake you were trying to correct. And I wasn't being facetious: I honestly meant that you should try it yourself and see what happens. By removing the addition, every thread will just print the first character of the string. \$\endgroup\$ – breadbox May 19 '12 at 17:44
  • \$\begingroup\$ I had originally written !!i++, but edited it a few seconds later, because I realized it would evaluate to 0 on the first iteration. I assumed you had seen the unedited version. I'm not able to test your code, because it only prints out the very first character, once. There's a lot of alternatives though; i++<13, using !!i, or even write(1,"Hello World\n",i++>13||fork()||main()) \$\endgroup\$ – primo May 19 '12 at 17:55

Ruby, 46 characters

"Hello World".chars{|c|Thread.new{$><<c}.join}

It is synchronized due to the fact that the program waits for the thread to end before starting the next thread and continuing with the next char.


Pythonect (35 chars)


"Hello World"|list|_.split()->print
  • \$\begingroup\$ This is the shortest so far. Since I have no idea what it actually does, I'll assume it's correct and accept it in a day or two if no-one speaks out against it or posts anything shorter. \$\endgroup\$ – Tharwen May 22 '12 at 19:59
  • 1
    \$\begingroup\$ Just had a brief look at the examples. Shouldn't print statement or list statement have brackets [] around it? \$\endgroup\$ – Dalin Seivewright May 22 '12 at 22:19
  • 1
    \$\begingroup\$ Hi, im forwarding Itzik's(creator of pythonect) answer: '->' and '|' are both Pythonect operators. The pipe operator passes one item at a item, while the other operator passes all items at once. What the program above does is, it takes "Hello World" string, turn's it into a list, split the list to chars, and send each char to print. It's possible to optimize the program even further, to the following: iter("Hello World") | print What it does is, it iterates "Hello World" string, and send each char to print (in a sync/blocking manner). Regards, Itzik Kotler | ikotler.org \$\endgroup\$ – Leon Fedotov May 22 '12 at 22:36
  • \$\begingroup\$ how is the threading being done here??? \$\endgroup\$ – Rohit May 24 '12 at 10:55
  • 1
    \$\begingroup\$ Like @LeonFedotov mentioned, and from the pythonect source (available at pythonect) after parsing, for each iteration and the '->' operator, threading is done like this: thread = threading.Thread(target=__run, args=([(operator, item)] + expression[1:], copy.copy(globals_), copy.copy(locals_), return_value_queue, not iterate_literal_arrays)) thread.start() \$\endgroup\$ – Jonathan Rom May 24 '12 at 11:44

Python (101 93 98)

This is Peter Taylor's solution. It works by delaying printing the N-th character by N seconds. See comments.

import sys.threading as t
for x in range(11):t.Timer(x,sys.stdout.write,"Hello World"[x]).start()

This is the original one:

import sys,threading as t
for x in "Hello World":t.Thread(None,sys.stdout.write,x,x).start()

It worked because the time it takes to print a single character is less than the time it takes Python to initialize a new thread, therefore the N-th thread would finish before the N+1-th thread was created. Apparently it is against the rules to rely on this.

  • \$\begingroup\$ You can save 3 chars by changing import sys,threading to import sys,threading as t and you can save 2 more, by passing the arguments to Thread as positional args, rather than keyword arguments. \$\endgroup\$ – Joel Cornett May 19 '12 at 20:51
  • 2
    \$\begingroup\$ Where is the code that deals with thread safety? You just fire threads hoping they'll run in the same order you start them. This won't always be true and is in fact the "hard part" of this problem. Instead of optimizing your program size you should re-consider the problem: you didn't get it in the first place. See gist.github.com/2761278 for a proof that this code doesn't work. \$\endgroup\$ – silviot May 21 '12 at 8:57
  • \$\begingroup\$ Quick fix. Use threading.Timer instead of threading.Thread. Pass in x as the sleep parameter. \$\endgroup\$ – Joel Cornett May 21 '12 at 23:58
  • 1
    \$\begingroup\$ Joel's suggestion can be improved by 4 to for x in range(11):t.Timer(x,sys.stdout.write,"Hello World"[x]).start() \$\endgroup\$ – Peter Taylor May 22 '12 at 7:16
  • 1
    \$\begingroup\$ @silviot: I was exploiting the fact that thread creation involves instantiating an object, and thus takes one- to two-thirds of a millisecond on the systems I've tested. Character output does not have this overhead, taking only a tenth of this time. Therefore, it will "always" work, as long as you don't override anything. Stdout is buffered so that shouldn't ever give problems either. \$\endgroup\$ – marinus May 22 '12 at 20:00

C# 73

"hello world".ToList().ForEach(c=>Task.Run(()=>Console.Write(c)).Wait());
  • \$\begingroup\$ not sure this satisfies the requirement that each letter be printed via its own thread since the tpl may reuse threads. \$\endgroup\$ – statichippo May 20 '12 at 16:15
  • \$\begingroup\$ In theory you're right, but on my pc ThreadPool.GetMaxThreads or ThreadPool.GetAvailableThreads returns a value around 1000 for both IO and worker threads. \$\endgroup\$ – JJoos May 20 '12 at 16:48

APL (Dyalog Unicode), 28 bytesSBCS

Full program. Prints to stderr. Inspired by marinus' solution.

'Hello World'{⍞←⍺⊣⎕DL⍵}&¨⍳11

Try it online!

⍳11 first 11 integers

'Hello World'{}&¨ for each integer as right argument (), spawn the following function with the corresponding character as left argument ():

⎕DL⍵delay right-argument seconds

⍺⊣ discard that (the effective delay) in favour of the left-argument character

⍞← print that to stdout without trailing line break

  • \$\begingroup\$ how about ⍞∘←&¨'dlroW olleH'? - I don't know if it's guaranteed theoretically but it seems to always print them in the correct order \$\endgroup\$ – ngn Jul 30 '18 at 8:26
  • \$\begingroup\$ @ngn Obviously, as there's no guarantee that the threads will operate in the order you start them, you have to make your program thread safe to ensure the output is printed in the right order. \$\endgroup\$ – Adám Jul 30 '18 at 9:20
  • \$\begingroup\$ that's the constraint I was trying to address, it might be guaranteed. I ran this 100 times and it looks like the thread scheduler always picks up the threads in reverse order. Or at least that's the case when there are ≤11 tasks. AFAIK ⍞∘← is not interruptible (or is it? maybe you can ask a C developer?). Dyalog implements green threads - 1 real thread pretending to be many, so if a (green) thread switch cannot occur, the order is predictable. \$\endgroup\$ – ngn Jul 30 '18 at 16:49

Java (160 chars)

class A{static int i;public static void main(String...a){new Thread(){public void run(){System.out.print("Hello World".charAt(i++));if(i<11)main();}}.start();}}

Yeah, I know this is the wrong language for code golf, I do it for fun.

  • \$\begingroup\$ class A{public static void main(String[]args){new B(0).start();}}class B extends Thread{int i;B(int j){i=j;}public void run(){System.out.print("Hello World".charAt(i));if(i<10)new B(i+1).start();}}-197 chars \$\endgroup\$ – Prince John Wesley May 20 '12 at 16:13
  • \$\begingroup\$ @Prince Yep, thanks for the correction! \$\endgroup\$ – Malcolm May 20 '12 at 19:23
  • \$\begingroup\$ class A extends Thread{static int i;public static void main(String[]args){System.out.print("Hello World".charAt(i++));if(i<11)new A().start();}public void run(){main(null);}} - 174 chars \$\endgroup\$ – Wouter Coekaerts May 20 '12 at 21:04
  • \$\begingroup\$ @Wouter Very good one! I totally missed it. \$\endgroup\$ – Malcolm May 20 '12 at 21:12
  • 1
    \$\begingroup\$ @Malcolm,@bkil,@Wouter: class A{static int i;public static void main(String...a){new Thread(){public void run(){System.out.print("Hello World".charAt(i++));if(i<11)main();}}.start();}} - 160 chars \$\endgroup\$ – Prince John Wesley May 22 '12 at 4:25

Bash (64)

:(){ [ "$1" ]&&(echo -n "${1:0:1}"&: "${1:1}")};: "Hello World"
  • \$\begingroup\$ @marinus Golfed doen by 3 chars: :()([ "$1" ]&&(printf "${1:0:1}"&: "${1:1}"));: Hello\ World \$\endgroup\$ – Digital Trauma Mar 17 '14 at 21:33
  • \$\begingroup\$ @fossilet Works for me on both Linux and OSX, several bash versions. The last one or two characters is sometimes printed after the shell prompt. \$\endgroup\$ – Digital Trauma Mar 17 '14 at 21:36

Haskell (120 118)

import Control.Concurrent
main=(\(x,y)->forkIO$t x>>putChar y)`mapM_`zip[0..]"Hello World">>t 99

I'm not all that sure about multiplying by 9999 - I have a 2Ghz Xeon on which it'll work fine even if you don't, but I also have a Pentium 4 that needs it (999 gave garbled output and 99 didn't do anything at all.)

  • \$\begingroup\$ Save 2 characters by using (*5^6) instead of (*9999) and not using backquotes for mapM_. \$\endgroup\$ – Mechanical snail May 19 '12 at 21:14
  • \$\begingroup\$ @Mechanicalsnail If you remove the backticks you need an extra pair of braces, otherwise it parses as (((mapM_ (\(x,y) ... )) zip) [0..]) ... which you don't want. \$\endgroup\$ – marinus May 19 '12 at 21:46
  • \$\begingroup\$ As for 999, it might be getting truncated to 0 due to operating system limitations, but I could be wrong. What OS are you using? \$\endgroup\$ – Joey Adams May 22 '12 at 21:58

scala(81 79 chars)

def?(l:String){if(l.size!=0)new Thread{print(l(0));?(l.tail)}}
?("Hello World")
  • \$\begingroup\$ A little bit shorter: def?(l:String){if(l.size>0)new Thread{print(l(0));?(l.tail)}} \$\endgroup\$ – Joa Ebert May 20 '12 at 10:03
  • \$\begingroup\$ @JoaEbert:yea,nice \$\endgroup\$ – Prince John Wesley May 20 '12 at 14:45

Groovy, 51 characters

"Hello World".each{a->Thread.start{print a}.join()}

D (135 chars)

import std.concurrency,std.stdio;
void main(){
    p("Hello World");
void p(string h){

I only start the next thread when I have already printed the current char

edit +2 chars for better bound check

  • \$\begingroup\$ I get core.exception.RangeError@test.d(6): Range violation error. \$\endgroup\$ – Fish Monitor May 19 '12 at 15:09
  • \$\begingroup\$ @fossilet I fixed it \$\endgroup\$ – ratchet freak May 19 '12 at 15:44

Scala 74

"Hello World".zipWithIndex.par.map(x=>{Thread.sleep(x._2*99);print(x._1)})
  • zipWithIndex produces ((H, 0), (e, 1), (l, 2) ...).
  • par makes it a parallel collection.


(1 to 10).foreach {_ => "Hello World".zipWithIndex.par.map(x=>{Thread.sleep(x._2*99);print(x._1)});println()}
Hello World
Hello World
Hello World
Hello World
  • \$\begingroup\$ scala> "Hello World".zipWithIndex.par.foreach(x=>{Thread.sleep(x._2*99);print(x._1)}) Hel lWrolod - I got this \$\endgroup\$ – Prince John Wesley May 20 '12 at 1:19
  • \$\begingroup\$ Also println(Thread.currentThread.getName) shows that the threads are not unique. \$\endgroup\$ – Prince John Wesley May 20 '12 at 1:23
  • \$\begingroup\$ @PrinceJohnWesley: I guess you need one core per letter, so that par will distribute the work over all cores. \$\endgroup\$ – user unknown May 20 '12 at 1:24
  • \$\begingroup\$ I got it. so one core per letter + high resolution of the system clock required. \$\endgroup\$ – Prince John Wesley May 20 '12 at 1:31
  • \$\begingroup\$ use map instead of foreach. you can save 4 characters. \$\endgroup\$ – Prince John Wesley May 20 '12 at 1:32

Javascript (72)

(function f(){console.log("Hello world"[i++]);i<11&&setTimeout(f)})(i=0)


Thread#join based solution

"Hello World"map{x=>new Thread{print(x)}join}


for(x<-"Hello World")new Thread{print(x)}join

This is my F# attempt. My first serious F# program. Please be kind.

let myprint c = async {
        printfn "%c"c
"Hello World"|>Seq.map myprint|>Async.Parallel|>Async.RunSynchronously|>ignore


package main
func main(){o:=make(chan int)
for _,c:=range"Hello World"{go func(c rune){fmt.Printf("%c",c)
for i:=0;i<11;i++{<-o}}
  • \$\begingroup\$ You don't need to count the characters - we will do so for you! \$\endgroup\$ – user unknown May 20 '12 at 1:35

Erlang (90)

r()->r("Hello World").

Compile erlc +export_all h.erl


Nimrod, 121

proc p(c:char){.thread.}=write(stdout,c)
for c in "Hello World":
 var t:TThread[char]

Python: too many characters, but it works.

# Ok. First we patch Threading.start to test wether our solution actually works

import threading
import random, time
original_run = threading.Thread.run

def myRun(self):
    tosleep = random.randint(0,200)/1000.0

threading.Thread.run = myRun

# And now the real code:
import time, sys, threading
string_to_write = "Hello World\n"
current_char_index = 0 # This integer represents the index of the next char to be written
# It will act as a semaphore: threads will wait until it reaches
# the index of the single char that particular thread is due to output

class Writer(threading.Thread):
    def __init__(self, char_to_write, index_to_write):
        self.char_to_write, self.index_to_write = char_to_write, index_to_write
        super(Writer, self).__init__()
    def run(self):
        ch = globals()['current_char_index']
        while not self.index_to_write == ch:
        # This will be atomic because no other thread will touch it while it has "our" index
        globals()['current_char_index'] += 1

for i, char in enumerate(string_to_write):
    Writer(char, i).start()
  • \$\begingroup\$ I don't understand what the purpose of randomizing sleep time is. \$\endgroup\$ – Joel Cornett May 22 '12 at 18:19
  • \$\begingroup\$ @Joel to ensure that, when it works, it's not a lucky coincidence of the threads being executed in the same order as they were fired. \$\endgroup\$ – silviot Jun 12 '12 at 13:45

C# 90 84

foreach(var c in"Hello World"){var t=new Thread(Console.Write);t.Start(c);t.Join();}

Running version: http://ideone.com/0dXNw

  • \$\begingroup\$ console.write is very fast which is why this may work for you but is definitely not thread safe! \$\endgroup\$ – statichippo May 20 '12 at 16:17
  • \$\begingroup\$ @statichippo you're right; I fixed that. \$\endgroup\$ – Cristian Lupascu May 20 '12 at 17:09

Objective-C (183 characters)

-(void) thread {[self performSelectorInBackground:@selector(printC) withObject:nil];}
-(void) printC {char *c = "Hello World"; for(int i = 0; c[i] != '\0'; i++) {printf("%c", c[i]);}}

Haskell 99 Characters

import Control.Concurrent
f(x:xs)=(putChar x)>>(forkIO$f xs)>>f[]
main=f"Hello World"

How it works is each thread starts the next after having displayed its character, so they actually useful stuff can not happen out of sequence.


Bash, 43 bytes

xargs -n1 printf<<<'H e l l o \  W o r l d'

Try it online!

xargs forks a separate printf process for each character (and waits for it to exit).

Bash, 45 bytes, no external utilities

eval \(printf\ {H,e,l,l,o,\\\ ,W,o,r,l,d}\)\;

Try it online!

Expands to (printf H); (printf e); (printf l); (printf l); (printf o); (printf \ ); (printf W); (printf o); (printf r); (printf l); (printf d); before evaluation. The parentheses make Bash fork a subshell for each letter (and wait for it to exit), but this time printf is the Bash builtin.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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