独自のソースコードをレンダリングする「ハッカータイパー」プログラムを作成する


25

あなたがハッカーのタイパーに慣れていない場合は、参照hackertyper.net。要するに、コメディ効果のために、キーストロークごとにコードベースのチャンクを1つ出力するプログラムです。しかし、hackertyper.netバージョンは実装が非常に簡単です。任意のコードから一度に3文字を出力するだけです。この課題のために、プログラムは独自のソースコードを出力し、キーストロークごとにスペースで区切られたコードチャンクを1つ印刷する必要があります。

詳細

  • プログラムのファイル名をハードコーディングすることはできません。名前を動的に決定する必要があります。プログラムを実行可能ファイルにコンパイルする場合、標準ファイル拡張子を実行可能ファイルの名前に追加し(Windowsを使用している場合は.exeを除く)、ソースファイルが実行可能ファイルのディレクトリ内にあると想定します。たとえば、C実行可能ファイルの名前が「hacker」の場合、同じディレクトリにある「hacker.c」という名前のファイルからソースコードをプルする必要があります。コンパイルされたプログラムに拡張子がある場合、ソースコードの名前を決定する前に削除する必要があります( "typer.exe"-> "typer.cs")。
  • プログラムには少なくとも5つのスペースが含まれ、各スペースの間に少なくとも1つの文字が必要です。つまり、このチャレンジの最小サイズは9バイトです。スペースは、プログラムの機能にとって重要である必要はありません。
  • 書式設定(インデント、改行など)は、出力で維持する必要があります。この書式設定は、それを実行するコードまたはその後に続くコードで印刷できます。重要なのは、書式設定が維持されることです。
  • 選択した言語でスペースを実装する他の方法がない限り、5スペース要件を満たすためにコメントを使用しないでください。

編集:スペースの代わりに、またはスペースに加えて、新しい行をチャンク区切りとして使用できます。


1
私は少し混乱しています。プログラムは馬ですか?
Orby

8
あなたがそれを説明した方法は、まるで元のソースファイルからコードを読むことが受け入れられるかのように聞こえますが、それは馬鹿ではありません。プログラムが実際の馬でなければならないなら、より良いコンテストになると思います。
Orby 14

1
@Orbyソースの読み取りが許可されているかどうかに関係なく、プログラムは伝統的な意味では馬ではありません。Quinesには入力がありませんが、これらのプログラムには明らかにあります。
カルバンの趣味14

@DrJPepper 3番目の箇条書きでは、空白のシーケンスが区切り文字としてカウントされるように聞こえますが、具体的にはスペースだけがそうであると言います。明確にできますか?
カルビンの趣味14

2
この課題は、プログラムの独自のソースコードの読み取りを促進します。これは、通常、クインの作成における冗長な練習です。
feersum

回答:


13

bash、51 58

for w in $(<$0);do read -sn 1;printf -- "$w ";done

2
それのbashのではなく、シェル:これは、(ダッシュの下では動作しません2: read: Illegal option -s
F. HAURI

1
bashを想定して、置換cat $0およびチルダで$(<$0)

フィードバック用の@broslow thx; ラベル付きbash、同じ長さ
2014

1
@ウィル問題ありません。IFS=\ シバンを省略すると、実際に必要ですか?デフォルトのIFSはのようなものでIFS=$'\n\t '、改行はもうないので、スペースだけに制限する必要はないと思います。

1
for w in `<$0`;{ read \-sn1;printf $w\ ;}
jimmy23013

21

HTMLおよびJavaScript、123

<head></head><body onload="s=(a=document.all)[i=0].innerHTML" onkeyup="a[2].textContent += s.split(/(?= )/)[i++%6]"></body>

これは、ハッカータイプラーと同様に機能しますが、独自のソースコードを使用します。ルールを誤解したかどうか教えてください。

そして、ここにスタイル付きバージョン(170文字)があります。

<head></head>
<body style="background:#000;color:lime" onload="s=(a=document.all)[i=0].innerHTML" onkeyup="a[3].textContent+=s.split(/(?=\s)/)[i++%6]">
<pre></pre></body>

デモを作成しました。JS Binは多くの余分なコードを追加するため変更されていますが、一般的な考え方は同じです。


2
<html>タグと<head>タグなしで、また終了</ body>なしでこれが正しくレンダリングされなかった場合、私は驚きます。この点に関して、すべてのブラウザがどれほど寛容であるかに驚くでしょう。
ウィル

2
@ウィルありがとう。含め<head>た理由は、ブラウザが存在しない場合はブラウザが追加するため、常に表示されるためです。でも忘れまし<html>た。
GRC

12

Perl + Term :: ReadKey、56バイト

use
Term'ReadKey;ReadMode
4;open
0;ReadKey,print
for
<0>

おかげThisSuitIsBlackNotオリジナルのインスピレーションのために、とのプリモ示唆ためopen 0<0>

空白カウントを指定された最小5まで増やすためにどこかfor1つの余分な改行を含める必要があることを除いて、その後の改行は実際には不要であることに注意してください。

また、ThisSuitIsBlackNotの提出のように、このプログラムにはCPANのTerm :: ReadKeyモジュールが必要です。Debian / Ubuntu Linuxでは、このモジュールは、まだ存在しない場合、コマンドで簡単にインストールできますsudo apt-get install libterm-readkey-perl

また、いくつかの文字を保存するために、このプログラムは終了時に入力モードを通常に戻さないため、後で入力しているものが見えないことがあります。シェルコマンドを実行するstty saneか、それresetを修正する必要があります。この問題は、10バイトの追加コストで修正できます。

use
Term'ReadKey;ReadMode
4;open
0;ReadKey,print
for<0>;ReadMode
0

ボーナス:ピュアクイン、81バイト

$_=q{use
Term'ReadKey;ReadMode
4;ReadKey,say
for
split$/,
"\$_=q{$_};eval"};eval

繰り返しますが、カンマの後の改行は、5つの空白の最小値を満たすためにのみ必要です。

上記の56バイトのプログラムとは異なり、このバージョンは独自のソースコードを読む必要はありません。これは、クインに基づいているためです。

$_=q{say"\$_=q{$_};eval"};eval

このクインの良い点は、q{ }ブロック内で任意の「ペイロード」を簡単に運ぶことができることです。ブロックを繰り返す必要はありません。短距離では勝て<0>ませんが、かなり近くなります。

注:このプログラムはPerl 5.10以降のsay機能を使用するため、コマンドラインスイッチ-M5.010(または-E)を使用して呼び出す必要があります。メタに関する確立されたコンセンサスに従って、最新の言語機能を有効にするために使用されるこのようなスイッチは、余分な文字としてカウントされません。私が見つけることsayができる最短の解決策は83バイトです:

$_=q{use
Term'ReadKey;ReadMode
4;ReadKey,print
for
split/^/,
"\$_=q{$_};eval"};eval

(最後の2行を結合して)以下を挿入することにより、これらの両方をより端末フレンドリーにします。

;ReadMode
0

最後の前に}


ワオ。ただすごい。とてもかっこいい。
ThisSuitIsBlackNot 14

+1、ただし、stty sane代わりに入力する習慣を付けることをお勧めしますreset(一部のOSでは、一部の端末パラメーターをリセットするだけではないことがあります^^)
オリビエデュラック14

とてもいい解決策。FWIW、open F,$0<F>置き換えることができるopen 0<0>。また、メタの1つの投稿は、実際にはコンセンサスを構成しないと主張します。このオプション-M5.01は、著者が示唆するように、「特定のポイントに言語を持ち込む」ことなく、機能を有効にします。これらの機能がデフォルトで有効になっているバージョンのperlはありません。
primo 14

3
@primo:既存のメタスレッドに同意できない場合は、メタスレッドに独自の回答を投稿してください。これまでのところ、3年半で誰もそうしなかったという事実は、少なくともメタを積極的に訪れている常連の間では合理的な程度のコンセンサスを示唆していますが、コンセンサスは常に変化します。(とにかく、ruby golfscript.rb foo.gsGolfScriptで記述されたプログラムを実行perl -M5.010 foo.plする有効なコマンドとしてカウントされる場合、 "Perl 5.10"で記述されたプログラムを実行する有効なコマンドとしてカウントする必要があります。こちら。)
イルマリカロネン14

5

Python 3-124バイト-7スペース


コード:

from curses import*
s=initscr();noecho()
for x in open(__file__).read().split(" "):s.getch();s.addstr(x+" ")
echo();endwin()

ゴルフをしていない:

from curses import*
# init curses
screen=initscr()
noecho()
# split code into spaces
code = open(__file__).read().split(" ")
for x in code:
    # wait for keypress
    screen.getch()
    # print a bit
    screen.addstr(x+" ")
# deactivate curses
echo()
endwin()

スタイル付きバージョン:

from curses import*
s=initscr();noecho();start_color();init_pair(2,COLOR_GREEN,COLOR_BLACK)
for x in open(__file__).read().split(" "):s.getch();s.addstr(x+" ",color_pair(2))
echo();endwin()

4

ルビー、85、71

require"io/console";f=File.open __FILE__;loop{STDIN.raw &:getc;print f.read(3)||exit}

残念 IO#raw、標準ライブラリの一部ではありません。

改善

require"io/console";24.times{|q|STDIN.raw &:getc;$><<IO.read($0,3,q*3)}

これにより、Kernel#exitの呼び出しが不要になり、グローバル変数を使用してコードが短縮されます。


4

Befunge-21

~ $ g , 1 +:54*`#@_:0

Befungeについて知ったばかりなので、これにはかなり満足しています。ポップアップウィンドウへの「入力」を気にしない場合は、ここまたはここで実行できます。より良いオンラインインタープリターが見つかるまで。



2

Python 3-299

a="""from curses import*
s=initscr()
raw()
noecho()
for x in e:
 s.getch()
 s.addstr(x+' ')
nocbreak()
echo()
endwin()
""";b="""e=(a+'a=#%s#;b=#%s#;%s'%(a,b,b.replace('#','""''"',4))+'exec(a)').split(' ')
""";e=('a="""%s""";b="""%s""";%s'%(a,b,b.replace('#','""''"',4))+'exec(a)').split(' ')
exec(a)

その馬。execいくつかのステートメントを使用および移動することにより、507から短縮されました。


2

C、211 186バイト

cursesライブラリを使用したCでの私のソリューション。他のCソリューションよりも長くなる場合がありますが、それは馬鹿です。質問では必須ではありませんが、それでもかなりいいです。また、非常にうまく機能します:

#define R(x)#x
#define T(x)R(x)
#define S(p)char*s="#define R(x)#x\n#define T(x)R(x)\n#define S(p)"p"\nS(T(S(p)))";main(){initscr();noecho();while(*s)if(~getch())addch(*s++);}
S(T(S(p)))

いくつかのコメントや内容を含む、より読みやすいバージョン:

#define R(x)#x /* macros to convert the source code in S into a C-string */
#define T(x)R(x)
#define S(p) char*s="#define R(x)#x\n" \
                    "#define T(x)R(x)\n" \
                    "#define S(p) " p "\n" \
                    "S(T(S(p)))";\
    main(){\
        initscr();\
        noecho(); /* don't echo input */ \
        while(*s)\
            if(~getch()) /*true if character has been typed */ \
                addch(*s++);\
}
S(T(S(p)))

コンパイル:

gcc -o h h.c -lncurses

2

C- 136 135バイト(Windowsのみ)

*fopen();**v;b[ 1<<20];main(p,q){v=q; strcpy(b,*v);strcat(b,".c") ;for(*v=fopen(b,"r");~fscanf(*v,"%s",b);printf("%s ",b))getch();} 

注:プログラムの最後にスペースがあり、おそらく表示されません。

このプログラムが非常にハッキングされているため、このプログラムが自分のコンピューター以外で動作することを保証することはできません。誰もが32ビットマシンしか持っていなかった頃は、状況はずっと簡単だったでしょう。それから私は心配する必要はないだろうsizeof(int*) 8であること(これは間違いなく、確認のために印刷しました)sizeof(int)が4であることです。

幸いなことに、実行可能ファイルの名前はargvの最初の文字列に保存されます。ただし、関数の引数としてポインターを置くことは、関数のすべての引数の型を明示的に指定する必要があることを意味します(つまり、int2回入力する必要があることを意味します)。幸いなことに、回避策が見つかりました。mainの2番目の引数はq、単なる別のintでした。次に割り当てるq、型の変数にint**なんとかスタックから必要なすべてのバイトを取得することができました。

の戻り型を解釈するためのそのようなトリックを見つけることに失敗しました fopen関数を宣言せずにポインターとして。

編集:EOFに達したときに戻り値が-1 ~fscanf(*v,"%s",b)であるfscanf(*v,"%s",b)>0ため、代わりに使用する必要があることに注意してください。


これは私にとってはセグメンテーション違反なので、テストすることはできませんがvoid **v;、プロトタイプの代わりにvoidポインター()を宣言できるはずfopen()です。
コミンテルン14

@Cominternこの変更は、の結果を正しく保存するのに役立ちませんでしたfopen。とにかくすべてのポインターが同じサイズであるため、intにvoidを代入することで違いが生じる理由はわかりません。
feersum

いい視点ね。ただし、ポインタを宣言するだけで、さらに短く安定しています。これは実際に実行されますb[1<<20];main(int *c,char **v){strcpy(b,*v);strcat(b,".c");c=fopen(b,"r");for(;fscanf(c,"%s",b)>0;printf("%s ",b))getch();}(ただし、代わりに使用するgetchar()必要getch()がありました)。
コミンテルン14

@Cominternあなたのコードはまだ私のシステムでクラッシュしますが、それを機能させるのは素晴らしい仕事です。私が言った通りだと思います-プログラムの各バージョンは1台のコンピューターで実行されます。
feersum 14

K&Rプロトタイプを使用してみませんか?例えば、*fopen()代わりに*fopen(a,b)
-FUZxxl

1

Perl-87バイト

#!/usr/bin/perl -040
use Term::ReadKey;open F,$0;ReadMode 3;print''.<F>while ReadKey 0

ファイルが最後まで読み取られた後の処理に関するルールには何も表示されなかったため、最後のチャンクを印刷した後、入力を待機するだけです。


1

LiveScriptを使用したnode.js:

#!/usr/local/bin/lsc
console.log <| require \fs .readFileSync __filename, encoding: \utf8

非同期バージョン:

#!/usr/local/bin/lsc
require \fs .readFile __filename, encoding: \utf8, -> console.log &1

1

コブラ-147

class P
    def main
        while 1,for a in File.readLines(CobraCore.exePath[:-4]+'.cobra'),print if('[Console.readKey]'and (Console.cursorLeft=0)<1,a,'')*

CobraCore.exePath とても便利です!


1

Javascript ES6、154

Firefox 154

(a= (i=1,b="(a= "+a+")()",s="") => {window.onkeydown=()=>{clear();i=b.indexOf(" ",i+1),d=b.slice(0,i<0?b.length:i);console.log(s+d);if(i<0){i=0,s+=d}}})()

Chrome 175

( a= function (i,s){b="( a= "+a+")()";c=console,window.onkeydown=function(){c.clear();s=s||"",i=b.indexOf(" ",i+1),d=b.slice(0,i<0?b.length:i);c.log(s+d);if(i<0){i=0,s+=d}}})()

両方274

( a= function (i,s){b="( a= "+a+")()";c=console,window.onkeydown=function(){(clear)?clear():c.clear?c.clear():0;s=s||"",i=b.indexOf(" ",i+1),d=b.slice(0,i<0?b.length:i);c.log(s+d);if(i<0){i=0,s+=d}}})()

Ungolfed(クローム):

( a= function (i,s){        // starting index | undefined, output string
    b="( a= "+a+")()";      // get a string representation of the function
    c=console,
    window.onkeydown=function(){    // on each key down event
        c.clear();                  // clear the output 
        s=s||"";
        i=b.indexOf(" ",i+1);       // get the index of next space
        d=b.slice(0,i<0?b.length:i);// get the string part wanted
        c.log(s+d);                 // print the string
        if(i<0){
            i=0,                    // reset counters
            s+=d                    // adding the string to the main output
        }
    }
})()

Chromeは矢印機能を処理せず、コンソールは同じメソッドでクリアされないため、2つのバージョンがあります

Firefoxはfirebugで動作しますが、デフォルトの開発者コンソールはスクリプトからクリアできないようです。


出力を印刷するために、ユーザーがランダムキーを押す必要があるという要件を見逃していませんか?
オプティマイザー

確かに!、これを書き換えます。
ハケット

0

グルーヴィー-379

import java.nio.file.*
Path p = Paths.get(System.getProperty("user.dir"))
DirectoryStream<Path> f = Files.newDirectoryStream(p,"*.groovy")
try{for(e in f){read(e.toAbsolutePath().toString())}}
catch(Exception e){ }
finally{f.close()}

void read(String x){
    def s = new File(x).text
    for(e in s.replace("%n"," %n").split(" ")) 
        print e + " " 
    Thread.sleep(200)
}   

getch()JavaおよびGroovyのようなJava風の言語にはないか、同等のものがあるため...基本的に、私のコードはキー入力を処理しません。それだけです:D


0

C、248文字

真の馬

UNIXでのみ機能し、Windowsでは_getchを使用して実装されます。

main(){char *p="main(){char *p=\"%s\",s[400];sprintf(s,p,p);system(\"stty raw\");for(p=s;*p!=0;putchar(*p++))getchar();system(\"stty cooked\");}",s[400];sprintf(s,p,p);system("stty raw");for(p=s;*p!=0;putchar(*p++))getchar();system("stty cooked");}

0

HTMLおよびJavascript、232バイト

<body><script>var n=0;var f=function (){document.onkeypress=function(){document.body.innerHTML+=("&lt;body>&lt;script>var n=0;var f="+f.toString()+"f()&lt;/script>&lt;/body>").split(" ")[n]+" ";n++;}};f()</script></body>

従来のJavascriptクインですが、修正されています。

JSFiddleはこちら


0

SmileBASIC、79 75バイト

LOAD"PRG1:"+PRGNAME$()
PRGEDIT 1
@L
IF BUTTON(2)THEN?PRGGET$();
WAIT
GOTO@L

SmileBASICでプログラムの特定のLINEを取得するのは非常に簡単なので、各改行の前にスペースを入れるだけです。私はとても賢く、各改行の前にスペースを入れていると思っていましたが、明らかにスペースの代わりに改行を使用することが許可されています...

説明:

LOAD "PRG1:"+PRGNAME$() 'load the code into slot 1 so we can easily read 1 line at a time
PRGEDIT 1 'Edit slot 1
@LOOP
IF BUTTON(2) THEN 'When a button is pressed...
                   PRINT PRGGET$(); 'get a line of code and print it
WAIT 'delay so we don't detect the same press multiple times in a single frame.
GOTO @LOOP 

-1

ハスケル

{-# LANGUAGE CPP #-}
main = readFile __FILE__ >>= putStrLn

これはそのソースを出力するだけです。
発がん性
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.