HelolW rdlo (Bir diş çekme mücadelesi)


39

Senin için bir sorunum var:

  • Herhangi bir dili kullanarak "Hello World" yazdırın.
  • Her karakter kendi benzersiz iş parçacığından basılmalıdır

Bu kadar. Açıkça görüldüğü üzere, iş parçacığı çalıştırma sırasına göre çalışacağının garantisi olmadığından, çıktının doğru sırada yazdırılmasını sağlamak için program iş parçacığınızı güvenli hale getirmelisiniz.

Ve, çünkü bu kod golf, en kısa program kazanıyor.

Güncelleme:

Kazanan Marinus'un APL üyeliği 34 karakterde. Aynı zamanda en az okunabilir giriş ödülü kazandı.


10
Bunun için daha iyi bir isim olurduHelolW rdlo
Cristian Lupascu

Ha, bunu sevdim. Hemen değiştirme: D
Tharwen

Aww ... çok kısa
Tharwen

1
Kaç kişinin görmezden geldiğini görmek çok komik. "Açıkçası, dişlilerin onları çalıştırma sırasına göre çalışacağının garantisi yok" ipucu ve doğru gördüklerini düşünüyorum.
Joa Ebert

Her ne kadar böyle bir önemsiz program için "dişlilerin onları başlattığınız sırada çalışacaklarının garantisi yoktur" pratikte olduğu doğru olsa da. Bu karışıklığı önlemek için, her bir iş parçacığının 1) bir (küçük) rastgele milisaniye beklemesi gerektiğini 2) belirtmek gerekir ; 3) başka bir rastgele (belki uzun süre) süre bekleyin. Kod sadece birkaç kez çalıştırarak çalışır. Ve join () çözümleri çok daha kötü performans gösterirdi. Rastgele bekleme olmadan, programın doğru olduğunu düşünmek için başarılı bir çalışma yanıltılabilir.
Silviot

Yanıtlar:


10

APL (Dyalog) ( 44 43 39 34)

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

Açıklama:

  • 2 11⍴'Hello World',⍳11 bir matris oluşturur: (H, 1), (e, 2), ...
  • &⌿ şu anlama gelir: matrisin her sütunu için ayrı bir iş parçacığı yapın:
  • Bir iş parçacığında, şimdi karakter ve şimdi zamanı
  • ⎕DL⊃⍵saniye bekler .
  • Sonra ⍞←⍺karakteri çıkarır.

11
Biliyor musun? Bunun için senin sözünü alacağım ... :)
Bolster

Tamam, bu en kısa. Tebrikler!
Tharwen

19

C, 61 62 karakter

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

Pthread kütüphanesi işlevlerinin hepsinde loooooong isimleri var, bu yüzden her karakter için ayrı bir süreç başlattım. fork()çok daha kısa.

Bunun write()yerine kullanmak gerekiyordu putchar()çünkü stdio tamponlama fonksiyonları iplik güvenli değil.

Düzenlendi : 62 karaktere kadar yedekleyin. Coşkumda 61 karaktere düşmek iplik güvenliğini de düşürdü.


Write ifadesini write(1,"Hello World\n",!!++i)2 bayt olarak değiştirmek mümkün olmalıdır . Aksi takdirde güzel bir çözüm.
primo

Bunu denemeli ve ne ürettiğini görmelisin.
breadbox

Benim hatam, demek istediğim!!++i
primo

İlk defa yazdığın gibi görünüyor, bu yüzden düzeltmeye çalıştığın hatayı görmüyorum. Ben de yüzün kibirli değildim: Dürüst olmak gerekirse, kendin denemeni ve ne olacağını görmeni istedim. Eklemeyi kaldırarak, her iş parçacığı sadece dizenin ilk karakterini basacaktır.
breadbox

İlk başta yazmıştım !!i++, ancak birkaç saniye sonra düzenledim, çünkü 0ilk tekrarlamaya göre değerlendirileceğini fark ettim . Düzenlenmemiş sürümü gördüğünü sanıyordum. Kodunuzu test edemiyorum, çünkü yalnızca ilk karakteri bir kez basar . Yine de birçok alternatif var; i++<13, kullanma !!i, hattawrite(1,"Hello World\n",i++>13||fork()||main())
primo

9

Yakut, 46 karakter

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

Programın bir sonraki konuya başlamadan ve bir sonraki karaktere devam etmeden önce iş parçacığının bitmesini beklemesi nedeniyle senkronize edilir.


7

Pythonect (35 karakter)

http://www.pythonect.org

"Hello World"|list|_.split()->print

Bu şimdiye kadarki en kısa. Aslında ne yaptığı hakkında hiçbir fikrim olmadığı için, doğru olduğunu kabul edeceğim ve eğer kimse karşı çıkmazsa veya daha kısa bir şey yayınlamazsa, bir veya iki gün içinde kabul edeceğim.
Tharwen

1
Sadece örneklere kısa bir bakış attı. İfadenin veya liste ifadesinin etrafında [] köşeli parantezler bulunmuyor mu?
Dalin Seivewright

1
Merhaba, Itzik'in (pythonect'in yaratıcısı) cevabını iletiyorum: '->' ve '|' Her ikisi de Pythonect operatörleridir. Boru operatörü bir maddeden bir maddeyi geçerken, diğer operatör tüm maddeleri bir kerede geçer. Yukarıdaki programın yaptığı şey, "Merhaba Dünya" dizesini alır, listeye çevirir, listeyi karakterlere ayırır ve yazdırmak için her karaktere gönderir. Programı daha da aşağıdakilere göre optimize etmek mümkündür: iter ("Merhaba Dünya") | print Bu, "Merhaba Dünya" dizesini yineler ve her char'i yazdırmaya gönderir (eşitleme / engelleme şeklinde). Saygılarımızla, Itzik Kotler | ikotler.org
Leon Fedotov

burada iş parçacığı nasıl yapılır ???
Rohit

1
Bahsedilen @LeonFedotov gibi ve her bir yineleme ve '->' işleci için ayrıştırma işleminden sonra pythonect kaynağından ( pythonect'te bulunabilir ) olduğu gibi, iş parçacığı böyle yapılır: thread = threading.Thread (target = __ run, args = ([( işleç, öğe)] + ifade [1:], copy.copy (globals_), copy.copy (locals_), return_value_queue, iterate_literal_arrays değil)) thread.start ()
Jonathan Rom

6

Python ( 101 93 98)

Bu Peter Taylor'ın çözümü. N'inci karakteri yazdırmayı N saniye geciktirerek çalışır. Yorumlara bakınız.

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

Bu orijinal olanıdır:

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

Tek bir karakterin basılması için geçen zaman Python'un yeni bir iş parçacığı başlatması için harcadığı zamandan daha az olduğu için, N + 1'inci iş parçacığı oluşturulmadan önce N-inci iş parçacığı bitecekti. Görünüşe göre buna güvenmek kurallara aykırı.


Sen değiştirerek 3 karakter kaydedebilirsiniz import sys,threadingiçin import sys,threading as tve oldukça anahtar kelime argümanlar yerine, pozisyonel args olarak Konuya argümanlar ileterek, daha 2 kaydedebilirsiniz.
Joel Cornett

2
İplik güvenliği ile ilgili kod nerede? Siz sadece, başlattıkları sırayla koşacaklarını umarak ateş açıyorsunuz. Bu her zaman doğru olmayacak ve aslında bu sorunun "zor kısmı" dır. Programınızın boyutunu optimize etmek yerine sorunu yeniden düşünmelisiniz: ilk etapta alamadınız. Bkz gist.github.com/2761278 bu kod çalışmaz bir kanıtı için.
Silviot

Hızlı düzeltme. Yerine threading.Timerkullanın threading.Thread. Aktarın xuyku parametre olarak.
Joel Cornett

1
Joel'in önerisi 4'e kadar geliştirilebilirfor x in range(11):t.Timer(x,sys.stdout.write,"Hello World"[x]).start()
Peter Taylor

1
@silviot: İplik oluşturmanın bir nesneyi başlatmayı içerdiği gerçeğinden faydalanıyordum ve bu yüzden test ettiğim sistemlerdeki milisaniyenin üçte ikisini alıyor. Karakter çıktısı bu zamana sahip değil, bu zamanın onda birini alarak. Bu nedenle, hiçbir şeyi geçersiz kılmadığınız sürece, “her zaman” çalışır. Stdout arabelleğe alınır, böylece hiçbir zaman sorun yaşanmaz.
marinus

4

C # 73

"hello world".ToList().ForEach(c=>Task.Run(()=>Console.Write(c)).Wait());

bu, her bir mektubun kendi teli üzerinden basılması şartını yerine getirdiğinden emin değildir, çünkü tpl konuları yeniden kullanabilir.
statichippo

Teoride haklısın, ama benim bilgisayarımda ThreadPool.GetMaxThreads veya ThreadPool.GetAvailableThreads hem GÇ hem de çalışan iş parçacığı için 1000 civarında bir değer döndürüyor.
JJoos

4

APL (Dyalog Unicode) , 28 bayt SBCS

Tam program Stderr'ye yazdırır. Esinlenerek Marinus' çözümü .

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

Çevrimiçi deneyin!

⍳11 ilk 11 tam sayı

'Hello World'{}&¨ Her bir tamsayı için doğru argüman ( ) olarak, aşağıdaki işlevi sol argüman ( ) olarak karşılık gelen karakterle oluşturun :

⎕DL⍵d , e l ay sağ bağımsız değişken saniye

⍺⊣ bunu, (etkili gecikme) sol argüman karakteri lehine atın

⍞← bunu satır sonu izlemeden stdout'a yazdır


nasıl ⍞∘←&¨'dlroW olleH'? - Teorik olarak garanti edilip edilmediğini bilmiyorum ama her zaman doğru sırayla yazdırıyor gibi görünüyor
ngn

@ngn ipler bunları başlatmak amacıyla çalışacağını garantisi yok, sen çıkış doğru sırada yazdırılır sağlamak için program parçacığı güvenli yapmak zorunda Açıkçası.
Adám

ele almaya çalıştığım sınırlama bu, garanti edilebilir. Bu 100 kez koştum ve iplik zamanlayıcı her zaman dişleri ters sırayla alır gibi görünüyor. Ya da en azından tasks11 görev olduğunda durum budur. AFAIK ⍞∘←yarıda kesilemez (ya da? Belki de bir C geliştiricisine sorabilirsiniz?). Dyalog uygular yeşil ipler - bir (yeşil) iplik geçiş gerçekleşmez eğer birçok taklidi 1 gerçek iplik, bu yüzden, sipariş olduğu tahmin edilebilir.
ngn

3

Java (160 karakter)

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();}}

Evet, kod golf için yanlış bir dil olduğunu biliyorum, eğlence için yapıyorum.


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 karakter
Prens John Wesley

@Prince Yep, düzeltme için teşekkürler!
Malcolm

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 karakter
Wouter Coekaerts

@Wouter Çok iyi biri! Tamamen özledim.
Malcolm

1
@ 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 karakter
Prens John Wesley

2

Bash (64)

:(){ [ "$1" ]&&(echo -n "${1:0:1}"&: "${1:1}")};: "Hello World"

@marinus Golfed 3 karakter tarafından doen::()([ "$1" ]&&(printf "${1:0:1}"&: "${1:1}"));: Hello\ World
Digital Trauma

@fossilet Hem Linux hem de OSX'te çeşitli bash versiyonlarında benim için çalışıyor. Son bir veya iki karakter bazen kabuk isteminden sonra yazdırılır.
Dijital Travma

2

Haskell ( 120 118)

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

9999 ile çarpma konusunda emin değilim - Ben olmasa bile iyi çalışacağı bir 2Ghz Xeon'um var, ama aynı zamanda ihtiyacı olan bir Pentium 4'üm var (999 bozuk çıktı verdi ve 99 hiçbir şey yapmayın.)


(*5^6)Bunun yerine (*9999)ters tırnak işaretleri kullanmak yerine, kullanarak 2 karakter kaydedin mapM_.
Mekanik salyangoz,

@Mekanik salyangoz Arka ayakları çıkarırsanız fazladan bir çift tel gerekir, aksi halde istemediğiniz şekilde ayrışır (((mapM_ (\(x,y) ... )) zip) [0..]) ....
marinus

Gelince 999, bunun nedeni işletim sistemi sınırlamaları nedeniyle 0'a kesildi alma olabilir, ama yanlış olabilir. Hangi işletim sistemini kullanıyorsunuz?
Joey Adams

2

scala ( 81 79 karakter)

def?(l:String){if(l.size!=0)new Thread{print(l(0));?(l.tail)}}
?("Hello World")

Biraz daha kısa: def? (L: String) {if (l.size> 0) new Thread {print (l (0));? (L.tail)}}
Joa Ebert

@JoaEbert: evet, güzel
Prens John Wesley


1

D (135 karakter)

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..$]);
}

Bir sonraki konuya sadece şimdiki karakteri basıp yazdırdığımda başlıyorum.

daha iyi cilt kontrolü için +2 karakterini düzenle


Ben olsun core.exception.RangeError@test.d(6): Range violationhatayı.
Balık Monitörü

@fossilet Onu tamir ettim
cırcır ucube

1

Scala 74

"Hello World".zipWithIndex.par.map(x=>{Thread.sleep(x._2*99);print(x._1)})
  • zipWithIndex ((H, 0), (e, 1), (1, 2) ...) üretir.
  • par paralel bir koleksiyon yapar.

Testler:

(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- Anladım
Prens John Wesley

Ayrıca println(Thread.currentThread.getName), ipliklerin benzersiz olmadığını da gösterir.
Prens John Wesley

@PrinceJohnWesley: Harf başına bir çekirdeğe ihtiyacınız olduğunu düşünüyorum, böylece par, çalışmayı tüm çekirdeklere dağıtır.
kullanıcı bilinmeyen

Anladım. harf başına bir çekirdek + sistem saatinin yüksek çözünürlüğü gerekli.
Prens John Wesley

mapyerine kullanın foreach. 4 karakter kaydedebilirsiniz.
Prens John Wesley

1

Javascript (72)

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

1

skala (45)

Thread # join bazlı bir çözüm

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

veya

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

1

Bu benim F # denemem. İlk ciddi F # programım. Lütfen nazik ol.

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

0

Git

package main
import"fmt"
func main(){o:=make(chan int)
for _,c:=range"Hello World"{go func(c rune){fmt.Printf("%c",c)
o<-0}(c)}
for i:=0;i<11;i++{<-o}}

Karakterleri saymanıza gerek yok - biz sizin için yapacağız!
kullanıcı bilinmeyen

0

Erlang (90)

-module(h).
r()->r("Hello World").
r([])->'';r([H|T])->spawn(h,r,[T]),io:format("~c",[H]).

derleme erlc +export_all h.erl



0

Python: Çok fazla karakter var ama işe yarıyor.

# 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()

Uyku zamanını randomize etmenin amacının ne olduğunu anlamıyorum.
Joel Cornett

@Joel, çalıştıklarında, dişlerin çalıştıkları sırayla yapılmasının şanslı bir tesadüf olmadığını garanti eder.
Silviot


0

Amaç-C (183 karakter)

-(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]);}}

0

Haskell 99 Karakterler

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

Nasıl çalıştığı her iş parçacığı karakterini gösterdikten sonra bir sonraki başlatır, bu yüzden aslında işe yaramaz şeyler sıra dışı olamaz.


0

Bash , 43 bayt

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

Çevrimiçi deneyin!

xargsprintfher karakter için ayrı bir işlem yapar (ve çıkmasını bekler).

Bash , 45 bayt, harici yardımcı program yok

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

Çevrimiçi deneyin!

(printf H); (printf e); (printf l); (printf l); (printf o); (printf \ ); (printf W); (printf o); (printf r); (printf l); (printf d);Değerlendirmeden önce genişler . Parantezler Bash çatalını her harf için bir alt kabuk haline getirir (ve çıkmasını bekleyin), fakat bu sefer printfBash yerleşiktir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.