我为您带来挑战:
- 使用任何语言打印“ Hello World”。
- 每个字符必须从其自己的唯一线程中打印
而已。显然,由于不能保证线程按启动顺序运行,因此必须确保程序线程安全以确保按正确的顺序打印输出。
并且,因为这是代码高尔夫,所以最短的程序将获胜。
更新:
获奖者是Marinus的APL参赛作品(34个字符)。它还赢得了可读性最差的奖项。
我为您带来挑战:
而已。显然,由于不能保证线程按启动顺序运行,因此必须确保程序线程安全以确保按正确的顺序打印输出。
并且,因为这是代码高尔夫,所以最短的程序将获胜。
更新:
获奖者是Marinus的APL参赛作品(34个字符)。它还赢得了可读性最差的奖项。
Answers:
{⍞←⍺⊣⎕DL⍵}&⌿2 11⍴'Hello World',⍳11
说明:
2 11⍴'Hello World',⍳11
创建一个矩阵:(H,1),(e,2),...&⌿
表示:对于矩阵的每一列,在单独的线程上执行:⍺
现在是角色,⍵
现在是时间⎕DL⊃⍵
等待⍵
几秒钟。⍞←⍺
输出字符。i;main(){write(1,"Hello World\n"+i++,1);i>13||fork()||main();}
pthread库函数都具有名字,所以我为每个字符启动了一个完整的单独进程。fork()
这么短。
有必要使用write()
代替,putchar()
因为stdio缓冲函数不是线程安全的。
编辑:最多备份62个字符。出于我的热心,降至61个字符也降低了线程安全性。
write(1,"Hello World\n",!!++i)
为2个字节。否则很好的解决方案。
!!++i
!!i++
,但几秒钟后进行了编辑,因为我意识到它会0
在第一次迭代时求值。我以为你看过未编辑的版本。我无法测试您的代码,因为它只会输出第一个字符一次。但是,还有很多选择。i++<13
,使用!!i
或什write(1,"Hello World\n",i++>13||fork()||main())
这就是彼得·泰勒的解决方案。它通过将第N个字符的打印延迟N秒来工作。看评论。
import sys.threading as t
for x in range(11):t.Timer(x,sys.stdout.write,"Hello World"[x]).start()
这是原始的一个:
import sys,threading as t
for x in "Hello World":t.Thread(None,sys.stdout.write,x,x).start()
之所以起作用,是因为打印单个字符所花费的时间少于Python初始化新线程所花费的时间,因此,第N个线程将在创建第N + 1个线程之前完成。显然,依靠它是违反规则的。
import sys,threading
为可以节省3个字符import sys,threading as t
,通过将参数作为位置args(而不是关键字参数)传递给Thread,可以节省2 个字符。
threading.Timer
代替threading.Thread
。x
作为睡眠参数传递。
for x in range(11):t.Timer(x,sys.stdout.write,"Hello World"[x]).start()
"hello world".ToList().ForEach(c=>Task.Run(()=>Console.Write(c)).Wait());
完整程序。打印到stderr。受到marinus解决方案的启发。
'Hello World'{⍞←⍺⊣⎕DL⍵}&¨⍳11
⍳11
前11个整数
'Hello World'{
… }&¨
对于每个作为右参数(⍵
)的整数,产生以下函数,并将相应的字符作为左参数(⍺
):
⎕DL⍵
d Ë 升 AY右参数秒
⍺⊣
抛弃(有效延迟)以支持左参数的字符
⍞←
将其打印到标准输出而不会出现换行符
⍞∘←&¨'dlroW olleH'
?-我不知道理论上是否可以保证,但是似乎总是以正确的顺序打印它们
⍞∘←
不是可中断的(或者是?也许您可以问问C开发人员?)。Dyalog实现了绿色线程-假装有很多真实线程,因此如果无法发生(绿色)线程切换,则该顺序是可预测的。
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();}}
是的,我知道这是代码高尔夫的错误语言,我这样做很有趣。
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个字符
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);}}
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个字符
:(){ [ "$1" ]&&(echo -n "${1:0:1}"&: "${1:1}")};: "Hello World"
:()([ "$1" ]&&(printf "${1:0:1}"&: "${1:1}"));: Hello\ World
import Control.Concurrent
t=threadDelay.(*3^8)
main=(\(x,y)->forkIO$t x>>putChar y)`mapM_`zip[0..]"Hello World">>t 99
我不确定要乘以9999-我有一个2Ghz Xeon,即使您不使用它也可以正常工作,但我也有需要它的Pentium 4(999输出乱码,而99则输出乱码)根本不做任何事情。)
(*5^6)
代替(*9999)
和不使用反引号保存2个字符mapM_
。
(((mapM_ (\(x,y) ... )) zip) [0..]) ...
。
999
,由于操作系统限制,它可能会被截断为0,但是我可能是错的。您正在使用什么操作系统?
def?(l:String){if(l.size!=0)new Thread{print(l(0));?(l.tail)}}
?("Hello World")
"Hello World".each{a->Thread.start{print a}.join()}
import std.concurrency,std.stdio;
void main(){
p("Hello World");
}
void p(string h){
write(h[0]);
if(h.length>1)spawn(&p,h[1..$]);
}
我仅在已经打印了当前字符时才开始下一个线程
编辑+2个字符以进行更好的边界检查
core.exception.RangeError@test.d(6): Range violation
出错了。
"Hello World".zipWithIndex.par.map(x=>{Thread.sleep(x._2*99);print(x._1)})
测试:
(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
scala> "Hello World".zipWithIndex.par.foreach(x=>{Thread.sleep(x._2*99);print(x._1)}) Hel lWrolod
-我知道了
println(Thread.currentThread.getName)
表明线程不是唯一的。
map
代替foreach
。您可以保存4个字符。
这是我的F#尝试。我的第一个认真的F#程序。请客气。
let myprint c = async {
printfn "%c"c
}
"Hello World"|>Seq.map myprint|>Async.Parallel|>Async.RunSynchronously|>ignore
# 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
time.sleep(tosleep)
original_run(self)
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:
time.sleep(0.005)
sys.stdout.write(self.char_to_write)
# 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()
foreach(var c in"Hello World"){var t=new Thread(Console.Write);t.Start(c);t.Join();}
运行版本:http://ideone.com/0dXNw
xargs -n1 printf<<<'H e l l o \ W o r l d'
xargs
printf
为每个字符分叉一个单独的进程(并等待其退出)。
eval \(printf\ {H,e,l,l,o,\\\ ,W,o,r,l,d}\)\;
扩展到(printf H); (printf e); (printf l); (printf l); (printf o); (printf \ ); (printf W); (printf o); (printf r); (printf l); (printf d);
评估之前。括号使Bash成为每个字母的子外壳(并等待其退出),但这一次printf
是Bash内置的。
HelolW rdlo