HelolW rdlo (스레딩 도전)


39

나는 당신에게 도전이 있습니다 :

  • 모든 언어를 사용하여 "Hello World"를 인쇄하십시오.
  • 각 문자는 고유 한 고유 스레드에서 인쇄해야합니다

그게 다야. 스레드가 시작 순서대로 작동한다는 보장이 없으므로 출력이 올바른 순서로 인쇄되도록 프로그램 스레드를 안전하게 만들어야합니다.

그리고 이것이 코드 골프이기 때문에 가장 짧은 프로그램이 승리합니다.

최신 정보:

우승자는 34자인 Marinus의 APL 출품작 입니다. 또한 가장 읽기 어려운 항목으로 선정되었습니다.


10
이에 대한 더 좋은 이름은 다음과 같습니다.HelolW rdlo
— Cristian Lupascu

하, 나도 좋아 바로 변경 : D
— Tharwen

Aww ... 너무 짧아요
— Tharwen

1
얼마나 많은 사람들이 "쓰레드가 시작한 순서대로 작동한다는 보장이 없기 때문에"힌트를 무시하고 그들이 올바른 것으로 생각한다고 생각하는 것은 재미있다.
— Joa Ebert

"실이 시작 순서대로 작동한다는 보장은 없다"는 것이 사실이지만, 실제로는 항상 그런 사소한 프로그램에 대해 거의 수행 할 것입니다. 이 혼란을 피하기 위해 각 스레드 가 1) (작은) 임의의 수의 밀리 초를 기다립니다 .2) char을 출력합니다 .3) 다른 임의의 (아마도) 시간을 기다립니다. 코드는 몇 번만 실행하면 작동합니다. 그리고 join () 솔루션은 훨씬 나빠질 것입니다. 무작위 대기 없이는 자신의 프로그램이 정확하다고 생각하는 성공적인 실행으로 오도 될 수 있습니다.
— silviot

답변:


10

APL (Dyalog) ( 44 43 39 34)

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

설명:

  • 2 11⍴'Hello World',⍳11 행렬을 생성합니다 : (H, 1), (e, 2), ...
  • &⌿ 의미 : 행렬의 각 열에 대해 별도의 스레드에서 수행하십시오.
  • 스레드에서, ⍺이제 캐릭터가되고 ⍵이제 시간입니다
  • ⎕DL⊃⍵⍵몇 초 동안 기다립니다 .
  • 그런 다음 ⍞←⍺문자를 출력합니다.

11
그거 알아? 나는 당신의 말을하겠습니다 ... :)
— Bolster 9:20에

좋습니다, 이것이 가장 짧습니다. 축하합니다!
— Tharwen

19

C, 61 62 자

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

pthread 라이브러리 함수는 모두 loooooong 이름을 가지므로 대신 각 문자에 대해 별도의 전체 프로세스를 시작했습니다. fork()너무 짧아요

stdio 버퍼링 기능은 스레드로부터 안전하지 않기 때문에 write()대신 사용해야 했습니다 putchar().

편집 : 최대 62 자까지 백업합니다. 내 열심에서 61 자로 떨어 뜨려도 스레드 안전성이 떨어졌습니다.


쓰기 명령문을 write(1,"Hello World\n",!!++i)2 바이트 로 변경할 수 있어야합니다 . 그렇지 않으면 좋은 해결책입니다.
— primo

당신은 그것을 시도하고 그것이 생산하는 것을 참조해야합니다.
— breadbox

내 실수는, !!++i
— 프리모

그것은 당신이 처음으로 쓴 것으로 보이므로, 당신이 어떤 실수를 고치려고했는지 모르겠습니다. 그리고 나는 정직하지 않았습니다. 솔직히 당신이 직접 시도해보고 무슨 일이 일어나는지보아야한다는 것을 의미했습니다. 추가를 제거하면 모든 스레드가 문자열의 첫 문자 만 인쇄합니다.
— breadbox

나는 원래 썼지 !!i++만 몇 초 후에 편집했다. 왜냐하면 0첫 번째 반복에서 평가 될 것이라는 것을 깨달았 기 때문이다 . 편집하지 않은 버전을 본 것으로 가정합니다. 첫 번째 문자 만 한 번만 인쇄하기 때문에 코드를 테스트 할 수 없습니다 . 그러나 많은 대안이 있습니다. i++<13, !!i또는 심지어write(1,"Hello World\n",i++>13||fork()||main())
— primo를

9

루비, 46 자

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

프로그램은 다음 스레드를 시작하고 다음 문자를 계속하기 전에 스레드가 종료 될 때까지 대기하기 때문에 동기화됩니다.


7

Pythonect (35 자)

http://www.pythonect.org

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

지금까지 가장 짧습니다. 나는 그것이 실제로 무엇을하는지 알지 못하기 때문에, 아무도 그것에 대해 말하거나 더 짧은 것을 게시하지 않으면 올바른 것으로 간주하고 하루나 이틀 안에 그것을 받아 들일 것입니다.
— Tharwen

1
예제를 간단히 살펴 보았습니다. 문장이나리스트 문장에 괄호 []가 붙어 있지 않아야합니까?
— Dalin Seivewright

1
안녕하세요, Itzik (pythonect의 작성자) 답변 전달 : '->'및 '|' 둘 다 Pythonect 연산자입니다. 파이프 연산자는 한 항목에서 한 항목을 전달하고 다른 연산자는 모든 항목을 한 번에 전달합니다. 위의 프로그램은 "Hello World"문자열을 가져 와서 목록으로 바꾸고 목록을 문자로 나누고 각 문자를 보내서 인쇄합니다. 다음과 같이 프로그램을 더욱 최적화 할 수 있습니다. iter ( "Hello World") | print "Hello World"문자열을 반복하고 인쇄 할 각 문자를 동기화 / 차단 방식으로 보냅니다. 감사합니다, Itzik Kotler | ikotler.org
— Leon Fedotov

스레딩은 어떻게 수행됩니까 ???
— Rohit

1
@LeonFedotov가 언급했듯이 파싱 ​​후 pythonect 소스 ( pythonect 에서 사용 가능)에서 각 반복 및 '->'연산자에 대해 스레딩은 다음과 같이 수행됩니다. thread = threading.Thread (target = __ run, args = ([( operator, item)] + expression [1 :], copy.copy (globals_), copy.copy (locals_), return_value_queue, iterate_literal_arrays가 아님)) thread.start ()
— Jonathan Rom

6

파이썬 ( 101 93 98)

이것이 Peter Taylor의 솔루션입니다. 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 + 1 스레드가 생성되기 전에 N 번째 스레드가 완료되기 때문에 작동했습니다. 분명히 이것에 의존하는 규칙에 위배됩니다.


당신은 변경하여 3 개 문자를 저장할 수 import sys,threading에 import sys,threading as t당신은 오히려 키워드 인자보다, 위치 인수로 스레드에 인수를 전달하여, 더 2를 저장할 수 있습니다.
— Joel Cornett

2
스레드 안전을 다루는 코드는 어디에 있습니까? 스레드는 시작하는 순서와 동일하게 실행되기를 바랍니다. 이것은 항상 사실이 아니며 실제로이 문제의 "어려운 부분"입니다. 프로그램 크기를 최적화하는 대신 문제를 다시 고려해야합니다. 처음에는 얻지 못했습니다. 이 코드가 작동하지 않는다는 증거는 gist.github.com/2761278 을 참조하십시오 .
— silviot

빠른 수정. threading.Timer대신에 사용하십시오 threading.Thread. 에서 통과 x슬립 매개 변수로.
— Joel Cornett

1
Joel for x in range(11):t.Timer(x,sys.stdout.write,"Hello World"[x]).start()
— Taylor

1
@ silviot : 스레드 생성에는 객체 인스턴스화가 포함되므로 테스트 한 시스템에서 1 ~ 3 분의 1 밀리 초가 걸립니다. 문자 출력에는이 오버 헤드가 없으며이 시간의 10 분의 1 만 걸립니다. 따라서 아무것도 무시하지 않는 한 "항상"작동합니다. Stdout은 버퍼링되므로 문제가 발생하지 않습니다.
— marinus

4

C # 73

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

tpl은 스레드를 재사용 할 수 있으므로 각 문자를 자체 스레드를 통해 인쇄해야한다는 요구 사항을 충족하지는 않습니다.
— statichippo

이론적으로는 맞지만 내 PC에서 ThreadPool.GetMaxThreads 또는 ThreadPool.GetAvailableThreads는 IO 및 작업자 스레드 모두에 대해 약 1000의 값을 반환합니다.
— JJoos

4

APL (Dyalog Unicode) , 28 바이트 SBCS

전체 프로그램. stderr에 인쇄합니다. marinus의 솔루션에서 영감을 얻었습니다 .

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

온라인으로 사용해보십시오!

⍳11 처음 11 개의 정수

'Hello World'{… }&¨ 오른쪽 인수 ( ⍵) 로 각 정수에 대해 해당 문자를 왼쪽 인수 ( ⍺) 로 사용하여 다음 함수를 생성합니다 .

 ⎕DL⍵ D의 예 리터 AY 오른쪽 인수 초

 ⍺⊣ 왼쪽 인수 특성에 찬성하여 (유효 지연) 버립니다

 ⍞← 줄 바꿈없이 stdout에 인쇄


방법은 ⍞∘←&¨'dlroW olleH'? -이론적으로 보장되는지는 모르겠지만 항상 올바른 순서로 인쇄하는 것 같습니다.
— ngn

@ngn 분명히, 스레드가 시작 순서대로 작동한다는 보장이 없으므로 출력이 올바른 순서로 인쇄되도록 프로그램 스레드를 안전하게 만들어야합니다.
— Adám

그것이 내가 해결하려는 제약 사항입니다. 나는 이것을 100 번 실행했으며 스레드 스케줄러가 항상 스레드를 역순으로 선택하는 것처럼 보입니다. 또는 적어도 ≤11 작업이있는 경우입니다. AFAIK ⍞∘←는 방해받지 않습니다 (또는 C 개발자에게 물어볼 수 있습니까?). Dyalog는 녹색 스레드를 구현합니다. 1 실제 스레드는 많은 척을하기 때문에 (녹색) 스레드 전환이 발생하지 않으면 순서 를 예측할 수 있습니다.
— ngn

3

자바 (160 자)

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 자
— 존 웨슬리 왕자

@ 프린스 그래, 정정 주셔서 감사합니다!
— 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 문자
— Wouter Coekaerts

@Wouter 아주 좋은 것! 나는 그것을 완전히 놓쳤다.
— 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 자
— John Wesley 왕자

2

배쉬 (64)

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

@marinus 골프는 3 개의 문자에 의해 행해진 다 ::()([ "$1" ]&&(printf "${1:0:1}"&: "${1:1}"));: Hello\ World
— Digital Trauma

@fossilet Linux와 OSX 모두에서 여러 bash 버전에서 작동합니다. 쉘 프롬프트 후에 마지막 한두 문자가 인쇄되는 경우가 있습니다.
— 디지털 외상

2

하스켈 ( 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를 곱한 것이 확실하지 않습니다-2Ghz Xeon이 있어도 잘 작동하지만 Pentium 4가 필요합니다. 아무것도하지 마십시오.)


에 대해 인용 부호를 사용하지 (*5^6)않고 대신 사용하여 2자를 저장하십시오 . (*9999)mapM_
— 기계 달팽이

@Mechanicalsnail 백틱을 제거하면 추가 괄호 쌍이 필요합니다. 그렇지 않으면 (((mapM_ (\(x,y) ... )) zip) [0..]) ...원하지 않는 구문으로 구문 분석됩니다 .
— marinus

에 관해서는 999운영 체제 제한으로 인해 0으로 잘릴 수 있지만 잘못되었을 수 있습니다. 어떤 OS를 사용하고 있습니까?
— Joey Adams



1

D (135 자)

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오류입니다.
— 물고기 모니터

@ fossilet 내가 고쳐
— 래칫 괴물

1

스칼라 74

"Hello World".zipWithIndex.par.map(x=>{Thread.sleep(x._2*99);print(x._1)})
  • zipWithIndex는 ((H, 0), (e, 1), (l, 2) ...)를 생성합니다.
  • par는 그것을 병렬 컬렉션으로 만듭니다.

테스트 :

(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)스레드가 고유하지 않음을 보여줍니다.
— 프린스 존 웨슬리

@ 프린스 존 웨슬리 (PrinceJohnWesley) : 편지 당 하나의 코어가 필요하다고 생각하므로 파는 모든 코어에 작업을 배포합니다.
— 사용자가 알 수 없음

알았어 따라서 문자 당 하나의 코어 + 시스템 시계의 높은 해상도가 필요합니다.
— 프린스 존 웨슬리

map대신에 사용하십시오 foreach. 당신은 4 문자를 저장할 수 있습니다.
— 프린스 존 웨슬리

1

자바 스크립트 (72)

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

1

스칼라 (45)

스레드 # 조인 기반 솔루션

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

또는

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

1

이것은 나의 F # 시도입니다. 나의 첫번째 심각한 F # 프로그램. 친절하세요.

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

0

가다

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}}

당신은 문자를 세지 않아도됩니다-우리는 당신을 위해 그렇게 할 것입니다!
— 사용자가 알 수 없음

0

에를 랑 (90)

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

엮다 erlc +export_all h.erl



0

파이썬 : 문자가 너무 많지만 작동합니다.

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

수면 시간을 무작위로 나누는 목적이 무엇인지 이해하지 못합니다.
— Joel Cornett

@Joel은 작동 할 때 스레드가 해고 된 순서와 동일한 순서로 실행되는 운이 우연의 일치가 아닌지 확인합니다.
— silviot


0

Objective-C (183 자)

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

하스켈 99 자

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

작동 방식은 각 스레드가 문자를 표시 한 후 다음에 시작되므로 실제로 유용한 항목은 순서가 맞지 않을 수 없습니다.


0

배쉬 , 43 바이트

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

온라인으로 사용해보십시오!

xargsprintf각 문자에 대해 별도의 프로세스를 분기하고 종료 될 때까지 기다립니다.

Bash , 45 바이트, 외부 유틸리티 없음

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가 내장되어 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.